@apifuse/provider-sdk 2.1.0-beta.2 → 2.1.0-beta.21

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.
Files changed (231) hide show
  1. package/AUTHORING.md +330 -8
  2. package/CHANGELOG.md +89 -1
  3. package/README.md +64 -17
  4. package/SUBMISSION.md +86 -0
  5. package/bin/apifuse-check.ts +60 -6
  6. package/bin/apifuse-dev.ts +58 -8
  7. package/bin/apifuse-pack-check.ts +32 -2
  8. package/bin/apifuse-pack-smoke.ts +133 -6
  9. package/bin/apifuse-perf.ts +142 -49
  10. package/bin/apifuse-record.ts +182 -104
  11. package/bin/apifuse-submit-check.ts +3243 -0
  12. package/bin/apifuse.ts +1 -1
  13. package/dist/auth.d.ts +76 -0
  14. package/dist/auth.js +436 -0
  15. package/dist/ceremonies/index.d.ts +41 -0
  16. package/dist/ceremonies/index.js +490 -0
  17. package/dist/choice-token.d.ts +24 -0
  18. package/dist/choice-token.js +74 -0
  19. package/dist/cli/commands.d.ts +10 -0
  20. package/dist/cli/commands.js +80 -0
  21. package/dist/cli/create.d.ts +47 -0
  22. package/dist/cli/create.js +777 -0
  23. package/dist/cli/templates/provider/.dockerignore.tpl +22 -0
  24. package/dist/cli/templates/provider/.gitignore.tpl +22 -0
  25. package/dist/cli/templates/provider/AGENTS.md.tpl +87 -0
  26. package/dist/cli/templates/provider/CLAUDE.md.tpl +1 -0
  27. package/dist/cli/templates/provider/Dockerfile.tpl +7 -0
  28. package/dist/cli/templates/provider/README.md.tpl +163 -0
  29. package/dist/cli/templates/provider/dev.ts.tpl +5 -0
  30. package/dist/cli/templates/provider/domain/README.md.tpl +3 -0
  31. package/dist/cli/templates/provider/index.test.ts.tpl +13 -0
  32. package/dist/cli/templates/provider/index.ts.tpl +15 -0
  33. package/dist/cli/templates/provider/mappers/README.md.tpl +3 -0
  34. package/dist/cli/templates/provider/meta.ts.tpl +7 -0
  35. package/dist/cli/templates/provider/operations/index.ts.tpl +5 -0
  36. package/dist/cli/templates/provider/operations/ping.ts.tpl +24 -0
  37. package/dist/cli/templates/provider/schemas/ping.ts.tpl +24 -0
  38. package/dist/cli/templates/provider/skills/fixtures-and-recording/SKILL.md.tpl +58 -0
  39. package/dist/cli/templates/provider/skills/health-checks-and-fail-closed/SKILL.md.tpl +65 -0
  40. package/dist/cli/templates/provider/skills/normalization-standards/SKILL.md.tpl +57 -0
  41. package/dist/cli/templates/provider/skills/pagination-and-counts/SKILL.md.tpl +52 -0
  42. package/dist/cli/templates/provider/skills/upstream-contract-verification/SKILL.md.tpl +45 -0
  43. package/dist/cli/templates/provider/skills/upstream-notes/README.md.tpl +13 -0
  44. package/dist/cli/templates/provider/start.ts.tpl +5 -0
  45. package/dist/cli/templates/provider/upstream/README.md.tpl +3 -0
  46. package/dist/config/loader.d.ts +107 -0
  47. package/dist/config/loader.js +935 -0
  48. package/dist/contract-json.d.ts +9 -0
  49. package/dist/contract-json.js +51 -0
  50. package/dist/contract-serialization.d.ts +4 -0
  51. package/dist/contract-serialization.js +78 -0
  52. package/dist/contract-types.d.ts +49 -0
  53. package/dist/contract-types.js +1 -0
  54. package/dist/contract.d.ts +6 -0
  55. package/dist/contract.js +156 -0
  56. package/dist/define.d.ts +100 -0
  57. package/dist/define.js +1383 -0
  58. package/dist/dev.d.ts +9 -0
  59. package/dist/dev.js +15 -0
  60. package/dist/errors.d.ts +59 -0
  61. package/dist/errors.js +97 -0
  62. package/dist/i18n/catalog.d.ts +29 -0
  63. package/dist/i18n/catalog.js +159 -0
  64. package/dist/i18n/index.d.ts +2 -0
  65. package/dist/i18n/index.js +2 -0
  66. package/dist/i18n/keys.d.ts +10 -0
  67. package/dist/i18n/keys.js +34 -0
  68. package/dist/index.d.ts +42 -0
  69. package/dist/index.js +38 -0
  70. package/dist/lint.d.ts +74 -0
  71. package/dist/lint.js +729 -0
  72. package/dist/observability.d.ts +5 -0
  73. package/dist/observability.js +39 -0
  74. package/dist/provider.d.ts +11 -0
  75. package/dist/provider.js +9 -0
  76. package/dist/public-schema-field-lint.d.ts +2 -0
  77. package/dist/public-schema-field-lint.js +158 -0
  78. package/dist/recipes/gov-api.d.ts +19 -0
  79. package/dist/recipes/gov-api.js +72 -0
  80. package/dist/recipes/rest-api.d.ts +21 -0
  81. package/dist/recipes/rest-api.js +115 -0
  82. package/dist/runtime/auth-flow.d.ts +14 -0
  83. package/dist/runtime/auth-flow.js +46 -0
  84. package/dist/runtime/browser.d.ts +25 -0
  85. package/dist/runtime/browser.js +1237 -0
  86. package/dist/runtime/cache.d.ts +10 -0
  87. package/dist/runtime/cache.js +372 -0
  88. package/dist/runtime/choice.d.ts +15 -0
  89. package/dist/runtime/choice.js +435 -0
  90. package/dist/runtime/credential.d.ts +8 -0
  91. package/dist/runtime/credential.js +61 -0
  92. package/dist/runtime/env.d.ts +2 -0
  93. package/dist/runtime/env.js +10 -0
  94. package/dist/runtime/executor.d.ts +16 -0
  95. package/dist/runtime/executor.js +51 -0
  96. package/dist/runtime/http.d.ts +8 -0
  97. package/dist/runtime/http.js +726 -0
  98. package/dist/runtime/insights.d.ts +9 -0
  99. package/dist/runtime/insights.js +324 -0
  100. package/dist/runtime/instrumentation.d.ts +8 -0
  101. package/dist/runtime/instrumentation.js +269 -0
  102. package/dist/runtime/key-derivation.d.ts +24 -0
  103. package/dist/runtime/key-derivation.js +73 -0
  104. package/dist/runtime/keyring.d.ts +25 -0
  105. package/dist/runtime/keyring.js +93 -0
  106. package/dist/runtime/namespace.d.ts +9 -0
  107. package/dist/runtime/namespace.js +19 -0
  108. package/dist/runtime/otlp.d.ts +39 -0
  109. package/dist/runtime/otlp.js +103 -0
  110. package/dist/runtime/perf.d.ts +12 -0
  111. package/dist/runtime/perf.js +52 -0
  112. package/dist/runtime/prevalidate.d.ts +12 -0
  113. package/dist/runtime/prevalidate.js +173 -0
  114. package/dist/runtime/provider.d.ts +2 -0
  115. package/dist/runtime/provider.js +11 -0
  116. package/dist/runtime/proxy-errors.d.ts +21 -0
  117. package/dist/runtime/proxy-errors.js +83 -0
  118. package/dist/runtime/proxy-telemetry.d.ts +8 -0
  119. package/dist/runtime/proxy-telemetry.js +174 -0
  120. package/dist/runtime/redis.d.ts +17 -0
  121. package/dist/runtime/redis.js +82 -0
  122. package/dist/runtime/request-options.d.ts +3 -0
  123. package/dist/runtime/request-options.js +42 -0
  124. package/dist/runtime/state.d.ts +17 -0
  125. package/dist/runtime/state.js +344 -0
  126. package/dist/runtime/stealth.d.ts +21 -0
  127. package/dist/runtime/stealth.js +980 -0
  128. package/dist/runtime/stt.d.ts +22 -0
  129. package/dist/runtime/stt.js +480 -0
  130. package/dist/runtime/trace.d.ts +26 -0
  131. package/dist/runtime/trace.js +142 -0
  132. package/dist/runtime/waterfall.d.ts +12 -0
  133. package/dist/runtime/waterfall.js +147 -0
  134. package/dist/schema.d.ts +74 -0
  135. package/dist/schema.js +243 -0
  136. package/dist/serve.d.ts +1 -0
  137. package/dist/serve.js +1 -0
  138. package/dist/server/index.d.ts +3 -0
  139. package/dist/server/index.js +2 -0
  140. package/dist/server/serve.d.ts +64 -0
  141. package/dist/server/serve.js +1118 -0
  142. package/dist/server/types.d.ts +136 -0
  143. package/dist/server/types.js +86 -0
  144. package/dist/stealth/profiles.d.ts +4 -0
  145. package/dist/stealth/profiles.js +259 -0
  146. package/dist/stream.d.ts +44 -0
  147. package/dist/stream.js +151 -0
  148. package/dist/testing/helpers.d.ts +23 -0
  149. package/dist/testing/helpers.js +95 -0
  150. package/dist/testing/index.d.ts +2 -0
  151. package/dist/testing/index.js +2 -0
  152. package/dist/testing/run.d.ts +34 -0
  153. package/dist/testing/run.js +307 -0
  154. package/dist/types.d.ts +1467 -0
  155. package/dist/types.js +61 -0
  156. package/dist/utils/date.d.ts +6 -0
  157. package/dist/utils/date.js +101 -0
  158. package/dist/utils/parse.d.ts +16 -0
  159. package/dist/utils/parse.js +51 -0
  160. package/dist/utils/text.d.ts +4 -0
  161. package/dist/utils/text.js +14 -0
  162. package/dist/utils/transform.d.ts +8 -0
  163. package/dist/utils/transform.js +48 -0
  164. package/package.json +57 -29
  165. package/src/auth.ts +786 -0
  166. package/src/ceremonies/index.ts +8 -2
  167. package/src/choice-token.ts +165 -0
  168. package/src/cli/commands.ts +34 -11
  169. package/src/cli/create.ts +254 -128
  170. package/src/cli/templates/provider/.dockerignore.tpl +22 -0
  171. package/src/cli/templates/provider/.gitignore.tpl +22 -0
  172. package/src/cli/templates/provider/AGENTS.md.tpl +87 -0
  173. package/src/cli/templates/provider/CLAUDE.md.tpl +1 -0
  174. package/src/cli/templates/provider/README.md.tpl +87 -7
  175. package/src/cli/templates/provider/dev.ts.tpl +1 -1
  176. package/src/cli/templates/provider/domain/README.md.tpl +3 -0
  177. package/src/cli/templates/provider/index.ts.tpl +5 -47
  178. package/src/cli/templates/provider/mappers/README.md.tpl +3 -0
  179. package/src/cli/templates/provider/meta.ts.tpl +7 -0
  180. package/src/cli/templates/provider/operations/index.ts.tpl +5 -0
  181. package/src/cli/templates/provider/operations/ping.ts.tpl +24 -0
  182. package/src/cli/templates/provider/schemas/ping.ts.tpl +24 -0
  183. package/src/cli/templates/provider/skills/fixtures-and-recording/SKILL.md.tpl +58 -0
  184. package/src/cli/templates/provider/skills/health-checks-and-fail-closed/SKILL.md.tpl +65 -0
  185. package/src/cli/templates/provider/skills/normalization-standards/SKILL.md.tpl +57 -0
  186. package/src/cli/templates/provider/skills/pagination-and-counts/SKILL.md.tpl +52 -0
  187. package/src/cli/templates/provider/skills/upstream-contract-verification/SKILL.md.tpl +45 -0
  188. package/src/cli/templates/provider/skills/upstream-notes/README.md.tpl +13 -0
  189. package/src/cli/templates/provider/start.ts.tpl +1 -1
  190. package/src/cli/templates/provider/upstream/README.md.tpl +3 -0
  191. package/src/config/loader.ts +1224 -9
  192. package/src/contract-json.ts +75 -0
  193. package/src/contract-serialization.ts +89 -0
  194. package/src/contract-types.ts +52 -0
  195. package/src/contract.ts +216 -0
  196. package/src/define.ts +1820 -70
  197. package/src/errors.ts +27 -0
  198. package/src/i18n/catalog.ts +277 -0
  199. package/src/i18n/index.ts +2 -0
  200. package/src/i18n/keys.ts +64 -0
  201. package/src/index.ts +189 -9
  202. package/src/lint.ts +580 -73
  203. package/src/observability.ts +41 -0
  204. package/src/provider.ts +131 -4
  205. package/src/public-schema-field-lint.ts +237 -0
  206. package/src/runtime/auth-flow.ts +9 -0
  207. package/src/runtime/browser.ts +1054 -51
  208. package/src/runtime/cache.ts +528 -0
  209. package/src/runtime/choice.ts +760 -0
  210. package/src/runtime/executor.ts +32 -3
  211. package/src/runtime/http.ts +980 -195
  212. package/src/runtime/insights.ts +11 -11
  213. package/src/runtime/instrumentation.ts +12 -4
  214. package/src/runtime/key-derivation.ts +1 -1
  215. package/src/runtime/keyring.ts +4 -3
  216. package/src/runtime/proxy-errors.ts +132 -0
  217. package/src/runtime/proxy-telemetry.ts +253 -0
  218. package/src/runtime/redis.ts +116 -0
  219. package/src/runtime/request-options.ts +66 -0
  220. package/src/runtime/state.ts +563 -0
  221. package/src/runtime/stealth.ts +1336 -0
  222. package/src/runtime/stt.ts +629 -0
  223. package/src/runtime/trace.ts +1 -1
  224. package/src/schema.ts +363 -1
  225. package/src/server/serve.ts +1192 -75
  226. package/src/server/types.ts +37 -0
  227. package/src/stream.ts +210 -0
  228. package/src/testing/run.ts +40 -6
  229. package/src/types.ts +1283 -59
  230. package/src/runtime/tls.ts +0 -434
  231. package/src/types/playwright-stealth.d.ts +0 -9
@@ -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
+ };
@@ -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
- const CONNECTOR_ID_REGEX = /^[a-z][a-z0-9]*(-[a-z][a-z0-9]*)+$/;
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 () => JSON.stringify(data),
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: { headers: {} },
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
- tls: {
159
- fetch: async () => unsupported("ctx.tls.fetch"),
160
- createSession: () => unsupported("ctx.tls.createSession"),
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