@apifuse/provider-sdk 2.2.0-beta.3 → 2.2.0-beta.4
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 +14 -0
- package/CHANGELOG.md +4 -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 +26 -21
- 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 +3 -3
- package/dist/server/self-test.js +3 -3
- package/dist/server/serve.d.ts +3 -3
- package/dist/server/serve.js +36 -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 +7 -7
- package/src/server/self-test-redaction.ts +2 -2
- package/src/server/self-test.ts +5 -5
- package/src/server/serve.ts +87 -242
- 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/server/serve.ts
CHANGED
|
@@ -3,63 +3,60 @@ import { join } from "node:path";
|
|
|
3
3
|
|
|
4
4
|
import { Hono } from "hono";
|
|
5
5
|
import { z } from "zod";
|
|
6
|
-
import { AuthAbortError, createAuthFlowHelpers } from "../auth";
|
|
6
|
+
import { AuthAbortError, createAuthFlowHelpers } from "../auth.js";
|
|
7
7
|
import {
|
|
8
8
|
AuthError,
|
|
9
9
|
isProviderError,
|
|
10
10
|
isSessionExpiredError,
|
|
11
11
|
isTransportError,
|
|
12
12
|
ProviderError,
|
|
13
|
-
} from "../errors";
|
|
13
|
+
} from "../errors.js";
|
|
14
14
|
import {
|
|
15
15
|
loadProviderLocaleCatalogs,
|
|
16
16
|
localizeAuthTurn,
|
|
17
17
|
type ProviderLocaleCatalogMap,
|
|
18
|
-
} from "../i18n/catalog";
|
|
19
|
-
import type { ProviderLocale } from "../i18n/keys";
|
|
18
|
+
} from "../i18n/catalog.js";
|
|
19
|
+
import type { ProviderLocale } from "../i18n/keys.js";
|
|
20
20
|
import {
|
|
21
21
|
categoryForStatus,
|
|
22
22
|
isRetryableCategory,
|
|
23
23
|
PROVIDER_OBSERVABILITY_TAXONOMY_VERSION,
|
|
24
24
|
type ProviderErrorCategory,
|
|
25
|
-
} from "../observability";
|
|
26
|
-
import { createScratchpad } from "../runtime/auth-flow";
|
|
27
|
-
import { createBrowserClient } from "../runtime/browser";
|
|
28
|
-
import { createProviderCache } from "../runtime/cache";
|
|
25
|
+
} from "../observability.js";
|
|
26
|
+
import { createScratchpad } from "../runtime/auth-flow.js";
|
|
27
|
+
import { createBrowserClient } from "../runtime/browser.js";
|
|
28
|
+
import { createProviderCache } from "../runtime/cache.js";
|
|
29
29
|
import {
|
|
30
30
|
createProviderChoiceContext,
|
|
31
31
|
PROVIDER_RUNTIME_CHOICE_TOKEN_MASTER_SECRET_ENV,
|
|
32
|
-
} from "../runtime/choice";
|
|
33
|
-
import { createCredentialContext } from "../runtime/credential";
|
|
34
|
-
import { createEnvContext } from "../runtime/env";
|
|
35
|
-
import { executeOperation } from "../runtime/executor";
|
|
36
|
-
import { createHttpClient } from "../runtime/http";
|
|
37
|
-
import { wrapWithInstrumentation } from "../runtime/instrumentation";
|
|
38
|
-
import { getProviderBaseUrl } from "../runtime/provider";
|
|
32
|
+
} from "../runtime/choice.js";
|
|
33
|
+
import { createCredentialContext } from "../runtime/credential.js";
|
|
34
|
+
import { createEnvContext } from "../runtime/env.js";
|
|
35
|
+
import { executeOperation } from "../runtime/executor.js";
|
|
36
|
+
import { createHttpClient } from "../runtime/http.js";
|
|
37
|
+
import { wrapWithInstrumentation } from "../runtime/instrumentation.js";
|
|
38
|
+
import { getProviderBaseUrl } from "../runtime/provider.js";
|
|
39
39
|
import {
|
|
40
40
|
PROXY_AUTH_IP_DENIED_CODE,
|
|
41
41
|
PROXY_EDGE_AUTH_REJECTED_CODE,
|
|
42
42
|
PROXY_POOL_EXHAUSTED_CODE,
|
|
43
|
-
} from "../runtime/proxy-errors";
|
|
44
|
-
import {
|
|
45
|
-
PROVIDER_TELEMETRY_HEADER,
|
|
46
|
-
ProxyTelemetryCollector,
|
|
47
|
-
} from "../runtime/proxy-telemetry";
|
|
43
|
+
} from "../runtime/proxy-errors.js";
|
|
44
|
+
import { PROVIDER_TELEMETRY_HEADER, ProxyTelemetryCollector } from "../runtime/proxy-telemetry.js";
|
|
48
45
|
import {
|
|
49
46
|
createProviderRuntimeStateFromEnv,
|
|
50
47
|
createUnsupportedProviderRuntimeState,
|
|
51
|
-
} from "../runtime/state";
|
|
52
|
-
import { createStealthClient } from "../runtime/stealth";
|
|
53
|
-
import { createSttClientFromEnv } from "../runtime/stt";
|
|
54
|
-
import { createTraceContext } from "../runtime/trace";
|
|
55
|
-
import { parseSchema } from "../schema";
|
|
56
|
-
import { getStealthProfile } from "../stealth/profiles";
|
|
48
|
+
} from "../runtime/state.js";
|
|
49
|
+
import { createStealthClient } from "../runtime/stealth.js";
|
|
50
|
+
import { createSttClientFromEnv } from "../runtime/stt.js";
|
|
51
|
+
import { createTraceContext } from "../runtime/trace.js";
|
|
52
|
+
import { parseSchema } from "../schema.js";
|
|
53
|
+
import { getStealthProfile } from "../stealth/profiles.js";
|
|
57
54
|
import {
|
|
58
55
|
APIFUSE_STREAM_DONE_EVENT,
|
|
59
56
|
APIFUSE_STREAM_ERROR_EVENT,
|
|
60
57
|
encodeSseEvent,
|
|
61
58
|
error as streamError,
|
|
62
|
-
} from "../stream";
|
|
59
|
+
} from "../stream.js";
|
|
63
60
|
import type {
|
|
64
61
|
AuthContext,
|
|
65
62
|
AuthTurn,
|
|
@@ -76,13 +73,9 @@ import type {
|
|
|
76
73
|
ProviderStreamEvent,
|
|
77
74
|
StealthClient,
|
|
78
75
|
SttContext,
|
|
79
|
-
} from "../types";
|
|
80
|
-
import {
|
|
81
|
-
|
|
82
|
-
createSelfTestInvoke,
|
|
83
|
-
resolveSelfTestPort,
|
|
84
|
-
} from "./self-test";
|
|
85
|
-
import { resolveSelfTestMasterSecrets } from "./self-test-token";
|
|
76
|
+
} from "../types.js";
|
|
77
|
+
import { createSelfTestApp, createSelfTestInvoke, resolveSelfTestPort } from "./self-test.js";
|
|
78
|
+
import { resolveSelfTestMasterSecrets } from "./self-test-token.js";
|
|
86
79
|
import {
|
|
87
80
|
type AuthFlowRequest,
|
|
88
81
|
AuthFlowRequestSchema,
|
|
@@ -93,7 +86,7 @@ import {
|
|
|
93
86
|
OperationRequestSchema,
|
|
94
87
|
type OperationResponse,
|
|
95
88
|
type OperationSuccessResponse,
|
|
96
|
-
} from "./types";
|
|
89
|
+
} from "./types.js";
|
|
97
90
|
|
|
98
91
|
const DEFAULT_HOST = "0.0.0.0";
|
|
99
92
|
const DEFAULT_PORT = 3000;
|
|
@@ -157,9 +150,7 @@ function createStealthStub(): StealthClient {
|
|
|
157
150
|
};
|
|
158
151
|
}
|
|
159
152
|
|
|
160
|
-
function getProviderStealthBaseUrl(
|
|
161
|
-
provider: ProviderDefinition,
|
|
162
|
-
): string | undefined {
|
|
153
|
+
function getProviderStealthBaseUrl(provider: ProviderDefinition): string | undefined {
|
|
163
154
|
const baseUrl = getProviderBaseUrl(provider);
|
|
164
155
|
if (baseUrl) {
|
|
165
156
|
return baseUrl;
|
|
@@ -169,15 +160,10 @@ function getProviderStealthBaseUrl(
|
|
|
169
160
|
}
|
|
170
161
|
|
|
171
162
|
function getProviderStealthProfile(provider: ProviderDefinition) {
|
|
172
|
-
return provider.stealth?.profile
|
|
173
|
-
? getStealthProfile(provider.stealth.profile)
|
|
174
|
-
: undefined;
|
|
163
|
+
return provider.stealth?.profile ? getStealthProfile(provider.stealth.profile) : undefined;
|
|
175
164
|
}
|
|
176
165
|
|
|
177
|
-
function isProductionProviderBrowserMode(
|
|
178
|
-
provider: ProviderDefinition,
|
|
179
|
-
env = process.env,
|
|
180
|
-
): boolean {
|
|
166
|
+
function isProductionProviderBrowserMode(provider: ProviderDefinition, env = process.env): boolean {
|
|
181
167
|
if (provider.runtime !== "browser") {
|
|
182
168
|
return false;
|
|
183
169
|
}
|
|
@@ -186,9 +172,7 @@ function isProductionProviderBrowserMode(
|
|
|
186
172
|
return true;
|
|
187
173
|
}
|
|
188
174
|
|
|
189
|
-
return
|
|
190
|
-
env.NODE_ENV === "production" && env.APIFUSE__PROVIDER__ID === provider.id
|
|
191
|
-
);
|
|
175
|
+
return env.NODE_ENV === "production" && env.APIFUSE__PROVIDER__ID === provider.id;
|
|
192
176
|
}
|
|
193
177
|
|
|
194
178
|
export function resolveProviderProxyAffinityKey(
|
|
@@ -196,21 +180,16 @@ export function resolveProviderProxyAffinityKey(
|
|
|
196
180
|
request: OperationRequest,
|
|
197
181
|
operationId: string,
|
|
198
182
|
): string {
|
|
199
|
-
const connectionKey =
|
|
200
|
-
resolveOperationConnectionId(request) ?? request.connection?.externalRef;
|
|
183
|
+
const connectionKey = resolveOperationConnectionId(request) ?? request.connection?.externalRef;
|
|
201
184
|
const affinity =
|
|
202
|
-
typeof provider.proxy === "object"
|
|
203
|
-
? provider.proxy.session?.affinity
|
|
204
|
-
: undefined;
|
|
185
|
+
typeof provider.proxy === "object" ? provider.proxy.session?.affinity : undefined;
|
|
205
186
|
if (affinity === "operation") {
|
|
206
187
|
return `${provider.id}/${operationId}`;
|
|
207
188
|
}
|
|
208
189
|
return connectionKey ?? provider.id;
|
|
209
190
|
}
|
|
210
191
|
|
|
211
|
-
function resolveOperationConnectionId(
|
|
212
|
-
request: OperationRequest,
|
|
213
|
-
): string | undefined {
|
|
192
|
+
function resolveOperationConnectionId(request: OperationRequest): string | undefined {
|
|
214
193
|
return request.connection?.id ?? request.connectionId;
|
|
215
194
|
}
|
|
216
195
|
|
|
@@ -227,11 +206,7 @@ function createProviderContext(
|
|
|
227
206
|
const stealthProfile = getProviderStealthProfile(provider);
|
|
228
207
|
const proxyClientOptions = {
|
|
229
208
|
upstream: { proxy: provider.proxy },
|
|
230
|
-
affinityKey: resolveProviderProxyAffinityKey(
|
|
231
|
-
provider,
|
|
232
|
-
request,
|
|
233
|
-
operationId,
|
|
234
|
-
),
|
|
209
|
+
affinityKey: resolveProviderProxyAffinityKey(provider, request, operationId),
|
|
235
210
|
telemetry: proxyTelemetry,
|
|
236
211
|
};
|
|
237
212
|
let wrappedContext: ProviderContext | undefined;
|
|
@@ -270,11 +245,7 @@ function createProviderContext(
|
|
|
270
245
|
state,
|
|
271
246
|
stealth: stealthBaseUrl
|
|
272
247
|
? stealthProfile
|
|
273
|
-
? createStealthClient(
|
|
274
|
-
stealthBaseUrl,
|
|
275
|
-
stealthProfile.name,
|
|
276
|
-
stealthClientOptions,
|
|
277
|
-
)
|
|
248
|
+
? createStealthClient(stealthBaseUrl, stealthProfile.name, stealthClientOptions)
|
|
278
249
|
: createStealthClient(stealthBaseUrl, stealthClientOptions)
|
|
279
250
|
: createStealthStub(),
|
|
280
251
|
browser:
|
|
@@ -387,11 +358,7 @@ function createAuthFlowContext(
|
|
|
387
358
|
http: createHttpClient(baseUrl, proxyClientOptions),
|
|
388
359
|
stealth: stealthBaseUrl
|
|
389
360
|
? stealthProfile
|
|
390
|
-
? createStealthClient(
|
|
391
|
-
stealthBaseUrl,
|
|
392
|
-
stealthProfile.name,
|
|
393
|
-
stealthClientOptions,
|
|
394
|
-
)
|
|
361
|
+
? createStealthClient(stealthBaseUrl, stealthProfile.name, stealthClientOptions)
|
|
395
362
|
: createStealthClient(stealthBaseUrl, stealthClientOptions)
|
|
396
363
|
: createStealthStub(),
|
|
397
364
|
env: createEnvContext(provider.secrets?.map((secret) => secret.name)),
|
|
@@ -504,10 +471,7 @@ function zodDetails(error: z.ZodError): Array<{
|
|
|
504
471
|
}));
|
|
505
472
|
}
|
|
506
473
|
|
|
507
|
-
function toErrorResponse(
|
|
508
|
-
error: unknown,
|
|
509
|
-
requestId?: string,
|
|
510
|
-
): OperationErrorResponse {
|
|
474
|
+
function toErrorResponse(error: unknown, requestId?: string): OperationErrorResponse {
|
|
511
475
|
if (isProviderError(error)) {
|
|
512
476
|
const details = publicProviderErrorDetails(error);
|
|
513
477
|
return {
|
|
@@ -645,9 +609,7 @@ function publicProviderErrorMessage(error: ProviderError): string {
|
|
|
645
609
|
return error.message;
|
|
646
610
|
}
|
|
647
611
|
|
|
648
|
-
function toStatusCode(
|
|
649
|
-
error: unknown,
|
|
650
|
-
): 400 | 401 | 404 | 429 | 500 | 502 | 503 | 504 {
|
|
612
|
+
function toStatusCode(error: unknown): 400 | 401 | 404 | 429 | 500 | 502 | 503 | 504 {
|
|
651
613
|
if (error instanceof z.ZodError) {
|
|
652
614
|
return 400;
|
|
653
615
|
}
|
|
@@ -702,20 +664,15 @@ function logProviderError(
|
|
|
702
664
|
status: number,
|
|
703
665
|
cost: ProviderRequestCost,
|
|
704
666
|
): void {
|
|
705
|
-
const code =
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
: "internal_error";
|
|
667
|
+
const code = isProviderError(error)
|
|
668
|
+
? (error.code ?? "provider_error")
|
|
669
|
+
: error instanceof z.ZodError
|
|
670
|
+
? "invalid_request"
|
|
671
|
+
: "internal_error";
|
|
711
672
|
const errorClass = error instanceof Error ? error.name : typeof error;
|
|
712
673
|
const message = error instanceof Error ? error.message : String(error);
|
|
713
|
-
const details =
|
|
714
|
-
|
|
715
|
-
? providerObservabilityDetails(error)
|
|
716
|
-
: undefined;
|
|
717
|
-
const emit =
|
|
718
|
-
typeof logger === "function" ? logger : defaultProviderServerLogger;
|
|
674
|
+
const details = isProviderError(error) ? providerObservabilityDetails(error) : undefined;
|
|
675
|
+
const emit = typeof logger === "function" ? logger : defaultProviderServerLogger;
|
|
719
676
|
emit({
|
|
720
677
|
level: status >= 500 ? "error" : "warn",
|
|
721
678
|
event: "provider_request_failed",
|
|
@@ -750,8 +707,7 @@ function logProviderCleanupError(
|
|
|
750
707
|
resource: "browser" | "stealth",
|
|
751
708
|
error: unknown,
|
|
752
709
|
): void {
|
|
753
|
-
const emit =
|
|
754
|
-
typeof logger === "function" ? logger : defaultProviderServerLogger;
|
|
710
|
+
const emit = typeof logger === "function" ? logger : defaultProviderServerLogger;
|
|
755
711
|
const errorClass = error instanceof Error ? error.name : typeof error;
|
|
756
712
|
const message = error instanceof Error ? error.message : String(error);
|
|
757
713
|
emit({
|
|
@@ -776,8 +732,7 @@ function logProviderSuccess(
|
|
|
776
732
|
status: number,
|
|
777
733
|
cost: ProviderRequestCost,
|
|
778
734
|
): void {
|
|
779
|
-
const emit =
|
|
780
|
-
typeof logger === "function" ? logger : defaultProviderServerLogger;
|
|
735
|
+
const emit = typeof logger === "function" ? logger : defaultProviderServerLogger;
|
|
781
736
|
emit({
|
|
782
737
|
level: "info",
|
|
783
738
|
event: "provider_request_completed",
|
|
@@ -823,18 +778,13 @@ function toJsonSuccessResponse(
|
|
|
823
778
|
};
|
|
824
779
|
}
|
|
825
780
|
|
|
826
|
-
function isAsyncIterable<T = unknown>(
|
|
827
|
-
value: unknown,
|
|
828
|
-
): value is AsyncIterable<T> {
|
|
781
|
+
function isAsyncIterable<T = unknown>(value: unknown): value is AsyncIterable<T> {
|
|
829
782
|
if (!value || typeof value !== "object") return false;
|
|
830
783
|
const iterator = Reflect.get(value, Symbol.asyncIterator);
|
|
831
784
|
return typeof iterator === "function";
|
|
832
785
|
}
|
|
833
786
|
|
|
834
|
-
function responseWithCleanup(
|
|
835
|
-
response: Response,
|
|
836
|
-
cleanup: RequestCleanup,
|
|
837
|
-
): Response {
|
|
787
|
+
function responseWithCleanup(response: Response, cleanup: RequestCleanup): Response {
|
|
838
788
|
if (!response.body) {
|
|
839
789
|
void cleanup();
|
|
840
790
|
return response;
|
|
@@ -883,10 +833,7 @@ async function validateSseEvent(
|
|
|
883
833
|
const transport = getSseTransport(operation);
|
|
884
834
|
const schema = transport?.events?.[event.event];
|
|
885
835
|
if (!schema) {
|
|
886
|
-
if (
|
|
887
|
-
event.event === APIFUSE_STREAM_ERROR_EVENT ||
|
|
888
|
-
event.event === APIFUSE_STREAM_DONE_EVENT
|
|
889
|
-
) {
|
|
836
|
+
if (event.event === APIFUSE_STREAM_ERROR_EVENT || event.event === APIFUSE_STREAM_DONE_EVENT) {
|
|
890
837
|
return event;
|
|
891
838
|
}
|
|
892
839
|
throw new ProviderError(
|
|
@@ -899,11 +846,7 @@ async function validateSseEvent(
|
|
|
899
846
|
},
|
|
900
847
|
);
|
|
901
848
|
}
|
|
902
|
-
const data = await parseSchema(
|
|
903
|
-
schema,
|
|
904
|
-
event.data,
|
|
905
|
-
`transport.events.${event.event}`,
|
|
906
|
-
);
|
|
849
|
+
const data = await parseSchema(schema, event.data, `transport.events.${event.event}`);
|
|
907
850
|
return { ...event, data };
|
|
908
851
|
}
|
|
909
852
|
|
|
@@ -923,8 +866,7 @@ function assertStreamPayloadWithinLimit(
|
|
|
923
866
|
throw new ProviderError(
|
|
924
867
|
`Stream ${kind} exceeded declared byte limit (${actualBytes} > ${maxBytes}).`,
|
|
925
868
|
{
|
|
926
|
-
code:
|
|
927
|
-
kind === "event" ? "STREAM_EVENT_TOO_LARGE" : "STREAM_CHUNK_TOO_LARGE",
|
|
869
|
+
code: kind === "event" ? "STREAM_EVENT_TOO_LARGE" : "STREAM_CHUNK_TOO_LARGE",
|
|
928
870
|
retryable: false,
|
|
929
871
|
category: "input_validation",
|
|
930
872
|
fix:
|
|
@@ -969,15 +911,10 @@ function toSseResponse(
|
|
|
969
911
|
const validated = await validateSseEvent(operation, next.value);
|
|
970
912
|
const encodedEvent = encodeSseEvent(validated);
|
|
971
913
|
const encodedBytes = encoder.encode(encodedEvent);
|
|
972
|
-
assertStreamPayloadWithinLimit(
|
|
973
|
-
encodedBytes.byteLength,
|
|
974
|
-
transport?.maxEventBytes,
|
|
975
|
-
"event",
|
|
976
|
-
);
|
|
914
|
+
assertStreamPayloadWithinLimit(encodedBytes.byteLength, transport?.maxEventBytes, "event");
|
|
977
915
|
controller.enqueue(encodedBytes);
|
|
978
916
|
} catch (error) {
|
|
979
|
-
const message =
|
|
980
|
-
error instanceof Error ? error.message : "Stream failed";
|
|
917
|
+
const message = error instanceof Error ? error.message : "Stream failed";
|
|
981
918
|
controller.enqueue(
|
|
982
919
|
encoder.encode(
|
|
983
920
|
encodeSseEvent(
|
|
@@ -1024,11 +961,7 @@ function enforceStreamChunkLimit(
|
|
|
1024
961
|
return;
|
|
1025
962
|
}
|
|
1026
963
|
if (value) {
|
|
1027
|
-
assertStreamPayloadWithinLimit(
|
|
1028
|
-
byteLength(value),
|
|
1029
|
-
maxChunkBytes,
|
|
1030
|
-
"chunk",
|
|
1031
|
-
);
|
|
964
|
+
assertStreamPayloadWithinLimit(byteLength(value), maxChunkBytes, "chunk");
|
|
1032
965
|
controller.enqueue(value);
|
|
1033
966
|
}
|
|
1034
967
|
} catch (error) {
|
|
@@ -1048,10 +981,7 @@ function toStreamingResponse(
|
|
|
1048
981
|
requestId?: string,
|
|
1049
982
|
): Response {
|
|
1050
983
|
const transport = operation.transport?.kind ?? "json";
|
|
1051
|
-
if (
|
|
1052
|
-
transport === "sse" &&
|
|
1053
|
-
(result instanceof Response || result instanceof ReadableStream)
|
|
1054
|
-
) {
|
|
984
|
+
if (transport === "sse" && (result instanceof Response || result instanceof ReadableStream)) {
|
|
1055
985
|
void cleanup();
|
|
1056
986
|
throw new ProviderError(
|
|
1057
987
|
"SSE operations must return an AsyncIterable of typed stream.event(...) values.",
|
|
@@ -1065,20 +995,13 @@ function toStreamingResponse(
|
|
|
1065
995
|
}
|
|
1066
996
|
if (result instanceof Response) {
|
|
1067
997
|
const httpTransport = getHttpStreamTransport(operation);
|
|
1068
|
-
if (
|
|
1069
|
-
httpTransport &&
|
|
1070
|
-
result.body &&
|
|
1071
|
-
httpTransport?.maxChunkBytes !== undefined
|
|
1072
|
-
) {
|
|
998
|
+
if (httpTransport && result.body && httpTransport?.maxChunkBytes !== undefined) {
|
|
1073
999
|
return responseWithCleanup(
|
|
1074
|
-
new Response(
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
statusText: result.statusText,
|
|
1080
|
-
},
|
|
1081
|
-
),
|
|
1000
|
+
new Response(enforceStreamChunkLimit(result.body, httpTransport.maxChunkBytes), {
|
|
1001
|
+
headers: result.headers,
|
|
1002
|
+
status: result.status,
|
|
1003
|
+
statusText: result.statusText,
|
|
1004
|
+
}),
|
|
1082
1005
|
cleanup,
|
|
1083
1006
|
);
|
|
1084
1007
|
}
|
|
@@ -1098,8 +1021,7 @@ function toStreamingResponse(
|
|
|
1098
1021
|
: {
|
|
1099
1022
|
"Content-Type":
|
|
1100
1023
|
operation.transport?.kind === "http-stream"
|
|
1101
|
-
? (operation.transport.contentType ??
|
|
1102
|
-
"application/octet-stream")
|
|
1024
|
+
? (operation.transport.contentType ?? "application/octet-stream")
|
|
1103
1025
|
: "application/octet-stream",
|
|
1104
1026
|
},
|
|
1105
1027
|
}),
|
|
@@ -1119,18 +1041,14 @@ function toStreamingResponse(
|
|
|
1119
1041
|
);
|
|
1120
1042
|
}
|
|
1121
1043
|
|
|
1122
|
-
function getSseTransport(
|
|
1123
|
-
operation: OperationDefinition,
|
|
1124
|
-
): OperationSseTransport | undefined {
|
|
1044
|
+
function getSseTransport(operation: OperationDefinition): OperationSseTransport | undefined {
|
|
1125
1045
|
return operation.transport?.kind === "sse" ? operation.transport : undefined;
|
|
1126
1046
|
}
|
|
1127
1047
|
|
|
1128
1048
|
function getHttpStreamTransport(
|
|
1129
1049
|
operation: OperationDefinition,
|
|
1130
1050
|
): OperationHttpStreamTransport | undefined {
|
|
1131
|
-
return operation.transport?.kind === "http-stream"
|
|
1132
|
-
? operation.transport
|
|
1133
|
-
: undefined;
|
|
1051
|
+
return operation.transport?.kind === "http-stream" ? operation.transport : undefined;
|
|
1134
1052
|
}
|
|
1135
1053
|
|
|
1136
1054
|
function toAuthFlowResponse(
|
|
@@ -1151,9 +1069,7 @@ function toAuthFlowResponse(
|
|
|
1151
1069
|
};
|
|
1152
1070
|
}
|
|
1153
1071
|
|
|
1154
|
-
function authFlowLocaleFromHeaders(
|
|
1155
|
-
headers?: Record<string, string>,
|
|
1156
|
-
): ProviderLocale {
|
|
1072
|
+
function authFlowLocaleFromHeaders(headers?: Record<string, string>): ProviderLocale {
|
|
1157
1073
|
const header = Object.entries(headers ?? {}).find(
|
|
1158
1074
|
([key]) => key.toLowerCase() === "accept-language",
|
|
1159
1075
|
)?.[1];
|
|
@@ -1171,9 +1087,7 @@ function isAuthFlowLocale(value: string | undefined): value is ProviderLocale {
|
|
|
1171
1087
|
}
|
|
1172
1088
|
|
|
1173
1089
|
function isAuthTurn(value: unknown): value is AuthTurn {
|
|
1174
|
-
return
|
|
1175
|
-
!!value && typeof value === "object" && "kind" in value && "turnId" in value
|
|
1176
|
-
);
|
|
1090
|
+
return !!value && typeof value === "object" && "kind" in value && "turnId" in value;
|
|
1177
1091
|
}
|
|
1178
1092
|
|
|
1179
1093
|
function loadAuthFlowLocaleCatalogs(
|
|
@@ -1210,10 +1124,7 @@ function materializeAuthFlowTurn(
|
|
|
1210
1124
|
});
|
|
1211
1125
|
}
|
|
1212
1126
|
|
|
1213
|
-
function withAuthRequestHeaders(
|
|
1214
|
-
request: AuthFlowRequest,
|
|
1215
|
-
headers: Headers,
|
|
1216
|
-
): AuthFlowRequest {
|
|
1127
|
+
function withAuthRequestHeaders(request: AuthFlowRequest, headers: Headers): AuthFlowRequest {
|
|
1217
1128
|
return {
|
|
1218
1129
|
...request,
|
|
1219
1130
|
headers: {
|
|
@@ -1231,17 +1142,9 @@ async function handleOperation(
|
|
|
1231
1142
|
state: ProviderRuntimeState = createUnsupportedProviderRuntimeState(),
|
|
1232
1143
|
proxyTelemetry?: ProxyTelemetryCollector,
|
|
1233
1144
|
): Promise<Response | OperationResponse> {
|
|
1234
|
-
const ctx = createProviderContext(
|
|
1235
|
-
provider,
|
|
1236
|
-
request,
|
|
1237
|
-
operationId,
|
|
1238
|
-
options,
|
|
1239
|
-
state,
|
|
1240
|
-
proxyTelemetry,
|
|
1241
|
-
);
|
|
1145
|
+
const ctx = createProviderContext(provider, request, operationId, options, state, proxyTelemetry);
|
|
1242
1146
|
const operation = provider.operations[operationId];
|
|
1243
|
-
const streaming =
|
|
1244
|
-
operation?.transport?.kind && operation.transport.kind !== "json";
|
|
1147
|
+
const streaming = operation?.transport?.kind && operation.transport.kind !== "json";
|
|
1245
1148
|
let cleanupCalled = false;
|
|
1246
1149
|
const cleanup = async () => {
|
|
1247
1150
|
if (cleanupCalled) return;
|
|
@@ -1272,12 +1175,7 @@ async function handleOperation(
|
|
|
1272
1175
|
}
|
|
1273
1176
|
};
|
|
1274
1177
|
try {
|
|
1275
|
-
const result = await executeOperation(
|
|
1276
|
-
provider,
|
|
1277
|
-
operationId,
|
|
1278
|
-
ctx,
|
|
1279
|
-
request.input,
|
|
1280
|
-
);
|
|
1178
|
+
const result = await executeOperation(provider, operationId, ctx, request.input);
|
|
1281
1179
|
if (streaming && operation) {
|
|
1282
1180
|
return toStreamingResponse(operation, result, cleanup, request.requestId);
|
|
1283
1181
|
}
|
|
@@ -1321,12 +1219,7 @@ async function handleAuthFlow(
|
|
|
1321
1219
|
});
|
|
1322
1220
|
}
|
|
1323
1221
|
|
|
1324
|
-
const { context, getPatch } = createAuthFlowContext(
|
|
1325
|
-
provider,
|
|
1326
|
-
request,
|
|
1327
|
-
options,
|
|
1328
|
-
signal,
|
|
1329
|
-
);
|
|
1222
|
+
const { context, getPatch } = createAuthFlowContext(provider, request, options, signal);
|
|
1330
1223
|
try {
|
|
1331
1224
|
const result =
|
|
1332
1225
|
route === "start"
|
|
@@ -1474,17 +1367,8 @@ export function createServerApp(
|
|
|
1474
1367
|
.clone()
|
|
1475
1368
|
.json()
|
|
1476
1369
|
.catch(() => undefined);
|
|
1477
|
-
const body = withAuthRequestHeaders(
|
|
1478
|
-
|
|
1479
|
-
c.req.raw.headers,
|
|
1480
|
-
);
|
|
1481
|
-
const response = await handleAuthFlow(
|
|
1482
|
-
provider,
|
|
1483
|
-
body,
|
|
1484
|
-
"start",
|
|
1485
|
-
options,
|
|
1486
|
-
c.req.raw.signal,
|
|
1487
|
-
);
|
|
1370
|
+
const body = withAuthRequestHeaders(AuthFlowRequestSchema.parse(rawBody), c.req.raw.headers);
|
|
1371
|
+
const response = await handleAuthFlow(provider, body, "start", options, c.req.raw.signal);
|
|
1488
1372
|
logProviderSuccess(
|
|
1489
1373
|
logger,
|
|
1490
1374
|
provider,
|
|
@@ -1520,17 +1404,8 @@ export function createServerApp(
|
|
|
1520
1404
|
.clone()
|
|
1521
1405
|
.json()
|
|
1522
1406
|
.catch(() => undefined);
|
|
1523
|
-
const body = withAuthRequestHeaders(
|
|
1524
|
-
|
|
1525
|
-
c.req.raw.headers,
|
|
1526
|
-
);
|
|
1527
|
-
const response = await handleAuthFlow(
|
|
1528
|
-
provider,
|
|
1529
|
-
body,
|
|
1530
|
-
"continue",
|
|
1531
|
-
options,
|
|
1532
|
-
c.req.raw.signal,
|
|
1533
|
-
);
|
|
1407
|
+
const body = withAuthRequestHeaders(AuthFlowRequestSchema.parse(rawBody), c.req.raw.headers);
|
|
1408
|
+
const response = await handleAuthFlow(provider, body, "continue", options, c.req.raw.signal);
|
|
1534
1409
|
logProviderSuccess(
|
|
1535
1410
|
logger,
|
|
1536
1411
|
provider,
|
|
@@ -1566,17 +1441,8 @@ export function createServerApp(
|
|
|
1566
1441
|
.clone()
|
|
1567
1442
|
.json()
|
|
1568
1443
|
.catch(() => undefined);
|
|
1569
|
-
const body = withAuthRequestHeaders(
|
|
1570
|
-
|
|
1571
|
-
c.req.raw.headers,
|
|
1572
|
-
);
|
|
1573
|
-
const response = await handleAuthFlow(
|
|
1574
|
-
provider,
|
|
1575
|
-
body,
|
|
1576
|
-
"poll",
|
|
1577
|
-
options,
|
|
1578
|
-
c.req.raw.signal,
|
|
1579
|
-
);
|
|
1444
|
+
const body = withAuthRequestHeaders(AuthFlowRequestSchema.parse(rawBody), c.req.raw.headers);
|
|
1445
|
+
const response = await handleAuthFlow(provider, body, "poll", options, c.req.raw.signal);
|
|
1580
1446
|
logProviderSuccess(
|
|
1581
1447
|
logger,
|
|
1582
1448
|
provider,
|
|
@@ -1612,17 +1478,8 @@ export function createServerApp(
|
|
|
1612
1478
|
.clone()
|
|
1613
1479
|
.json()
|
|
1614
1480
|
.catch(() => undefined);
|
|
1615
|
-
const body = withAuthRequestHeaders(
|
|
1616
|
-
|
|
1617
|
-
c.req.raw.headers,
|
|
1618
|
-
);
|
|
1619
|
-
const response = await handleAuthFlow(
|
|
1620
|
-
provider,
|
|
1621
|
-
body,
|
|
1622
|
-
"refresh",
|
|
1623
|
-
options,
|
|
1624
|
-
c.req.raw.signal,
|
|
1625
|
-
);
|
|
1481
|
+
const body = withAuthRequestHeaders(AuthFlowRequestSchema.parse(rawBody), c.req.raw.headers);
|
|
1482
|
+
const response = await handleAuthFlow(provider, body, "refresh", options, c.req.raw.signal);
|
|
1626
1483
|
logProviderSuccess(
|
|
1627
1484
|
logger,
|
|
1628
1485
|
provider,
|
|
@@ -1658,17 +1515,8 @@ export function createServerApp(
|
|
|
1658
1515
|
.clone()
|
|
1659
1516
|
.json()
|
|
1660
1517
|
.catch(() => undefined);
|
|
1661
|
-
const body = withAuthRequestHeaders(
|
|
1662
|
-
|
|
1663
|
-
c.req.raw.headers,
|
|
1664
|
-
);
|
|
1665
|
-
const response = await handleAuthFlow(
|
|
1666
|
-
provider,
|
|
1667
|
-
body,
|
|
1668
|
-
"abort",
|
|
1669
|
-
options,
|
|
1670
|
-
c.req.raw.signal,
|
|
1671
|
-
);
|
|
1518
|
+
const body = withAuthRequestHeaders(AuthFlowRequestSchema.parse(rawBody), c.req.raw.headers);
|
|
1519
|
+
const response = await handleAuthFlow(provider, body, "abort", options, c.req.raw.signal);
|
|
1672
1520
|
logProviderSuccess(
|
|
1673
1521
|
logger,
|
|
1674
1522
|
provider,
|
|
@@ -1743,12 +1591,9 @@ export async function serve(
|
|
|
1743
1591
|
const bunRuntime = getBunServeRuntime();
|
|
1744
1592
|
|
|
1745
1593
|
if (bunRuntime === undefined) {
|
|
1746
|
-
throw new ProviderError(
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
code: "RUNTIME_UNSUPPORTED",
|
|
1750
|
-
},
|
|
1751
|
-
);
|
|
1594
|
+
throw new ProviderError("Bun runtime is required to start the provider server", {
|
|
1595
|
+
code: "RUNTIME_UNSUPPORTED",
|
|
1596
|
+
});
|
|
1752
1597
|
}
|
|
1753
1598
|
|
|
1754
1599
|
const app = createServerApp(provider, {
|
package/src/server/types.ts
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
|
-
import { HttpRetryPreset } from "../types";
|
|
3
|
+
import { HttpRetryPreset } from "../types.js";
|
|
4
4
|
|
|
5
|
-
export const ConnectionModeSchema = z.enum([
|
|
6
|
-
"oauth2",
|
|
7
|
-
"credentials",
|
|
8
|
-
"platform-managed",
|
|
9
|
-
"none",
|
|
10
|
-
]);
|
|
5
|
+
export const ConnectionModeSchema = z.enum(["oauth2", "credentials", "platform-managed", "none"]);
|
|
11
6
|
|
|
12
7
|
export const OperationConnectionSchema = z.object({
|
|
13
8
|
id: z.string(),
|
|
@@ -99,18 +94,10 @@ export const AuthFlowErrorResponseSchema = OperationErrorResponseSchema;
|
|
|
99
94
|
export type ConnectionMode = z.infer<typeof ConnectionModeSchema>;
|
|
100
95
|
export type OperationConnection = z.infer<typeof OperationConnectionSchema>;
|
|
101
96
|
export type OperationRequest = z.infer<typeof OperationRequestSchema>;
|
|
102
|
-
export type OperationSuccessResponse = z.infer<
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
export type OperationErrorResponse = z.infer<
|
|
106
|
-
typeof OperationErrorResponseSchema
|
|
107
|
-
>;
|
|
108
|
-
export type OperationResponse =
|
|
109
|
-
| OperationSuccessResponse
|
|
110
|
-
| OperationErrorResponse;
|
|
97
|
+
export type OperationSuccessResponse = z.infer<typeof OperationSuccessResponseSchema>;
|
|
98
|
+
export type OperationErrorResponse = z.infer<typeof OperationErrorResponseSchema>;
|
|
99
|
+
export type OperationResponse = OperationSuccessResponse | OperationErrorResponse;
|
|
111
100
|
export type AuthFlowRequest = z.infer<typeof AuthFlowRequestSchema>;
|
|
112
|
-
export type AuthFlowSuccessResponse = z.infer<
|
|
113
|
-
typeof AuthFlowSuccessResponseSchema
|
|
114
|
-
>;
|
|
101
|
+
export type AuthFlowSuccessResponse = z.infer<typeof AuthFlowSuccessResponseSchema>;
|
|
115
102
|
export type AuthFlowErrorResponse = z.infer<typeof AuthFlowErrorResponseSchema>;
|
|
116
103
|
export type AuthFlowResponse = AuthFlowSuccessResponse | AuthFlowErrorResponse;
|