@apifuse/provider-sdk 2.2.0-beta.62 → 2.2.0-beta.64
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 +367 -9
- package/CHANGELOG.md +8 -0
- package/LICENSE +21 -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 +187 -4
- package/bin/apifuse-record.ts +44 -32
- package/bin/apifuse-submit-check.ts +9 -5
- 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 +36 -1
- package/dist/handle-meta.js +16 -0
- package/dist/handle.d.ts +23 -5
- package/dist/handle.js +54 -8
- package/dist/health-scenario.d.ts +38 -0
- 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 +11 -3
- package/dist/index.js +9 -1
- package/dist/lint.d.ts +15 -0
- package/dist/lint.js +469 -82
- package/dist/provider.d.ts +6 -6
- package/dist/provider.js +3 -3
- 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 +9 -1
- package/dist/runtime/http-telemetry-guard.d.ts +10 -0
- package/dist/runtime/http-telemetry-guard.js +62 -10
- package/dist/runtime/http.js +141 -35
- 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 +35 -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/runtime-boundary-lint.d.ts +132 -0
- package/dist/runtime-boundary-lint.js +586 -0
- 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 +7 -0
- package/dist/server/index.js +4 -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 +51 -2
- package/dist/server/serve-implementation.js +337 -90
- 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 +123 -1
- package/dist/typescript-module.d.ts +39 -0
- package/dist/typescript-module.js +72 -0
- 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 +51 -1
- package/src/handle.ts +92 -10
- package/src/health-scenario.ts +38 -0
- 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 +86 -0
- package/src/lint.ts +604 -91
- package/src/provider.ts +12 -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 +9 -1
- package/src/runtime/http-telemetry-guard.ts +66 -13
- package/src/runtime/http.ts +168 -37
- package/src/runtime/instrumentation.ts +105 -16
- package/src/runtime/ocr-telemetry.ts +308 -0
- package/src/runtime/ocr.ts +114 -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/runtime-boundary-lint.ts +703 -0
- package/src/server/error-stack-frames.ts +214 -0
- package/src/server/index.ts +53 -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 +569 -108
- 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 +128 -1
- package/src/typescript-module.ts +100 -0
- 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/http.ts
CHANGED
|
@@ -7,7 +7,9 @@ import {
|
|
|
7
7
|
import { HttpRedirectError, ProviderError, TransportError } from "../errors.js";
|
|
8
8
|
import { parseSseStream, readableBytes, readableLines, readableTextChunks } from "../stream.js";
|
|
9
9
|
import type {
|
|
10
|
+
HttpAttemptContext,
|
|
10
11
|
HttpClient,
|
|
12
|
+
HttpHeadersFactory,
|
|
11
13
|
HttpMethod,
|
|
12
14
|
HttpRedirectPolicy,
|
|
13
15
|
HttpResponse,
|
|
@@ -194,26 +196,108 @@ function hasHeader(headers: Record<string, string>, name: string): boolean {
|
|
|
194
196
|
return Object.keys(headers).some((key) => key.toLowerCase() === needle);
|
|
195
197
|
}
|
|
196
198
|
|
|
197
|
-
function
|
|
198
|
-
|
|
199
|
+
function withClientHeaderDefaults(
|
|
200
|
+
headers: Record<string, string> | undefined,
|
|
199
201
|
clientOptions: HttpClientOptions,
|
|
200
202
|
body: unknown,
|
|
201
|
-
):
|
|
202
|
-
const
|
|
203
|
+
): Record<string, string> {
|
|
204
|
+
const merged: Record<string, string> = {
|
|
203
205
|
...(clientOptions.userAgent ? { "User-Agent": clientOptions.userAgent } : {}),
|
|
204
|
-
...
|
|
206
|
+
...headers,
|
|
205
207
|
};
|
|
206
208
|
|
|
207
|
-
if (body !== undefined && !hasHeader(
|
|
208
|
-
|
|
209
|
+
if (body !== undefined && !hasHeader(merged, "Content-Type")) {
|
|
210
|
+
merged["Content-Type"] = "application/json";
|
|
209
211
|
}
|
|
210
212
|
|
|
213
|
+
return merged;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function withClientHeaders(
|
|
217
|
+
options: RequestOptions | undefined,
|
|
218
|
+
clientOptions: HttpClientOptions,
|
|
219
|
+
body: unknown,
|
|
220
|
+
): RequestOptions {
|
|
221
|
+
// The ambient client signal is merged into the per-request one here so every
|
|
222
|
+
// downstream read (retry loop, sleep, body consumption) sees a single signal.
|
|
223
|
+
// The header-factory branch needs it too, otherwise factory-header requests
|
|
224
|
+
// would lose ambient cancellation entirely.
|
|
225
|
+
const signal = mergeAbortSignals(clientOptions.signal, options?.signal);
|
|
226
|
+
// A header factory is resolved per issued attempt (resolveAttemptHeaders);
|
|
227
|
+
// the client defaults are applied to its output at that point.
|
|
228
|
+
if (typeof options?.headers === "function") return { ...options, signal };
|
|
211
229
|
return {
|
|
212
230
|
...options,
|
|
213
|
-
headers,
|
|
231
|
+
headers: withClientHeaderDefaults(options?.headers, clientOptions, body),
|
|
232
|
+
signal,
|
|
214
233
|
};
|
|
215
234
|
}
|
|
216
235
|
|
|
236
|
+
function headerFactoryFailure(message: string, cause?: unknown): TransportError {
|
|
237
|
+
// A dedicated code keeps a broken proof minter out of the retry predicate:
|
|
238
|
+
// toHttpTransportError would otherwise brand a plain throw as
|
|
239
|
+
// transport_network_error, which the default retry policy re-issues.
|
|
240
|
+
// retryable:false is explicit so the served error envelope does not
|
|
241
|
+
// advertise a deterministic signing failure as retryable, and
|
|
242
|
+
// category:provider_error keeps a provider-local minting bug out of the
|
|
243
|
+
// upstream-failure signal (status 0 would otherwise fall through the
|
|
244
|
+
// observability ladder to upstream_http / source upstream_failure).
|
|
245
|
+
return new TransportError(message, {
|
|
246
|
+
code: "http_header_factory_failed",
|
|
247
|
+
status: 0,
|
|
248
|
+
retryable: false,
|
|
249
|
+
category: "provider_error",
|
|
250
|
+
...(cause instanceof Error ? { cause } : {}),
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function isHeaderRecord(value: unknown): value is Record<string, string> {
|
|
255
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Settle `promise`, or reject with the signal's reason as soon as it aborts, so
|
|
259
|
+
// a pending header factory cannot outlive the request deadline or an ambient
|
|
260
|
+
// cancellation (native fetch has not started yet, so nothing else observes them).
|
|
261
|
+
function settleBeforeAbort<T>(promise: Promise<T>, signal: AbortSignal | undefined): Promise<T> {
|
|
262
|
+
if (!signal) return promise;
|
|
263
|
+
return new Promise<T>((resolve, reject) => {
|
|
264
|
+
const onAbort = () => reject(signal.reason);
|
|
265
|
+
if (signal.aborted) onAbort();
|
|
266
|
+
else signal.addEventListener("abort", onAbort, { once: true });
|
|
267
|
+
// Always attach handlers: a late rejection after the abort must settle
|
|
268
|
+
// here (a no-op on the already-rejected promise), never go unhandled.
|
|
269
|
+
promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", onAbort));
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
async function resolveAttemptHeaders(
|
|
274
|
+
options: RequestOptions & { body?: unknown },
|
|
275
|
+
clientOptions: HttpClientOptions,
|
|
276
|
+
attempt: () => HttpAttemptContext,
|
|
277
|
+
signal: AbortSignal | undefined,
|
|
278
|
+
): Promise<Record<string, string> | undefined> {
|
|
279
|
+
const { headers } = options;
|
|
280
|
+
if (typeof headers !== "function") return headers;
|
|
281
|
+
// The per-call timeout may have fired during proxy resolution: do not start
|
|
282
|
+
// the factory at all once the request is already aborted.
|
|
283
|
+
if (signal?.aborted) throw signal.reason;
|
|
284
|
+
let minted: unknown;
|
|
285
|
+
try {
|
|
286
|
+
minted = await settleBeforeAbort(
|
|
287
|
+
Promise.resolve().then(() => headers(attempt())),
|
|
288
|
+
signal,
|
|
289
|
+
);
|
|
290
|
+
} catch (error) {
|
|
291
|
+
// An abort is classified by toHttpTransportError (cancelled / timed out).
|
|
292
|
+
if (signal?.aborted) throw error;
|
|
293
|
+
throw headerFactoryFailure("Request header factory failed", error);
|
|
294
|
+
}
|
|
295
|
+
if (!isHeaderRecord(minted)) {
|
|
296
|
+
throw headerFactoryFailure("Request header factory must return a header record");
|
|
297
|
+
}
|
|
298
|
+
return withClientHeaderDefaults(minted, clientOptions, options.body);
|
|
299
|
+
}
|
|
300
|
+
|
|
217
301
|
function parseHttpData(body: string, headers: Record<string, string>): unknown {
|
|
218
302
|
const contentType = headers["content-type"] ?? headers["Content-Type"] ?? headers["CONTENT-TYPE"];
|
|
219
303
|
|
|
@@ -469,7 +553,7 @@ function toNativeHttpStreamResponse(
|
|
|
469
553
|
};
|
|
470
554
|
}
|
|
471
555
|
|
|
472
|
-
function normalizeHttpMethod(method: string): HttpMethod {
|
|
556
|
+
function normalizeHttpMethod(method: string): Uppercase<HttpMethod> {
|
|
473
557
|
switch (method.toUpperCase()) {
|
|
474
558
|
case "HEAD":
|
|
475
559
|
return "HEAD";
|
|
@@ -765,7 +849,7 @@ function serializeHttpRequestUrl(
|
|
|
765
849
|
async function fetchNativeHttp(
|
|
766
850
|
baseUrl: string | undefined,
|
|
767
851
|
url: string,
|
|
768
|
-
method: HttpMethod
|
|
852
|
+
method: Uppercase<HttpMethod>,
|
|
769
853
|
options: RequestOptions & { body?: unknown },
|
|
770
854
|
clientOptions: HttpClientOptions,
|
|
771
855
|
warn: (message: string) => void,
|
|
@@ -773,24 +857,30 @@ async function fetchNativeHttp(
|
|
|
773
857
|
proxyAttemptOffset = 0,
|
|
774
858
|
dedupe?: { attempted: Set<string> },
|
|
775
859
|
observeProxy?: (used: boolean, status?: number) => void,
|
|
860
|
+
nextHeaderAttempt: () => number = () => 1,
|
|
776
861
|
): Promise<NativeHttpAttemptOutcome> {
|
|
777
862
|
const serializedUrl = serializeHttpRequestUrl(baseUrl, url, options);
|
|
778
863
|
const { requestUrl } = serializedUrl;
|
|
779
864
|
const controller = options.timeout ? new AbortController() : undefined;
|
|
780
|
-
const signal = mergeAbortSignals(
|
|
781
|
-
|
|
865
|
+
const signal = mergeAbortSignals(options.signal, controller?.signal);
|
|
866
|
+
let timeoutHandle = options.timeout
|
|
782
867
|
? setTimeout(() => controller?.abort(), options.timeout)
|
|
783
868
|
: undefined;
|
|
869
|
+
const disarmTimeout = () => {
|
|
870
|
+
if (!timeoutHandle) return;
|
|
871
|
+
clearTimeout(timeoutHandle);
|
|
872
|
+
timeoutHandle = undefined;
|
|
873
|
+
};
|
|
784
874
|
|
|
785
875
|
let proxy: string | undefined;
|
|
786
876
|
try {
|
|
787
|
-
throwIfAmbientAborted(
|
|
877
|
+
throwIfAmbientAborted(options.signal);
|
|
788
878
|
// Resolve inside the try (and after the timeout is armed) so allocator
|
|
789
879
|
// failures are branded as TransportErrors and count against the request
|
|
790
880
|
// deadline, exactly as an inline resolve would.
|
|
791
881
|
proxy = await resolveNativeProxy(options, clientOptions, warn, proxyAttemptOffset);
|
|
792
882
|
observeProxy?.(Boolean(proxy));
|
|
793
|
-
throwIfAmbientAborted(
|
|
883
|
+
throwIfAmbientAborted(options.signal);
|
|
794
884
|
// For a registry allocator chain, skip an endpoint a prior attempt already
|
|
795
885
|
// tried rather than re-issuing the same request. Returning the sentinel
|
|
796
886
|
// (instead of breaking) lets the loop keep advancing the flat offset until
|
|
@@ -801,8 +891,17 @@ async function fetchNativeHttp(
|
|
|
801
891
|
}
|
|
802
892
|
dedupe.attempted.add(proxy);
|
|
803
893
|
}
|
|
894
|
+
// Resolve after the dedupe check so a skipped duplicate offset never burns
|
|
895
|
+
// a single-use proof, and with the serialized URL so URL-bound proofs
|
|
896
|
+
// match what is actually issued.
|
|
897
|
+
const requestHeaders = await resolveAttemptHeaders(
|
|
898
|
+
options,
|
|
899
|
+
clientOptions,
|
|
900
|
+
() => ({ attempt: nextHeaderAttempt(), url: requestUrl, method }),
|
|
901
|
+
signal,
|
|
902
|
+
);
|
|
804
903
|
const requestInit: NativeFetchInit = {
|
|
805
|
-
headers:
|
|
904
|
+
headers: requestHeaders,
|
|
806
905
|
method,
|
|
807
906
|
...(proxy ? { proxy } : {}),
|
|
808
907
|
...(signal ? { signal } : {}),
|
|
@@ -837,7 +936,15 @@ async function fetchNativeHttp(
|
|
|
837
936
|
});
|
|
838
937
|
}
|
|
839
938
|
|
|
840
|
-
|
|
939
|
+
// `timeout` bounds the header phase (types.ts RequestOptions.timeout), so it
|
|
940
|
+
// is disarmed before the body is read: awaiting the buffered body inside
|
|
941
|
+
// this try brands a mid-body failure as a transport error, but must not
|
|
942
|
+
// extend the deadline over the download. Cancellation still applies —
|
|
943
|
+
// `signal` stays attached to the native response. The discarded non-2xx
|
|
944
|
+
// bodies drained above stay under the deadline on purpose: nothing else
|
|
945
|
+
// bounds them, and their content is never returned to the caller.
|
|
946
|
+
disarmTimeout();
|
|
947
|
+
return await toNativeHttpResponse(response);
|
|
841
948
|
} catch (error) {
|
|
842
949
|
if (error instanceof SyntaxError) {
|
|
843
950
|
throw redactSensitiveError(
|
|
@@ -848,7 +955,7 @@ async function fetchNativeHttp(
|
|
|
848
955
|
);
|
|
849
956
|
}
|
|
850
957
|
const transportError: NativeHttpAttemptError = redactSensitiveError(
|
|
851
|
-
toHttpTransportError(error,
|
|
958
|
+
toHttpTransportError(error, options.signal, controller?.signal),
|
|
852
959
|
serializedUrl.sensitiveValues,
|
|
853
960
|
serializedUrl.requestUrl,
|
|
854
961
|
serializedUrl.redactedUrl,
|
|
@@ -856,14 +963,14 @@ async function fetchNativeHttp(
|
|
|
856
963
|
transportError.proxyUsed = Boolean(proxy);
|
|
857
964
|
throw transportError;
|
|
858
965
|
} finally {
|
|
859
|
-
|
|
966
|
+
disarmTimeout();
|
|
860
967
|
}
|
|
861
968
|
}
|
|
862
969
|
|
|
863
970
|
async function fetchNativeHttpStream(
|
|
864
971
|
baseUrl: string | undefined,
|
|
865
972
|
url: string,
|
|
866
|
-
method: HttpMethod
|
|
973
|
+
method: Uppercase<HttpMethod>,
|
|
867
974
|
options: RequestOptions & { body?: unknown },
|
|
868
975
|
clientOptions: HttpClientOptions,
|
|
869
976
|
warn: (message: string) => void,
|
|
@@ -872,18 +979,25 @@ async function fetchNativeHttpStream(
|
|
|
872
979
|
const serializedUrl = serializeHttpRequestUrl(baseUrl, url, options);
|
|
873
980
|
const { requestUrl } = serializedUrl;
|
|
874
981
|
const controller = options.timeout ? new AbortController() : undefined;
|
|
875
|
-
const signal = mergeAbortSignals(
|
|
982
|
+
const signal = mergeAbortSignals(options.signal, controller?.signal);
|
|
876
983
|
const timeoutHandle = options.timeout
|
|
877
984
|
? setTimeout(() => controller?.abort(), options.timeout)
|
|
878
985
|
: undefined;
|
|
879
986
|
|
|
880
987
|
try {
|
|
881
|
-
throwIfAmbientAborted(
|
|
988
|
+
throwIfAmbientAborted(options.signal);
|
|
882
989
|
const proxy = await resolveNativeProxy(options, clientOptions, warn);
|
|
883
990
|
observeProxy?.(Boolean(proxy));
|
|
884
|
-
throwIfAmbientAborted(
|
|
991
|
+
throwIfAmbientAborted(options.signal);
|
|
992
|
+
// Streams never retry: a header factory is resolved once, as attempt 1.
|
|
993
|
+
const headers = await resolveAttemptHeaders(
|
|
994
|
+
options,
|
|
995
|
+
clientOptions,
|
|
996
|
+
() => ({ attempt: 1, url: requestUrl, method }),
|
|
997
|
+
signal,
|
|
998
|
+
);
|
|
885
999
|
const requestInit: NativeFetchInit = {
|
|
886
|
-
headers
|
|
1000
|
+
headers,
|
|
887
1001
|
method,
|
|
888
1002
|
...(proxy ? { proxy } : {}),
|
|
889
1003
|
...(signal ? { signal } : {}),
|
|
@@ -905,9 +1019,9 @@ async function fetchNativeHttpStream(
|
|
|
905
1019
|
});
|
|
906
1020
|
}
|
|
907
1021
|
|
|
908
|
-
//
|
|
909
|
-
// stays attached to
|
|
910
|
-
return toNativeHttpStreamResponse(response, serializedUrl,
|
|
1022
|
+
// The stream timeout remains header-scoped; composed ambient and local
|
|
1023
|
+
// cancellation stays attached to native fetch for the body's full lifetime.
|
|
1024
|
+
return toNativeHttpStreamResponse(response, serializedUrl, options.signal);
|
|
911
1025
|
} catch (error) {
|
|
912
1026
|
if (error instanceof SyntaxError) {
|
|
913
1027
|
throw redactSensitiveError(
|
|
@@ -918,7 +1032,7 @@ async function fetchNativeHttpStream(
|
|
|
918
1032
|
);
|
|
919
1033
|
}
|
|
920
1034
|
throw redactSensitiveError(
|
|
921
|
-
toHttpTransportError(error,
|
|
1035
|
+
toHttpTransportError(error, options.signal, controller?.signal),
|
|
922
1036
|
serializedUrl.sensitiveValues,
|
|
923
1037
|
serializedUrl.requestUrl,
|
|
924
1038
|
serializedUrl.redactedUrl,
|
|
@@ -1052,6 +1166,16 @@ export function createHttpClient(
|
|
|
1052
1166
|
});
|
|
1053
1167
|
const dedupeContext = dedupeAllocatorEndpoints ? { attempted: new Set<string>() } : undefined;
|
|
1054
1168
|
|
|
1169
|
+
// Numbers the attempts a header factory sees: only requests that reached
|
|
1170
|
+
// header resolution count, so a failed proxy allocation (which increments
|
|
1171
|
+
// the telemetry `issued` count below) or a dedupe-skipped offset does not
|
|
1172
|
+
// make the first request that is actually built report `attempt: 2`.
|
|
1173
|
+
let headerAttempts = 0;
|
|
1174
|
+
const nextHeaderAttempt = () => {
|
|
1175
|
+
headerAttempts += 1;
|
|
1176
|
+
return headerAttempts;
|
|
1177
|
+
};
|
|
1178
|
+
|
|
1055
1179
|
const executeOnce = async (proxyAttemptOffset = 0): Promise<NativeHttpAttemptOutcome> => {
|
|
1056
1180
|
const started = performance.now();
|
|
1057
1181
|
let proxyUsed = false;
|
|
@@ -1074,6 +1198,7 @@ export function createHttpClient(
|
|
|
1074
1198
|
proxyUsed = used;
|
|
1075
1199
|
observedStatus = status;
|
|
1076
1200
|
},
|
|
1201
|
+
nextHeaderAttempt,
|
|
1077
1202
|
);
|
|
1078
1203
|
if (!isDedupeSkipOutcome(outcome))
|
|
1079
1204
|
record({
|
|
@@ -1091,7 +1216,7 @@ export function createHttpClient(
|
|
|
1091
1216
|
};
|
|
1092
1217
|
|
|
1093
1218
|
if (!retryEnabled || !retryOptions) {
|
|
1094
|
-
throwIfAmbientAborted(
|
|
1219
|
+
throwIfAmbientAborted(headersOptions.signal);
|
|
1095
1220
|
const outcome = await executeOnce();
|
|
1096
1221
|
if (isDedupeSkipOutcome(outcome)) {
|
|
1097
1222
|
// Single-shot path never de-duplicates (dedupeContext is undefined),
|
|
@@ -1114,7 +1239,7 @@ export function createHttpClient(
|
|
|
1114
1239
|
// allocations skip offsets.
|
|
1115
1240
|
let issued = 0;
|
|
1116
1241
|
for (let attempt = 1; attempt <= transportAttemptCap; attempt += 1) {
|
|
1117
|
-
throwIfAmbientAborted(
|
|
1242
|
+
throwIfAmbientAborted(headersOptions.signal);
|
|
1118
1243
|
// Whether this offset actually issued a request (vs. a skipped duplicate),
|
|
1119
1244
|
// so the catch counts a thrown *transport* failure once without
|
|
1120
1245
|
// double-counting a status outcome that already incremented before it
|
|
@@ -1134,7 +1259,7 @@ export function createHttpClient(
|
|
|
1134
1259
|
if (outcome.retryable && issued < retryOptions.attempts) {
|
|
1135
1260
|
await sleep(
|
|
1136
1261
|
computeProxyTransportRetryDelayMs(retryOptions, attempt, outcome.headers),
|
|
1137
|
-
|
|
1262
|
+
headersOptions.signal,
|
|
1138
1263
|
);
|
|
1139
1264
|
continue;
|
|
1140
1265
|
}
|
|
@@ -1152,7 +1277,7 @@ export function createHttpClient(
|
|
|
1152
1277
|
}
|
|
1153
1278
|
return response;
|
|
1154
1279
|
} catch (error) {
|
|
1155
|
-
throwIfAmbientAborted(
|
|
1280
|
+
throwIfAmbientAborted(headersOptions.signal);
|
|
1156
1281
|
if (!issuedThisAttempt) issued += 1;
|
|
1157
1282
|
lastError = error;
|
|
1158
1283
|
const proxyUsed = Boolean((error as NativeHttpAttemptError).proxyUsed);
|
|
@@ -1168,7 +1293,7 @@ export function createHttpClient(
|
|
|
1168
1293
|
) {
|
|
1169
1294
|
await sleep(
|
|
1170
1295
|
computeProxyTransportRetryDelayMs(retryOptions, attempt),
|
|
1171
|
-
|
|
1296
|
+
headersOptions.signal,
|
|
1172
1297
|
);
|
|
1173
1298
|
continue;
|
|
1174
1299
|
}
|
|
@@ -1218,7 +1343,7 @@ export function createHttpClient(
|
|
|
1218
1343
|
// Streams never retry. Observe the header fetch without consuming its body.
|
|
1219
1344
|
const telemetry = startHttpTelemetry(scopedHttpTelemetry(clientOptions.httpTelemetry), "off");
|
|
1220
1345
|
const started = performance.now();
|
|
1221
|
-
const alreadyAborted =
|
|
1346
|
+
const alreadyAborted = headersOptions.signal?.aborted === true;
|
|
1222
1347
|
let proxyUsed = false;
|
|
1223
1348
|
const record = (event: Omit<HttpAttemptTelemetryEvent, "ms" | "proxyUsed">) => {
|
|
1224
1349
|
if (alreadyAborted) return;
|
|
@@ -1259,10 +1384,16 @@ export function createHttpClient(
|
|
|
1259
1384
|
url,
|
|
1260
1385
|
options: RequestWithMethodOptions = {},
|
|
1261
1386
|
): Promise<AsyncIterable<SseMessage>> => {
|
|
1262
|
-
const
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1387
|
+
const callerHeaders = options.headers;
|
|
1388
|
+
const headers: Record<string, string> | HttpHeadersFactory =
|
|
1389
|
+
typeof callerHeaders === "function"
|
|
1390
|
+
? async (attempt) => {
|
|
1391
|
+
// Pass a malformed result through unchanged so the factory
|
|
1392
|
+
// validation rejects it instead of spreading it into `{}`.
|
|
1393
|
+
const minted = await callerHeaders(attempt);
|
|
1394
|
+
return isHeaderRecord(minted) ? { Accept: "text/event-stream", ...minted } : minted;
|
|
1395
|
+
}
|
|
1396
|
+
: { Accept: "text/event-stream", ...callerHeaders };
|
|
1266
1397
|
const response = await streamRequest(url, options.method ?? "GET", {
|
|
1267
1398
|
...options,
|
|
1268
1399
|
headers,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { runCapabilitySpan } from "./capability-telemetry.js";
|
|
1
2
|
import { registerDiagnosticSensitiveValues } from "./diagnostic-redactor.js";
|
|
2
3
|
import type {
|
|
3
4
|
HttpStreamResponse,
|
|
@@ -35,9 +36,26 @@ export type InstrumentedProviderContext<T extends Pick<ProviderContext, "trace">
|
|
|
35
36
|
trace: TraceContext;
|
|
36
37
|
};
|
|
37
38
|
|
|
38
|
-
type InstrumentedNamespace =
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
type InstrumentedNamespace =
|
|
40
|
+
| "http"
|
|
41
|
+
| "stealth"
|
|
42
|
+
| "browser"
|
|
43
|
+
| "session"
|
|
44
|
+
| "state"
|
|
45
|
+
| "resolver"
|
|
46
|
+
| "ocr"
|
|
47
|
+
| "stt";
|
|
48
|
+
|
|
49
|
+
const BROWSER_PAGE_METHODS = new Set([
|
|
50
|
+
"goto",
|
|
51
|
+
"fill",
|
|
52
|
+
"click",
|
|
53
|
+
"type",
|
|
54
|
+
"waitForSelector",
|
|
55
|
+
"evaluate",
|
|
56
|
+
"content",
|
|
57
|
+
"screenshot",
|
|
58
|
+
]);
|
|
41
59
|
const DIAGNOSTIC_BASE_URL = "http://apifuse-instrumentation.invalid";
|
|
42
60
|
|
|
43
61
|
type RequestDiagnostics = {
|
|
@@ -398,9 +416,19 @@ function buildSpanAttributes(
|
|
|
398
416
|
attributes.method = method;
|
|
399
417
|
}
|
|
400
418
|
|
|
401
|
-
if (
|
|
419
|
+
if (
|
|
420
|
+
status !== undefined &&
|
|
421
|
+
(namespace === "http" || namespace === "stealth" || namespace === "ocr" || namespace === "stt")
|
|
422
|
+
) {
|
|
402
423
|
attributes.status = status;
|
|
403
424
|
}
|
|
425
|
+
if ((namespace === "ocr" || namespace === "stt") && result && typeof result === "object") {
|
|
426
|
+
if ("model" in result && typeof result.model === "string") attributes.model = result.model;
|
|
427
|
+
if ("durationMs" in result && typeof result.durationMs === "number")
|
|
428
|
+
attributes.duration_ms = result.durationMs;
|
|
429
|
+
if ("warnings" in result && Array.isArray(result.warnings))
|
|
430
|
+
attributes.warnings = result.warnings.length;
|
|
431
|
+
}
|
|
404
432
|
|
|
405
433
|
if (duration !== undefined) {
|
|
406
434
|
attributes.duration_ms = duration;
|
|
@@ -538,18 +566,33 @@ function wrapPage<T extends object>(page: T, trace: TraceContext): T {
|
|
|
538
566
|
const methodName = String(property);
|
|
539
567
|
const wrapped = (...args: unknown[]) => {
|
|
540
568
|
let elapsedMs = 0;
|
|
569
|
+
const diagnostics = snapshotRequestDiagnostics("browser", methodName, args);
|
|
570
|
+
registerDiagnosticSensitiveValues(trace, diagnostics.sensitiveValues);
|
|
541
571
|
|
|
542
572
|
return recorder.runSpan(
|
|
543
|
-
|
|
573
|
+
["evaluate", "content", "screenshot"].includes(methodName)
|
|
574
|
+
? `browser.${methodName}`
|
|
575
|
+
: `browser.page.${methodName}`,
|
|
544
576
|
async () => {
|
|
545
577
|
const startedAt = Date.now();
|
|
546
|
-
|
|
578
|
+
let result: unknown;
|
|
579
|
+
try {
|
|
580
|
+
result = await Reflect.apply(value, pageTarget, args);
|
|
581
|
+
} catch (error) {
|
|
582
|
+
throw sanitizeRequestError(error, diagnostics);
|
|
583
|
+
}
|
|
547
584
|
elapsedMs = Date.now() - startedAt;
|
|
548
585
|
return result;
|
|
549
586
|
},
|
|
550
587
|
{
|
|
551
|
-
onSuccess: () =>
|
|
552
|
-
|
|
588
|
+
onSuccess: () => ({
|
|
589
|
+
...getBrowserPageAttributes(methodName, args, elapsedMs),
|
|
590
|
+
...(diagnostics.traceUrl ? { url: diagnostics.traceUrl } : {}),
|
|
591
|
+
}),
|
|
592
|
+
onError: (error) => ({
|
|
593
|
+
...getBrowserPageAttributes(methodName, args, undefined, error),
|
|
594
|
+
...(diagnostics.traceUrl ? { url: diagnostics.traceUrl } : {}),
|
|
595
|
+
}),
|
|
553
596
|
},
|
|
554
597
|
);
|
|
555
598
|
};
|
|
@@ -621,10 +664,15 @@ function wrapNamespace<T extends object>(
|
|
|
621
664
|
trace: TraceContext,
|
|
622
665
|
shouldInstrument?: (methodName: string, args: unknown[]) => boolean,
|
|
623
666
|
): T {
|
|
624
|
-
const
|
|
625
|
-
if (!
|
|
626
|
-
|
|
627
|
-
|
|
667
|
+
const baseRecorder = getTraceRecorder(trace);
|
|
668
|
+
if (!baseRecorder) return target;
|
|
669
|
+
const recorder: NonNullable<ReturnType<typeof getTraceRecorder>> =
|
|
670
|
+
namespace === "ocr" || namespace === "stt"
|
|
671
|
+
? {
|
|
672
|
+
runSpan: (name, fn, options) =>
|
|
673
|
+
runCapabilitySpan(target, () => baseRecorder.runSpan(name, fn, options)),
|
|
674
|
+
}
|
|
675
|
+
: baseRecorder;
|
|
628
676
|
|
|
629
677
|
const wrappedMethods = new Map<PropertyKey, unknown>();
|
|
630
678
|
const resolverMetadata =
|
|
@@ -719,6 +767,32 @@ function wrapNamespace<T extends object>(
|
|
|
719
767
|
return wrapped;
|
|
720
768
|
}
|
|
721
769
|
|
|
770
|
+
if (namespace === "browser" && property === "rawPage") {
|
|
771
|
+
if (wrappedMethods.has(property)) return wrappedMethods.get(property);
|
|
772
|
+
const wrapped = (...args: unknown[]) =>
|
|
773
|
+
recorder.runSpan("browser.rawPage", async () => {
|
|
774
|
+
const page = await Reflect.apply(value, namespaceTarget, args);
|
|
775
|
+
return wrapPage(page, trace);
|
|
776
|
+
});
|
|
777
|
+
wrappedMethods.set(property, wrapped);
|
|
778
|
+
return wrapped;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
if (namespace === "browser" && property === "withIsolatedContext") {
|
|
782
|
+
if (wrappedMethods.has(property)) return wrappedMethods.get(property);
|
|
783
|
+
const wrapped = (handler: unknown, ...args: unknown[]) =>
|
|
784
|
+
recorder.runSpan("browser.withIsolatedContext", async () => {
|
|
785
|
+
if (typeof handler !== "function")
|
|
786
|
+
return Reflect.apply(value, namespaceTarget, [handler, ...args]);
|
|
787
|
+
return Reflect.apply(value, namespaceTarget, [
|
|
788
|
+
(page: object) => Reflect.apply(handler, undefined, [wrapPage(page, trace)]),
|
|
789
|
+
...args,
|
|
790
|
+
]);
|
|
791
|
+
});
|
|
792
|
+
wrappedMethods.set(property, wrapped);
|
|
793
|
+
return wrapped;
|
|
794
|
+
}
|
|
795
|
+
|
|
722
796
|
if (wrappedMethods.has(property)) {
|
|
723
797
|
return wrappedMethods.get(property);
|
|
724
798
|
}
|
|
@@ -727,18 +801,31 @@ function wrapNamespace<T extends object>(
|
|
|
727
801
|
if (namespace === "browser") {
|
|
728
802
|
const wrapped = (...args: unknown[]) => {
|
|
729
803
|
let elapsedMs = 0;
|
|
804
|
+
const diagnostics = snapshotRequestDiagnostics("browser", methodName, args);
|
|
805
|
+
registerDiagnosticSensitiveValues(trace, diagnostics.sensitiveValues);
|
|
730
806
|
|
|
731
807
|
return recorder.runSpan(
|
|
732
808
|
`browser.${methodName}`,
|
|
733
809
|
async () => {
|
|
734
810
|
const startedAt = Date.now();
|
|
735
|
-
|
|
811
|
+
let result: unknown;
|
|
812
|
+
try {
|
|
813
|
+
result = await Reflect.apply(value, namespaceTarget, args);
|
|
814
|
+
} catch (error) {
|
|
815
|
+
throw sanitizeRequestError(error, diagnostics);
|
|
816
|
+
}
|
|
736
817
|
elapsedMs = Date.now() - startedAt;
|
|
737
818
|
return result;
|
|
738
819
|
},
|
|
739
820
|
{
|
|
740
|
-
onSuccess: () =>
|
|
741
|
-
|
|
821
|
+
onSuccess: () => ({
|
|
822
|
+
...getBrowserPageAttributes(methodName, args, elapsedMs),
|
|
823
|
+
...(diagnostics.traceUrl ? { url: diagnostics.traceUrl } : {}),
|
|
824
|
+
}),
|
|
825
|
+
onError: (error) => ({
|
|
826
|
+
...getBrowserPageAttributes(methodName, args, undefined, error),
|
|
827
|
+
...(diagnostics.traceUrl ? { url: diagnostics.traceUrl } : {}),
|
|
828
|
+
}),
|
|
742
829
|
},
|
|
743
830
|
);
|
|
744
831
|
};
|
|
@@ -878,7 +965,9 @@ export function wrapWithInstrumentation<T extends Pick<ProviderContext, "trace">
|
|
|
878
965
|
property === "browser" ||
|
|
879
966
|
property === "session" ||
|
|
880
967
|
property === "state" ||
|
|
881
|
-
property === "resolver"
|
|
968
|
+
property === "resolver" ||
|
|
969
|
+
property === "ocr" ||
|
|
970
|
+
property === "stt"
|
|
882
971
|
) {
|
|
883
972
|
const namespace = property;
|
|
884
973
|
if (wrappedTargets.has(namespace)) {
|