@apifuse/provider-sdk 2.1.0-beta.2 → 2.1.0-beta.20
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 +330 -8
- package/CHANGELOG.md +85 -1
- package/README.md +64 -17
- package/SUBMISSION.md +86 -0
- package/bin/apifuse-check.ts +60 -6
- package/bin/apifuse-dev.ts +58 -8
- package/bin/apifuse-pack-check.ts +32 -2
- package/bin/apifuse-pack-smoke.ts +133 -6
- package/bin/apifuse-perf.ts +142 -49
- package/bin/apifuse-record.ts +182 -104
- package/bin/apifuse-submit-check.ts +2849 -0
- package/bin/apifuse.ts +1 -1
- package/dist/auth.d.ts +76 -0
- package/dist/auth.js +436 -0
- package/dist/ceremonies/index.d.ts +41 -0
- package/dist/ceremonies/index.js +490 -0
- package/dist/choice-token.d.ts +24 -0
- package/dist/choice-token.js +74 -0
- package/dist/cli/commands.d.ts +10 -0
- package/dist/cli/commands.js +80 -0
- package/dist/cli/create.d.ts +47 -0
- package/dist/cli/create.js +745 -0
- package/dist/cli/templates/provider/.dockerignore.tpl +22 -0
- package/dist/cli/templates/provider/.gitignore.tpl +22 -0
- package/dist/cli/templates/provider/Dockerfile.tpl +7 -0
- package/dist/cli/templates/provider/README.md.tpl +163 -0
- package/dist/cli/templates/provider/dev.ts.tpl +5 -0
- package/dist/cli/templates/provider/domain/README.md.tpl +3 -0
- package/dist/cli/templates/provider/index.test.ts.tpl +13 -0
- package/dist/cli/templates/provider/index.ts.tpl +15 -0
- package/dist/cli/templates/provider/mappers/README.md.tpl +3 -0
- package/dist/cli/templates/provider/meta.ts.tpl +7 -0
- package/dist/cli/templates/provider/operations/index.ts.tpl +5 -0
- package/dist/cli/templates/provider/operations/ping.ts.tpl +24 -0
- package/dist/cli/templates/provider/schemas/ping.ts.tpl +24 -0
- package/dist/cli/templates/provider/start.ts.tpl +5 -0
- package/dist/cli/templates/provider/upstream/README.md.tpl +3 -0
- package/dist/config/loader.d.ts +107 -0
- package/dist/config/loader.js +935 -0
- package/dist/contract-json.d.ts +9 -0
- package/dist/contract-json.js +51 -0
- package/dist/contract-serialization.d.ts +4 -0
- package/dist/contract-serialization.js +78 -0
- package/dist/contract-types.d.ts +49 -0
- package/dist/contract-types.js +1 -0
- package/dist/contract.d.ts +6 -0
- package/dist/contract.js +156 -0
- package/dist/define.d.ts +100 -0
- package/dist/define.js +1383 -0
- package/dist/dev.d.ts +9 -0
- package/dist/dev.js +15 -0
- package/dist/errors.d.ts +59 -0
- package/dist/errors.js +97 -0
- package/dist/i18n/catalog.d.ts +29 -0
- package/dist/i18n/catalog.js +159 -0
- package/dist/i18n/index.d.ts +2 -0
- package/dist/i18n/index.js +2 -0
- package/dist/i18n/keys.d.ts +10 -0
- package/dist/i18n/keys.js +34 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +38 -0
- package/dist/lint.d.ts +74 -0
- package/dist/lint.js +729 -0
- package/dist/observability.d.ts +5 -0
- package/dist/observability.js +39 -0
- package/dist/provider.d.ts +11 -0
- package/dist/provider.js +9 -0
- package/dist/public-schema-field-lint.d.ts +2 -0
- package/dist/public-schema-field-lint.js +158 -0
- package/dist/recipes/gov-api.d.ts +19 -0
- package/dist/recipes/gov-api.js +72 -0
- package/dist/recipes/rest-api.d.ts +21 -0
- package/dist/recipes/rest-api.js +115 -0
- package/dist/runtime/auth-flow.d.ts +14 -0
- package/dist/runtime/auth-flow.js +46 -0
- package/dist/runtime/browser.d.ts +25 -0
- package/dist/runtime/browser.js +1237 -0
- package/dist/runtime/cache.d.ts +10 -0
- package/dist/runtime/cache.js +372 -0
- package/dist/runtime/choice.d.ts +15 -0
- package/dist/runtime/choice.js +435 -0
- package/dist/runtime/credential.d.ts +8 -0
- package/dist/runtime/credential.js +61 -0
- package/dist/runtime/env.d.ts +2 -0
- package/dist/runtime/env.js +10 -0
- package/dist/runtime/executor.d.ts +16 -0
- package/dist/runtime/executor.js +51 -0
- package/dist/runtime/http.d.ts +8 -0
- package/dist/runtime/http.js +726 -0
- package/dist/runtime/insights.d.ts +9 -0
- package/dist/runtime/insights.js +324 -0
- package/dist/runtime/instrumentation.d.ts +8 -0
- package/dist/runtime/instrumentation.js +269 -0
- package/dist/runtime/key-derivation.d.ts +24 -0
- package/dist/runtime/key-derivation.js +73 -0
- package/dist/runtime/keyring.d.ts +25 -0
- package/dist/runtime/keyring.js +93 -0
- package/dist/runtime/namespace.d.ts +9 -0
- package/dist/runtime/namespace.js +19 -0
- package/dist/runtime/otlp.d.ts +39 -0
- package/dist/runtime/otlp.js +103 -0
- package/dist/runtime/perf.d.ts +12 -0
- package/dist/runtime/perf.js +52 -0
- package/dist/runtime/prevalidate.d.ts +12 -0
- package/dist/runtime/prevalidate.js +173 -0
- package/dist/runtime/provider.d.ts +2 -0
- package/dist/runtime/provider.js +11 -0
- package/dist/runtime/proxy-errors.d.ts +21 -0
- package/dist/runtime/proxy-errors.js +83 -0
- package/dist/runtime/proxy-telemetry.d.ts +8 -0
- package/dist/runtime/proxy-telemetry.js +174 -0
- package/dist/runtime/redis.d.ts +17 -0
- package/dist/runtime/redis.js +82 -0
- package/dist/runtime/request-options.d.ts +3 -0
- package/dist/runtime/request-options.js +42 -0
- package/dist/runtime/state.d.ts +17 -0
- package/dist/runtime/state.js +344 -0
- package/dist/runtime/stealth.d.ts +21 -0
- package/dist/runtime/stealth.js +980 -0
- package/dist/runtime/stt.d.ts +22 -0
- package/dist/runtime/stt.js +480 -0
- package/dist/runtime/trace.d.ts +26 -0
- package/dist/runtime/trace.js +142 -0
- package/dist/runtime/waterfall.d.ts +12 -0
- package/dist/runtime/waterfall.js +147 -0
- package/dist/schema.d.ts +74 -0
- package/dist/schema.js +243 -0
- package/dist/serve.d.ts +1 -0
- package/dist/serve.js +1 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +2 -0
- package/dist/server/serve.d.ts +64 -0
- package/dist/server/serve.js +1118 -0
- package/dist/server/types.d.ts +136 -0
- package/dist/server/types.js +86 -0
- package/dist/stealth/profiles.d.ts +4 -0
- package/dist/stealth/profiles.js +259 -0
- package/dist/stream.d.ts +44 -0
- package/dist/stream.js +151 -0
- package/dist/testing/helpers.d.ts +23 -0
- package/dist/testing/helpers.js +95 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +2 -0
- package/dist/testing/run.d.ts +34 -0
- package/dist/testing/run.js +307 -0
- package/dist/types.d.ts +1467 -0
- package/dist/types.js +61 -0
- package/dist/utils/date.d.ts +6 -0
- package/dist/utils/date.js +101 -0
- package/dist/utils/parse.d.ts +16 -0
- package/dist/utils/parse.js +51 -0
- package/dist/utils/text.d.ts +4 -0
- package/dist/utils/text.js +14 -0
- package/dist/utils/transform.d.ts +8 -0
- package/dist/utils/transform.js +48 -0
- package/package.json +56 -29
- package/src/auth.ts +786 -0
- package/src/ceremonies/index.ts +8 -2
- package/src/choice-token.ts +165 -0
- package/src/cli/commands.ts +34 -11
- package/src/cli/create.ts +222 -128
- package/src/cli/templates/provider/.dockerignore.tpl +22 -0
- package/src/cli/templates/provider/.gitignore.tpl +22 -0
- package/src/cli/templates/provider/README.md.tpl +87 -7
- package/src/cli/templates/provider/dev.ts.tpl +1 -1
- package/src/cli/templates/provider/domain/README.md.tpl +3 -0
- package/src/cli/templates/provider/index.ts.tpl +5 -47
- package/src/cli/templates/provider/mappers/README.md.tpl +3 -0
- package/src/cli/templates/provider/meta.ts.tpl +7 -0
- package/src/cli/templates/provider/operations/index.ts.tpl +5 -0
- package/src/cli/templates/provider/operations/ping.ts.tpl +24 -0
- package/src/cli/templates/provider/schemas/ping.ts.tpl +24 -0
- package/src/cli/templates/provider/start.ts.tpl +1 -1
- package/src/cli/templates/provider/upstream/README.md.tpl +3 -0
- package/src/config/loader.ts +1224 -9
- package/src/contract-json.ts +75 -0
- package/src/contract-serialization.ts +89 -0
- package/src/contract-types.ts +52 -0
- package/src/contract.ts +216 -0
- package/src/define.ts +1820 -70
- package/src/errors.ts +27 -0
- package/src/i18n/catalog.ts +277 -0
- package/src/i18n/index.ts +2 -0
- package/src/i18n/keys.ts +64 -0
- package/src/index.ts +189 -9
- package/src/lint.ts +580 -73
- package/src/observability.ts +41 -0
- package/src/provider.ts +131 -4
- package/src/public-schema-field-lint.ts +237 -0
- package/src/runtime/auth-flow.ts +9 -0
- package/src/runtime/browser.ts +1054 -51
- package/src/runtime/cache.ts +528 -0
- package/src/runtime/choice.ts +760 -0
- package/src/runtime/executor.ts +32 -3
- package/src/runtime/http.ts +980 -195
- package/src/runtime/insights.ts +11 -11
- package/src/runtime/instrumentation.ts +12 -4
- package/src/runtime/key-derivation.ts +1 -1
- package/src/runtime/keyring.ts +4 -3
- package/src/runtime/proxy-errors.ts +132 -0
- package/src/runtime/proxy-telemetry.ts +253 -0
- package/src/runtime/redis.ts +116 -0
- package/src/runtime/request-options.ts +66 -0
- package/src/runtime/state.ts +563 -0
- package/src/runtime/stealth.ts +1336 -0
- package/src/runtime/stt.ts +629 -0
- package/src/runtime/trace.ts +1 -1
- package/src/schema.ts +363 -1
- package/src/server/serve.ts +1192 -75
- package/src/server/types.ts +37 -0
- package/src/stream.ts +210 -0
- package/src/testing/run.ts +40 -6
- package/src/types.ts +1283 -59
- package/src/runtime/tls.ts +0 -434
- package/src/types/playwright-stealth.d.ts +0 -9
package/src/server/types.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
|
+
import { HttpRetryPreset } from "../types";
|
|
4
|
+
|
|
3
5
|
export const ConnectionModeSchema = z.enum([
|
|
4
6
|
"oauth2",
|
|
5
7
|
"credentials",
|
|
@@ -34,6 +36,39 @@ export const ErrorEnvelopeSchema = z.object({
|
|
|
34
36
|
|
|
35
37
|
export const OperationSuccessResponseSchema = z.object({
|
|
36
38
|
data: z.unknown(),
|
|
39
|
+
meta: z
|
|
40
|
+
.object({
|
|
41
|
+
cached: z.boolean().optional(),
|
|
42
|
+
stale: z.boolean().optional(),
|
|
43
|
+
cache: z
|
|
44
|
+
.object({
|
|
45
|
+
hit: z.boolean(),
|
|
46
|
+
stale: z.boolean(),
|
|
47
|
+
keys: z.array(z.string()),
|
|
48
|
+
source: z.enum(["redis", "memory", "loader", "mixed"]).optional(),
|
|
49
|
+
})
|
|
50
|
+
.optional(),
|
|
51
|
+
retry: z
|
|
52
|
+
.object({
|
|
53
|
+
attempts: z.number().int().min(1),
|
|
54
|
+
retries: z.number().int().min(0),
|
|
55
|
+
preset: z
|
|
56
|
+
.enum([
|
|
57
|
+
HttpRetryPreset.Off,
|
|
58
|
+
HttpRetryPreset.TransportTransient,
|
|
59
|
+
HttpRetryPreset.SafeRead,
|
|
60
|
+
HttpRetryPreset.AggressiveRead,
|
|
61
|
+
HttpRetryPreset.RateLimitAware,
|
|
62
|
+
])
|
|
63
|
+
.optional(),
|
|
64
|
+
transport: z.enum(["native"]),
|
|
65
|
+
lastErrorCode: z.string().optional(),
|
|
66
|
+
lastStatus: z.number().int().optional(),
|
|
67
|
+
})
|
|
68
|
+
.optional(),
|
|
69
|
+
})
|
|
70
|
+
.passthrough()
|
|
71
|
+
.optional(),
|
|
37
72
|
});
|
|
38
73
|
|
|
39
74
|
export const OperationErrorResponseSchema = z.object({
|
|
@@ -47,8 +82,10 @@ export const AuthFlowRequestSchema = z.object({
|
|
|
47
82
|
externalRef: z.string().optional(),
|
|
48
83
|
tenantId: z.string().optional(),
|
|
49
84
|
providerId: z.string().optional(),
|
|
85
|
+
headers: z.record(z.string(), z.string()).optional(),
|
|
50
86
|
input: z.record(z.string(), z.unknown()).optional(),
|
|
51
87
|
context: z.record(z.string(), z.unknown()).optional(),
|
|
88
|
+
connection: OperationConnectionSchema.optional(),
|
|
52
89
|
});
|
|
53
90
|
|
|
54
91
|
export const AuthFlowSuccessResponseSchema = z.object({
|
package/src/stream.ts
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import type { SseMessage } from "./types";
|
|
2
|
+
|
|
3
|
+
export interface SseEvent<TData = unknown> {
|
|
4
|
+
event: string;
|
|
5
|
+
data: TData;
|
|
6
|
+
id?: string;
|
|
7
|
+
retry?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface SseErrorData {
|
|
11
|
+
code: string;
|
|
12
|
+
message: string;
|
|
13
|
+
requestId?: string;
|
|
14
|
+
retryable?: boolean;
|
|
15
|
+
details?: unknown;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const APIFUSE_STREAM_ERROR_EVENT = "apifuse.error";
|
|
19
|
+
export const APIFUSE_STREAM_DONE_EVENT = "apifuse.done";
|
|
20
|
+
|
|
21
|
+
export function event<TData>(
|
|
22
|
+
eventName: string,
|
|
23
|
+
data: TData,
|
|
24
|
+
options: { id?: string; retry?: number } = {},
|
|
25
|
+
): SseEvent<TData> {
|
|
26
|
+
return {
|
|
27
|
+
event: eventName,
|
|
28
|
+
data,
|
|
29
|
+
...(options.id ? { id: options.id } : {}),
|
|
30
|
+
...(options.retry !== undefined ? { retry: options.retry } : {}),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function error(
|
|
35
|
+
code: string,
|
|
36
|
+
message: string,
|
|
37
|
+
options: Omit<SseErrorData, "code" | "message"> & {
|
|
38
|
+
id?: string;
|
|
39
|
+
retry?: number;
|
|
40
|
+
} = {},
|
|
41
|
+
): SseEvent<SseErrorData> {
|
|
42
|
+
const { id, retry, ...dataOptions } = options;
|
|
43
|
+
return event(
|
|
44
|
+
APIFUSE_STREAM_ERROR_EVENT,
|
|
45
|
+
{ code, message, ...dataOptions },
|
|
46
|
+
{ ...(id ? { id } : {}), ...(retry !== undefined ? { retry } : {}) },
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function done(): SseEvent<Record<string, never>>;
|
|
51
|
+
export function done<TData>(
|
|
52
|
+
data: TData,
|
|
53
|
+
options?: { id?: string; retry?: number },
|
|
54
|
+
): SseEvent<TData>;
|
|
55
|
+
export function done<TData>(
|
|
56
|
+
data?: TData,
|
|
57
|
+
options: { id?: string; retry?: number } = {},
|
|
58
|
+
): SseEvent<TData | Record<string, never>> {
|
|
59
|
+
return event(APIFUSE_STREAM_DONE_EVENT, data ?? {}, options);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function encodeSseEvent(input: SseEvent): string {
|
|
63
|
+
const lines: string[] = [];
|
|
64
|
+
if (input.id !== undefined)
|
|
65
|
+
lines.push(`id: ${sseFieldValue(input.id, "id")}`);
|
|
66
|
+
if (input.event) lines.push(`event: ${sseFieldValue(input.event, "event")}`);
|
|
67
|
+
if (input.retry !== undefined) {
|
|
68
|
+
if (!Number.isInteger(input.retry) || input.retry < 0) {
|
|
69
|
+
throw new TypeError("SSE retry must be a non-negative integer.");
|
|
70
|
+
}
|
|
71
|
+
lines.push(`retry: ${input.retry}`);
|
|
72
|
+
}
|
|
73
|
+
const data =
|
|
74
|
+
typeof input.data === "string" ? input.data : JSON.stringify(input.data);
|
|
75
|
+
for (const line of data.split(/\r?\n/)) {
|
|
76
|
+
lines.push(`data: ${line}`);
|
|
77
|
+
}
|
|
78
|
+
return `${lines.join("\n")}\n\n`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function sseFieldValue(value: string, field: "event" | "id"): string {
|
|
82
|
+
if (/[\r\n]/.test(value)) {
|
|
83
|
+
throw new TypeError(`SSE ${field} must not contain CR or LF.`);
|
|
84
|
+
}
|
|
85
|
+
return value;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export async function* readableBytes(
|
|
89
|
+
body: ReadableStream<Uint8Array>,
|
|
90
|
+
): AsyncIterable<Uint8Array> {
|
|
91
|
+
const reader = body.getReader();
|
|
92
|
+
try {
|
|
93
|
+
for (;;) {
|
|
94
|
+
const { value, done } = await reader.read();
|
|
95
|
+
if (done) return;
|
|
96
|
+
if (value) yield value;
|
|
97
|
+
}
|
|
98
|
+
} finally {
|
|
99
|
+
reader.releaseLock();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export async function* readableTextChunks(
|
|
104
|
+
body: ReadableStream<Uint8Array>,
|
|
105
|
+
): AsyncIterable<string> {
|
|
106
|
+
const decoder = new TextDecoder();
|
|
107
|
+
for await (const chunk of readableBytes(body)) {
|
|
108
|
+
yield decoder.decode(chunk, { stream: true });
|
|
109
|
+
}
|
|
110
|
+
const tail = decoder.decode();
|
|
111
|
+
if (tail) yield tail;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function* readableLines(
|
|
115
|
+
body: ReadableStream<Uint8Array>,
|
|
116
|
+
): AsyncIterable<string> {
|
|
117
|
+
let buffer = "";
|
|
118
|
+
for await (const chunk of readableTextChunks(body)) {
|
|
119
|
+
buffer += chunk;
|
|
120
|
+
for (;;) {
|
|
121
|
+
const index = buffer.search(/\r?\n/);
|
|
122
|
+
if (index < 0) break;
|
|
123
|
+
const line = buffer.slice(0, index);
|
|
124
|
+
const newlineLength =
|
|
125
|
+
buffer[index] === "\r" && buffer[index + 1] === "\n" ? 2 : 1;
|
|
126
|
+
buffer = buffer.slice(index + newlineLength);
|
|
127
|
+
yield line;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (buffer) yield buffer;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function createSseMessage(
|
|
134
|
+
eventName: string,
|
|
135
|
+
data: string,
|
|
136
|
+
options: { id?: string; retry?: number },
|
|
137
|
+
): SseMessage {
|
|
138
|
+
return {
|
|
139
|
+
event: eventName || "message",
|
|
140
|
+
data,
|
|
141
|
+
...(options.id !== undefined ? { id: options.id } : {}),
|
|
142
|
+
...(options.retry !== undefined ? { retry: options.retry } : {}),
|
|
143
|
+
json<T = unknown>() {
|
|
144
|
+
return parseJson<T>(data);
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function parseJson<T>(data: string): T {
|
|
150
|
+
return JSON.parse(data);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export async function* parseSseStream(
|
|
154
|
+
body: ReadableStream<Uint8Array>,
|
|
155
|
+
): AsyncIterable<SseMessage> {
|
|
156
|
+
let eventName = "message";
|
|
157
|
+
let dataLines: string[] = [];
|
|
158
|
+
let id: string | undefined;
|
|
159
|
+
let retry: number | undefined;
|
|
160
|
+
|
|
161
|
+
const dispatch = function* () {
|
|
162
|
+
if (dataLines.length === 0 && id === undefined && retry === undefined) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
yield createSseMessage(eventName, dataLines.join("\n"), { id, retry });
|
|
166
|
+
eventName = "message";
|
|
167
|
+
dataLines = [];
|
|
168
|
+
retry = undefined;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
for await (const line of readableLines(body)) {
|
|
172
|
+
if (line === "") {
|
|
173
|
+
yield* dispatch();
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (line.startsWith(":")) continue;
|
|
177
|
+
const separator = line.indexOf(":");
|
|
178
|
+
const field = separator < 0 ? line : line.slice(0, separator);
|
|
179
|
+
const rawValue = separator < 0 ? "" : line.slice(separator + 1);
|
|
180
|
+
const value = rawValue.startsWith(" ") ? rawValue.slice(1) : rawValue;
|
|
181
|
+
switch (field) {
|
|
182
|
+
case "event":
|
|
183
|
+
eventName = value;
|
|
184
|
+
break;
|
|
185
|
+
case "data":
|
|
186
|
+
dataLines.push(value);
|
|
187
|
+
break;
|
|
188
|
+
case "id":
|
|
189
|
+
id = value;
|
|
190
|
+
break;
|
|
191
|
+
case "retry": {
|
|
192
|
+
const parsed = Number(value);
|
|
193
|
+
if (Number.isInteger(parsed) && parsed >= 0) retry = parsed;
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
yield* dispatch();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export const stream = {
|
|
202
|
+
event,
|
|
203
|
+
error,
|
|
204
|
+
done,
|
|
205
|
+
encodeSseEvent,
|
|
206
|
+
parseSseStream,
|
|
207
|
+
readableBytes,
|
|
208
|
+
readableTextChunks,
|
|
209
|
+
readableLines,
|
|
210
|
+
};
|
package/src/testing/run.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { describe, expect, it } from "bun:test";
|
|
2
2
|
|
|
3
|
+
import { createProviderCache } from "../runtime/cache";
|
|
4
|
+
import { createTestProviderChoiceContext } from "../runtime/choice";
|
|
5
|
+
import { createMemoryProviderRuntimeState } from "../runtime/state";
|
|
6
|
+
import { createUnsupportedSttClient } from "../runtime/stt";
|
|
3
7
|
import { safeParseSchemaSync } from "../schema";
|
|
4
8
|
import type {
|
|
5
9
|
AuthMode,
|
|
@@ -9,7 +13,10 @@ import type {
|
|
|
9
13
|
ProviderDefinition,
|
|
10
14
|
} from "../types";
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
// Mirrors CONNECTOR_ID_REGEX in ../define.ts, which defineProvider() enforces.
|
|
17
|
+
// A single lowercase segment (no hyphen) is a valid id, so the trailing group
|
|
18
|
+
// is optional (`*`), matching providers like `kakaomap`, `kstartup`, `triple`.
|
|
19
|
+
const CONNECTOR_ID_REGEX = /^[a-z][a-z0-9]*(-[a-z][a-z0-9]*)*$/;
|
|
13
20
|
const VALID_AUTH_MODES = [
|
|
14
21
|
"none",
|
|
15
22
|
"platform-managed",
|
|
@@ -121,13 +128,21 @@ function inferFixtureDir(providerId: string): string {
|
|
|
121
128
|
}
|
|
122
129
|
|
|
123
130
|
function jsonResponse(data: unknown): HttpResponse {
|
|
131
|
+
const body = JSON.stringify(data);
|
|
132
|
+
const bodyBytes = new TextEncoder().encode(body);
|
|
124
133
|
return {
|
|
125
134
|
status: 200,
|
|
126
135
|
ok: true,
|
|
127
136
|
headers: {},
|
|
128
137
|
data,
|
|
129
138
|
json: async <_T = unknown>() => JSON.parse(JSON.stringify(data)),
|
|
130
|
-
text: async () =>
|
|
139
|
+
text: async () => body,
|
|
140
|
+
arrayBuffer: async () =>
|
|
141
|
+
bodyBytes.buffer.slice(
|
|
142
|
+
bodyBytes.byteOffset,
|
|
143
|
+
bodyBytes.byteOffset + bodyBytes.byteLength,
|
|
144
|
+
),
|
|
145
|
+
bytes: async () => bodyBytes.slice(0),
|
|
131
146
|
};
|
|
132
147
|
}
|
|
133
148
|
|
|
@@ -143,25 +158,35 @@ function createSnapshotContext(rawFixture: unknown): ProviderContext {
|
|
|
143
158
|
getAccessToken: () => undefined,
|
|
144
159
|
getScopes: () => [],
|
|
145
160
|
};
|
|
161
|
+
const request = { headers: {} };
|
|
162
|
+
const state = createMemoryProviderRuntimeState();
|
|
146
163
|
|
|
147
164
|
return {
|
|
148
165
|
env: { get: () => undefined },
|
|
149
166
|
credential,
|
|
150
|
-
request
|
|
167
|
+
request,
|
|
151
168
|
http: {
|
|
152
169
|
request: async () => jsonResponse(rawFixture),
|
|
153
170
|
get: async () => jsonResponse(rawFixture),
|
|
154
171
|
post: async () => jsonResponse(rawFixture),
|
|
155
172
|
put: async () => jsonResponse(rawFixture),
|
|
156
173
|
delete: async () => jsonResponse(rawFixture),
|
|
174
|
+
stream: async () => unsupported("ctx.http.stream"),
|
|
175
|
+
sse: async () => unsupported("ctx.http.sse"),
|
|
157
176
|
},
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
177
|
+
cache: createProviderCache({ providerId: "standard-test" }),
|
|
178
|
+
state,
|
|
179
|
+
stealth: {
|
|
180
|
+
fetch: async () => unsupported("ctx.stealth.fetch"),
|
|
181
|
+
createSession: () => unsupported("ctx.stealth.createSession"),
|
|
161
182
|
},
|
|
162
183
|
browser: {
|
|
163
184
|
engine: "playwright-stealth",
|
|
164
185
|
newPage: async () => unsupported("ctx.browser.newPage"),
|
|
186
|
+
rawPage: async () => unsupported("ctx.browser.rawPage"),
|
|
187
|
+
withIsolatedContext: async () =>
|
|
188
|
+
unsupported("ctx.browser.withIsolatedContext"),
|
|
189
|
+
solveChallenge: async () => unsupported("ctx.browser.solveChallenge"),
|
|
165
190
|
},
|
|
166
191
|
trace: {
|
|
167
192
|
span: async (_name, fn) => fn(),
|
|
@@ -170,6 +195,15 @@ function createSnapshotContext(rawFixture: unknown): ProviderContext {
|
|
|
170
195
|
requestField: async (name) =>
|
|
171
196
|
unsupported(`ctx.auth.requestField(${name})`),
|
|
172
197
|
},
|
|
198
|
+
stt: createUnsupportedSttClient(
|
|
199
|
+
"Standard test snapshot context does not support ctx.stt.transcribe",
|
|
200
|
+
),
|
|
201
|
+
choice: createTestProviderChoiceContext({
|
|
202
|
+
providerId: "standard-test",
|
|
203
|
+
request,
|
|
204
|
+
credential,
|
|
205
|
+
state,
|
|
206
|
+
}),
|
|
173
207
|
};
|
|
174
208
|
}
|
|
175
209
|
|