@jterrazz/test 7.0.0 → 7.1.0
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/dist/index.cjs +5 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/intercept.cjs +40 -28
- package/dist/intercept.cjs.map +1 -1
- package/dist/intercept.d.cts +15 -13
- package/dist/intercept.d.ts +15 -13
- package/dist/intercept.js +40 -28
- package/dist/intercept.js.map +1 -1
- package/dist/types.d.cts +5 -4
- package/dist/types.d.ts +5 -4
- package/package.json +1 -1
package/dist/intercept.cjs
CHANGED
|
@@ -19,42 +19,45 @@ function matchesFilter(body, filter) {
|
|
|
19
19
|
if (filter.user instanceof RegExp && !filter.user.test(text)) return false;
|
|
20
20
|
}
|
|
21
21
|
if (filter.tools) {
|
|
22
|
-
const
|
|
23
|
-
if (!filter.tools.every((t) =>
|
|
22
|
+
const names = body?.tools?.map((t) => t.name).filter(Boolean) ?? [];
|
|
23
|
+
if (!filter.tools.every((t) => names.includes(t))) return false;
|
|
24
24
|
}
|
|
25
25
|
return true;
|
|
26
26
|
}
|
|
27
|
+
function buildReply(data) {
|
|
28
|
+
return {
|
|
29
|
+
status: 200,
|
|
30
|
+
body: {
|
|
31
|
+
id: "msg-test",
|
|
32
|
+
type: "message",
|
|
33
|
+
role: "assistant",
|
|
34
|
+
content: [{
|
|
35
|
+
type: "text",
|
|
36
|
+
text: typeof data === "string" ? data : JSON.stringify(data)
|
|
37
|
+
}],
|
|
38
|
+
model: "claude-sonnet-4-20250514",
|
|
39
|
+
stop_reason: "end_turn",
|
|
40
|
+
usage: {
|
|
41
|
+
input_tokens: 10,
|
|
42
|
+
output_tokens: 10
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
27
47
|
/**
|
|
28
48
|
* Anthropic API intercept helpers.
|
|
29
49
|
*/
|
|
30
50
|
const anthropic = {
|
|
31
|
-
|
|
51
|
+
request(filter) {
|
|
32
52
|
return {
|
|
53
|
+
adapter: "anthropic",
|
|
33
54
|
method: "POST",
|
|
34
55
|
url: ANTHROPIC_MESSAGES_URL,
|
|
35
|
-
match: filter ? (body) => matchesFilter(body, filter) : void 0
|
|
36
|
-
|
|
37
|
-
},
|
|
38
|
-
response(data) {
|
|
39
|
-
return {
|
|
40
|
-
status: 200,
|
|
41
|
-
body: {
|
|
42
|
-
id: "msg-test",
|
|
43
|
-
type: "message",
|
|
44
|
-
role: "assistant",
|
|
45
|
-
content: [{
|
|
46
|
-
type: "text",
|
|
47
|
-
text: typeof data === "string" ? data : JSON.stringify(data)
|
|
48
|
-
}],
|
|
49
|
-
model: "claude-sonnet-4-20250514",
|
|
50
|
-
stop_reason: "end_turn",
|
|
51
|
-
usage: {
|
|
52
|
-
input_tokens: 10,
|
|
53
|
-
output_tokens: 10
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
+
match: filter ? (body) => matchesFilter(body, filter) : void 0,
|
|
57
|
+
wrap: buildReply
|
|
56
58
|
};
|
|
57
59
|
},
|
|
60
|
+
reply: buildReply,
|
|
58
61
|
error(status, message) {
|
|
59
62
|
return {
|
|
60
63
|
status,
|
|
@@ -73,11 +76,14 @@ const anthropic = {
|
|
|
73
76
|
body: {},
|
|
74
77
|
delay: 3e4
|
|
75
78
|
};
|
|
76
|
-
}
|
|
79
|
+
},
|
|
80
|
+
messages(filter) {
|
|
81
|
+
return anthropic.request(filter);
|
|
82
|
+
},
|
|
83
|
+
response: buildReply
|
|
77
84
|
};
|
|
78
85
|
//#endregion
|
|
79
86
|
//#region src/builder/common/intercept/adapters/http.ts
|
|
80
|
-
/** Default wrap: raw JSON data becomes the response body. */
|
|
81
87
|
function wrapJson(data) {
|
|
82
88
|
return {
|
|
83
89
|
status: 200,
|
|
@@ -88,12 +94,12 @@ function wrapJson(data) {
|
|
|
88
94
|
* Generic HTTP intercept helpers for any URL.
|
|
89
95
|
*
|
|
90
96
|
* @example
|
|
91
|
-
* .intercept(http.get('https://api.example.com/data'), 'response.json')
|
|
92
|
-
* .intercept(http.post('https://api.stripe.com/v1/charges'), http.json({ id: 'ch_...' }))
|
|
97
|
+
* .intercept(http.get('https://api.example.com/data'), 'http/response.json')
|
|
93
98
|
*/
|
|
94
99
|
const http = {
|
|
95
100
|
get(url) {
|
|
96
101
|
return {
|
|
102
|
+
adapter: "http",
|
|
97
103
|
method: "GET",
|
|
98
104
|
url,
|
|
99
105
|
wrap: wrapJson
|
|
@@ -101,6 +107,7 @@ const http = {
|
|
|
101
107
|
},
|
|
102
108
|
post(url) {
|
|
103
109
|
return {
|
|
110
|
+
adapter: "http",
|
|
104
111
|
method: "POST",
|
|
105
112
|
url,
|
|
106
113
|
wrap: wrapJson
|
|
@@ -108,6 +115,7 @@ const http = {
|
|
|
108
115
|
},
|
|
109
116
|
put(url) {
|
|
110
117
|
return {
|
|
118
|
+
adapter: "http",
|
|
111
119
|
method: "PUT",
|
|
112
120
|
url,
|
|
113
121
|
wrap: wrapJson
|
|
@@ -115,6 +123,7 @@ const http = {
|
|
|
115
123
|
},
|
|
116
124
|
delete(url) {
|
|
117
125
|
return {
|
|
126
|
+
adapter: "http",
|
|
118
127
|
method: "DELETE",
|
|
119
128
|
url,
|
|
120
129
|
wrap: wrapJson
|
|
@@ -122,6 +131,7 @@ const http = {
|
|
|
122
131
|
},
|
|
123
132
|
any(url) {
|
|
124
133
|
return {
|
|
134
|
+
adapter: "http",
|
|
125
135
|
method: "*",
|
|
126
136
|
url,
|
|
127
137
|
wrap: wrapJson
|
|
@@ -249,6 +259,7 @@ function buildResponsesReply(data) {
|
|
|
249
259
|
const openai = {
|
|
250
260
|
request(filter) {
|
|
251
261
|
return {
|
|
262
|
+
adapter: "openai",
|
|
252
263
|
method: "POST",
|
|
253
264
|
url: OPENAI_CHAT_URL,
|
|
254
265
|
match: filter ? (body) => matchesChatFilter(body, filter) : void 0,
|
|
@@ -257,6 +268,7 @@ const openai = {
|
|
|
257
268
|
},
|
|
258
269
|
agent(filter, url) {
|
|
259
270
|
return {
|
|
271
|
+
adapter: "openai",
|
|
260
272
|
method: "POST",
|
|
261
273
|
url: url ?? OPENAI_RESPONSES_URL,
|
|
262
274
|
match: filter ? (body) => matchesResponsesFilter(body, filter) : void 0,
|
package/dist/intercept.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intercept.cjs","names":[],"sources":["../src/builder/common/intercept/adapters/anthropic.ts","../src/builder/common/intercept/adapters/http.ts","../src/builder/common/intercept/adapters/openai.ts"],"sourcesContent":["import type { InterceptResponse, InterceptTrigger } from '../types.js';\n\nconst ANTHROPIC_MESSAGES_URL = 'https://api.anthropic.com/v1/messages';\n\nexport interface AnthropicMessagesFilter {\n /** Match by model name. */\n model?: RegExp | string;\n /** Match by system message content. */\n system?: RegExp | string;\n /** Match by user message content. */\n user?: RegExp | string;\n /** Match by tool names. */\n tools?: string[];\n}\n\nfunction matchesFilter(body: any, filter: AnthropicMessagesFilter): boolean {\n if (filter.model) {\n const model = body?.model;\n if (typeof filter.model === 'string' && model !== filter.model) {\n return false;\n }\n if (filter.model instanceof RegExp && !filter.model.test(model ?? '')) {\n return false;\n }\n }\n\n if (filter.system) {\n const system = typeof body?.system === 'string' ? body.system : '';\n if (typeof filter.system === 'string' && !system.includes(filter.system)) {\n return false;\n }\n if (filter.system instanceof RegExp && !filter.system.test(system)) {\n return false;\n }\n }\n\n if (filter.user) {\n const userMsg = body?.messages?.find((m: any) => m.role === 'user')?.content ?? '';\n const text = typeof userMsg === 'string' ? userMsg : JSON.stringify(userMsg);\n if (typeof filter.user === 'string' && !text.includes(filter.user)) {\n return false;\n }\n if (filter.user instanceof RegExp && !filter.user.test(text)) {\n return false;\n }\n }\n\n if (filter.tools) {\n const requestTools = body?.tools?.map((t: any) => t.name).filter(Boolean) ?? [];\n if (!filter.tools.every((t) => requestTools.includes(t))) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Anthropic API intercept helpers.\n */\nexport const anthropic = {\n /**\n * Trigger: match Anthropic messages API requests.\n */\n messages(filter?: AnthropicMessagesFilter): InterceptTrigger {\n return {\n method: 'POST',\n url: ANTHROPIC_MESSAGES_URL,\n match: filter ? (body: unknown) => matchesFilter(body, filter) : undefined,\n };\n },\n\n /** Response: wrap data in Anthropic messages format. */\n response(data: unknown): InterceptResponse {\n const content = typeof data === 'string' ? data : JSON.stringify(data);\n return {\n status: 200,\n body: {\n id: 'msg-test',\n type: 'message',\n role: 'assistant',\n content: [{ type: 'text', text: content }],\n model: 'claude-sonnet-4-20250514',\n stop_reason: 'end_turn',\n usage: { input_tokens: 10, output_tokens: 10 },\n },\n };\n },\n\n /** Response: return an Anthropic error. */\n error(status: number, message?: string): InterceptResponse {\n return {\n status,\n body: {\n type: 'error',\n error: {\n type: status === 429 ? 'rate_limit_error' : 'api_error',\n message: message ?? `Anthropic error (${status})`,\n },\n },\n };\n },\n\n /** Response: simulate a timeout. */\n timeout(): InterceptResponse {\n return { status: 200, body: {}, delay: 30_000 };\n },\n};\n","import type { InterceptResponse, InterceptTrigger } from '../types.js';\n\n/** Default wrap: raw JSON data becomes the response body. */\nfunction wrapJson(data: unknown): InterceptResponse {\n return { status: 200, body: data };\n}\n\n/**\n * Generic HTTP intercept helpers for any URL.\n *\n * @example\n * .intercept(http.get('https://api.example.com/data'), 'response.json')\n * .intercept(http.post('https://api.stripe.com/v1/charges'), http.json({ id: 'ch_...' }))\n */\nexport const http = {\n /** Trigger: match GET requests to a URL pattern. */\n get(url: RegExp | string): InterceptTrigger {\n return { method: 'GET', url, wrap: wrapJson };\n },\n\n /** Trigger: match POST requests to a URL pattern. */\n post(url: RegExp | string): InterceptTrigger {\n return { method: 'POST', url, wrap: wrapJson };\n },\n\n /** Trigger: match PUT requests to a URL pattern. */\n put(url: RegExp | string): InterceptTrigger {\n return { method: 'PUT', url, wrap: wrapJson };\n },\n\n /** Trigger: match DELETE requests to a URL pattern. */\n delete(url: RegExp | string): InterceptTrigger {\n return { method: 'DELETE', url, wrap: wrapJson };\n },\n\n /** Trigger: match any method to a URL pattern. */\n any(url: RegExp | string): InterceptTrigger {\n return { method: '*', url, wrap: wrapJson };\n },\n\n /** Response: simple JSON success. */\n json(data: unknown, status = 200): InterceptResponse {\n return { status, body: data };\n },\n\n /** Response: error with message. */\n error(status: number, message?: string): InterceptResponse {\n return { status, body: { error: message ?? `HTTP ${status}` } };\n },\n};\n","import type { InterceptResponse, InterceptTrigger } from '../types.js';\n\nconst OPENAI_CHAT_URL = 'https://api.openai.com/v1/chat/completions';\nconst OPENAI_RESPONSES_URL = 'https://api.openai.com/v1/responses';\n\n// ── Chat Completions filters ──\n\nexport interface OpenAIChatFilter {\n model?: RegExp | string;\n system?: RegExp | string;\n user?: RegExp | string;\n tools?: string[];\n temperature?: number;\n}\n\nfunction matchesChatFilter(body: any, filter: OpenAIChatFilter): boolean {\n if (filter.model) {\n const model = body?.model;\n if (typeof filter.model === 'string' && model !== filter.model) {\n return false;\n }\n if (filter.model instanceof RegExp && !filter.model.test(model ?? '')) {\n return false;\n }\n }\n if (filter.system) {\n const msg = body?.messages?.find((m: any) => m.role === 'system')?.content ?? '';\n if (typeof filter.system === 'string' && !msg.includes(filter.system)) {\n return false;\n }\n if (filter.system instanceof RegExp && !filter.system.test(msg)) {\n return false;\n }\n }\n if (filter.user) {\n const msg = body?.messages?.find((m: any) => m.role === 'user')?.content ?? '';\n if (typeof filter.user === 'string' && !msg.includes(filter.user)) {\n return false;\n }\n if (filter.user instanceof RegExp && !filter.user.test(msg)) {\n return false;\n }\n }\n if (filter.tools) {\n const names = body?.tools?.map((t: any) => t.function?.name).filter(Boolean) ?? [];\n if (!filter.tools.every((t) => names.includes(t))) {\n return false;\n }\n }\n if (filter.temperature !== undefined && body?.temperature !== filter.temperature) {\n return false;\n }\n return true;\n}\n\n// ── Responses API filters ──\n\nexport interface OpenAIResponsesFilter {\n model?: RegExp | string;\n system?: RegExp | string;\n user?: RegExp | string;\n tools?: string[];\n}\n\nfunction matchesResponsesFilter(body: any, filter: OpenAIResponsesFilter): boolean {\n if (filter.model) {\n const model = body?.model;\n if (typeof filter.model === 'string' && model !== filter.model) {\n return false;\n }\n if (filter.model instanceof RegExp && !filter.model.test(model ?? '')) {\n return false;\n }\n }\n if (filter.system) {\n const instructions = body?.instructions ?? '';\n const systemInput = body?.input?.find?.((m: any) => m.role === 'system')?.content ?? '';\n const text = instructions || systemInput;\n if (typeof filter.system === 'string' && !text.includes(filter.system)) {\n return false;\n }\n if (filter.system instanceof RegExp && !filter.system.test(text)) {\n return false;\n }\n }\n if (filter.user) {\n const msgs = (body?.input ?? [])\n .filter((m: any) => m.role === 'user')\n .map((m: any) =>\n typeof m.content === 'string' ? m.content : JSON.stringify(m.content),\n )\n .join(' ');\n if (typeof filter.user === 'string' && !msgs.includes(filter.user)) {\n return false;\n }\n if (filter.user instanceof RegExp && !filter.user.test(msgs)) {\n return false;\n }\n }\n if (filter.tools) {\n const names =\n body?.tools?.map((t: any) => t.name ?? t.function?.name).filter(Boolean) ?? [];\n if (!filter.tools.every((t) => names.includes(t))) {\n return false;\n }\n }\n return true;\n}\n\n// ── Response builders ──\n\nfunction buildChatReply(data: unknown): InterceptResponse {\n const content = typeof data === 'string' ? data : JSON.stringify(data);\n return {\n status: 200,\n body: {\n id: 'chatcmpl-test',\n object: 'chat.completion',\n created: Math.floor(Date.now() / 1000),\n model: 'gpt-4o-test',\n choices: [{ index: 0, message: { role: 'assistant', content }, finish_reason: 'stop' }],\n usage: { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n },\n };\n}\n\nfunction buildResponsesReply(data: unknown): InterceptResponse {\n const text = typeof data === 'string' ? data : JSON.stringify(data);\n return {\n status: 200,\n body: {\n id: 'resp-test',\n object: 'response',\n created_at: Math.floor(Date.now() / 1000),\n model: 'gpt-4o-test',\n output: [\n {\n type: 'message',\n id: 'msg-test',\n role: 'assistant',\n content: [{ type: 'output_text', text, annotations: [] }],\n },\n ],\n usage: { input_tokens: 10, output_tokens: 10, total_tokens: 20 },\n },\n };\n}\n\n// ── Public API ──\n\n/**\n * OpenAI API intercept helpers.\n */\nexport const openai = {\n /**\n * Trigger: match Chat Completions API requests.\n *\n * @example\n * openai.request() // any chat call\n * openai.request({ model: 'gpt-4o' }) // specific model\n * openai.request({ system: /classify/ }) // system prompt match\n */\n request(filter?: OpenAIChatFilter): InterceptTrigger {\n return {\n method: 'POST',\n url: OPENAI_CHAT_URL,\n match: filter ? (body: unknown) => matchesChatFilter(body, filter) : undefined,\n wrap: buildChatReply,\n };\n },\n\n /**\n * Trigger: match Responses API requests (AI SDK v5+) with auto-wrapping.\n * When used with a JSON file, the data is automatically wrapped in the\n * Responses API envelope.\n *\n * @param filter - Optional body filters.\n * @param url - Custom gateway URL (default: api.openai.com).\n *\n * @example\n * openai.agent({ user: /Report Ingestion/ }, GATEWAY)\n */\n agent(filter?: OpenAIResponsesFilter, url?: string): InterceptTrigger {\n return {\n method: 'POST',\n url: url ?? OPENAI_RESPONSES_URL,\n match: filter ? (body: unknown) => matchesResponsesFilter(body, filter) : undefined,\n wrap: buildResponsesReply,\n };\n },\n\n /**\n * Response: wrap data in Chat Completions format.\n *\n * @example\n * openai.reply({ categories: ['TECH'] })\n */\n reply: buildChatReply,\n\n /** Response: return an OpenAI error. */\n error(status: number, message?: string): InterceptResponse {\n return {\n status,\n body: {\n error: {\n message: message ?? `OpenAI error (${status})`,\n type: status === 429 ? 'rate_limit_error' : 'api_error',\n code: status === 429 ? 'rate_limit_exceeded' : null,\n },\n },\n };\n },\n\n /** Response: return malformed content. */\n malformed(content: string): InterceptResponse {\n return buildChatReply(content);\n },\n\n /** Response: simulate a timeout. */\n timeout(): InterceptResponse {\n return { status: 200, body: {}, delay: 30_000 };\n },\n\n // ── Legacy aliases ──\n\n /** @deprecated Use openai.request() instead. */\n chat(filter?: OpenAIChatFilter): InterceptTrigger {\n return openai.request(filter);\n },\n\n /** @deprecated Use openai.reply() instead. */\n response: buildChatReply,\n\n /** @deprecated Use openai.agent() instead. */\n responses(filter?: OpenAIResponsesFilter, url?: string): InterceptTrigger {\n return openai.agent(filter, url);\n },\n\n /** @deprecated Use openai.reply() or .intercept(trigger, 'file.json') instead. */\n responsesResponse: buildResponsesReply,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"intercept.cjs","names":[],"sources":["../src/builder/common/intercept/adapters/anthropic.ts","../src/builder/common/intercept/adapters/http.ts","../src/builder/common/intercept/adapters/openai.ts"],"sourcesContent":["import type { InterceptResponse, InterceptTrigger } from '../types.js';\n\nconst ANTHROPIC_MESSAGES_URL = 'https://api.anthropic.com/v1/messages';\n\nexport interface AnthropicMessagesFilter {\n model?: RegExp | string;\n system?: RegExp | string;\n user?: RegExp | string;\n tools?: string[];\n}\n\nfunction matchesFilter(body: any, filter: AnthropicMessagesFilter): boolean {\n if (filter.model) {\n const model = body?.model;\n if (typeof filter.model === 'string' && model !== filter.model) {\n return false;\n }\n if (filter.model instanceof RegExp && !filter.model.test(model ?? '')) {\n return false;\n }\n }\n if (filter.system) {\n const system = typeof body?.system === 'string' ? body.system : '';\n if (typeof filter.system === 'string' && !system.includes(filter.system)) {\n return false;\n }\n if (filter.system instanceof RegExp && !filter.system.test(system)) {\n return false;\n }\n }\n if (filter.user) {\n const userMsg = body?.messages?.find((m: any) => m.role === 'user')?.content ?? '';\n const text = typeof userMsg === 'string' ? userMsg : JSON.stringify(userMsg);\n if (typeof filter.user === 'string' && !text.includes(filter.user)) {\n return false;\n }\n if (filter.user instanceof RegExp && !filter.user.test(text)) {\n return false;\n }\n }\n if (filter.tools) {\n const names = body?.tools?.map((t: any) => t.name).filter(Boolean) ?? [];\n if (!filter.tools.every((t) => names.includes(t))) {\n return false;\n }\n }\n return true;\n}\n\nfunction buildReply(data: unknown): InterceptResponse {\n const content = typeof data === 'string' ? data : JSON.stringify(data);\n return {\n status: 200,\n body: {\n id: 'msg-test',\n type: 'message',\n role: 'assistant',\n content: [{ type: 'text', text: content }],\n model: 'claude-sonnet-4-20250514',\n stop_reason: 'end_turn',\n usage: { input_tokens: 10, output_tokens: 10 },\n },\n };\n}\n\n/**\n * Anthropic API intercept helpers.\n */\nexport const anthropic = {\n /**\n * Trigger: match Anthropic messages API requests.\n *\n * @example\n * anthropic.request()\n * anthropic.request({ system: /classify/ })\n */\n request(filter?: AnthropicMessagesFilter): InterceptTrigger {\n return {\n adapter: 'anthropic',\n method: 'POST',\n url: ANTHROPIC_MESSAGES_URL,\n match: filter ? (body: unknown) => matchesFilter(body, filter) : undefined,\n wrap: buildReply,\n };\n },\n\n /** Response: wrap data in Anthropic messages format. */\n reply: buildReply,\n\n /** Response: return an Anthropic error. */\n error(status: number, message?: string): InterceptResponse {\n return {\n status,\n body: {\n type: 'error',\n error: {\n type: status === 429 ? 'rate_limit_error' : 'api_error',\n message: message ?? `Anthropic error (${status})`,\n },\n },\n };\n },\n\n /** Response: simulate a timeout. */\n timeout(): InterceptResponse {\n return { status: 200, body: {}, delay: 30_000 };\n },\n\n // Legacy aliases\n /** @deprecated Use anthropic.request() instead. */\n messages(filter?: AnthropicMessagesFilter): InterceptTrigger {\n return anthropic.request(filter);\n },\n /** @deprecated Use anthropic.reply() instead. */\n response: buildReply,\n};\n","import type { InterceptResponse, InterceptTrigger } from '../types.js';\n\nfunction wrapJson(data: unknown): InterceptResponse {\n return { status: 200, body: data };\n}\n\n/**\n * Generic HTTP intercept helpers for any URL.\n *\n * @example\n * .intercept(http.get('https://api.example.com/data'), 'http/response.json')\n */\nexport const http = {\n get(url: RegExp | string): InterceptTrigger {\n return { adapter: 'http', method: 'GET', url, wrap: wrapJson };\n },\n\n post(url: RegExp | string): InterceptTrigger {\n return { adapter: 'http', method: 'POST', url, wrap: wrapJson };\n },\n\n put(url: RegExp | string): InterceptTrigger {\n return { adapter: 'http', method: 'PUT', url, wrap: wrapJson };\n },\n\n delete(url: RegExp | string): InterceptTrigger {\n return { adapter: 'http', method: 'DELETE', url, wrap: wrapJson };\n },\n\n any(url: RegExp | string): InterceptTrigger {\n return { adapter: 'http', method: '*', url, wrap: wrapJson };\n },\n\n /** Response: simple JSON success. */\n json(data: unknown, status = 200): InterceptResponse {\n return { status, body: data };\n },\n\n /** Response: error with message. */\n error(status: number, message?: string): InterceptResponse {\n return { status, body: { error: message ?? `HTTP ${status}` } };\n },\n};\n","import type { InterceptResponse, InterceptTrigger } from '../types.js';\n\nconst OPENAI_CHAT_URL = 'https://api.openai.com/v1/chat/completions';\nconst OPENAI_RESPONSES_URL = 'https://api.openai.com/v1/responses';\n\n// ── Chat Completions filters ──\n\nexport interface OpenAIChatFilter {\n model?: RegExp | string;\n system?: RegExp | string;\n user?: RegExp | string;\n tools?: string[];\n temperature?: number;\n}\n\nfunction matchesChatFilter(body: any, filter: OpenAIChatFilter): boolean {\n if (filter.model) {\n const model = body?.model;\n if (typeof filter.model === 'string' && model !== filter.model) {\n return false;\n }\n if (filter.model instanceof RegExp && !filter.model.test(model ?? '')) {\n return false;\n }\n }\n if (filter.system) {\n const msg = body?.messages?.find((m: any) => m.role === 'system')?.content ?? '';\n if (typeof filter.system === 'string' && !msg.includes(filter.system)) {\n return false;\n }\n if (filter.system instanceof RegExp && !filter.system.test(msg)) {\n return false;\n }\n }\n if (filter.user) {\n const msg = body?.messages?.find((m: any) => m.role === 'user')?.content ?? '';\n if (typeof filter.user === 'string' && !msg.includes(filter.user)) {\n return false;\n }\n if (filter.user instanceof RegExp && !filter.user.test(msg)) {\n return false;\n }\n }\n if (filter.tools) {\n const names = body?.tools?.map((t: any) => t.function?.name).filter(Boolean) ?? [];\n if (!filter.tools.every((t) => names.includes(t))) {\n return false;\n }\n }\n if (filter.temperature !== undefined && body?.temperature !== filter.temperature) {\n return false;\n }\n return true;\n}\n\n// ── Responses API filters ──\n\nexport interface OpenAIResponsesFilter {\n model?: RegExp | string;\n system?: RegExp | string;\n user?: RegExp | string;\n tools?: string[];\n}\n\nfunction matchesResponsesFilter(body: any, filter: OpenAIResponsesFilter): boolean {\n if (filter.model) {\n const model = body?.model;\n if (typeof filter.model === 'string' && model !== filter.model) {\n return false;\n }\n if (filter.model instanceof RegExp && !filter.model.test(model ?? '')) {\n return false;\n }\n }\n if (filter.system) {\n const instructions = body?.instructions ?? '';\n const systemInput = body?.input?.find?.((m: any) => m.role === 'system')?.content ?? '';\n const text = instructions || systemInput;\n if (typeof filter.system === 'string' && !text.includes(filter.system)) {\n return false;\n }\n if (filter.system instanceof RegExp && !filter.system.test(text)) {\n return false;\n }\n }\n if (filter.user) {\n const msgs = (body?.input ?? [])\n .filter((m: any) => m.role === 'user')\n .map((m: any) =>\n typeof m.content === 'string' ? m.content : JSON.stringify(m.content),\n )\n .join(' ');\n if (typeof filter.user === 'string' && !msgs.includes(filter.user)) {\n return false;\n }\n if (filter.user instanceof RegExp && !filter.user.test(msgs)) {\n return false;\n }\n }\n if (filter.tools) {\n const names =\n body?.tools?.map((t: any) => t.name ?? t.function?.name).filter(Boolean) ?? [];\n if (!filter.tools.every((t) => names.includes(t))) {\n return false;\n }\n }\n return true;\n}\n\n// ── Response builders ──\n\nfunction buildChatReply(data: unknown): InterceptResponse {\n const content = typeof data === 'string' ? data : JSON.stringify(data);\n return {\n status: 200,\n body: {\n id: 'chatcmpl-test',\n object: 'chat.completion',\n created: Math.floor(Date.now() / 1000),\n model: 'gpt-4o-test',\n choices: [{ index: 0, message: { role: 'assistant', content }, finish_reason: 'stop' }],\n usage: { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n },\n };\n}\n\nfunction buildResponsesReply(data: unknown): InterceptResponse {\n const text = typeof data === 'string' ? data : JSON.stringify(data);\n return {\n status: 200,\n body: {\n id: 'resp-test',\n object: 'response',\n created_at: Math.floor(Date.now() / 1000),\n model: 'gpt-4o-test',\n output: [\n {\n type: 'message',\n id: 'msg-test',\n role: 'assistant',\n content: [{ type: 'output_text', text, annotations: [] }],\n },\n ],\n usage: { input_tokens: 10, output_tokens: 10, total_tokens: 20 },\n },\n };\n}\n\n// ── Public API ──\n\n/**\n * OpenAI API intercept helpers.\n */\nexport const openai = {\n /**\n * Trigger: match Chat Completions API requests.\n *\n * @example\n * openai.request() // any chat call\n * openai.request({ model: 'gpt-4o' }) // specific model\n * openai.request({ system: /classify/ }) // system prompt match\n */\n request(filter?: OpenAIChatFilter): InterceptTrigger {\n return {\n adapter: 'openai',\n method: 'POST',\n url: OPENAI_CHAT_URL,\n match: filter ? (body: unknown) => matchesChatFilter(body, filter) : undefined,\n wrap: buildChatReply,\n };\n },\n\n /**\n * Trigger: match Responses API requests (AI SDK v5+) with auto-wrapping.\n * When used with a JSON file, the data is automatically wrapped in the\n * Responses API envelope.\n *\n * @param filter - Optional body filters.\n * @param url - Custom gateway URL (default: api.openai.com).\n *\n * @example\n * openai.agent({ user: /Report Ingestion/ }, GATEWAY)\n */\n agent(filter?: OpenAIResponsesFilter, url?: string): InterceptTrigger {\n return {\n adapter: 'openai',\n method: 'POST',\n url: url ?? OPENAI_RESPONSES_URL,\n match: filter ? (body: unknown) => matchesResponsesFilter(body, filter) : undefined,\n wrap: buildResponsesReply,\n };\n },\n\n /**\n * Response: wrap data in Chat Completions format.\n *\n * @example\n * openai.reply({ categories: ['TECH'] })\n */\n reply: buildChatReply,\n\n /** Response: return an OpenAI error. */\n error(status: number, message?: string): InterceptResponse {\n return {\n status,\n body: {\n error: {\n message: message ?? `OpenAI error (${status})`,\n type: status === 429 ? 'rate_limit_error' : 'api_error',\n code: status === 429 ? 'rate_limit_exceeded' : null,\n },\n },\n };\n },\n\n /** Response: return malformed content. */\n malformed(content: string): InterceptResponse {\n return buildChatReply(content);\n },\n\n /** Response: simulate a timeout. */\n timeout(): InterceptResponse {\n return { status: 200, body: {}, delay: 30_000 };\n },\n\n // ── Legacy aliases ──\n\n /** @deprecated Use openai.request() instead. */\n chat(filter?: OpenAIChatFilter): InterceptTrigger {\n return openai.request(filter);\n },\n\n /** @deprecated Use openai.reply() instead. */\n response: buildChatReply,\n\n /** @deprecated Use openai.agent() instead. */\n responses(filter?: OpenAIResponsesFilter, url?: string): InterceptTrigger {\n return openai.agent(filter, url);\n },\n\n /** @deprecated Use openai.reply() or .intercept(trigger, 'file.json') instead. */\n responsesResponse: buildResponsesReply,\n};\n"],"mappings":"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"}
|
package/dist/intercept.d.cts
CHANGED
|
@@ -2,26 +2,29 @@ import { n as InterceptResponse, r as InterceptTrigger, t as InterceptEntry } fr
|
|
|
2
2
|
|
|
3
3
|
//#region src/builder/common/intercept/adapters/anthropic.d.ts
|
|
4
4
|
interface AnthropicMessagesFilter {
|
|
5
|
-
/** Match by model name. */
|
|
6
5
|
model?: RegExp | string;
|
|
7
|
-
/** Match by system message content. */
|
|
8
6
|
system?: RegExp | string;
|
|
9
|
-
/** Match by user message content. */
|
|
10
7
|
user?: RegExp | string;
|
|
11
|
-
/** Match by tool names. */
|
|
12
8
|
tools?: string[];
|
|
13
9
|
}
|
|
10
|
+
declare function buildReply(data: unknown): InterceptResponse;
|
|
14
11
|
/**
|
|
15
12
|
* Anthropic API intercept helpers.
|
|
16
13
|
*/
|
|
17
14
|
declare const anthropic: {
|
|
18
15
|
/**
|
|
19
16
|
* Trigger: match Anthropic messages API requests.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* anthropic.request()
|
|
20
|
+
* anthropic.request({ system: /classify/ })
|
|
20
21
|
*/
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
request(filter?: AnthropicMessagesFilter): InterceptTrigger; /** Response: wrap data in Anthropic messages format. */
|
|
23
|
+
reply: typeof buildReply; /** Response: return an Anthropic error. */
|
|
23
24
|
error(status: number, message?: string): InterceptResponse; /** Response: simulate a timeout. */
|
|
24
|
-
timeout(): InterceptResponse;
|
|
25
|
+
timeout(): InterceptResponse; /** @deprecated Use anthropic.request() instead. */
|
|
26
|
+
messages(filter?: AnthropicMessagesFilter): InterceptTrigger; /** @deprecated Use anthropic.reply() instead. */
|
|
27
|
+
response: typeof buildReply;
|
|
25
28
|
};
|
|
26
29
|
//#endregion
|
|
27
30
|
//#region src/builder/common/intercept/adapters/http.d.ts
|
|
@@ -29,14 +32,13 @@ declare const anthropic: {
|
|
|
29
32
|
* Generic HTTP intercept helpers for any URL.
|
|
30
33
|
*
|
|
31
34
|
* @example
|
|
32
|
-
* .intercept(http.get('https://api.example.com/data'), 'response.json')
|
|
33
|
-
* .intercept(http.post('https://api.stripe.com/v1/charges'), http.json({ id: 'ch_...' }))
|
|
35
|
+
* .intercept(http.get('https://api.example.com/data'), 'http/response.json')
|
|
34
36
|
*/
|
|
35
37
|
declare const http: {
|
|
36
|
-
|
|
37
|
-
post(url: RegExp | string): InterceptTrigger;
|
|
38
|
-
put(url: RegExp | string): InterceptTrigger;
|
|
39
|
-
delete(url: RegExp | string): InterceptTrigger;
|
|
38
|
+
get(url: RegExp | string): InterceptTrigger;
|
|
39
|
+
post(url: RegExp | string): InterceptTrigger;
|
|
40
|
+
put(url: RegExp | string): InterceptTrigger;
|
|
41
|
+
delete(url: RegExp | string): InterceptTrigger;
|
|
40
42
|
any(url: RegExp | string): InterceptTrigger; /** Response: simple JSON success. */
|
|
41
43
|
json(data: unknown, status?: number): InterceptResponse; /** Response: error with message. */
|
|
42
44
|
error(status: number, message?: string): InterceptResponse;
|
package/dist/intercept.d.ts
CHANGED
|
@@ -2,26 +2,29 @@ import { n as InterceptResponse, r as InterceptTrigger, t as InterceptEntry } fr
|
|
|
2
2
|
|
|
3
3
|
//#region src/builder/common/intercept/adapters/anthropic.d.ts
|
|
4
4
|
interface AnthropicMessagesFilter {
|
|
5
|
-
/** Match by model name. */
|
|
6
5
|
model?: RegExp | string;
|
|
7
|
-
/** Match by system message content. */
|
|
8
6
|
system?: RegExp | string;
|
|
9
|
-
/** Match by user message content. */
|
|
10
7
|
user?: RegExp | string;
|
|
11
|
-
/** Match by tool names. */
|
|
12
8
|
tools?: string[];
|
|
13
9
|
}
|
|
10
|
+
declare function buildReply(data: unknown): InterceptResponse;
|
|
14
11
|
/**
|
|
15
12
|
* Anthropic API intercept helpers.
|
|
16
13
|
*/
|
|
17
14
|
declare const anthropic: {
|
|
18
15
|
/**
|
|
19
16
|
* Trigger: match Anthropic messages API requests.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* anthropic.request()
|
|
20
|
+
* anthropic.request({ system: /classify/ })
|
|
20
21
|
*/
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
request(filter?: AnthropicMessagesFilter): InterceptTrigger; /** Response: wrap data in Anthropic messages format. */
|
|
23
|
+
reply: typeof buildReply; /** Response: return an Anthropic error. */
|
|
23
24
|
error(status: number, message?: string): InterceptResponse; /** Response: simulate a timeout. */
|
|
24
|
-
timeout(): InterceptResponse;
|
|
25
|
+
timeout(): InterceptResponse; /** @deprecated Use anthropic.request() instead. */
|
|
26
|
+
messages(filter?: AnthropicMessagesFilter): InterceptTrigger; /** @deprecated Use anthropic.reply() instead. */
|
|
27
|
+
response: typeof buildReply;
|
|
25
28
|
};
|
|
26
29
|
//#endregion
|
|
27
30
|
//#region src/builder/common/intercept/adapters/http.d.ts
|
|
@@ -29,14 +32,13 @@ declare const anthropic: {
|
|
|
29
32
|
* Generic HTTP intercept helpers for any URL.
|
|
30
33
|
*
|
|
31
34
|
* @example
|
|
32
|
-
* .intercept(http.get('https://api.example.com/data'), 'response.json')
|
|
33
|
-
* .intercept(http.post('https://api.stripe.com/v1/charges'), http.json({ id: 'ch_...' }))
|
|
35
|
+
* .intercept(http.get('https://api.example.com/data'), 'http/response.json')
|
|
34
36
|
*/
|
|
35
37
|
declare const http: {
|
|
36
|
-
|
|
37
|
-
post(url: RegExp | string): InterceptTrigger;
|
|
38
|
-
put(url: RegExp | string): InterceptTrigger;
|
|
39
|
-
delete(url: RegExp | string): InterceptTrigger;
|
|
38
|
+
get(url: RegExp | string): InterceptTrigger;
|
|
39
|
+
post(url: RegExp | string): InterceptTrigger;
|
|
40
|
+
put(url: RegExp | string): InterceptTrigger;
|
|
41
|
+
delete(url: RegExp | string): InterceptTrigger;
|
|
40
42
|
any(url: RegExp | string): InterceptTrigger; /** Response: simple JSON success. */
|
|
41
43
|
json(data: unknown, status?: number): InterceptResponse; /** Response: error with message. */
|
|
42
44
|
error(status: number, message?: string): InterceptResponse;
|
package/dist/intercept.js
CHANGED
|
@@ -18,42 +18,45 @@ function matchesFilter(body, filter) {
|
|
|
18
18
|
if (filter.user instanceof RegExp && !filter.user.test(text)) return false;
|
|
19
19
|
}
|
|
20
20
|
if (filter.tools) {
|
|
21
|
-
const
|
|
22
|
-
if (!filter.tools.every((t) =>
|
|
21
|
+
const names = body?.tools?.map((t) => t.name).filter(Boolean) ?? [];
|
|
22
|
+
if (!filter.tools.every((t) => names.includes(t))) return false;
|
|
23
23
|
}
|
|
24
24
|
return true;
|
|
25
25
|
}
|
|
26
|
+
function buildReply(data) {
|
|
27
|
+
return {
|
|
28
|
+
status: 200,
|
|
29
|
+
body: {
|
|
30
|
+
id: "msg-test",
|
|
31
|
+
type: "message",
|
|
32
|
+
role: "assistant",
|
|
33
|
+
content: [{
|
|
34
|
+
type: "text",
|
|
35
|
+
text: typeof data === "string" ? data : JSON.stringify(data)
|
|
36
|
+
}],
|
|
37
|
+
model: "claude-sonnet-4-20250514",
|
|
38
|
+
stop_reason: "end_turn",
|
|
39
|
+
usage: {
|
|
40
|
+
input_tokens: 10,
|
|
41
|
+
output_tokens: 10
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
26
46
|
/**
|
|
27
47
|
* Anthropic API intercept helpers.
|
|
28
48
|
*/
|
|
29
49
|
const anthropic = {
|
|
30
|
-
|
|
50
|
+
request(filter) {
|
|
31
51
|
return {
|
|
52
|
+
adapter: "anthropic",
|
|
32
53
|
method: "POST",
|
|
33
54
|
url: ANTHROPIC_MESSAGES_URL,
|
|
34
|
-
match: filter ? (body) => matchesFilter(body, filter) : void 0
|
|
35
|
-
|
|
36
|
-
},
|
|
37
|
-
response(data) {
|
|
38
|
-
return {
|
|
39
|
-
status: 200,
|
|
40
|
-
body: {
|
|
41
|
-
id: "msg-test",
|
|
42
|
-
type: "message",
|
|
43
|
-
role: "assistant",
|
|
44
|
-
content: [{
|
|
45
|
-
type: "text",
|
|
46
|
-
text: typeof data === "string" ? data : JSON.stringify(data)
|
|
47
|
-
}],
|
|
48
|
-
model: "claude-sonnet-4-20250514",
|
|
49
|
-
stop_reason: "end_turn",
|
|
50
|
-
usage: {
|
|
51
|
-
input_tokens: 10,
|
|
52
|
-
output_tokens: 10
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
+
match: filter ? (body) => matchesFilter(body, filter) : void 0,
|
|
56
|
+
wrap: buildReply
|
|
55
57
|
};
|
|
56
58
|
},
|
|
59
|
+
reply: buildReply,
|
|
57
60
|
error(status, message) {
|
|
58
61
|
return {
|
|
59
62
|
status,
|
|
@@ -72,11 +75,14 @@ const anthropic = {
|
|
|
72
75
|
body: {},
|
|
73
76
|
delay: 3e4
|
|
74
77
|
};
|
|
75
|
-
}
|
|
78
|
+
},
|
|
79
|
+
messages(filter) {
|
|
80
|
+
return anthropic.request(filter);
|
|
81
|
+
},
|
|
82
|
+
response: buildReply
|
|
76
83
|
};
|
|
77
84
|
//#endregion
|
|
78
85
|
//#region src/builder/common/intercept/adapters/http.ts
|
|
79
|
-
/** Default wrap: raw JSON data becomes the response body. */
|
|
80
86
|
function wrapJson(data) {
|
|
81
87
|
return {
|
|
82
88
|
status: 200,
|
|
@@ -87,12 +93,12 @@ function wrapJson(data) {
|
|
|
87
93
|
* Generic HTTP intercept helpers for any URL.
|
|
88
94
|
*
|
|
89
95
|
* @example
|
|
90
|
-
* .intercept(http.get('https://api.example.com/data'), 'response.json')
|
|
91
|
-
* .intercept(http.post('https://api.stripe.com/v1/charges'), http.json({ id: 'ch_...' }))
|
|
96
|
+
* .intercept(http.get('https://api.example.com/data'), 'http/response.json')
|
|
92
97
|
*/
|
|
93
98
|
const http = {
|
|
94
99
|
get(url) {
|
|
95
100
|
return {
|
|
101
|
+
adapter: "http",
|
|
96
102
|
method: "GET",
|
|
97
103
|
url,
|
|
98
104
|
wrap: wrapJson
|
|
@@ -100,6 +106,7 @@ const http = {
|
|
|
100
106
|
},
|
|
101
107
|
post(url) {
|
|
102
108
|
return {
|
|
109
|
+
adapter: "http",
|
|
103
110
|
method: "POST",
|
|
104
111
|
url,
|
|
105
112
|
wrap: wrapJson
|
|
@@ -107,6 +114,7 @@ const http = {
|
|
|
107
114
|
},
|
|
108
115
|
put(url) {
|
|
109
116
|
return {
|
|
117
|
+
adapter: "http",
|
|
110
118
|
method: "PUT",
|
|
111
119
|
url,
|
|
112
120
|
wrap: wrapJson
|
|
@@ -114,6 +122,7 @@ const http = {
|
|
|
114
122
|
},
|
|
115
123
|
delete(url) {
|
|
116
124
|
return {
|
|
125
|
+
adapter: "http",
|
|
117
126
|
method: "DELETE",
|
|
118
127
|
url,
|
|
119
128
|
wrap: wrapJson
|
|
@@ -121,6 +130,7 @@ const http = {
|
|
|
121
130
|
},
|
|
122
131
|
any(url) {
|
|
123
132
|
return {
|
|
133
|
+
adapter: "http",
|
|
124
134
|
method: "*",
|
|
125
135
|
url,
|
|
126
136
|
wrap: wrapJson
|
|
@@ -248,6 +258,7 @@ function buildResponsesReply(data) {
|
|
|
248
258
|
const openai = {
|
|
249
259
|
request(filter) {
|
|
250
260
|
return {
|
|
261
|
+
adapter: "openai",
|
|
251
262
|
method: "POST",
|
|
252
263
|
url: OPENAI_CHAT_URL,
|
|
253
264
|
match: filter ? (body) => matchesChatFilter(body, filter) : void 0,
|
|
@@ -256,6 +267,7 @@ const openai = {
|
|
|
256
267
|
},
|
|
257
268
|
agent(filter, url) {
|
|
258
269
|
return {
|
|
270
|
+
adapter: "openai",
|
|
259
271
|
method: "POST",
|
|
260
272
|
url: url ?? OPENAI_RESPONSES_URL,
|
|
261
273
|
match: filter ? (body) => matchesResponsesFilter(body, filter) : void 0,
|
package/dist/intercept.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intercept.js","names":[],"sources":["../src/builder/common/intercept/adapters/anthropic.ts","../src/builder/common/intercept/adapters/http.ts","../src/builder/common/intercept/adapters/openai.ts"],"sourcesContent":["import type { InterceptResponse, InterceptTrigger } from '../types.js';\n\nconst ANTHROPIC_MESSAGES_URL = 'https://api.anthropic.com/v1/messages';\n\nexport interface AnthropicMessagesFilter {\n /** Match by model name. */\n model?: RegExp | string;\n /** Match by system message content. */\n system?: RegExp | string;\n /** Match by user message content. */\n user?: RegExp | string;\n /** Match by tool names. */\n tools?: string[];\n}\n\nfunction matchesFilter(body: any, filter: AnthropicMessagesFilter): boolean {\n if (filter.model) {\n const model = body?.model;\n if (typeof filter.model === 'string' && model !== filter.model) {\n return false;\n }\n if (filter.model instanceof RegExp && !filter.model.test(model ?? '')) {\n return false;\n }\n }\n\n if (filter.system) {\n const system = typeof body?.system === 'string' ? body.system : '';\n if (typeof filter.system === 'string' && !system.includes(filter.system)) {\n return false;\n }\n if (filter.system instanceof RegExp && !filter.system.test(system)) {\n return false;\n }\n }\n\n if (filter.user) {\n const userMsg = body?.messages?.find((m: any) => m.role === 'user')?.content ?? '';\n const text = typeof userMsg === 'string' ? userMsg : JSON.stringify(userMsg);\n if (typeof filter.user === 'string' && !text.includes(filter.user)) {\n return false;\n }\n if (filter.user instanceof RegExp && !filter.user.test(text)) {\n return false;\n }\n }\n\n if (filter.tools) {\n const requestTools = body?.tools?.map((t: any) => t.name).filter(Boolean) ?? [];\n if (!filter.tools.every((t) => requestTools.includes(t))) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Anthropic API intercept helpers.\n */\nexport const anthropic = {\n /**\n * Trigger: match Anthropic messages API requests.\n */\n messages(filter?: AnthropicMessagesFilter): InterceptTrigger {\n return {\n method: 'POST',\n url: ANTHROPIC_MESSAGES_URL,\n match: filter ? (body: unknown) => matchesFilter(body, filter) : undefined,\n };\n },\n\n /** Response: wrap data in Anthropic messages format. */\n response(data: unknown): InterceptResponse {\n const content = typeof data === 'string' ? data : JSON.stringify(data);\n return {\n status: 200,\n body: {\n id: 'msg-test',\n type: 'message',\n role: 'assistant',\n content: [{ type: 'text', text: content }],\n model: 'claude-sonnet-4-20250514',\n stop_reason: 'end_turn',\n usage: { input_tokens: 10, output_tokens: 10 },\n },\n };\n },\n\n /** Response: return an Anthropic error. */\n error(status: number, message?: string): InterceptResponse {\n return {\n status,\n body: {\n type: 'error',\n error: {\n type: status === 429 ? 'rate_limit_error' : 'api_error',\n message: message ?? `Anthropic error (${status})`,\n },\n },\n };\n },\n\n /** Response: simulate a timeout. */\n timeout(): InterceptResponse {\n return { status: 200, body: {}, delay: 30_000 };\n },\n};\n","import type { InterceptResponse, InterceptTrigger } from '../types.js';\n\n/** Default wrap: raw JSON data becomes the response body. */\nfunction wrapJson(data: unknown): InterceptResponse {\n return { status: 200, body: data };\n}\n\n/**\n * Generic HTTP intercept helpers for any URL.\n *\n * @example\n * .intercept(http.get('https://api.example.com/data'), 'response.json')\n * .intercept(http.post('https://api.stripe.com/v1/charges'), http.json({ id: 'ch_...' }))\n */\nexport const http = {\n /** Trigger: match GET requests to a URL pattern. */\n get(url: RegExp | string): InterceptTrigger {\n return { method: 'GET', url, wrap: wrapJson };\n },\n\n /** Trigger: match POST requests to a URL pattern. */\n post(url: RegExp | string): InterceptTrigger {\n return { method: 'POST', url, wrap: wrapJson };\n },\n\n /** Trigger: match PUT requests to a URL pattern. */\n put(url: RegExp | string): InterceptTrigger {\n return { method: 'PUT', url, wrap: wrapJson };\n },\n\n /** Trigger: match DELETE requests to a URL pattern. */\n delete(url: RegExp | string): InterceptTrigger {\n return { method: 'DELETE', url, wrap: wrapJson };\n },\n\n /** Trigger: match any method to a URL pattern. */\n any(url: RegExp | string): InterceptTrigger {\n return { method: '*', url, wrap: wrapJson };\n },\n\n /** Response: simple JSON success. */\n json(data: unknown, status = 200): InterceptResponse {\n return { status, body: data };\n },\n\n /** Response: error with message. */\n error(status: number, message?: string): InterceptResponse {\n return { status, body: { error: message ?? `HTTP ${status}` } };\n },\n};\n","import type { InterceptResponse, InterceptTrigger } from '../types.js';\n\nconst OPENAI_CHAT_URL = 'https://api.openai.com/v1/chat/completions';\nconst OPENAI_RESPONSES_URL = 'https://api.openai.com/v1/responses';\n\n// ── Chat Completions filters ──\n\nexport interface OpenAIChatFilter {\n model?: RegExp | string;\n system?: RegExp | string;\n user?: RegExp | string;\n tools?: string[];\n temperature?: number;\n}\n\nfunction matchesChatFilter(body: any, filter: OpenAIChatFilter): boolean {\n if (filter.model) {\n const model = body?.model;\n if (typeof filter.model === 'string' && model !== filter.model) {\n return false;\n }\n if (filter.model instanceof RegExp && !filter.model.test(model ?? '')) {\n return false;\n }\n }\n if (filter.system) {\n const msg = body?.messages?.find((m: any) => m.role === 'system')?.content ?? '';\n if (typeof filter.system === 'string' && !msg.includes(filter.system)) {\n return false;\n }\n if (filter.system instanceof RegExp && !filter.system.test(msg)) {\n return false;\n }\n }\n if (filter.user) {\n const msg = body?.messages?.find((m: any) => m.role === 'user')?.content ?? '';\n if (typeof filter.user === 'string' && !msg.includes(filter.user)) {\n return false;\n }\n if (filter.user instanceof RegExp && !filter.user.test(msg)) {\n return false;\n }\n }\n if (filter.tools) {\n const names = body?.tools?.map((t: any) => t.function?.name).filter(Boolean) ?? [];\n if (!filter.tools.every((t) => names.includes(t))) {\n return false;\n }\n }\n if (filter.temperature !== undefined && body?.temperature !== filter.temperature) {\n return false;\n }\n return true;\n}\n\n// ── Responses API filters ──\n\nexport interface OpenAIResponsesFilter {\n model?: RegExp | string;\n system?: RegExp | string;\n user?: RegExp | string;\n tools?: string[];\n}\n\nfunction matchesResponsesFilter(body: any, filter: OpenAIResponsesFilter): boolean {\n if (filter.model) {\n const model = body?.model;\n if (typeof filter.model === 'string' && model !== filter.model) {\n return false;\n }\n if (filter.model instanceof RegExp && !filter.model.test(model ?? '')) {\n return false;\n }\n }\n if (filter.system) {\n const instructions = body?.instructions ?? '';\n const systemInput = body?.input?.find?.((m: any) => m.role === 'system')?.content ?? '';\n const text = instructions || systemInput;\n if (typeof filter.system === 'string' && !text.includes(filter.system)) {\n return false;\n }\n if (filter.system instanceof RegExp && !filter.system.test(text)) {\n return false;\n }\n }\n if (filter.user) {\n const msgs = (body?.input ?? [])\n .filter((m: any) => m.role === 'user')\n .map((m: any) =>\n typeof m.content === 'string' ? m.content : JSON.stringify(m.content),\n )\n .join(' ');\n if (typeof filter.user === 'string' && !msgs.includes(filter.user)) {\n return false;\n }\n if (filter.user instanceof RegExp && !filter.user.test(msgs)) {\n return false;\n }\n }\n if (filter.tools) {\n const names =\n body?.tools?.map((t: any) => t.name ?? t.function?.name).filter(Boolean) ?? [];\n if (!filter.tools.every((t) => names.includes(t))) {\n return false;\n }\n }\n return true;\n}\n\n// ── Response builders ──\n\nfunction buildChatReply(data: unknown): InterceptResponse {\n const content = typeof data === 'string' ? data : JSON.stringify(data);\n return {\n status: 200,\n body: {\n id: 'chatcmpl-test',\n object: 'chat.completion',\n created: Math.floor(Date.now() / 1000),\n model: 'gpt-4o-test',\n choices: [{ index: 0, message: { role: 'assistant', content }, finish_reason: 'stop' }],\n usage: { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n },\n };\n}\n\nfunction buildResponsesReply(data: unknown): InterceptResponse {\n const text = typeof data === 'string' ? data : JSON.stringify(data);\n return {\n status: 200,\n body: {\n id: 'resp-test',\n object: 'response',\n created_at: Math.floor(Date.now() / 1000),\n model: 'gpt-4o-test',\n output: [\n {\n type: 'message',\n id: 'msg-test',\n role: 'assistant',\n content: [{ type: 'output_text', text, annotations: [] }],\n },\n ],\n usage: { input_tokens: 10, output_tokens: 10, total_tokens: 20 },\n },\n };\n}\n\n// ── Public API ──\n\n/**\n * OpenAI API intercept helpers.\n */\nexport const openai = {\n /**\n * Trigger: match Chat Completions API requests.\n *\n * @example\n * openai.request() // any chat call\n * openai.request({ model: 'gpt-4o' }) // specific model\n * openai.request({ system: /classify/ }) // system prompt match\n */\n request(filter?: OpenAIChatFilter): InterceptTrigger {\n return {\n method: 'POST',\n url: OPENAI_CHAT_URL,\n match: filter ? (body: unknown) => matchesChatFilter(body, filter) : undefined,\n wrap: buildChatReply,\n };\n },\n\n /**\n * Trigger: match Responses API requests (AI SDK v5+) with auto-wrapping.\n * When used with a JSON file, the data is automatically wrapped in the\n * Responses API envelope.\n *\n * @param filter - Optional body filters.\n * @param url - Custom gateway URL (default: api.openai.com).\n *\n * @example\n * openai.agent({ user: /Report Ingestion/ }, GATEWAY)\n */\n agent(filter?: OpenAIResponsesFilter, url?: string): InterceptTrigger {\n return {\n method: 'POST',\n url: url ?? OPENAI_RESPONSES_URL,\n match: filter ? (body: unknown) => matchesResponsesFilter(body, filter) : undefined,\n wrap: buildResponsesReply,\n };\n },\n\n /**\n * Response: wrap data in Chat Completions format.\n *\n * @example\n * openai.reply({ categories: ['TECH'] })\n */\n reply: buildChatReply,\n\n /** Response: return an OpenAI error. */\n error(status: number, message?: string): InterceptResponse {\n return {\n status,\n body: {\n error: {\n message: message ?? `OpenAI error (${status})`,\n type: status === 429 ? 'rate_limit_error' : 'api_error',\n code: status === 429 ? 'rate_limit_exceeded' : null,\n },\n },\n };\n },\n\n /** Response: return malformed content. */\n malformed(content: string): InterceptResponse {\n return buildChatReply(content);\n },\n\n /** Response: simulate a timeout. */\n timeout(): InterceptResponse {\n return { status: 200, body: {}, delay: 30_000 };\n },\n\n // ── Legacy aliases ──\n\n /** @deprecated Use openai.request() instead. */\n chat(filter?: OpenAIChatFilter): InterceptTrigger {\n return openai.request(filter);\n },\n\n /** @deprecated Use openai.reply() instead. */\n response: buildChatReply,\n\n /** @deprecated Use openai.agent() instead. */\n responses(filter?: OpenAIResponsesFilter, url?: string): InterceptTrigger {\n return openai.agent(filter, url);\n },\n\n /** @deprecated Use openai.reply() or .intercept(trigger, 'file.json') instead. */\n responsesResponse: buildResponsesReply,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"intercept.js","names":[],"sources":["../src/builder/common/intercept/adapters/anthropic.ts","../src/builder/common/intercept/adapters/http.ts","../src/builder/common/intercept/adapters/openai.ts"],"sourcesContent":["import type { InterceptResponse, InterceptTrigger } from '../types.js';\n\nconst ANTHROPIC_MESSAGES_URL = 'https://api.anthropic.com/v1/messages';\n\nexport interface AnthropicMessagesFilter {\n model?: RegExp | string;\n system?: RegExp | string;\n user?: RegExp | string;\n tools?: string[];\n}\n\nfunction matchesFilter(body: any, filter: AnthropicMessagesFilter): boolean {\n if (filter.model) {\n const model = body?.model;\n if (typeof filter.model === 'string' && model !== filter.model) {\n return false;\n }\n if (filter.model instanceof RegExp && !filter.model.test(model ?? '')) {\n return false;\n }\n }\n if (filter.system) {\n const system = typeof body?.system === 'string' ? body.system : '';\n if (typeof filter.system === 'string' && !system.includes(filter.system)) {\n return false;\n }\n if (filter.system instanceof RegExp && !filter.system.test(system)) {\n return false;\n }\n }\n if (filter.user) {\n const userMsg = body?.messages?.find((m: any) => m.role === 'user')?.content ?? '';\n const text = typeof userMsg === 'string' ? userMsg : JSON.stringify(userMsg);\n if (typeof filter.user === 'string' && !text.includes(filter.user)) {\n return false;\n }\n if (filter.user instanceof RegExp && !filter.user.test(text)) {\n return false;\n }\n }\n if (filter.tools) {\n const names = body?.tools?.map((t: any) => t.name).filter(Boolean) ?? [];\n if (!filter.tools.every((t) => names.includes(t))) {\n return false;\n }\n }\n return true;\n}\n\nfunction buildReply(data: unknown): InterceptResponse {\n const content = typeof data === 'string' ? data : JSON.stringify(data);\n return {\n status: 200,\n body: {\n id: 'msg-test',\n type: 'message',\n role: 'assistant',\n content: [{ type: 'text', text: content }],\n model: 'claude-sonnet-4-20250514',\n stop_reason: 'end_turn',\n usage: { input_tokens: 10, output_tokens: 10 },\n },\n };\n}\n\n/**\n * Anthropic API intercept helpers.\n */\nexport const anthropic = {\n /**\n * Trigger: match Anthropic messages API requests.\n *\n * @example\n * anthropic.request()\n * anthropic.request({ system: /classify/ })\n */\n request(filter?: AnthropicMessagesFilter): InterceptTrigger {\n return {\n adapter: 'anthropic',\n method: 'POST',\n url: ANTHROPIC_MESSAGES_URL,\n match: filter ? (body: unknown) => matchesFilter(body, filter) : undefined,\n wrap: buildReply,\n };\n },\n\n /** Response: wrap data in Anthropic messages format. */\n reply: buildReply,\n\n /** Response: return an Anthropic error. */\n error(status: number, message?: string): InterceptResponse {\n return {\n status,\n body: {\n type: 'error',\n error: {\n type: status === 429 ? 'rate_limit_error' : 'api_error',\n message: message ?? `Anthropic error (${status})`,\n },\n },\n };\n },\n\n /** Response: simulate a timeout. */\n timeout(): InterceptResponse {\n return { status: 200, body: {}, delay: 30_000 };\n },\n\n // Legacy aliases\n /** @deprecated Use anthropic.request() instead. */\n messages(filter?: AnthropicMessagesFilter): InterceptTrigger {\n return anthropic.request(filter);\n },\n /** @deprecated Use anthropic.reply() instead. */\n response: buildReply,\n};\n","import type { InterceptResponse, InterceptTrigger } from '../types.js';\n\nfunction wrapJson(data: unknown): InterceptResponse {\n return { status: 200, body: data };\n}\n\n/**\n * Generic HTTP intercept helpers for any URL.\n *\n * @example\n * .intercept(http.get('https://api.example.com/data'), 'http/response.json')\n */\nexport const http = {\n get(url: RegExp | string): InterceptTrigger {\n return { adapter: 'http', method: 'GET', url, wrap: wrapJson };\n },\n\n post(url: RegExp | string): InterceptTrigger {\n return { adapter: 'http', method: 'POST', url, wrap: wrapJson };\n },\n\n put(url: RegExp | string): InterceptTrigger {\n return { adapter: 'http', method: 'PUT', url, wrap: wrapJson };\n },\n\n delete(url: RegExp | string): InterceptTrigger {\n return { adapter: 'http', method: 'DELETE', url, wrap: wrapJson };\n },\n\n any(url: RegExp | string): InterceptTrigger {\n return { adapter: 'http', method: '*', url, wrap: wrapJson };\n },\n\n /** Response: simple JSON success. */\n json(data: unknown, status = 200): InterceptResponse {\n return { status, body: data };\n },\n\n /** Response: error with message. */\n error(status: number, message?: string): InterceptResponse {\n return { status, body: { error: message ?? `HTTP ${status}` } };\n },\n};\n","import type { InterceptResponse, InterceptTrigger } from '../types.js';\n\nconst OPENAI_CHAT_URL = 'https://api.openai.com/v1/chat/completions';\nconst OPENAI_RESPONSES_URL = 'https://api.openai.com/v1/responses';\n\n// ── Chat Completions filters ──\n\nexport interface OpenAIChatFilter {\n model?: RegExp | string;\n system?: RegExp | string;\n user?: RegExp | string;\n tools?: string[];\n temperature?: number;\n}\n\nfunction matchesChatFilter(body: any, filter: OpenAIChatFilter): boolean {\n if (filter.model) {\n const model = body?.model;\n if (typeof filter.model === 'string' && model !== filter.model) {\n return false;\n }\n if (filter.model instanceof RegExp && !filter.model.test(model ?? '')) {\n return false;\n }\n }\n if (filter.system) {\n const msg = body?.messages?.find((m: any) => m.role === 'system')?.content ?? '';\n if (typeof filter.system === 'string' && !msg.includes(filter.system)) {\n return false;\n }\n if (filter.system instanceof RegExp && !filter.system.test(msg)) {\n return false;\n }\n }\n if (filter.user) {\n const msg = body?.messages?.find((m: any) => m.role === 'user')?.content ?? '';\n if (typeof filter.user === 'string' && !msg.includes(filter.user)) {\n return false;\n }\n if (filter.user instanceof RegExp && !filter.user.test(msg)) {\n return false;\n }\n }\n if (filter.tools) {\n const names = body?.tools?.map((t: any) => t.function?.name).filter(Boolean) ?? [];\n if (!filter.tools.every((t) => names.includes(t))) {\n return false;\n }\n }\n if (filter.temperature !== undefined && body?.temperature !== filter.temperature) {\n return false;\n }\n return true;\n}\n\n// ── Responses API filters ──\n\nexport interface OpenAIResponsesFilter {\n model?: RegExp | string;\n system?: RegExp | string;\n user?: RegExp | string;\n tools?: string[];\n}\n\nfunction matchesResponsesFilter(body: any, filter: OpenAIResponsesFilter): boolean {\n if (filter.model) {\n const model = body?.model;\n if (typeof filter.model === 'string' && model !== filter.model) {\n return false;\n }\n if (filter.model instanceof RegExp && !filter.model.test(model ?? '')) {\n return false;\n }\n }\n if (filter.system) {\n const instructions = body?.instructions ?? '';\n const systemInput = body?.input?.find?.((m: any) => m.role === 'system')?.content ?? '';\n const text = instructions || systemInput;\n if (typeof filter.system === 'string' && !text.includes(filter.system)) {\n return false;\n }\n if (filter.system instanceof RegExp && !filter.system.test(text)) {\n return false;\n }\n }\n if (filter.user) {\n const msgs = (body?.input ?? [])\n .filter((m: any) => m.role === 'user')\n .map((m: any) =>\n typeof m.content === 'string' ? m.content : JSON.stringify(m.content),\n )\n .join(' ');\n if (typeof filter.user === 'string' && !msgs.includes(filter.user)) {\n return false;\n }\n if (filter.user instanceof RegExp && !filter.user.test(msgs)) {\n return false;\n }\n }\n if (filter.tools) {\n const names =\n body?.tools?.map((t: any) => t.name ?? t.function?.name).filter(Boolean) ?? [];\n if (!filter.tools.every((t) => names.includes(t))) {\n return false;\n }\n }\n return true;\n}\n\n// ── Response builders ──\n\nfunction buildChatReply(data: unknown): InterceptResponse {\n const content = typeof data === 'string' ? data : JSON.stringify(data);\n return {\n status: 200,\n body: {\n id: 'chatcmpl-test',\n object: 'chat.completion',\n created: Math.floor(Date.now() / 1000),\n model: 'gpt-4o-test',\n choices: [{ index: 0, message: { role: 'assistant', content }, finish_reason: 'stop' }],\n usage: { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n },\n };\n}\n\nfunction buildResponsesReply(data: unknown): InterceptResponse {\n const text = typeof data === 'string' ? data : JSON.stringify(data);\n return {\n status: 200,\n body: {\n id: 'resp-test',\n object: 'response',\n created_at: Math.floor(Date.now() / 1000),\n model: 'gpt-4o-test',\n output: [\n {\n type: 'message',\n id: 'msg-test',\n role: 'assistant',\n content: [{ type: 'output_text', text, annotations: [] }],\n },\n ],\n usage: { input_tokens: 10, output_tokens: 10, total_tokens: 20 },\n },\n };\n}\n\n// ── Public API ──\n\n/**\n * OpenAI API intercept helpers.\n */\nexport const openai = {\n /**\n * Trigger: match Chat Completions API requests.\n *\n * @example\n * openai.request() // any chat call\n * openai.request({ model: 'gpt-4o' }) // specific model\n * openai.request({ system: /classify/ }) // system prompt match\n */\n request(filter?: OpenAIChatFilter): InterceptTrigger {\n return {\n adapter: 'openai',\n method: 'POST',\n url: OPENAI_CHAT_URL,\n match: filter ? (body: unknown) => matchesChatFilter(body, filter) : undefined,\n wrap: buildChatReply,\n };\n },\n\n /**\n * Trigger: match Responses API requests (AI SDK v5+) with auto-wrapping.\n * When used with a JSON file, the data is automatically wrapped in the\n * Responses API envelope.\n *\n * @param filter - Optional body filters.\n * @param url - Custom gateway URL (default: api.openai.com).\n *\n * @example\n * openai.agent({ user: /Report Ingestion/ }, GATEWAY)\n */\n agent(filter?: OpenAIResponsesFilter, url?: string): InterceptTrigger {\n return {\n adapter: 'openai',\n method: 'POST',\n url: url ?? OPENAI_RESPONSES_URL,\n match: filter ? (body: unknown) => matchesResponsesFilter(body, filter) : undefined,\n wrap: buildResponsesReply,\n };\n },\n\n /**\n * Response: wrap data in Chat Completions format.\n *\n * @example\n * openai.reply({ categories: ['TECH'] })\n */\n reply: buildChatReply,\n\n /** Response: return an OpenAI error. */\n error(status: number, message?: string): InterceptResponse {\n return {\n status,\n body: {\n error: {\n message: message ?? `OpenAI error (${status})`,\n type: status === 429 ? 'rate_limit_error' : 'api_error',\n code: status === 429 ? 'rate_limit_exceeded' : null,\n },\n },\n };\n },\n\n /** Response: return malformed content. */\n malformed(content: string): InterceptResponse {\n return buildChatReply(content);\n },\n\n /** Response: simulate a timeout. */\n timeout(): InterceptResponse {\n return { status: 200, body: {}, delay: 30_000 };\n },\n\n // ── Legacy aliases ──\n\n /** @deprecated Use openai.request() instead. */\n chat(filter?: OpenAIChatFilter): InterceptTrigger {\n return openai.request(filter);\n },\n\n /** @deprecated Use openai.reply() instead. */\n response: buildChatReply,\n\n /** @deprecated Use openai.agent() instead. */\n responses(filter?: OpenAIResponsesFilter, url?: string): InterceptTrigger {\n return openai.agent(filter, url);\n },\n\n /** @deprecated Use openai.reply() or .intercept(trigger, 'file.json') instead. */\n responsesResponse: buildResponsesReply,\n};\n"],"mappings":"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"}
|
package/dist/types.d.cts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* An intercept trigger describes which HTTP request to match.
|
|
4
4
|
*/
|
|
5
5
|
interface InterceptTrigger {
|
|
6
|
+
/** Adapter name - must match the folder prefix in file-based intercepts. */
|
|
7
|
+
adapter: string;
|
|
6
8
|
/** HTTP method to match. */
|
|
7
9
|
method: string;
|
|
8
10
|
/** URL pattern to match (string for exact prefix, RegExp for pattern). */
|
|
@@ -10,11 +12,10 @@ interface InterceptTrigger {
|
|
|
10
12
|
/** Optional request body matcher - the handler only fires if this returns true. */
|
|
11
13
|
match?: (body: unknown) => boolean;
|
|
12
14
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* passed through wrap() to produce the correct response envelope.
|
|
15
|
+
* Transform raw JSON data into a provider-specific response envelope.
|
|
16
|
+
* Called when .intercept(trigger, 'adapter/file.json') loads a file.
|
|
16
17
|
*/
|
|
17
|
-
wrap
|
|
18
|
+
wrap: (data: unknown) => InterceptResponse;
|
|
18
19
|
}
|
|
19
20
|
/**
|
|
20
21
|
* An intercept response describes what to return when the trigger matches.
|
package/dist/types.d.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* An intercept trigger describes which HTTP request to match.
|
|
4
4
|
*/
|
|
5
5
|
interface InterceptTrigger {
|
|
6
|
+
/** Adapter name - must match the folder prefix in file-based intercepts. */
|
|
7
|
+
adapter: string;
|
|
6
8
|
/** HTTP method to match. */
|
|
7
9
|
method: string;
|
|
8
10
|
/** URL pattern to match (string for exact prefix, RegExp for pattern). */
|
|
@@ -10,11 +12,10 @@ interface InterceptTrigger {
|
|
|
10
12
|
/** Optional request body matcher - the handler only fires if this returns true. */
|
|
11
13
|
match?: (body: unknown) => boolean;
|
|
12
14
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* passed through wrap() to produce the correct response envelope.
|
|
15
|
+
* Transform raw JSON data into a provider-specific response envelope.
|
|
16
|
+
* Called when .intercept(trigger, 'adapter/file.json') loads a file.
|
|
16
17
|
*/
|
|
17
|
-
wrap
|
|
18
|
+
wrap: (data: unknown) => InterceptResponse;
|
|
18
19
|
}
|
|
19
20
|
/**
|
|
20
21
|
* An intercept response describes what to return when the trigger matches.
|