@apifuse/provider-sdk 2.2.0-beta.3 → 2.2.0-beta.5
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 +53 -0
- package/CHANGELOG.md +8 -0
- package/bin/apifuse-check.ts +18 -58
- package/bin/apifuse-create.ts +1 -1
- package/bin/apifuse-dev.ts +27 -52
- package/bin/apifuse-pack-smoke.ts +22 -81
- package/bin/apifuse-pack-types.ts +266 -0
- package/bin/apifuse-perf.ts +45 -127
- package/bin/apifuse-record.ts +23 -61
- package/bin/apifuse-submit-check.ts +266 -34
- package/bin/apifuse.ts +1 -1
- package/bin/submit-check-xml.ts +1 -1
- package/dist/auth-turn/index.d.ts +1 -1
- package/dist/auth.d.ts +2 -2
- package/dist/auth.js +9 -18
- package/dist/ceremonies/index.d.ts +1 -1
- package/dist/ceremonies/index.js +8 -18
- package/dist/config/loader.d.ts +2 -2
- package/dist/config/loader.js +19 -42
- package/dist/contract-serialization.d.ts +2 -2
- package/dist/contract-serialization.js +3 -6
- package/dist/contract-types.d.ts +2 -2
- package/dist/contract.d.ts +3 -3
- package/dist/contract.js +4 -6
- package/dist/define.d.ts +8 -1
- package/dist/define.js +57 -115
- package/dist/dev.d.ts +1 -1
- package/dist/dev.js +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.js +1 -3
- package/dist/i18n/catalog.d.ts +2 -2
- package/dist/i18n/catalog.js +4 -10
- package/dist/i18n/index.d.ts +2 -2
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/keys.d.ts +2 -2
- package/dist/index.d.ts +43 -42
- package/dist/index.js +38 -37
- package/dist/lint.js +8 -15
- package/dist/provider.d.ts +11 -11
- package/dist/provider.js +9 -9
- package/dist/public-schema-field-lint.d.ts +1 -1
- package/dist/recipes/gov-api.js +1 -1
- package/dist/runtime/auth-flow.d.ts +1 -1
- package/dist/runtime/auth-flow.js +3 -3
- package/dist/runtime/browser.d.ts +1 -1
- package/dist/runtime/browser.js +15 -29
- package/dist/runtime/cache.d.ts +1 -1
- package/dist/runtime/cache.js +4 -8
- package/dist/runtime/choice.d.ts +1 -1
- package/dist/runtime/choice.js +12 -34
- package/dist/runtime/credential.d.ts +1 -1
- package/dist/runtime/credential.js +1 -1
- package/dist/runtime/env.d.ts +1 -1
- package/dist/runtime/executor.d.ts +1 -1
- package/dist/runtime/executor.js +2 -2
- package/dist/runtime/http.d.ts +2 -2
- package/dist/runtime/http.js +5 -5
- package/dist/runtime/insights.d.ts +1 -1
- package/dist/runtime/insights.js +6 -13
- package/dist/runtime/instrumentation.d.ts +2 -2
- package/dist/runtime/instrumentation.js +5 -15
- package/dist/runtime/keyring.js +1 -1
- package/dist/runtime/namespace.js +1 -1
- package/dist/runtime/otlp.d.ts +1 -1
- package/dist/runtime/perf.d.ts +1 -1
- package/dist/runtime/provider.d.ts +1 -1
- package/dist/runtime/provider.js +1 -2
- package/dist/runtime/proxy-errors.d.ts +1 -1
- package/dist/runtime/proxy-errors.js +3 -5
- package/dist/runtime/proxy-retry-policy.d.ts +2 -2
- package/dist/runtime/proxy-retry-policy.js +2 -2
- package/dist/runtime/proxy-telemetry.d.ts +1 -1
- package/dist/runtime/proxy-telemetry.js +16 -48
- package/dist/runtime/redis.d.ts +1 -1
- package/dist/runtime/redis.js +2 -4
- package/dist/runtime/request-options.d.ts +1 -1
- package/dist/runtime/state.d.ts +2 -2
- package/dist/runtime/state.js +3 -3
- package/dist/runtime/stealth.d.ts +2 -2
- package/dist/runtime/stealth.js +6 -6
- package/dist/runtime/stt.d.ts +1 -1
- package/dist/runtime/stt.js +11 -15
- package/dist/runtime/trace.d.ts +2 -2
- package/dist/runtime/trace.js +2 -4
- package/dist/runtime/waterfall.d.ts +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +7 -15
- package/dist/serve.d.ts +1 -1
- package/dist/serve.js +1 -1
- package/dist/server/index.d.ts +7 -7
- package/dist/server/index.js +6 -6
- package/dist/server/self-test-redaction.d.ts +1 -1
- package/dist/server/self-test-redaction.js +1 -1
- package/dist/server/self-test.d.ts +104 -3
- package/dist/server/self-test.js +673 -115
- package/dist/server/serve.d.ts +3 -3
- package/dist/server/serve.js +37 -49
- package/dist/server/types.js +2 -7
- package/dist/stealth/profiles.d.ts +1 -1
- package/dist/stealth/profiles.js +5 -14
- package/dist/stream.d.ts +1 -1
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +2 -2
- package/dist/testing/run.d.ts +1 -1
- package/dist/testing/run.js +7 -14
- package/dist/types.d.ts +57 -0
- package/dist/user-input.d.ts +30 -0
- package/dist/user-input.js +66 -0
- package/package.json +6 -4
- package/src/auth-turn/index.ts +1 -1
- package/src/auth.ts +28 -86
- package/src/ceremonies/index.ts +24 -78
- package/src/config/loader.ts +58 -176
- package/src/contract-serialization.ts +5 -11
- package/src/contract-types.ts +2 -2
- package/src/contract.ts +12 -28
- package/src/define.ts +174 -495
- package/src/dev.ts +4 -9
- package/src/errors.ts +4 -11
- package/src/i18n/catalog.ts +10 -32
- package/src/i18n/index.ts +2 -2
- package/src/i18n/keys.ts +5 -11
- package/src/index.ts +44 -42
- package/src/lint.ts +89 -159
- package/src/provider.ts +12 -11
- package/src/public-schema-field-lint.ts +7 -33
- package/src/recipes/gov-api.ts +2 -5
- package/src/runtime/auth-flow.ts +5 -7
- package/src/runtime/browser.ts +64 -187
- package/src/runtime/cache.ts +20 -67
- package/src/runtime/choice.ts +55 -129
- package/src/runtime/credential.ts +2 -2
- package/src/runtime/env.ts +1 -1
- package/src/runtime/executor.ts +9 -19
- package/src/runtime/http.ts +7 -7
- package/src/runtime/insights.ts +15 -53
- package/src/runtime/instrumentation.ts +19 -58
- package/src/runtime/keyring.ts +7 -19
- package/src/runtime/namespace.ts +2 -7
- package/src/runtime/otlp.ts +12 -23
- package/src/runtime/perf.ts +1 -1
- package/src/runtime/provider.ts +4 -9
- package/src/runtime/proxy-errors.ts +17 -38
- package/src/runtime/proxy-retry-policy.ts +3 -3
- package/src/runtime/proxy-telemetry.ts +23 -72
- package/src/runtime/redis.ts +4 -12
- package/src/runtime/request-options.ts +4 -13
- package/src/runtime/state.ts +30 -109
- package/src/runtime/stealth.ts +8 -8
- package/src/runtime/stt.ts +38 -94
- package/src/runtime/trace.ts +14 -44
- package/src/runtime/waterfall.ts +5 -18
- package/src/schema.ts +23 -84
- package/src/serve.ts +1 -1
- package/src/server/index.ts +12 -7
- package/src/server/self-test-redaction.ts +2 -2
- package/src/server/self-test.ts +857 -132
- package/src/server/serve.ts +89 -238
- package/src/server/types.ts +6 -19
- package/src/stealth/profiles.ts +10 -26
- package/src/stream.ts +8 -19
- package/src/testing/index.ts +2 -2
- package/src/testing/run.ts +19 -67
- package/src/types.ts +58 -0
- package/src/user-input.ts +118 -0
package/src/runtime/insights.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { computePercentile } from "./perf";
|
|
2
|
-
import type { Span, SpanAttributeValue } from "./trace";
|
|
1
|
+
import { computePercentile } from "./perf.js";
|
|
2
|
+
import type { Span, SpanAttributeValue } from "./trace.js";
|
|
3
3
|
|
|
4
4
|
export type InsightSeverity = "info" | "warning" | "error";
|
|
5
5
|
|
|
@@ -115,11 +115,7 @@ function parseHostname(url: string | undefined): string | undefined {
|
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
function makeInsight(
|
|
119
|
-
id: string,
|
|
120
|
-
severity: InsightSeverity,
|
|
121
|
-
result: InsightResult,
|
|
122
|
-
): Insight {
|
|
118
|
+
function makeInsight(id: string, severity: InsightSeverity, result: InsightResult): Insight {
|
|
123
119
|
return {
|
|
124
120
|
id,
|
|
125
121
|
severity,
|
|
@@ -266,8 +262,7 @@ function getDnsRepeatedCandidate(spans: Span[]): DnsHostInsight | null {
|
|
|
266
262
|
}
|
|
267
263
|
|
|
268
264
|
const avgDnsMs =
|
|
269
|
-
entry.dnsDurations.reduce((sum, value) => sum + value, 0) /
|
|
270
|
-
entry.dnsDurations.length;
|
|
265
|
+
entry.dnsDurations.reduce((sum, value) => sum + value, 0) / entry.dnsDurations.length;
|
|
271
266
|
const reuseRate = entry.reuseCount / entry.totalCount;
|
|
272
267
|
|
|
273
268
|
if (avgDnsMs > DNS_WARN_MS && reuseRate < 0.2) {
|
|
@@ -301,9 +296,7 @@ function getDnsRepeatedInsight(spans: Span[]): InsightResult {
|
|
|
301
296
|
|
|
302
297
|
function getProxyOverheadInsight(spans: Span[]): InsightResult {
|
|
303
298
|
const requestSpans = spans.filter(isRequestSpan);
|
|
304
|
-
const proxiedDurations = requestSpans
|
|
305
|
-
.filter(hasProxy)
|
|
306
|
-
.map((span) => span.duration_ms);
|
|
299
|
+
const proxiedDurations = requestSpans.filter(hasProxy).map((span) => span.duration_ms);
|
|
307
300
|
const directDurations = requestSpans
|
|
308
301
|
.filter((span) => !hasProxy(span))
|
|
309
302
|
.map((span) => span.duration_ms);
|
|
@@ -316,11 +309,8 @@ function getProxyOverheadInsight(spans: Span[]): InsightResult {
|
|
|
316
309
|
}
|
|
317
310
|
|
|
318
311
|
const proxyAvg =
|
|
319
|
-
proxiedDurations.reduce((sum, value) => sum + value, 0) /
|
|
320
|
-
|
|
321
|
-
const directAvg =
|
|
322
|
-
directDurations.reduce((sum, value) => sum + value, 0) /
|
|
323
|
-
directDurations.length;
|
|
312
|
+
proxiedDurations.reduce((sum, value) => sum + value, 0) / proxiedDurations.length;
|
|
313
|
+
const directAvg = directDurations.reduce((sum, value) => sum + value, 0) / directDurations.length;
|
|
324
314
|
|
|
325
315
|
if (directAvg > 0 && proxyAvg >= directAvg * 2) {
|
|
326
316
|
return {
|
|
@@ -345,9 +335,7 @@ function getBrowserIdleInsight(spans: Span[]): InsightResult {
|
|
|
345
335
|
return waitMs;
|
|
346
336
|
}
|
|
347
337
|
|
|
348
|
-
return span.name.toLowerCase().includes("wait")
|
|
349
|
-
? span.duration_ms
|
|
350
|
-
: undefined;
|
|
338
|
+
return span.name.toLowerCase().includes("wait") ? span.duration_ms : undefined;
|
|
351
339
|
})
|
|
352
340
|
.filter((value): value is number => value !== undefined);
|
|
353
341
|
|
|
@@ -374,9 +362,7 @@ function getBrowserIdleInsight(spans: Span[]): InsightResult {
|
|
|
374
362
|
}
|
|
375
363
|
|
|
376
364
|
function getSessionExpiryInsight(spans: Span[]): InsightResult {
|
|
377
|
-
const refreshCount = spans.filter(
|
|
378
|
-
(span) => span.name === "credential.refresh",
|
|
379
|
-
).length;
|
|
365
|
+
const refreshCount = spans.filter((span) => span.name === "credential.refresh").length;
|
|
380
366
|
const requestCount = spans.filter(isRequestSpan).length;
|
|
381
367
|
|
|
382
368
|
if (requestCount === 0) {
|
|
@@ -415,36 +401,12 @@ export function generateInsights(spans: Span[]): Insight[] {
|
|
|
415
401
|
const sessionExpiry = getSessionExpiryInsight(spans);
|
|
416
402
|
|
|
417
403
|
const rules = [
|
|
418
|
-
makeInsight(
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
),
|
|
423
|
-
makeInsight(
|
|
424
|
-
"slow_transform",
|
|
425
|
-
slowTransform.triggered ? "warning" : "info",
|
|
426
|
-
slowTransform,
|
|
427
|
-
),
|
|
428
|
-
makeInsight(
|
|
429
|
-
"large_response",
|
|
430
|
-
largeResponse.triggered ? "warning" : "info",
|
|
431
|
-
largeResponse,
|
|
432
|
-
),
|
|
433
|
-
makeInsight(
|
|
434
|
-
"dns_repeated",
|
|
435
|
-
dnsRepeated.triggered ? "warning" : "info",
|
|
436
|
-
dnsRepeated,
|
|
437
|
-
),
|
|
438
|
-
makeInsight(
|
|
439
|
-
"proxy_overhead",
|
|
440
|
-
proxyOverhead.triggered ? "warning" : "info",
|
|
441
|
-
proxyOverhead,
|
|
442
|
-
),
|
|
443
|
-
makeInsight(
|
|
444
|
-
"browser_idle",
|
|
445
|
-
browserIdle.triggered ? "warning" : "info",
|
|
446
|
-
browserIdle,
|
|
447
|
-
),
|
|
404
|
+
makeInsight("tls_reuse_failure", tlsReuse.triggered ? "warning" : "info", tlsReuse),
|
|
405
|
+
makeInsight("slow_transform", slowTransform.triggered ? "warning" : "info", slowTransform),
|
|
406
|
+
makeInsight("large_response", largeResponse.triggered ? "warning" : "info", largeResponse),
|
|
407
|
+
makeInsight("dns_repeated", dnsRepeated.triggered ? "warning" : "info", dnsRepeated),
|
|
408
|
+
makeInsight("proxy_overhead", proxyOverhead.triggered ? "warning" : "info", proxyOverhead),
|
|
409
|
+
makeInsight("browser_idle", browserIdle.triggered ? "warning" : "info", browserIdle),
|
|
448
410
|
makeInsight(
|
|
449
411
|
"session_expiry_frequent",
|
|
450
412
|
sessionExpiry.triggered ? "warning" : "info",
|
|
@@ -1,34 +1,20 @@
|
|
|
1
|
-
import type { ProviderContext } from "../types";
|
|
1
|
+
import type { ProviderContext } from "../types.js";
|
|
2
2
|
import {
|
|
3
3
|
type CreateTraceContextOptions,
|
|
4
4
|
createTraceContext,
|
|
5
5
|
getTraceRecorder,
|
|
6
6
|
type TraceContext,
|
|
7
|
-
} from "./trace";
|
|
7
|
+
} from "./trace.js";
|
|
8
8
|
|
|
9
9
|
export interface InstrumentationOptions extends CreateTraceContextOptions {}
|
|
10
10
|
|
|
11
|
-
export type InstrumentedProviderContext<T extends ProviderContext> = Omit<
|
|
12
|
-
T,
|
|
13
|
-
"trace"
|
|
14
|
-
> & {
|
|
11
|
+
export type InstrumentedProviderContext<T extends ProviderContext> = Omit<T, "trace"> & {
|
|
15
12
|
trace: TraceContext;
|
|
16
13
|
};
|
|
17
14
|
|
|
18
|
-
type InstrumentedNamespace =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
| "browser"
|
|
22
|
-
| "session"
|
|
23
|
-
| "state";
|
|
24
|
-
|
|
25
|
-
const BROWSER_PAGE_METHODS = new Set([
|
|
26
|
-
"goto",
|
|
27
|
-
"fill",
|
|
28
|
-
"click",
|
|
29
|
-
"type",
|
|
30
|
-
"waitForSelector",
|
|
31
|
-
]);
|
|
15
|
+
type InstrumentedNamespace = "http" | "stealth" | "browser" | "session" | "state";
|
|
16
|
+
|
|
17
|
+
const BROWSER_PAGE_METHODS = new Set(["goto", "fill", "click", "type", "waitForSelector"]);
|
|
32
18
|
|
|
33
19
|
function getErrorStatus(error: unknown): number | undefined {
|
|
34
20
|
if (
|
|
@@ -59,10 +45,7 @@ function getResponseDuration(result: unknown): number | undefined {
|
|
|
59
45
|
return undefined;
|
|
60
46
|
}
|
|
61
47
|
|
|
62
|
-
function getResponseStatus(
|
|
63
|
-
namespace: InstrumentedNamespace,
|
|
64
|
-
result: unknown,
|
|
65
|
-
): number | undefined {
|
|
48
|
+
function getResponseStatus(namespace: InstrumentedNamespace, result: unknown): number | undefined {
|
|
66
49
|
if (
|
|
67
50
|
typeof result === "object" &&
|
|
68
51
|
result !== null &&
|
|
@@ -111,8 +94,7 @@ function getMethod(
|
|
|
111
94
|
}
|
|
112
95
|
|
|
113
96
|
if (namespace === "stealth") {
|
|
114
|
-
const options =
|
|
115
|
-
typeof args[1] === "object" && args[1] !== null ? args[1] : undefined;
|
|
97
|
+
const options = typeof args[1] === "object" && args[1] !== null ? args[1] : undefined;
|
|
116
98
|
if (options && "method" in options && typeof options.method === "string") {
|
|
117
99
|
return options.method.toUpperCase();
|
|
118
100
|
}
|
|
@@ -133,9 +115,7 @@ function buildSpanAttributes(
|
|
|
133
115
|
const attributes: Record<string, string | number | boolean> = {};
|
|
134
116
|
const url = getUrl(namespace, args, result);
|
|
135
117
|
const method = getMethod(namespace, methodName, args);
|
|
136
|
-
const status = error
|
|
137
|
-
? getErrorStatus(error)
|
|
138
|
-
: getResponseStatus(namespace, result);
|
|
118
|
+
const status = error ? getErrorStatus(error) : getResponseStatus(namespace, result);
|
|
139
119
|
const duration = error ? undefined : getResponseDuration(result);
|
|
140
120
|
|
|
141
121
|
if (url) {
|
|
@@ -146,10 +126,7 @@ function buildSpanAttributes(
|
|
|
146
126
|
attributes.method = method;
|
|
147
127
|
}
|
|
148
128
|
|
|
149
|
-
if (
|
|
150
|
-
status !== undefined &&
|
|
151
|
-
(namespace === "http" || namespace === "stealth")
|
|
152
|
-
) {
|
|
129
|
+
if (status !== undefined && (namespace === "http" || namespace === "stealth")) {
|
|
153
130
|
attributes.status = status;
|
|
154
131
|
}
|
|
155
132
|
|
|
@@ -241,10 +218,8 @@ function wrapPage<T extends object>(page: T, trace: TraceContext): T {
|
|
|
241
218
|
return result;
|
|
242
219
|
},
|
|
243
220
|
{
|
|
244
|
-
onSuccess: () =>
|
|
245
|
-
|
|
246
|
-
onError: (error) =>
|
|
247
|
-
getBrowserPageAttributes(methodName, args, undefined, error),
|
|
221
|
+
onSuccess: () => getBrowserPageAttributes(methodName, args, elapsedMs),
|
|
222
|
+
onError: (error) => getBrowserPageAttributes(methodName, args, undefined, error),
|
|
248
223
|
},
|
|
249
224
|
);
|
|
250
225
|
};
|
|
@@ -310,18 +285,14 @@ function wrapNamespace<T extends object>(
|
|
|
310
285
|
namespaceTarget &&
|
|
311
286
|
typeof namespaceTarget === "object" &&
|
|
312
287
|
"engine" in namespaceTarget &&
|
|
313
|
-
typeof (namespaceTarget as { engine?: unknown }).engine ===
|
|
314
|
-
"string"
|
|
288
|
+
typeof (namespaceTarget as { engine?: unknown }).engine === "string"
|
|
315
289
|
) {
|
|
316
|
-
attributes.engine = (
|
|
317
|
-
namespaceTarget as { engine: string }
|
|
318
|
-
).engine;
|
|
290
|
+
attributes.engine = (namespaceTarget as { engine: string }).engine;
|
|
319
291
|
}
|
|
320
292
|
|
|
321
293
|
return attributes;
|
|
322
294
|
},
|
|
323
|
-
onError: (error) =>
|
|
324
|
-
getBrowserPageAttributes("newPage", args, undefined, error),
|
|
295
|
+
onError: (error) => getBrowserPageAttributes("newPage", args, undefined, error),
|
|
325
296
|
},
|
|
326
297
|
);
|
|
327
298
|
};
|
|
@@ -348,10 +319,8 @@ function wrapNamespace<T extends object>(
|
|
|
348
319
|
return result;
|
|
349
320
|
},
|
|
350
321
|
{
|
|
351
|
-
onSuccess: () =>
|
|
352
|
-
|
|
353
|
-
onError: (error) =>
|
|
354
|
-
getBrowserPageAttributes(methodName, args, undefined, error),
|
|
322
|
+
onSuccess: () => getBrowserPageAttributes(methodName, args, elapsedMs),
|
|
323
|
+
onError: (error) => getBrowserPageAttributes(methodName, args, undefined, error),
|
|
355
324
|
},
|
|
356
325
|
);
|
|
357
326
|
};
|
|
@@ -365,16 +334,8 @@ function wrapNamespace<T extends object>(
|
|
|
365
334
|
`${namespace}.${methodName}`,
|
|
366
335
|
() => Reflect.apply(value, namespaceTarget, args),
|
|
367
336
|
{
|
|
368
|
-
onSuccess: (result) =>
|
|
369
|
-
|
|
370
|
-
onError: (error) =>
|
|
371
|
-
buildSpanAttributes(
|
|
372
|
-
namespace,
|
|
373
|
-
methodName,
|
|
374
|
-
args,
|
|
375
|
-
undefined,
|
|
376
|
-
error,
|
|
377
|
-
),
|
|
337
|
+
onSuccess: (result) => buildSpanAttributes(namespace, methodName, args, result),
|
|
338
|
+
onError: (error) => buildSpanAttributes(namespace, methodName, args, undefined, error),
|
|
378
339
|
},
|
|
379
340
|
);
|
|
380
341
|
|
package/src/runtime/keyring.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConfigurationError, decodeMasterKey } from "./key-derivation";
|
|
1
|
+
import { ConfigurationError, decodeMasterKey } from "./key-derivation.js";
|
|
2
2
|
|
|
3
3
|
export interface KeyRingOptions {
|
|
4
4
|
env: NodeJS.ProcessEnv;
|
|
@@ -16,16 +16,12 @@ export interface KeyRing {
|
|
|
16
16
|
accept(version: number): KeyRingEntry;
|
|
17
17
|
activeWriter(): KeyRingEntry;
|
|
18
18
|
versions(): number[];
|
|
19
|
-
purgeVersion(
|
|
20
|
-
version: number,
|
|
21
|
-
isActiveInStore: (v: number) => Promise<boolean>,
|
|
22
|
-
): Promise<void>;
|
|
19
|
+
purgeVersion(version: number, isActiveInStore: (v: number) => Promise<boolean>): Promise<void>;
|
|
23
20
|
}
|
|
24
21
|
|
|
25
22
|
const DEFAULT_KEY_PREFIX = "APIFUSE__KEYRING__MASTER_KEY_V";
|
|
26
23
|
const DEFAULT_ACCEPT_LIST_VAR = "APIFUSE__KEYRING__MASTER_KEY_ACCEPT_LIST";
|
|
27
|
-
const DEFAULT_WRITER_VERSION_VAR =
|
|
28
|
-
"APIFUSE__KEYRING__MASTER_KEY_WRITER_VERSION";
|
|
24
|
+
const DEFAULT_WRITER_VERSION_VAR = "APIFUSE__KEYRING__MASTER_KEY_WRITER_VERSION";
|
|
29
25
|
|
|
30
26
|
function parseAcceptList(raw: string | undefined): number[] {
|
|
31
27
|
if (!raw || raw.trim().length === 0) {
|
|
@@ -56,19 +52,14 @@ function parseAcceptList(raw: string | undefined): number[] {
|
|
|
56
52
|
return versions;
|
|
57
53
|
}
|
|
58
54
|
|
|
59
|
-
function parseWriterVersion(
|
|
60
|
-
raw: string | undefined,
|
|
61
|
-
acceptList: number[],
|
|
62
|
-
): number {
|
|
55
|
+
function parseWriterVersion(raw: string | undefined, acceptList: number[]): number {
|
|
63
56
|
if (!raw || raw.trim().length === 0) {
|
|
64
57
|
throw new ConfigurationError("writer-version env var is empty");
|
|
65
58
|
}
|
|
66
59
|
const trimmed = raw.trim();
|
|
67
60
|
const v = Number.parseInt(trimmed, 10);
|
|
68
61
|
if (!Number.isInteger(v) || v <= 0 || String(v) !== trimmed) {
|
|
69
|
-
throw new ConfigurationError(
|
|
70
|
-
`writer-version "${trimmed}" is not a positive integer`,
|
|
71
|
-
);
|
|
62
|
+
throw new ConfigurationError(`writer-version "${trimmed}" is not a positive integer`);
|
|
72
63
|
}
|
|
73
64
|
if (!acceptList.includes(v)) {
|
|
74
65
|
throw new ConfigurationError(
|
|
@@ -90,8 +81,7 @@ export function loadKeyRing(options: KeyRingOptions): KeyRing {
|
|
|
90
81
|
const env = options.env;
|
|
91
82
|
const prefix = options.envPrefix ?? DEFAULT_KEY_PREFIX;
|
|
92
83
|
const acceptListVar = options.acceptListVar ?? DEFAULT_ACCEPT_LIST_VAR;
|
|
93
|
-
const writerVersionVar =
|
|
94
|
-
options.writerVersionVar ?? DEFAULT_WRITER_VERSION_VAR;
|
|
84
|
+
const writerVersionVar = options.writerVersionVar ?? DEFAULT_WRITER_VERSION_VAR;
|
|
95
85
|
|
|
96
86
|
const acceptList = parseAcceptList(env[acceptListVar]);
|
|
97
87
|
const writerVersion = parseWriterVersion(env[writerVersionVar], acceptList);
|
|
@@ -100,9 +90,7 @@ export function loadKeyRing(options: KeyRingOptions): KeyRing {
|
|
|
100
90
|
for (const version of acceptList) {
|
|
101
91
|
const raw = env[`${prefix}${version}`];
|
|
102
92
|
if (raw === undefined) {
|
|
103
|
-
throw new ConfigurationError(
|
|
104
|
-
`${prefix}${version} is missing (listed in accept-list)`,
|
|
105
|
-
);
|
|
93
|
+
throw new ConfigurationError(`${prefix}${version} is missing (listed in accept-list)`);
|
|
106
94
|
}
|
|
107
95
|
const key = decodeMasterKey(raw);
|
|
108
96
|
entries.set(version, { version, key });
|
package/src/runtime/namespace.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHmac } from "node:crypto";
|
|
2
2
|
|
|
3
|
-
import { deriveSubkey } from "./key-derivation";
|
|
3
|
+
import { deriveSubkey } from "./key-derivation.js";
|
|
4
4
|
|
|
5
5
|
const HMAC_HEX_LENGTH = 16;
|
|
6
6
|
|
|
@@ -22,12 +22,7 @@ export function deriveContextNamespace(
|
|
|
22
22
|
throw new Error("sessionId is empty");
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
const subkey = deriveSubkey(
|
|
26
|
-
masterSecret,
|
|
27
|
-
providerId,
|
|
28
|
-
"context-namespace",
|
|
29
|
-
keyVersion,
|
|
30
|
-
);
|
|
25
|
+
const subkey = deriveSubkey(masterSecret, providerId, "context-namespace", keyVersion);
|
|
31
26
|
const hmac = createHmac("sha256", subkey).update(providerId).digest("hex");
|
|
32
27
|
return `provider:${hmac.slice(0, HMAC_HEX_LENGTH)}:${sessionId}`;
|
|
33
28
|
}
|
package/src/runtime/otlp.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TraceSpan } from "../types";
|
|
1
|
+
import type { TraceSpan } from "../types.js";
|
|
2
2
|
|
|
3
3
|
export interface OTLPExportOptions {
|
|
4
4
|
endpoint: string;
|
|
@@ -32,10 +32,7 @@ function createTraceId(signature: string): string {
|
|
|
32
32
|
return traceId;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
function normalizeHexId(
|
|
36
|
-
value: string | undefined,
|
|
37
|
-
length: number,
|
|
38
|
-
): string | undefined {
|
|
35
|
+
function normalizeHexId(value: string | undefined, length: number): string | undefined {
|
|
39
36
|
if (!value) {
|
|
40
37
|
return undefined;
|
|
41
38
|
}
|
|
@@ -44,9 +41,7 @@ function normalizeHexId(
|
|
|
44
41
|
return normalized.padStart(length, "0").slice(-length);
|
|
45
42
|
}
|
|
46
43
|
|
|
47
|
-
function toAttributeValue(
|
|
48
|
-
value: unknown,
|
|
49
|
-
): Record<string, string | number | boolean> {
|
|
44
|
+
function toAttributeValue(value: unknown): Record<string, string | number | boolean> {
|
|
50
45
|
if (typeof value === "string") {
|
|
51
46
|
return { stringValue: value };
|
|
52
47
|
}
|
|
@@ -92,20 +87,16 @@ export function spansToOTLP(
|
|
|
92
87
|
}>;
|
|
93
88
|
}>;
|
|
94
89
|
} {
|
|
95
|
-
const traceId = createTraceId(
|
|
96
|
-
createBatchSignature(spans, resourceAttributes),
|
|
97
|
-
);
|
|
90
|
+
const traceId = createTraceId(createBatchSignature(spans, resourceAttributes));
|
|
98
91
|
|
|
99
92
|
return {
|
|
100
93
|
resourceSpans: [
|
|
101
94
|
{
|
|
102
95
|
resource: {
|
|
103
|
-
attributes: Object.entries(resourceAttributes ?? {}).map(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}),
|
|
108
|
-
),
|
|
96
|
+
attributes: Object.entries(resourceAttributes ?? {}).map(([key, value]) => ({
|
|
97
|
+
key,
|
|
98
|
+
value: { stringValue: value },
|
|
99
|
+
})),
|
|
109
100
|
},
|
|
110
101
|
scopeSpans: [
|
|
111
102
|
{
|
|
@@ -122,12 +113,10 @@ export function spansToOTLP(
|
|
|
122
113
|
startTimeUnixNano: String(span.startedAt * 1_000_000),
|
|
123
114
|
endTimeUnixNano: String(span.endedAt * 1_000_000),
|
|
124
115
|
status: { code: span.status === "ok" ? 1 : 2 },
|
|
125
|
-
attributes: Object.entries(span.attributes ?? {}).map(
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}),
|
|
130
|
-
),
|
|
116
|
+
attributes: Object.entries(span.attributes ?? {}).map(([key, value]) => ({
|
|
117
|
+
key,
|
|
118
|
+
value: toAttributeValue(value),
|
|
119
|
+
})),
|
|
131
120
|
})),
|
|
132
121
|
},
|
|
133
122
|
],
|
package/src/runtime/perf.ts
CHANGED
package/src/runtime/provider.ts
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
|
-
import type { ProviderDefinition } from "../types";
|
|
1
|
+
import type { ProviderDefinition } from "../types.js";
|
|
2
2
|
|
|
3
|
-
export function getProviderBaseUrl(
|
|
4
|
-
provider
|
|
5
|
-
): string | undefined {
|
|
6
|
-
const operations = Object.values(
|
|
7
|
-
provider.operations as Record<string, unknown>,
|
|
8
|
-
);
|
|
3
|
+
export function getProviderBaseUrl(provider: ProviderDefinition): string | undefined {
|
|
4
|
+
const operations = Object.values(provider.operations as Record<string, unknown>);
|
|
9
5
|
|
|
10
6
|
for (const operation of operations) {
|
|
11
|
-
const baseUrl = (operation as { upstream?: { baseUrl?: unknown } }).upstream
|
|
12
|
-
?.baseUrl;
|
|
7
|
+
const baseUrl = (operation as { upstream?: { baseUrl?: unknown } }).upstream?.baseUrl;
|
|
13
8
|
|
|
14
9
|
if (typeof baseUrl === "string" && baseUrl.length > 0) {
|
|
15
10
|
return baseUrl;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TransportError } from "../errors";
|
|
1
|
+
import { TransportError } from "../errors.js";
|
|
2
2
|
|
|
3
3
|
export const PROXY_AUTH_IP_DENIED_CODE = "PROXY_AUTH_IP_DENIED";
|
|
4
4
|
export const PROXY_AUTH_IP_DENIED_MESSAGE =
|
|
@@ -39,9 +39,7 @@ export function isProxyEdgeAuthRejectedMessage(message: string): boolean {
|
|
|
39
39
|
return PROXY_EDGE_AUTH_REJECTED_PATTERN.test(message);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
export function createProxyEdgeAuthRejectedError(
|
|
43
|
-
cause?: Error,
|
|
44
|
-
): TransportError {
|
|
42
|
+
export function createProxyEdgeAuthRejectedError(cause?: Error): TransportError {
|
|
45
43
|
return new TransportError(PROXY_EDGE_AUTH_REJECTED_MESSAGE, {
|
|
46
44
|
code: PROXY_EDGE_AUTH_REJECTED_CODE,
|
|
47
45
|
cause,
|
|
@@ -52,10 +50,7 @@ export function isProxyPoolStaleStatus(status: number): boolean {
|
|
|
52
50
|
return PROXY_POOL_STALE_STATUS_CODES.has(status);
|
|
53
51
|
}
|
|
54
52
|
|
|
55
|
-
export function isProxyEdgeTlsRejectedResponse(
|
|
56
|
-
status: number,
|
|
57
|
-
evidence: string,
|
|
58
|
-
): boolean {
|
|
53
|
+
export function isProxyEdgeTlsRejectedResponse(status: number, evidence: string): boolean {
|
|
59
54
|
return (
|
|
60
55
|
PROXY_EDGE_TLS_REJECTED_STATUS_CODES.has(status) &&
|
|
61
56
|
PROXY_EDGE_TLS_REJECTED_MESSAGE_PATTERN.test(evidence)
|
|
@@ -67,10 +62,7 @@ export function isProxyPoolStaleMessage(message: string): boolean {
|
|
|
67
62
|
}
|
|
68
63
|
|
|
69
64
|
export function isProxyPoolRefreshableError(error: unknown): boolean {
|
|
70
|
-
if (
|
|
71
|
-
error instanceof TransportError &&
|
|
72
|
-
error.code === PROXY_AUTH_IP_DENIED_CODE
|
|
73
|
-
) {
|
|
65
|
+
if (error instanceof TransportError && error.code === PROXY_AUTH_IP_DENIED_CODE) {
|
|
74
66
|
return false;
|
|
75
67
|
}
|
|
76
68
|
|
|
@@ -89,39 +81,26 @@ export function isProxyPoolRefreshableError(error: unknown): boolean {
|
|
|
89
81
|
cause instanceof Error ? cause.message : "",
|
|
90
82
|
].join(" ");
|
|
91
83
|
return (
|
|
92
|
-
PROXY_POOL_STALE_MESSAGE_PATTERN.test(message) ||
|
|
93
|
-
PROXY_EDGE_AUTH_REJECTED_PATTERN.test(message)
|
|
84
|
+
PROXY_POOL_STALE_MESSAGE_PATTERN.test(message) || PROXY_EDGE_AUTH_REJECTED_PATTERN.test(message)
|
|
94
85
|
);
|
|
95
86
|
}
|
|
96
87
|
|
|
97
88
|
export const isProxyPoolStaleError = isProxyPoolRefreshableError;
|
|
98
89
|
|
|
99
|
-
export function createProxyPoolStaleError(
|
|
100
|
-
status
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
{
|
|
106
|
-
code: PROXY_POOL_STALE_CODE,
|
|
107
|
-
status,
|
|
108
|
-
cause,
|
|
109
|
-
},
|
|
110
|
-
);
|
|
90
|
+
export function createProxyPoolStaleError(status: number, cause?: Error): TransportError {
|
|
91
|
+
return new TransportError(`Proxy provider pool failed with status ${status}`, {
|
|
92
|
+
code: PROXY_POOL_STALE_CODE,
|
|
93
|
+
status,
|
|
94
|
+
cause,
|
|
95
|
+
});
|
|
111
96
|
}
|
|
112
97
|
|
|
113
|
-
export function createProxyEdgeTlsRejectedError(
|
|
114
|
-
status
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
{
|
|
120
|
-
code: PROXY_EDGE_TLS_REJECTED_CODE,
|
|
121
|
-
status,
|
|
122
|
-
cause,
|
|
123
|
-
},
|
|
124
|
-
);
|
|
98
|
+
export function createProxyEdgeTlsRejectedError(status: number, cause?: Error): TransportError {
|
|
99
|
+
return new TransportError(`Proxy edge TLS request was rejected with status ${status}`, {
|
|
100
|
+
code: PROXY_EDGE_TLS_REJECTED_CODE,
|
|
101
|
+
status,
|
|
102
|
+
cause,
|
|
103
|
+
});
|
|
125
104
|
}
|
|
126
105
|
|
|
127
106
|
export function createProxyPoolExhaustedError(cause?: Error): TransportError {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { ProviderError, TransportError } from "../errors";
|
|
2
|
-
import type { HttpMethod, HttpRetryOptions, RequestOptions } from "../types";
|
|
1
|
+
import { ProviderError, TransportError } from "../errors.js";
|
|
2
|
+
import type { HttpMethod, HttpRetryOptions, RequestOptions } from "../types.js";
|
|
3
3
|
import {
|
|
4
4
|
HttpRetryAfterPolicy,
|
|
5
5
|
HttpRetryDelayStrategy,
|
|
6
6
|
HttpRetryJitter,
|
|
7
7
|
HttpRetryPreset,
|
|
8
8
|
HttpRetryUnsafeMethodPolicy,
|
|
9
|
-
} from "../types";
|
|
9
|
+
} from "../types.js";
|
|
10
10
|
|
|
11
11
|
export type NormalizedProxyTransportRetryOptions = Required<
|
|
12
12
|
Pick<
|