@waitkit/core 0.1.0 → 0.2.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/README.md +49 -0
- package/dist/index.cjs +35 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +35 -8
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -26,8 +26,11 @@ regular dependency instead:
|
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
28
|
npm install @waitkit/core
|
|
29
|
+
# or
|
|
29
30
|
pnpm add @waitkit/core
|
|
31
|
+
# or
|
|
30
32
|
yarn add @waitkit/core
|
|
33
|
+
# or
|
|
31
34
|
bun add @waitkit/core
|
|
32
35
|
```
|
|
33
36
|
|
|
@@ -92,6 +95,11 @@ waitkit.restore();
|
|
|
92
95
|
|
|
93
96
|
## Error Responses
|
|
94
97
|
|
|
98
|
+
Object bodies are serialized as JSON and receive `content-type:
|
|
99
|
+
application/json` when no content type is already provided.
|
|
100
|
+
When `statusText` is omitted, Waitkit uses the runtime `Response` default for
|
|
101
|
+
the configured status.
|
|
102
|
+
|
|
95
103
|
```ts
|
|
96
104
|
setupWaitKit({
|
|
97
105
|
enabled: import.meta.env.DEV,
|
|
@@ -111,6 +119,10 @@ setupWaitKit({
|
|
|
111
119
|
|
|
112
120
|
## Timeouts
|
|
113
121
|
|
|
122
|
+
Timeout rules throw a `WaitKitTimeoutError`. If a rule also has `delay`,
|
|
123
|
+
Waitkit waits for the delay first and then waits for `timeoutMs`, so the total
|
|
124
|
+
simulated wait can be `delay + timeoutMs`.
|
|
125
|
+
|
|
114
126
|
```ts
|
|
115
127
|
setupWaitKit({
|
|
116
128
|
enabled: import.meta.env.DEV,
|
|
@@ -118,6 +130,9 @@ setupWaitKit({
|
|
|
118
130
|
});
|
|
119
131
|
```
|
|
120
132
|
|
|
133
|
+
Waitkit does not currently cancel simulated delay or timeout sleeps when a
|
|
134
|
+
request `AbortSignal` aborts.
|
|
135
|
+
|
|
121
136
|
## Controller API
|
|
122
137
|
|
|
123
138
|
`setupWaitKit` returns a controller:
|
|
@@ -142,6 +157,25 @@ setupWaitKit({
|
|
|
142
157
|
|
|
143
158
|
The first matching rule is applied.
|
|
144
159
|
|
|
160
|
+
## Rule Matching
|
|
161
|
+
|
|
162
|
+
String, `RegExp`, and predicate URL matchers receive the request's full URL
|
|
163
|
+
string, including any query string. Use a predicate matcher if you want to
|
|
164
|
+
match only part of the URL.
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
setupWaitKit({
|
|
168
|
+
rules: [
|
|
169
|
+
{
|
|
170
|
+
url: (url) => new URL(url, window.location.origin).pathname === '/api/users',
|
|
171
|
+
delay: 1000,
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
});
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
When multiple rules match a request, the first matching rule in the array wins.
|
|
178
|
+
|
|
145
179
|
## Events
|
|
146
180
|
|
|
147
181
|
```ts
|
|
@@ -153,9 +187,24 @@ setupWaitKit({
|
|
|
153
187
|
onDelayStart: (event) => console.log(event.delayMs),
|
|
154
188
|
onDelayEnd: (event) => console.log(event.delayMs),
|
|
155
189
|
onError: (event) => console.error(event.error),
|
|
190
|
+
onScenarioChange: (event) => console.log(event.scenario),
|
|
156
191
|
});
|
|
157
192
|
```
|
|
158
193
|
|
|
194
|
+
Event payloads include the original `input` and `init`, normalized `url` and
|
|
195
|
+
`method`, and match events also include the matched `rule`, active `scenario`
|
|
196
|
+
name, and resolved `delayMs`. `onError` additionally receives the simulated
|
|
197
|
+
`error`.
|
|
198
|
+
|
|
199
|
+
The request lifecycle event names are stable: `onRequest`, `onMatch`,
|
|
200
|
+
`onDelayStart`, `onDelayEnd`, and `onError`.
|
|
201
|
+
|
|
202
|
+
`onScenarioChange` runs when `setScenario()` or `resetScenario()` changes the
|
|
203
|
+
active scenario. It does not run for the initial `activeScenario` value passed
|
|
204
|
+
to `setupWaitKit`, setting the same scenario again, or resetting when no
|
|
205
|
+
scenario is active. Its payload includes `previousScenario`, `scenario`, and
|
|
206
|
+
`reason` (`setScenario` or `resetScenario`).
|
|
207
|
+
|
|
159
208
|
## Production Safety
|
|
160
209
|
|
|
161
210
|
Waitkit does not force development-only usage. Gate it explicitly with your
|
package/dist/index.cjs
CHANGED
|
@@ -106,14 +106,18 @@ function getRequestMethod(input, init) {
|
|
|
106
106
|
|
|
107
107
|
// src/response.ts
|
|
108
108
|
function createErrorResponse(errorResponse) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
109
|
+
try {
|
|
110
|
+
const status = errorResponse?.status ?? 500;
|
|
111
|
+
const headers = new Headers(errorResponse?.headers);
|
|
112
|
+
const body = serializeBody(errorResponse?.body, headers);
|
|
113
|
+
return new Response(body, {
|
|
114
|
+
status,
|
|
115
|
+
statusText: errorResponse?.statusText,
|
|
116
|
+
headers
|
|
117
|
+
});
|
|
118
|
+
} catch (error) {
|
|
119
|
+
throw createResponseError(error);
|
|
120
|
+
}
|
|
117
121
|
}
|
|
118
122
|
function serializeBody(body, headers) {
|
|
119
123
|
if (body === void 0 || body === null) {
|
|
@@ -139,6 +143,12 @@ function isFormData(body) {
|
|
|
139
143
|
function isUrlSearchParams(body) {
|
|
140
144
|
return typeof URLSearchParams !== "undefined" && body instanceof URLSearchParams;
|
|
141
145
|
}
|
|
146
|
+
function createResponseError(error) {
|
|
147
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
148
|
+
return new Error(`WaitKit failed to create simulated error response: ${reason}`, {
|
|
149
|
+
cause: error
|
|
150
|
+
});
|
|
151
|
+
}
|
|
142
152
|
|
|
143
153
|
// src/setup-wait-kit.ts
|
|
144
154
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
@@ -221,13 +231,23 @@ function setupWaitKit(options) {
|
|
|
221
231
|
if (options.scenarios?.[name] === void 0) {
|
|
222
232
|
throw new Error(`WaitKit scenario "${name}" does not exist.`);
|
|
223
233
|
}
|
|
234
|
+
if (activeScenario === name) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const previousScenario = activeScenario;
|
|
224
238
|
activeScenario = name;
|
|
239
|
+
emitScenarioChange(options, previousScenario, activeScenario, "setScenario");
|
|
225
240
|
},
|
|
226
241
|
getScenario() {
|
|
227
242
|
return activeScenario;
|
|
228
243
|
},
|
|
229
244
|
resetScenario() {
|
|
245
|
+
if (activeScenario === void 0) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const previousScenario = activeScenario;
|
|
230
249
|
activeScenario = void 0;
|
|
250
|
+
emitScenarioChange(options, previousScenario, activeScenario, "resetScenario");
|
|
231
251
|
}
|
|
232
252
|
};
|
|
233
253
|
}
|
|
@@ -302,6 +322,13 @@ function emitError(options, matchEvent, error) {
|
|
|
302
322
|
};
|
|
303
323
|
options.onError?.(errorEvent);
|
|
304
324
|
}
|
|
325
|
+
function emitScenarioChange(options, previousScenario, scenario, reason) {
|
|
326
|
+
options.onScenarioChange?.({
|
|
327
|
+
previousScenario,
|
|
328
|
+
scenario,
|
|
329
|
+
reason
|
|
330
|
+
});
|
|
331
|
+
}
|
|
305
332
|
function debug(options, message) {
|
|
306
333
|
if (options.debug === true) {
|
|
307
334
|
console.info(`[waitkit] ${message}`);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/delay.ts","../src/matcher.ts","../src/response.ts","../src/setup-wait-kit.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export class WaitKitTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WaitKitTimeoutError';\n }\n}\n","import type { DelayValue } from './types';\n\nexport function resolveDelay(delay: DelayValue | undefined): number {\n if (delay === undefined) {\n return 0;\n }\n\n if (typeof delay === 'number') {\n return delay;\n }\n\n const [min, max] = delay;\n return Math.floor(min + Math.random() * (max - min + 1));\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nexport function validateDelay(delay: DelayValue | undefined): void {\n if (delay === undefined) {\n return;\n }\n\n if (typeof delay === 'number') {\n assertNonNegativeFiniteNumber(delay, 'delay');\n return;\n }\n\n const [min, max] = delay;\n assertNonNegativeFiniteNumber(min, 'delay min');\n assertNonNegativeFiniteNumber(max, 'delay max');\n\n if (min > max) {\n throw new Error('WaitKit delay range must have min less than or equal to max.');\n }\n}\n\nexport function validateRate(rate: number | undefined, name: string): void {\n if (rate === undefined) {\n return;\n }\n\n if (!Number.isFinite(rate) || rate < 0 || rate > 1) {\n throw new Error(`WaitKit ${name} must be a number between 0 and 1.`);\n }\n}\n\nexport function validateTimeoutMs(timeoutMs: number | undefined): void {\n if (timeoutMs === undefined) {\n return;\n }\n\n assertNonNegativeFiniteNumber(timeoutMs, 'timeoutMs');\n}\n\nfunction assertNonNegativeFiniteNumber(value: number, name: string): void {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`WaitKit ${name} must be a non-negative finite number.`);\n }\n}\n","import type { WaitKitRule } from './types';\n\nexport function matchesRule(rule: WaitKitRule, url: string, method: string): boolean {\n return matchesUrl(rule.url, url) && matchesMethod(rule.method, method);\n}\n\nfunction matchesUrl(ruleUrl: WaitKitRule['url'], url: string): boolean {\n if (typeof ruleUrl === 'string') {\n return url.includes(ruleUrl);\n }\n\n if (ruleUrl instanceof RegExp) {\n return ruleUrl.test(url);\n }\n\n return ruleUrl(url);\n}\n\nfunction matchesMethod(ruleMethod: WaitKitRule['method'], method: string): boolean {\n if (ruleMethod === undefined) {\n return true;\n }\n\n const normalizedMethod = normalizeMethod(method);\n\n if (typeof ruleMethod === 'string') {\n return normalizeMethod(ruleMethod) === normalizedMethod;\n }\n\n return ruleMethod.some((item) => normalizeMethod(item) === normalizedMethod);\n}\n\nexport function normalizeMethod(method: string | undefined): string {\n return (method ?? 'GET').toUpperCase();\n}\n\nexport function getRequestUrl(input: RequestInfo | URL): string {\n if (typeof input === 'string') {\n return input;\n }\n\n if (input instanceof URL) {\n return input.toString();\n }\n\n return input.url;\n}\n\nexport function getRequestMethod(input: RequestInfo | URL, init?: RequestInit): string {\n if (init?.method !== undefined) {\n return normalizeMethod(init.method);\n }\n\n if (typeof input === 'string' || input instanceof URL) {\n return 'GET';\n }\n\n return normalizeMethod(input.method);\n}\n","import type { WaitKitErrorResponse } from './types';\n\nexport function createErrorResponse(errorResponse: WaitKitErrorResponse | undefined): Response {\n const status = errorResponse?.status ?? 500;\n const headers = new Headers(errorResponse?.headers);\n const body = serializeBody(errorResponse?.body, headers);\n\n return new Response(body, {\n status,\n statusText: errorResponse?.statusText,\n headers,\n });\n}\n\nfunction serializeBody(body: unknown, headers: Headers): BodyInit | null {\n if (body === undefined || body === null) {\n return null;\n }\n\n if (typeof body === 'string' || isBlob(body) || isFormData(body)) {\n return body;\n }\n\n if (body instanceof ArrayBuffer || ArrayBuffer.isView(body) || isUrlSearchParams(body)) {\n return body as BodyInit;\n }\n\n if (!headers.has('content-type')) {\n headers.set('content-type', 'application/json');\n }\n\n return JSON.stringify(body);\n}\n\nfunction isBlob(body: unknown): body is Blob {\n return typeof Blob !== 'undefined' && body instanceof Blob;\n}\n\nfunction isFormData(body: unknown): body is FormData {\n return typeof FormData !== 'undefined' && body instanceof FormData;\n}\n\nfunction isUrlSearchParams(body: unknown): body is URLSearchParams {\n return typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams;\n}\n","import { resolveDelay, sleep, validateDelay, validateRate, validateTimeoutMs } from './delay';\nimport { WaitKitTimeoutError } from './errors';\nimport { getRequestMethod, getRequestUrl, matchesRule } from './matcher';\nimport { createErrorResponse } from './response';\nimport type {\n WaitKitController,\n WaitKitErrorEvent,\n WaitKitMatchEvent,\n WaitKitOptions,\n WaitKitRequestEvent,\n WaitKitRule,\n} from './types';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nexport function setupWaitKit(options: WaitKitOptions): WaitKitController {\n validateRuntime();\n validateOptions(options);\n\n const originalFetch = globalThis.fetch;\n let enabled = options.enabled ?? true;\n let activeScenario = options.activeScenario;\n let restored = false;\n\n const patchedFetch: typeof fetch = async (input, init) => {\n if (!enabled) {\n return originalFetch.call(globalThis, input, init);\n }\n\n const requestEvent = createRequestEvent(input, init);\n options.onRequest?.(requestEvent);\n\n const rule = findMatchingRule(getActiveRules(), requestEvent.url, requestEvent.method);\n\n if (rule === undefined) {\n return originalFetch.call(globalThis, input, init);\n }\n\n const delayMs = resolveDelay(rule.delay);\n const matchEvent = createMatchEvent(requestEvent, rule, activeScenario, delayMs);\n options.onMatch?.(matchEvent);\n\n if (delayMs > 0) {\n options.onDelayStart?.(matchEvent);\n debug(options, `${requestEvent.method} ${requestEvent.url} delayed by ${delayMs}ms`);\n await sleep(delayMs);\n options.onDelayEnd?.(matchEvent);\n }\n\n if (shouldTrigger(rule.timeoutRate)) {\n const timeoutMs = rule.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const error = new WaitKitTimeoutError(\n `WaitKit timed out ${requestEvent.method} ${requestEvent.url} after ${timeoutMs}ms.`,\n );\n emitError(options, matchEvent, error);\n debug(options, `${requestEvent.method} ${requestEvent.url} timed out after ${timeoutMs}ms`);\n await sleep(timeoutMs);\n throw error;\n }\n\n if (shouldTrigger(rule.errorRate)) {\n const response = createErrorResponse(rule.errorResponse);\n const error = new Error(\n `WaitKit simulated ${response.status} response for ${requestEvent.method} ${requestEvent.url}.`,\n );\n emitError(options, matchEvent, error);\n debug(options, `${requestEvent.method} ${requestEvent.url} returned ${response.status}`);\n return response;\n }\n\n return originalFetch.call(globalThis, input, init);\n };\n\n globalThis.fetch = patchedFetch;\n\n function getActiveRules(): readonly WaitKitRule[] {\n if (activeScenario === undefined) {\n return options.rules ?? [];\n }\n\n return options.scenarios?.[activeScenario] ?? [];\n }\n\n return {\n enable() {\n enabled = true;\n\n if (restored) {\n globalThis.fetch = patchedFetch;\n restored = false;\n }\n },\n disable() {\n enabled = false;\n },\n restore() {\n if (globalThis.fetch === patchedFetch) {\n globalThis.fetch = originalFetch;\n }\n\n enabled = false;\n restored = true;\n },\n isEnabled() {\n return enabled;\n },\n setScenario(name: string) {\n if (options.scenarios?.[name] === undefined) {\n throw new Error(`WaitKit scenario \"${name}\" does not exist.`);\n }\n\n activeScenario = name;\n },\n getScenario() {\n return activeScenario;\n },\n resetScenario() {\n activeScenario = undefined;\n },\n };\n}\n\nfunction validateRuntime(): void {\n if (typeof globalThis.fetch !== 'function') {\n throw new Error('WaitKit requires globalThis.fetch.');\n }\n\n if (typeof Response !== 'function') {\n throw new Error('WaitKit requires globalThis.Response.');\n }\n}\n\nfunction validateOptions(options: WaitKitOptions): void {\n validateRules(options.rules ?? []);\n\n if (options.scenarios !== undefined) {\n for (const rules of Object.values(options.scenarios)) {\n validateRules(rules);\n }\n }\n\n if (\n options.activeScenario !== undefined &&\n options.scenarios?.[options.activeScenario] === undefined\n ) {\n throw new Error(`WaitKit scenario \"${options.activeScenario}\" does not exist.`);\n }\n}\n\nfunction validateRules(rules: readonly WaitKitRule[]): void {\n for (const rule of rules) {\n validateDelay(rule.delay);\n validateRate(rule.errorRate, 'errorRate');\n validateRate(rule.timeoutRate, 'timeoutRate');\n validateTimeoutMs(rule.timeoutMs);\n validateStatus(rule.errorResponse?.status);\n }\n}\n\nfunction validateStatus(status: number | undefined): void {\n if (status === undefined) {\n return;\n }\n\n if (!Number.isInteger(status) || status < 200 || status > 599) {\n throw new Error('WaitKit errorResponse.status must be an integer between 200 and 599.');\n }\n}\n\nfunction createRequestEvent(input: RequestInfo | URL, init?: RequestInit): WaitKitRequestEvent {\n return {\n input,\n init,\n url: getRequestUrl(input),\n method: getRequestMethod(input, init),\n };\n}\n\nfunction createMatchEvent(\n requestEvent: WaitKitRequestEvent,\n rule: WaitKitRule,\n scenario: string | undefined,\n delayMs: number,\n): WaitKitMatchEvent {\n return {\n ...requestEvent,\n rule,\n scenario,\n delayMs,\n };\n}\n\nfunction findMatchingRule(\n rules: readonly WaitKitRule[],\n url: string,\n method: string,\n): WaitKitRule | undefined {\n return rules.find((rule) => matchesRule(rule, url, method));\n}\n\nfunction shouldTrigger(rate: number | undefined): boolean {\n if (rate === undefined || rate <= 0) {\n return false;\n }\n\n if (rate >= 1) {\n return true;\n }\n\n return Math.random() < rate;\n}\n\nfunction emitError(options: WaitKitOptions, matchEvent: WaitKitMatchEvent, error: Error): void {\n const errorEvent: WaitKitErrorEvent = {\n ...matchEvent,\n error,\n };\n\n options.onError?.(errorEvent);\n}\n\nfunction debug(options: WaitKitOptions, message: string): void {\n if (options.debug === true) {\n console.info(`[waitkit] ${message}`);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/delay.ts","../src/matcher.ts","../src/response.ts","../src/setup-wait-kit.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export class WaitKitTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WaitKitTimeoutError';\n }\n}\n","import type { DelayValue } from './types';\n\nexport function resolveDelay(delay: DelayValue | undefined): number {\n if (delay === undefined) {\n return 0;\n }\n\n if (typeof delay === 'number') {\n return delay;\n }\n\n const [min, max] = delay;\n return Math.floor(min + Math.random() * (max - min + 1));\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nexport function validateDelay(delay: DelayValue | undefined): void {\n if (delay === undefined) {\n return;\n }\n\n if (typeof delay === 'number') {\n assertNonNegativeFiniteNumber(delay, 'delay');\n return;\n }\n\n const [min, max] = delay;\n assertNonNegativeFiniteNumber(min, 'delay min');\n assertNonNegativeFiniteNumber(max, 'delay max');\n\n if (min > max) {\n throw new Error('WaitKit delay range must have min less than or equal to max.');\n }\n}\n\nexport function validateRate(rate: number | undefined, name: string): void {\n if (rate === undefined) {\n return;\n }\n\n if (!Number.isFinite(rate) || rate < 0 || rate > 1) {\n throw new Error(`WaitKit ${name} must be a number between 0 and 1.`);\n }\n}\n\nexport function validateTimeoutMs(timeoutMs: number | undefined): void {\n if (timeoutMs === undefined) {\n return;\n }\n\n assertNonNegativeFiniteNumber(timeoutMs, 'timeoutMs');\n}\n\nfunction assertNonNegativeFiniteNumber(value: number, name: string): void {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`WaitKit ${name} must be a non-negative finite number.`);\n }\n}\n","import type { WaitKitRule } from './types';\n\nexport function matchesRule(rule: WaitKitRule, url: string, method: string): boolean {\n return matchesUrl(rule.url, url) && matchesMethod(rule.method, method);\n}\n\nfunction matchesUrl(ruleUrl: WaitKitRule['url'], url: string): boolean {\n if (typeof ruleUrl === 'string') {\n return url.includes(ruleUrl);\n }\n\n if (ruleUrl instanceof RegExp) {\n return ruleUrl.test(url);\n }\n\n return ruleUrl(url);\n}\n\nfunction matchesMethod(ruleMethod: WaitKitRule['method'], method: string): boolean {\n if (ruleMethod === undefined) {\n return true;\n }\n\n const normalizedMethod = normalizeMethod(method);\n\n if (typeof ruleMethod === 'string') {\n return normalizeMethod(ruleMethod) === normalizedMethod;\n }\n\n return ruleMethod.some((item) => normalizeMethod(item) === normalizedMethod);\n}\n\nexport function normalizeMethod(method: string | undefined): string {\n return (method ?? 'GET').toUpperCase();\n}\n\nexport function getRequestUrl(input: RequestInfo | URL): string {\n if (typeof input === 'string') {\n return input;\n }\n\n if (input instanceof URL) {\n return input.toString();\n }\n\n return input.url;\n}\n\nexport function getRequestMethod(input: RequestInfo | URL, init?: RequestInit): string {\n if (init?.method !== undefined) {\n return normalizeMethod(init.method);\n }\n\n if (typeof input === 'string' || input instanceof URL) {\n return 'GET';\n }\n\n return normalizeMethod(input.method);\n}\n","import type { WaitKitErrorResponse } from './types';\n\nexport function createErrorResponse(errorResponse: WaitKitErrorResponse | undefined): Response {\n try {\n const status = errorResponse?.status ?? 500;\n const headers = new Headers(errorResponse?.headers);\n const body = serializeBody(errorResponse?.body, headers);\n\n return new Response(body, {\n status,\n statusText: errorResponse?.statusText,\n headers,\n });\n } catch (error) {\n throw createResponseError(error);\n }\n}\n\nfunction serializeBody(body: unknown, headers: Headers): BodyInit | null {\n if (body === undefined || body === null) {\n return null;\n }\n\n if (typeof body === 'string' || isBlob(body) || isFormData(body)) {\n return body;\n }\n\n if (body instanceof ArrayBuffer || ArrayBuffer.isView(body) || isUrlSearchParams(body)) {\n return body as BodyInit;\n }\n\n if (!headers.has('content-type')) {\n headers.set('content-type', 'application/json');\n }\n\n return JSON.stringify(body);\n}\n\nfunction isBlob(body: unknown): body is Blob {\n return typeof Blob !== 'undefined' && body instanceof Blob;\n}\n\nfunction isFormData(body: unknown): body is FormData {\n return typeof FormData !== 'undefined' && body instanceof FormData;\n}\n\nfunction isUrlSearchParams(body: unknown): body is URLSearchParams {\n return typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams;\n}\n\nfunction createResponseError(error: unknown): Error {\n const reason = error instanceof Error ? error.message : String(error);\n\n return new Error(`WaitKit failed to create simulated error response: ${reason}`, {\n cause: error,\n });\n}\n","import { resolveDelay, sleep, validateDelay, validateRate, validateTimeoutMs } from './delay';\nimport { WaitKitTimeoutError } from './errors';\nimport { getRequestMethod, getRequestUrl, matchesRule } from './matcher';\nimport { createErrorResponse } from './response';\nimport type {\n WaitKitController,\n WaitKitErrorEvent,\n WaitKitMatchEvent,\n WaitKitOptions,\n WaitKitRequestEvent,\n WaitKitRule,\n WaitKitScenarioChangeReason,\n} from './types';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nexport function setupWaitKit(options: WaitKitOptions): WaitKitController {\n validateRuntime();\n validateOptions(options);\n\n const originalFetch = globalThis.fetch;\n let enabled = options.enabled ?? true;\n let activeScenario = options.activeScenario;\n let restored = false;\n\n const patchedFetch: typeof fetch = async (input, init) => {\n if (!enabled) {\n return originalFetch.call(globalThis, input, init);\n }\n\n const requestEvent = createRequestEvent(input, init);\n options.onRequest?.(requestEvent);\n\n const rule = findMatchingRule(getActiveRules(), requestEvent.url, requestEvent.method);\n\n if (rule === undefined) {\n return originalFetch.call(globalThis, input, init);\n }\n\n const delayMs = resolveDelay(rule.delay);\n const matchEvent = createMatchEvent(requestEvent, rule, activeScenario, delayMs);\n options.onMatch?.(matchEvent);\n\n if (delayMs > 0) {\n options.onDelayStart?.(matchEvent);\n debug(options, `${requestEvent.method} ${requestEvent.url} delayed by ${delayMs}ms`);\n await sleep(delayMs);\n options.onDelayEnd?.(matchEvent);\n }\n\n if (shouldTrigger(rule.timeoutRate)) {\n const timeoutMs = rule.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const error = new WaitKitTimeoutError(\n `WaitKit timed out ${requestEvent.method} ${requestEvent.url} after ${timeoutMs}ms.`,\n );\n emitError(options, matchEvent, error);\n debug(options, `${requestEvent.method} ${requestEvent.url} timed out after ${timeoutMs}ms`);\n await sleep(timeoutMs);\n throw error;\n }\n\n if (shouldTrigger(rule.errorRate)) {\n const response = createErrorResponse(rule.errorResponse);\n const error = new Error(\n `WaitKit simulated ${response.status} response for ${requestEvent.method} ${requestEvent.url}.`,\n );\n emitError(options, matchEvent, error);\n debug(options, `${requestEvent.method} ${requestEvent.url} returned ${response.status}`);\n return response;\n }\n\n return originalFetch.call(globalThis, input, init);\n };\n\n globalThis.fetch = patchedFetch;\n\n function getActiveRules(): readonly WaitKitRule[] {\n if (activeScenario === undefined) {\n return options.rules ?? [];\n }\n\n return options.scenarios?.[activeScenario] ?? [];\n }\n\n return {\n enable() {\n enabled = true;\n\n if (restored) {\n globalThis.fetch = patchedFetch;\n restored = false;\n }\n },\n disable() {\n enabled = false;\n },\n restore() {\n if (globalThis.fetch === patchedFetch) {\n globalThis.fetch = originalFetch;\n }\n\n enabled = false;\n restored = true;\n },\n isEnabled() {\n return enabled;\n },\n setScenario(name: string) {\n if (options.scenarios?.[name] === undefined) {\n throw new Error(`WaitKit scenario \"${name}\" does not exist.`);\n }\n\n if (activeScenario === name) {\n return;\n }\n\n const previousScenario = activeScenario;\n activeScenario = name;\n emitScenarioChange(options, previousScenario, activeScenario, 'setScenario');\n },\n getScenario() {\n return activeScenario;\n },\n resetScenario() {\n if (activeScenario === undefined) {\n return;\n }\n\n const previousScenario = activeScenario;\n activeScenario = undefined;\n emitScenarioChange(options, previousScenario, activeScenario, 'resetScenario');\n },\n };\n}\n\nfunction validateRuntime(): void {\n if (typeof globalThis.fetch !== 'function') {\n throw new Error('WaitKit requires globalThis.fetch.');\n }\n\n if (typeof Response !== 'function') {\n throw new Error('WaitKit requires globalThis.Response.');\n }\n}\n\nfunction validateOptions(options: WaitKitOptions): void {\n validateRules(options.rules ?? []);\n\n if (options.scenarios !== undefined) {\n for (const rules of Object.values(options.scenarios)) {\n validateRules(rules);\n }\n }\n\n if (\n options.activeScenario !== undefined &&\n options.scenarios?.[options.activeScenario] === undefined\n ) {\n throw new Error(`WaitKit scenario \"${options.activeScenario}\" does not exist.`);\n }\n}\n\nfunction validateRules(rules: readonly WaitKitRule[]): void {\n for (const rule of rules) {\n validateDelay(rule.delay);\n validateRate(rule.errorRate, 'errorRate');\n validateRate(rule.timeoutRate, 'timeoutRate');\n validateTimeoutMs(rule.timeoutMs);\n validateStatus(rule.errorResponse?.status);\n }\n}\n\nfunction validateStatus(status: number | undefined): void {\n if (status === undefined) {\n return;\n }\n\n if (!Number.isInteger(status) || status < 200 || status > 599) {\n throw new Error('WaitKit errorResponse.status must be an integer between 200 and 599.');\n }\n}\n\nfunction createRequestEvent(input: RequestInfo | URL, init?: RequestInit): WaitKitRequestEvent {\n return {\n input,\n init,\n url: getRequestUrl(input),\n method: getRequestMethod(input, init),\n };\n}\n\nfunction createMatchEvent(\n requestEvent: WaitKitRequestEvent,\n rule: WaitKitRule,\n scenario: string | undefined,\n delayMs: number,\n): WaitKitMatchEvent {\n return {\n ...requestEvent,\n rule,\n scenario,\n delayMs,\n };\n}\n\nfunction findMatchingRule(\n rules: readonly WaitKitRule[],\n url: string,\n method: string,\n): WaitKitRule | undefined {\n return rules.find((rule) => matchesRule(rule, url, method));\n}\n\nfunction shouldTrigger(rate: number | undefined): boolean {\n if (rate === undefined || rate <= 0) {\n return false;\n }\n\n if (rate >= 1) {\n return true;\n }\n\n return Math.random() < rate;\n}\n\nfunction emitError(options: WaitKitOptions, matchEvent: WaitKitMatchEvent, error: Error): void {\n const errorEvent: WaitKitErrorEvent = {\n ...matchEvent,\n error,\n };\n\n options.onError?.(errorEvent);\n}\n\nfunction emitScenarioChange(\n options: WaitKitOptions,\n previousScenario: string | undefined,\n scenario: string | undefined,\n reason: WaitKitScenarioChangeReason,\n): void {\n options.onScenarioChange?.({\n previousScenario,\n scenario,\n reason,\n });\n}\n\nfunction debug(options: WaitKitOptions, message: string): void {\n if (options.debug === true) {\n console.info(`[waitkit] ${message}`);\n }\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -35,6 +35,12 @@ type WaitKitDelayEvent = WaitKitMatchEvent;
|
|
|
35
35
|
interface WaitKitErrorEvent extends WaitKitMatchEvent {
|
|
36
36
|
error: Error;
|
|
37
37
|
}
|
|
38
|
+
type WaitKitScenarioChangeReason = 'setScenario' | 'resetScenario';
|
|
39
|
+
interface WaitKitScenarioChangeEvent {
|
|
40
|
+
previousScenario?: string;
|
|
41
|
+
scenario?: string;
|
|
42
|
+
reason: WaitKitScenarioChangeReason;
|
|
43
|
+
}
|
|
38
44
|
interface WaitKitOptions {
|
|
39
45
|
enabled?: boolean;
|
|
40
46
|
rules?: readonly WaitKitRule[];
|
|
@@ -46,6 +52,7 @@ interface WaitKitOptions {
|
|
|
46
52
|
onDelayStart?: (event: WaitKitDelayEvent) => void;
|
|
47
53
|
onDelayEnd?: (event: WaitKitDelayEvent) => void;
|
|
48
54
|
onError?: (event: WaitKitErrorEvent) => void;
|
|
55
|
+
onScenarioChange?: (event: WaitKitScenarioChangeEvent) => void;
|
|
49
56
|
}
|
|
50
57
|
interface WaitKitController {
|
|
51
58
|
enable: () => void;
|
|
@@ -59,4 +66,4 @@ interface WaitKitController {
|
|
|
59
66
|
|
|
60
67
|
declare function setupWaitKit(options: WaitKitOptions): WaitKitController;
|
|
61
68
|
|
|
62
|
-
export { type DelayValue, type HttpMethod, type UrlMatcher, type WaitKitController, type WaitKitDelayEvent, type WaitKitErrorEvent, type WaitKitErrorResponse, type WaitKitMatchEvent, type WaitKitOptions, type WaitKitRequestEvent, type WaitKitRule, WaitKitTimeoutError, setupWaitKit };
|
|
69
|
+
export { type DelayValue, type HttpMethod, type UrlMatcher, type WaitKitController, type WaitKitDelayEvent, type WaitKitErrorEvent, type WaitKitErrorResponse, type WaitKitMatchEvent, type WaitKitOptions, type WaitKitRequestEvent, type WaitKitRule, type WaitKitScenarioChangeEvent, type WaitKitScenarioChangeReason, WaitKitTimeoutError, setupWaitKit };
|
package/dist/index.d.ts
CHANGED
|
@@ -35,6 +35,12 @@ type WaitKitDelayEvent = WaitKitMatchEvent;
|
|
|
35
35
|
interface WaitKitErrorEvent extends WaitKitMatchEvent {
|
|
36
36
|
error: Error;
|
|
37
37
|
}
|
|
38
|
+
type WaitKitScenarioChangeReason = 'setScenario' | 'resetScenario';
|
|
39
|
+
interface WaitKitScenarioChangeEvent {
|
|
40
|
+
previousScenario?: string;
|
|
41
|
+
scenario?: string;
|
|
42
|
+
reason: WaitKitScenarioChangeReason;
|
|
43
|
+
}
|
|
38
44
|
interface WaitKitOptions {
|
|
39
45
|
enabled?: boolean;
|
|
40
46
|
rules?: readonly WaitKitRule[];
|
|
@@ -46,6 +52,7 @@ interface WaitKitOptions {
|
|
|
46
52
|
onDelayStart?: (event: WaitKitDelayEvent) => void;
|
|
47
53
|
onDelayEnd?: (event: WaitKitDelayEvent) => void;
|
|
48
54
|
onError?: (event: WaitKitErrorEvent) => void;
|
|
55
|
+
onScenarioChange?: (event: WaitKitScenarioChangeEvent) => void;
|
|
49
56
|
}
|
|
50
57
|
interface WaitKitController {
|
|
51
58
|
enable: () => void;
|
|
@@ -59,4 +66,4 @@ interface WaitKitController {
|
|
|
59
66
|
|
|
60
67
|
declare function setupWaitKit(options: WaitKitOptions): WaitKitController;
|
|
61
68
|
|
|
62
|
-
export { type DelayValue, type HttpMethod, type UrlMatcher, type WaitKitController, type WaitKitDelayEvent, type WaitKitErrorEvent, type WaitKitErrorResponse, type WaitKitMatchEvent, type WaitKitOptions, type WaitKitRequestEvent, type WaitKitRule, WaitKitTimeoutError, setupWaitKit };
|
|
69
|
+
export { type DelayValue, type HttpMethod, type UrlMatcher, type WaitKitController, type WaitKitDelayEvent, type WaitKitErrorEvent, type WaitKitErrorResponse, type WaitKitMatchEvent, type WaitKitOptions, type WaitKitRequestEvent, type WaitKitRule, type WaitKitScenarioChangeEvent, type WaitKitScenarioChangeReason, WaitKitTimeoutError, setupWaitKit };
|
package/dist/index.js
CHANGED
|
@@ -104,14 +104,18 @@ function getRequestMethod(input, init) {
|
|
|
104
104
|
|
|
105
105
|
// src/response.ts
|
|
106
106
|
function createErrorResponse(errorResponse) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
107
|
+
try {
|
|
108
|
+
const status = errorResponse?.status ?? 500;
|
|
109
|
+
const headers = new Headers(errorResponse?.headers);
|
|
110
|
+
const body = serializeBody(errorResponse?.body, headers);
|
|
111
|
+
return new Response(body, {
|
|
112
|
+
status,
|
|
113
|
+
statusText: errorResponse?.statusText,
|
|
114
|
+
headers
|
|
115
|
+
});
|
|
116
|
+
} catch (error) {
|
|
117
|
+
throw createResponseError(error);
|
|
118
|
+
}
|
|
115
119
|
}
|
|
116
120
|
function serializeBody(body, headers) {
|
|
117
121
|
if (body === void 0 || body === null) {
|
|
@@ -137,6 +141,12 @@ function isFormData(body) {
|
|
|
137
141
|
function isUrlSearchParams(body) {
|
|
138
142
|
return typeof URLSearchParams !== "undefined" && body instanceof URLSearchParams;
|
|
139
143
|
}
|
|
144
|
+
function createResponseError(error) {
|
|
145
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
146
|
+
return new Error(`WaitKit failed to create simulated error response: ${reason}`, {
|
|
147
|
+
cause: error
|
|
148
|
+
});
|
|
149
|
+
}
|
|
140
150
|
|
|
141
151
|
// src/setup-wait-kit.ts
|
|
142
152
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
@@ -219,13 +229,23 @@ function setupWaitKit(options) {
|
|
|
219
229
|
if (options.scenarios?.[name] === void 0) {
|
|
220
230
|
throw new Error(`WaitKit scenario "${name}" does not exist.`);
|
|
221
231
|
}
|
|
232
|
+
if (activeScenario === name) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const previousScenario = activeScenario;
|
|
222
236
|
activeScenario = name;
|
|
237
|
+
emitScenarioChange(options, previousScenario, activeScenario, "setScenario");
|
|
223
238
|
},
|
|
224
239
|
getScenario() {
|
|
225
240
|
return activeScenario;
|
|
226
241
|
},
|
|
227
242
|
resetScenario() {
|
|
243
|
+
if (activeScenario === void 0) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
const previousScenario = activeScenario;
|
|
228
247
|
activeScenario = void 0;
|
|
248
|
+
emitScenarioChange(options, previousScenario, activeScenario, "resetScenario");
|
|
229
249
|
}
|
|
230
250
|
};
|
|
231
251
|
}
|
|
@@ -300,6 +320,13 @@ function emitError(options, matchEvent, error) {
|
|
|
300
320
|
};
|
|
301
321
|
options.onError?.(errorEvent);
|
|
302
322
|
}
|
|
323
|
+
function emitScenarioChange(options, previousScenario, scenario, reason) {
|
|
324
|
+
options.onScenarioChange?.({
|
|
325
|
+
previousScenario,
|
|
326
|
+
scenario,
|
|
327
|
+
reason
|
|
328
|
+
});
|
|
329
|
+
}
|
|
303
330
|
function debug(options, message) {
|
|
304
331
|
if (options.debug === true) {
|
|
305
332
|
console.info(`[waitkit] ${message}`);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/delay.ts","../src/matcher.ts","../src/response.ts","../src/setup-wait-kit.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export class WaitKitTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WaitKitTimeoutError';\n }\n}\n","import type { DelayValue } from './types';\n\nexport function resolveDelay(delay: DelayValue | undefined): number {\n if (delay === undefined) {\n return 0;\n }\n\n if (typeof delay === 'number') {\n return delay;\n }\n\n const [min, max] = delay;\n return Math.floor(min + Math.random() * (max - min + 1));\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nexport function validateDelay(delay: DelayValue | undefined): void {\n if (delay === undefined) {\n return;\n }\n\n if (typeof delay === 'number') {\n assertNonNegativeFiniteNumber(delay, 'delay');\n return;\n }\n\n const [min, max] = delay;\n assertNonNegativeFiniteNumber(min, 'delay min');\n assertNonNegativeFiniteNumber(max, 'delay max');\n\n if (min > max) {\n throw new Error('WaitKit delay range must have min less than or equal to max.');\n }\n}\n\nexport function validateRate(rate: number | undefined, name: string): void {\n if (rate === undefined) {\n return;\n }\n\n if (!Number.isFinite(rate) || rate < 0 || rate > 1) {\n throw new Error(`WaitKit ${name} must be a number between 0 and 1.`);\n }\n}\n\nexport function validateTimeoutMs(timeoutMs: number | undefined): void {\n if (timeoutMs === undefined) {\n return;\n }\n\n assertNonNegativeFiniteNumber(timeoutMs, 'timeoutMs');\n}\n\nfunction assertNonNegativeFiniteNumber(value: number, name: string): void {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`WaitKit ${name} must be a non-negative finite number.`);\n }\n}\n","import type { WaitKitRule } from './types';\n\nexport function matchesRule(rule: WaitKitRule, url: string, method: string): boolean {\n return matchesUrl(rule.url, url) && matchesMethod(rule.method, method);\n}\n\nfunction matchesUrl(ruleUrl: WaitKitRule['url'], url: string): boolean {\n if (typeof ruleUrl === 'string') {\n return url.includes(ruleUrl);\n }\n\n if (ruleUrl instanceof RegExp) {\n return ruleUrl.test(url);\n }\n\n return ruleUrl(url);\n}\n\nfunction matchesMethod(ruleMethod: WaitKitRule['method'], method: string): boolean {\n if (ruleMethod === undefined) {\n return true;\n }\n\n const normalizedMethod = normalizeMethod(method);\n\n if (typeof ruleMethod === 'string') {\n return normalizeMethod(ruleMethod) === normalizedMethod;\n }\n\n return ruleMethod.some((item) => normalizeMethod(item) === normalizedMethod);\n}\n\nexport function normalizeMethod(method: string | undefined): string {\n return (method ?? 'GET').toUpperCase();\n}\n\nexport function getRequestUrl(input: RequestInfo | URL): string {\n if (typeof input === 'string') {\n return input;\n }\n\n if (input instanceof URL) {\n return input.toString();\n }\n\n return input.url;\n}\n\nexport function getRequestMethod(input: RequestInfo | URL, init?: RequestInit): string {\n if (init?.method !== undefined) {\n return normalizeMethod(init.method);\n }\n\n if (typeof input === 'string' || input instanceof URL) {\n return 'GET';\n }\n\n return normalizeMethod(input.method);\n}\n","import type { WaitKitErrorResponse } from './types';\n\nexport function createErrorResponse(errorResponse: WaitKitErrorResponse | undefined): Response {\n const status = errorResponse?.status ?? 500;\n const headers = new Headers(errorResponse?.headers);\n const body = serializeBody(errorResponse?.body, headers);\n\n return new Response(body, {\n status,\n statusText: errorResponse?.statusText,\n headers,\n });\n}\n\nfunction serializeBody(body: unknown, headers: Headers): BodyInit | null {\n if (body === undefined || body === null) {\n return null;\n }\n\n if (typeof body === 'string' || isBlob(body) || isFormData(body)) {\n return body;\n }\n\n if (body instanceof ArrayBuffer || ArrayBuffer.isView(body) || isUrlSearchParams(body)) {\n return body as BodyInit;\n }\n\n if (!headers.has('content-type')) {\n headers.set('content-type', 'application/json');\n }\n\n return JSON.stringify(body);\n}\n\nfunction isBlob(body: unknown): body is Blob {\n return typeof Blob !== 'undefined' && body instanceof Blob;\n}\n\nfunction isFormData(body: unknown): body is FormData {\n return typeof FormData !== 'undefined' && body instanceof FormData;\n}\n\nfunction isUrlSearchParams(body: unknown): body is URLSearchParams {\n return typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams;\n}\n","import { resolveDelay, sleep, validateDelay, validateRate, validateTimeoutMs } from './delay';\nimport { WaitKitTimeoutError } from './errors';\nimport { getRequestMethod, getRequestUrl, matchesRule } from './matcher';\nimport { createErrorResponse } from './response';\nimport type {\n WaitKitController,\n WaitKitErrorEvent,\n WaitKitMatchEvent,\n WaitKitOptions,\n WaitKitRequestEvent,\n WaitKitRule,\n} from './types';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nexport function setupWaitKit(options: WaitKitOptions): WaitKitController {\n validateRuntime();\n validateOptions(options);\n\n const originalFetch = globalThis.fetch;\n let enabled = options.enabled ?? true;\n let activeScenario = options.activeScenario;\n let restored = false;\n\n const patchedFetch: typeof fetch = async (input, init) => {\n if (!enabled) {\n return originalFetch.call(globalThis, input, init);\n }\n\n const requestEvent = createRequestEvent(input, init);\n options.onRequest?.(requestEvent);\n\n const rule = findMatchingRule(getActiveRules(), requestEvent.url, requestEvent.method);\n\n if (rule === undefined) {\n return originalFetch.call(globalThis, input, init);\n }\n\n const delayMs = resolveDelay(rule.delay);\n const matchEvent = createMatchEvent(requestEvent, rule, activeScenario, delayMs);\n options.onMatch?.(matchEvent);\n\n if (delayMs > 0) {\n options.onDelayStart?.(matchEvent);\n debug(options, `${requestEvent.method} ${requestEvent.url} delayed by ${delayMs}ms`);\n await sleep(delayMs);\n options.onDelayEnd?.(matchEvent);\n }\n\n if (shouldTrigger(rule.timeoutRate)) {\n const timeoutMs = rule.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const error = new WaitKitTimeoutError(\n `WaitKit timed out ${requestEvent.method} ${requestEvent.url} after ${timeoutMs}ms.`,\n );\n emitError(options, matchEvent, error);\n debug(options, `${requestEvent.method} ${requestEvent.url} timed out after ${timeoutMs}ms`);\n await sleep(timeoutMs);\n throw error;\n }\n\n if (shouldTrigger(rule.errorRate)) {\n const response = createErrorResponse(rule.errorResponse);\n const error = new Error(\n `WaitKit simulated ${response.status} response for ${requestEvent.method} ${requestEvent.url}.`,\n );\n emitError(options, matchEvent, error);\n debug(options, `${requestEvent.method} ${requestEvent.url} returned ${response.status}`);\n return response;\n }\n\n return originalFetch.call(globalThis, input, init);\n };\n\n globalThis.fetch = patchedFetch;\n\n function getActiveRules(): readonly WaitKitRule[] {\n if (activeScenario === undefined) {\n return options.rules ?? [];\n }\n\n return options.scenarios?.[activeScenario] ?? [];\n }\n\n return {\n enable() {\n enabled = true;\n\n if (restored) {\n globalThis.fetch = patchedFetch;\n restored = false;\n }\n },\n disable() {\n enabled = false;\n },\n restore() {\n if (globalThis.fetch === patchedFetch) {\n globalThis.fetch = originalFetch;\n }\n\n enabled = false;\n restored = true;\n },\n isEnabled() {\n return enabled;\n },\n setScenario(name: string) {\n if (options.scenarios?.[name] === undefined) {\n throw new Error(`WaitKit scenario \"${name}\" does not exist.`);\n }\n\n activeScenario = name;\n },\n getScenario() {\n return activeScenario;\n },\n resetScenario() {\n activeScenario = undefined;\n },\n };\n}\n\nfunction validateRuntime(): void {\n if (typeof globalThis.fetch !== 'function') {\n throw new Error('WaitKit requires globalThis.fetch.');\n }\n\n if (typeof Response !== 'function') {\n throw new Error('WaitKit requires globalThis.Response.');\n }\n}\n\nfunction validateOptions(options: WaitKitOptions): void {\n validateRules(options.rules ?? []);\n\n if (options.scenarios !== undefined) {\n for (const rules of Object.values(options.scenarios)) {\n validateRules(rules);\n }\n }\n\n if (\n options.activeScenario !== undefined &&\n options.scenarios?.[options.activeScenario] === undefined\n ) {\n throw new Error(`WaitKit scenario \"${options.activeScenario}\" does not exist.`);\n }\n}\n\nfunction validateRules(rules: readonly WaitKitRule[]): void {\n for (const rule of rules) {\n validateDelay(rule.delay);\n validateRate(rule.errorRate, 'errorRate');\n validateRate(rule.timeoutRate, 'timeoutRate');\n validateTimeoutMs(rule.timeoutMs);\n validateStatus(rule.errorResponse?.status);\n }\n}\n\nfunction validateStatus(status: number | undefined): void {\n if (status === undefined) {\n return;\n }\n\n if (!Number.isInteger(status) || status < 200 || status > 599) {\n throw new Error('WaitKit errorResponse.status must be an integer between 200 and 599.');\n }\n}\n\nfunction createRequestEvent(input: RequestInfo | URL, init?: RequestInit): WaitKitRequestEvent {\n return {\n input,\n init,\n url: getRequestUrl(input),\n method: getRequestMethod(input, init),\n };\n}\n\nfunction createMatchEvent(\n requestEvent: WaitKitRequestEvent,\n rule: WaitKitRule,\n scenario: string | undefined,\n delayMs: number,\n): WaitKitMatchEvent {\n return {\n ...requestEvent,\n rule,\n scenario,\n delayMs,\n };\n}\n\nfunction findMatchingRule(\n rules: readonly WaitKitRule[],\n url: string,\n method: string,\n): WaitKitRule | undefined {\n return rules.find((rule) => matchesRule(rule, url, method));\n}\n\nfunction shouldTrigger(rate: number | undefined): boolean {\n if (rate === undefined || rate <= 0) {\n return false;\n }\n\n if (rate >= 1) {\n return true;\n }\n\n return Math.random() < rate;\n}\n\nfunction emitError(options: WaitKitOptions, matchEvent: WaitKitMatchEvent, error: Error): void {\n const errorEvent: WaitKitErrorEvent = {\n ...matchEvent,\n error,\n };\n\n options.onError?.(errorEvent);\n}\n\nfunction debug(options: WaitKitOptions, message: string): void {\n if (options.debug === true) {\n console.info(`[waitkit] ${message}`);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/delay.ts","../src/matcher.ts","../src/response.ts","../src/setup-wait-kit.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export class WaitKitTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WaitKitTimeoutError';\n }\n}\n","import type { DelayValue } from './types';\n\nexport function resolveDelay(delay: DelayValue | undefined): number {\n if (delay === undefined) {\n return 0;\n }\n\n if (typeof delay === 'number') {\n return delay;\n }\n\n const [min, max] = delay;\n return Math.floor(min + Math.random() * (max - min + 1));\n}\n\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nexport function validateDelay(delay: DelayValue | undefined): void {\n if (delay === undefined) {\n return;\n }\n\n if (typeof delay === 'number') {\n assertNonNegativeFiniteNumber(delay, 'delay');\n return;\n }\n\n const [min, max] = delay;\n assertNonNegativeFiniteNumber(min, 'delay min');\n assertNonNegativeFiniteNumber(max, 'delay max');\n\n if (min > max) {\n throw new Error('WaitKit delay range must have min less than or equal to max.');\n }\n}\n\nexport function validateRate(rate: number | undefined, name: string): void {\n if (rate === undefined) {\n return;\n }\n\n if (!Number.isFinite(rate) || rate < 0 || rate > 1) {\n throw new Error(`WaitKit ${name} must be a number between 0 and 1.`);\n }\n}\n\nexport function validateTimeoutMs(timeoutMs: number | undefined): void {\n if (timeoutMs === undefined) {\n return;\n }\n\n assertNonNegativeFiniteNumber(timeoutMs, 'timeoutMs');\n}\n\nfunction assertNonNegativeFiniteNumber(value: number, name: string): void {\n if (!Number.isFinite(value) || value < 0) {\n throw new Error(`WaitKit ${name} must be a non-negative finite number.`);\n }\n}\n","import type { WaitKitRule } from './types';\n\nexport function matchesRule(rule: WaitKitRule, url: string, method: string): boolean {\n return matchesUrl(rule.url, url) && matchesMethod(rule.method, method);\n}\n\nfunction matchesUrl(ruleUrl: WaitKitRule['url'], url: string): boolean {\n if (typeof ruleUrl === 'string') {\n return url.includes(ruleUrl);\n }\n\n if (ruleUrl instanceof RegExp) {\n return ruleUrl.test(url);\n }\n\n return ruleUrl(url);\n}\n\nfunction matchesMethod(ruleMethod: WaitKitRule['method'], method: string): boolean {\n if (ruleMethod === undefined) {\n return true;\n }\n\n const normalizedMethod = normalizeMethod(method);\n\n if (typeof ruleMethod === 'string') {\n return normalizeMethod(ruleMethod) === normalizedMethod;\n }\n\n return ruleMethod.some((item) => normalizeMethod(item) === normalizedMethod);\n}\n\nexport function normalizeMethod(method: string | undefined): string {\n return (method ?? 'GET').toUpperCase();\n}\n\nexport function getRequestUrl(input: RequestInfo | URL): string {\n if (typeof input === 'string') {\n return input;\n }\n\n if (input instanceof URL) {\n return input.toString();\n }\n\n return input.url;\n}\n\nexport function getRequestMethod(input: RequestInfo | URL, init?: RequestInit): string {\n if (init?.method !== undefined) {\n return normalizeMethod(init.method);\n }\n\n if (typeof input === 'string' || input instanceof URL) {\n return 'GET';\n }\n\n return normalizeMethod(input.method);\n}\n","import type { WaitKitErrorResponse } from './types';\n\nexport function createErrorResponse(errorResponse: WaitKitErrorResponse | undefined): Response {\n try {\n const status = errorResponse?.status ?? 500;\n const headers = new Headers(errorResponse?.headers);\n const body = serializeBody(errorResponse?.body, headers);\n\n return new Response(body, {\n status,\n statusText: errorResponse?.statusText,\n headers,\n });\n } catch (error) {\n throw createResponseError(error);\n }\n}\n\nfunction serializeBody(body: unknown, headers: Headers): BodyInit | null {\n if (body === undefined || body === null) {\n return null;\n }\n\n if (typeof body === 'string' || isBlob(body) || isFormData(body)) {\n return body;\n }\n\n if (body instanceof ArrayBuffer || ArrayBuffer.isView(body) || isUrlSearchParams(body)) {\n return body as BodyInit;\n }\n\n if (!headers.has('content-type')) {\n headers.set('content-type', 'application/json');\n }\n\n return JSON.stringify(body);\n}\n\nfunction isBlob(body: unknown): body is Blob {\n return typeof Blob !== 'undefined' && body instanceof Blob;\n}\n\nfunction isFormData(body: unknown): body is FormData {\n return typeof FormData !== 'undefined' && body instanceof FormData;\n}\n\nfunction isUrlSearchParams(body: unknown): body is URLSearchParams {\n return typeof URLSearchParams !== 'undefined' && body instanceof URLSearchParams;\n}\n\nfunction createResponseError(error: unknown): Error {\n const reason = error instanceof Error ? error.message : String(error);\n\n return new Error(`WaitKit failed to create simulated error response: ${reason}`, {\n cause: error,\n });\n}\n","import { resolveDelay, sleep, validateDelay, validateRate, validateTimeoutMs } from './delay';\nimport { WaitKitTimeoutError } from './errors';\nimport { getRequestMethod, getRequestUrl, matchesRule } from './matcher';\nimport { createErrorResponse } from './response';\nimport type {\n WaitKitController,\n WaitKitErrorEvent,\n WaitKitMatchEvent,\n WaitKitOptions,\n WaitKitRequestEvent,\n WaitKitRule,\n WaitKitScenarioChangeReason,\n} from './types';\n\nconst DEFAULT_TIMEOUT_MS = 30_000;\n\nexport function setupWaitKit(options: WaitKitOptions): WaitKitController {\n validateRuntime();\n validateOptions(options);\n\n const originalFetch = globalThis.fetch;\n let enabled = options.enabled ?? true;\n let activeScenario = options.activeScenario;\n let restored = false;\n\n const patchedFetch: typeof fetch = async (input, init) => {\n if (!enabled) {\n return originalFetch.call(globalThis, input, init);\n }\n\n const requestEvent = createRequestEvent(input, init);\n options.onRequest?.(requestEvent);\n\n const rule = findMatchingRule(getActiveRules(), requestEvent.url, requestEvent.method);\n\n if (rule === undefined) {\n return originalFetch.call(globalThis, input, init);\n }\n\n const delayMs = resolveDelay(rule.delay);\n const matchEvent = createMatchEvent(requestEvent, rule, activeScenario, delayMs);\n options.onMatch?.(matchEvent);\n\n if (delayMs > 0) {\n options.onDelayStart?.(matchEvent);\n debug(options, `${requestEvent.method} ${requestEvent.url} delayed by ${delayMs}ms`);\n await sleep(delayMs);\n options.onDelayEnd?.(matchEvent);\n }\n\n if (shouldTrigger(rule.timeoutRate)) {\n const timeoutMs = rule.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const error = new WaitKitTimeoutError(\n `WaitKit timed out ${requestEvent.method} ${requestEvent.url} after ${timeoutMs}ms.`,\n );\n emitError(options, matchEvent, error);\n debug(options, `${requestEvent.method} ${requestEvent.url} timed out after ${timeoutMs}ms`);\n await sleep(timeoutMs);\n throw error;\n }\n\n if (shouldTrigger(rule.errorRate)) {\n const response = createErrorResponse(rule.errorResponse);\n const error = new Error(\n `WaitKit simulated ${response.status} response for ${requestEvent.method} ${requestEvent.url}.`,\n );\n emitError(options, matchEvent, error);\n debug(options, `${requestEvent.method} ${requestEvent.url} returned ${response.status}`);\n return response;\n }\n\n return originalFetch.call(globalThis, input, init);\n };\n\n globalThis.fetch = patchedFetch;\n\n function getActiveRules(): readonly WaitKitRule[] {\n if (activeScenario === undefined) {\n return options.rules ?? [];\n }\n\n return options.scenarios?.[activeScenario] ?? [];\n }\n\n return {\n enable() {\n enabled = true;\n\n if (restored) {\n globalThis.fetch = patchedFetch;\n restored = false;\n }\n },\n disable() {\n enabled = false;\n },\n restore() {\n if (globalThis.fetch === patchedFetch) {\n globalThis.fetch = originalFetch;\n }\n\n enabled = false;\n restored = true;\n },\n isEnabled() {\n return enabled;\n },\n setScenario(name: string) {\n if (options.scenarios?.[name] === undefined) {\n throw new Error(`WaitKit scenario \"${name}\" does not exist.`);\n }\n\n if (activeScenario === name) {\n return;\n }\n\n const previousScenario = activeScenario;\n activeScenario = name;\n emitScenarioChange(options, previousScenario, activeScenario, 'setScenario');\n },\n getScenario() {\n return activeScenario;\n },\n resetScenario() {\n if (activeScenario === undefined) {\n return;\n }\n\n const previousScenario = activeScenario;\n activeScenario = undefined;\n emitScenarioChange(options, previousScenario, activeScenario, 'resetScenario');\n },\n };\n}\n\nfunction validateRuntime(): void {\n if (typeof globalThis.fetch !== 'function') {\n throw new Error('WaitKit requires globalThis.fetch.');\n }\n\n if (typeof Response !== 'function') {\n throw new Error('WaitKit requires globalThis.Response.');\n }\n}\n\nfunction validateOptions(options: WaitKitOptions): void {\n validateRules(options.rules ?? []);\n\n if (options.scenarios !== undefined) {\n for (const rules of Object.values(options.scenarios)) {\n validateRules(rules);\n }\n }\n\n if (\n options.activeScenario !== undefined &&\n options.scenarios?.[options.activeScenario] === undefined\n ) {\n throw new Error(`WaitKit scenario \"${options.activeScenario}\" does not exist.`);\n }\n}\n\nfunction validateRules(rules: readonly WaitKitRule[]): void {\n for (const rule of rules) {\n validateDelay(rule.delay);\n validateRate(rule.errorRate, 'errorRate');\n validateRate(rule.timeoutRate, 'timeoutRate');\n validateTimeoutMs(rule.timeoutMs);\n validateStatus(rule.errorResponse?.status);\n }\n}\n\nfunction validateStatus(status: number | undefined): void {\n if (status === undefined) {\n return;\n }\n\n if (!Number.isInteger(status) || status < 200 || status > 599) {\n throw new Error('WaitKit errorResponse.status must be an integer between 200 and 599.');\n }\n}\n\nfunction createRequestEvent(input: RequestInfo | URL, init?: RequestInit): WaitKitRequestEvent {\n return {\n input,\n init,\n url: getRequestUrl(input),\n method: getRequestMethod(input, init),\n };\n}\n\nfunction createMatchEvent(\n requestEvent: WaitKitRequestEvent,\n rule: WaitKitRule,\n scenario: string | undefined,\n delayMs: number,\n): WaitKitMatchEvent {\n return {\n ...requestEvent,\n rule,\n scenario,\n delayMs,\n };\n}\n\nfunction findMatchingRule(\n rules: readonly WaitKitRule[],\n url: string,\n method: string,\n): WaitKitRule | undefined {\n return rules.find((rule) => matchesRule(rule, url, method));\n}\n\nfunction shouldTrigger(rate: number | undefined): boolean {\n if (rate === undefined || rate <= 0) {\n return false;\n }\n\n if (rate >= 1) {\n return true;\n }\n\n return Math.random() < rate;\n}\n\nfunction emitError(options: WaitKitOptions, matchEvent: WaitKitMatchEvent, error: Error): void {\n const errorEvent: WaitKitErrorEvent = {\n ...matchEvent,\n error,\n };\n\n options.onError?.(errorEvent);\n}\n\nfunction emitScenarioChange(\n options: WaitKitOptions,\n previousScenario: string | undefined,\n scenario: string | undefined,\n reason: WaitKitScenarioChangeReason,\n): void {\n options.onScenarioChange?.({\n previousScenario,\n scenario,\n reason,\n });\n}\n\nfunction debug(options: WaitKitOptions, message: string): void {\n if (options.debug === true) {\n console.info(`[waitkit] ${message}`);\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@waitkit/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Development-only fetch interceptor for testing loading, error, and timeout states.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"tsup": "^8.5.1",
|
|
48
48
|
"typescript": "^5.9.3",
|
|
49
49
|
"vitest": "^4.1.6",
|
|
50
|
-
"@waitkit/
|
|
51
|
-
"@waitkit/
|
|
50
|
+
"@waitkit/eslint-config": "0.0.0",
|
|
51
|
+
"@waitkit/typescript-config": "0.0.0"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
54
|
"dev": "tsup --watch",
|