@useairfoil/effect-vcr 0.4.6 → 0.4.7
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 +31 -229
- package/dist/{cassette-store-BMtcjh5h.d.ts → cassette-store.d.mts} +13 -17
- package/dist/{cassette-store-BF9e0rz3.js → cassette-store.mjs} +6 -7
- package/dist/cassette-store.mjs.map +1 -0
- package/dist/file-system-cassette-store.d.mts +17 -0
- package/dist/{file-system-cassette-store-CyOsu3z5.js → file-system-cassette-store.mjs} +7 -8
- package/dist/file-system-cassette-store.mjs.map +1 -0
- package/dist/{index.d.ts → index.d.mts} +4 -4
- package/dist/index.mjs +5 -0
- package/dist/{chunk-Bp6m_JJh.js → rolldown-runtime-D7D4PA-g.mjs} +4 -4
- package/dist/{types-XZehMu_v.d.ts → types-v6cSTgDp.d.mts} +3 -3
- package/dist/{types.d.ts → types.d.mts} +1 -1
- package/dist/{types-DMuz_JGd.js → types.mjs} +3 -4
- package/dist/types.mjs.map +1 -0
- package/dist/{vcr-http-client-Ba0WYPV9.js → vcr-http-client-5K20k6US.mjs} +67 -45
- package/dist/vcr-http-client-5K20k6US.mjs.map +1 -0
- package/dist/vcr-http-client.d.mts +21 -0
- package/dist/vcr-http-client.mjs +3 -0
- package/dist/{vitest-state-CiW5dzXZ.js → vitest-state-rX5XIlH6.mjs} +2 -2
- package/dist/vitest-state-rX5XIlH6.mjs.map +1 -0
- package/package.json +25 -25
- package/src/sanitize.ts +21 -2
- package/src/types.ts +2 -0
- package/src/vcr-http-client.ts +81 -33
- package/dist/cassette-store-BF9e0rz3.js.map +0 -1
- package/dist/cassette-store.d.ts +0 -3
- package/dist/cassette-store.js +0 -4
- package/dist/file-system-cassette-store-ClYAuH7U.d.ts +0 -19
- package/dist/file-system-cassette-store-CyOsu3z5.js.map +0 -1
- package/dist/file-system-cassette-store.d.ts +0 -4
- package/dist/file-system-cassette-store.js +0 -6
- package/dist/index.js +0 -7
- package/dist/types-DMuz_JGd.js.map +0 -1
- package/dist/types.js +0 -3
- package/dist/vcr-http-client-Ba0WYPV9.js.map +0 -1
- package/dist/vcr-http-client-BveeoOoW.d.ts +0 -26
- package/dist/vcr-http-client.d.ts +0 -4
- package/dist/vcr-http-client.js +0 -6
- package/dist/vitest-state-CiW5dzXZ.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,247 +1,49 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Effect VCR
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This package records Effect HTTP requests into cassette files. Tests can replay
|
|
4
|
+
the same requests later.
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
## Install
|
|
6
7
|
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
import { Effect } from "effect";
|
|
10
|
-
import { HttpClient } from "effect/unstable/http";
|
|
11
|
-
|
|
12
|
-
export const program = Effect.gen(function* () {
|
|
13
|
-
const client = yield* HttpClient.HttpClient;
|
|
14
|
-
const response = yield* client.get("https://httpbin.org/robots.txt");
|
|
15
|
-
return yield* response.text;
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
// my-program.test.ts
|
|
19
|
-
import { NodeServices } from "@effect/platform-node";
|
|
20
|
-
import { FileSystemCassetteStore, VcrHttpClient } from "@useairfoil/effect-vcr";
|
|
21
|
-
import { describe, it } from "@effect/vitest";
|
|
22
|
-
import { Effect, Layer } from "effect";
|
|
23
|
-
import { FetchHttpClient } from "effect/unstable/http";
|
|
24
|
-
|
|
25
|
-
const cassetteStoreLayer = FileSystemCassetteStore.layer().pipe(Layer.provide(NodeServices.layer));
|
|
26
|
-
|
|
27
|
-
const vcrRuntimeLayer = Layer.mergeAll(
|
|
28
|
-
FetchHttpClient.layer,
|
|
29
|
-
NodeServices.layer,
|
|
30
|
-
cassetteStoreLayer,
|
|
31
|
-
);
|
|
32
|
-
|
|
33
|
-
const vcrLayer = VcrHttpClient.layer({
|
|
34
|
-
vcrName: "httpbin",
|
|
35
|
-
mode: "auto",
|
|
36
|
-
}).pipe(Layer.provide(vcrRuntimeLayer));
|
|
37
|
-
|
|
38
|
-
describe("my awesome program", () => {
|
|
39
|
-
it.effect("works", () => program.pipe(Effect.provide(vcrLayer)));
|
|
40
|
-
});
|
|
8
|
+
```bash
|
|
9
|
+
pnpm add -D @useairfoil/effect-vcr @effect/platform-node@^4 effect@^4
|
|
41
10
|
```
|
|
42
11
|
|
|
43
|
-
The main use case for the VCR is to let open source projects run tests against a real upstream API without exposing secrets to forks.
|
|
44
|
-
|
|
45
|
-
- project owners generate cassettes locally by talking to the real API
|
|
46
|
-
- external contributors run tests against committed cassettes
|
|
47
|
-
- CI runs deterministically from cassettes
|
|
48
|
-
- scheduled or manual runs can still hit the live API to catch upstream drift
|
|
49
|
-
|
|
50
|
-
## Package shape
|
|
51
|
-
|
|
52
|
-
Root exports:
|
|
53
|
-
|
|
54
|
-
- `CassetteStore`
|
|
55
|
-
- `FileSystemCassetteStore`
|
|
56
|
-
- `VcrHttpClient`
|
|
57
|
-
- `VcrConfig`
|
|
58
|
-
- `VcrMode`
|
|
59
|
-
- `VcrRequest`
|
|
60
|
-
- `VcrResponse`
|
|
61
|
-
- `VcrEntry`
|
|
62
|
-
- `Cassette`
|
|
63
|
-
- `CassetteFile`
|
|
64
|
-
|
|
65
|
-
Focused subpath exports are also available:
|
|
66
|
-
|
|
67
|
-
- `@useairfoil/effect-vcr/cassette-store`
|
|
68
|
-
- `@useairfoil/effect-vcr/file-system-cassette-store`
|
|
69
|
-
- `@useairfoil/effect-vcr/types`
|
|
70
|
-
- `@useairfoil/effect-vcr/vcr-http-client`
|
|
71
|
-
|
|
72
12
|
## Usage
|
|
73
13
|
|
|
74
|
-
Use
|
|
75
|
-
|
|
76
|
-
- `VcrHttpClient` wraps an existing `HttpClient` and adds record/replay behavior
|
|
77
|
-
- `FileSystemCassetteStore` persists cassette files to disk
|
|
78
|
-
|
|
79
|
-
`VcrHttpClient.layer(...)` depends on:
|
|
80
|
-
|
|
81
|
-
- a live `HttpClient` implementation such as `FetchHttpClient.layer`
|
|
82
|
-
- `Path.Path` for cassette name resolution
|
|
83
|
-
- `CassetteStore.CassetteStore` for persistence
|
|
84
|
-
|
|
85
|
-
`FileSystemCassetteStore.layer(...)` depends on:
|
|
86
|
-
|
|
87
|
-
- `FileSystem.FileSystem`
|
|
88
|
-
- `Path.Path`
|
|
89
|
-
|
|
90
|
-
In Node tests, `NodeServices.layer` satisfies those platform services.
|
|
91
|
-
|
|
92
|
-
## Configuration and defaults
|
|
93
|
-
|
|
94
|
-
### VcrHttpClient
|
|
95
|
-
|
|
96
|
-
```ts
|
|
97
|
-
type VcrConfig = {
|
|
98
|
-
readonly vcrName?: string;
|
|
99
|
-
readonly cassetteName?: string;
|
|
100
|
-
readonly mode?: "record" | "replay" | "auto";
|
|
101
|
-
readonly redact?: {
|
|
102
|
-
readonly requestHeaders?: ReadonlyArray<string>;
|
|
103
|
-
readonly responseHeaders?: ReadonlyArray<string>;
|
|
104
|
-
readonly requestBodyKeys?: ReadonlyArray<string>;
|
|
105
|
-
readonly responseBodyKeys?: ReadonlyArray<string>;
|
|
106
|
-
readonly requestBodyReplacements?: Readonly<Record<string, string | number | boolean | null>>;
|
|
107
|
-
readonly responseBodyReplacements?: Readonly<Record<string, string | number | boolean | null>>;
|
|
108
|
-
};
|
|
109
|
-
readonly matchIgnore?: {
|
|
110
|
-
readonly requestHeaders?: ReadonlyArray<string>;
|
|
111
|
-
readonly requestBodyKeys?: ReadonlyArray<string>;
|
|
112
|
-
};
|
|
113
|
-
readonly match?: (request: VcrRequest, entry: VcrEntry) => boolean;
|
|
114
|
-
};
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
- `vcrName?: string`
|
|
118
|
-
- logical VCR name used by `ACK_DISABLE_VCR`
|
|
119
|
-
- `cassetteName?: string`
|
|
120
|
-
- cassette file basename or full file name
|
|
121
|
-
- `users` resolves to `users.cassette`
|
|
122
|
-
- `users.cassette` is preserved as-is
|
|
123
|
-
- when omitted in Vitest, the cassette file defaults to `<test-file>.cassette` and the current test name becomes the export key inside that file
|
|
124
|
-
- `mode?: "record" | "replay" | "auto"`
|
|
125
|
-
- `record`: always call the live client and write a cassette
|
|
126
|
-
- `replay`: only serve from cassette; missing entries fail
|
|
127
|
-
- `auto`: replay if the cassette exists, otherwise record; when `CI=true`, missing cassettes fail instead of recording
|
|
128
|
-
- `redact`
|
|
129
|
-
- remove sensitive headers or JSON and URL-encoded body keys before writing to disk
|
|
130
|
-
- replace body values with safe placeholders when the field must remain available during replay
|
|
131
|
-
- request fields redacted here are also ignored when building cassette keys
|
|
132
|
-
- `matchIgnore`
|
|
133
|
-
- ignore request headers or JSON and URL-encoded body keys when computing the request lookup key
|
|
134
|
-
- `match`
|
|
135
|
-
- custom request matcher for advanced lookup behavior
|
|
136
|
-
|
|
137
|
-
Defaults:
|
|
138
|
-
|
|
139
|
-
- `mode` defaults to `"auto"`
|
|
140
|
-
- `authorization` is ignored for matching by default
|
|
141
|
-
- `authorization` is redacted from recorded request headers by default
|
|
142
|
-
|
|
143
|
-
### FileSystemCassetteStore
|
|
144
|
-
|
|
145
|
-
- `cassetteDir?: string`
|
|
146
|
-
- changes the cassette root directory
|
|
147
|
-
- when omitted in Vitest, cassettes are written to the `__cassettes__` directory beside the test file
|
|
148
|
-
- outside Vitest, provide `cassetteDir` explicitly
|
|
149
|
-
|
|
150
|
-
## Matching and redaction
|
|
151
|
-
|
|
152
|
-
`matchIgnore` and `redact` solve different problems.
|
|
153
|
-
|
|
154
|
-
- `matchIgnore` changes how requests are matched to cassette entries
|
|
155
|
-
- `redact` changes what is persisted to disk
|
|
156
|
-
|
|
157
|
-
Typical usage:
|
|
158
|
-
|
|
159
|
-
```ts
|
|
160
|
-
const vcrLayer = VcrHttpClient.layer({
|
|
161
|
-
vcrName: "shopify-products",
|
|
162
|
-
mode: "auto",
|
|
163
|
-
redact: {
|
|
164
|
-
requestHeaders: ["x-shopify-access-token", "authorization"],
|
|
165
|
-
requestBodyReplacements: {
|
|
166
|
-
client_secret: "client-secret-placeholder",
|
|
167
|
-
},
|
|
168
|
-
responseBodyReplacements: {
|
|
169
|
-
access_token: "access-token-placeholder",
|
|
170
|
-
},
|
|
171
|
-
},
|
|
172
|
-
});
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
Use `matchIgnore` when a request field should not affect cassette identity.
|
|
176
|
-
|
|
177
|
-
Use `redact` when a field should never be written to disk.
|
|
178
|
-
Replacement values are useful for fields such as access tokens that a replayed
|
|
179
|
-
response must still contain. If body redaction changes the encoded length, the VCR
|
|
180
|
-
also removes and ignores the stale `content-length` header.
|
|
181
|
-
|
|
182
|
-
## Runtime configuration
|
|
183
|
-
|
|
184
|
-
The VCR is controlled by the following environment variables:
|
|
185
|
-
|
|
186
|
-
- `CI=true`
|
|
187
|
-
- if the VCR mode is `auto`, tests with a missing cassette fail instead of recording
|
|
188
|
-
- `ACK_DISABLE_VCR=<...>`
|
|
189
|
-
- disables the VCR and falls back to the wrapped live client
|
|
190
|
-
- `*` disables all configured VCRs
|
|
191
|
-
- a comma-separated list disables only matching `vcrName` values
|
|
192
|
-
|
|
193
|
-
When the VCR is disabled, cassette files are not updated.
|
|
194
|
-
|
|
195
|
-
## Common patterns
|
|
196
|
-
|
|
197
|
-
### Build the VCR runtime once
|
|
14
|
+
Use `VcrHttpClient.layer(...)` around the live Effect HTTP client and
|
|
15
|
+
`FileSystemCassetteStore.layer(...)` for cassette files.
|
|
198
16
|
|
|
199
17
|
```ts
|
|
200
|
-
|
|
18
|
+
import { NodeServices } from "@effect/platform-node";
|
|
19
|
+
import { FileSystemCassetteStore, VcrHttpClient } from "@useairfoil/effect-vcr";
|
|
20
|
+
import { Layer } from "effect";
|
|
21
|
+
import { FetchHttpClient } from "effect/http";
|
|
201
22
|
|
|
202
|
-
const
|
|
203
|
-
FetchHttpClient.layer,
|
|
204
|
-
NodeServices.layer,
|
|
205
|
-
cassetteStoreLayer,
|
|
206
|
-
);
|
|
23
|
+
const store = FileSystemCassetteStore.layer().pipe(Layer.provide(NodeServices.layer));
|
|
207
24
|
|
|
208
|
-
const
|
|
209
|
-
vcrName: "
|
|
25
|
+
const VcrLive = VcrHttpClient.layer({
|
|
26
|
+
vcrName: "provider-api",
|
|
210
27
|
mode: "auto",
|
|
211
|
-
}).pipe(Layer.provide(
|
|
28
|
+
}).pipe(Layer.provide(Layer.mergeAll(FetchHttpClient.layer, NodeServices.layer, store)));
|
|
212
29
|
```
|
|
213
30
|
|
|
214
|
-
|
|
31
|
+
Auto mode replays a cassette if it is present. It records one if it is missing.
|
|
32
|
+
On CI, a missing cassette fails. `ACK_DISABLE_VCR=*` skips VCR and uses live
|
|
33
|
+
HTTP.
|
|
215
34
|
|
|
216
|
-
|
|
217
|
-
|
|
35
|
+
Requests match on method, URL with its query params, headers, and body.
|
|
36
|
+
Authorization headers are ignored while matching and removed before a cassette
|
|
37
|
+
is written. Add other secrets to `redact`. Query params listed in
|
|
38
|
+
`redact.requestQueryParams` are removed from the cassette and ignored while
|
|
39
|
+
matching, which also helps when a param comes from local config.
|
|
218
40
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
```ts
|
|
222
|
-
import { ConfigProvider, Layer } from "effect";
|
|
41
|
+
Requests can record at the same time. Cassette writes take turns, so no entry
|
|
42
|
+
is lost.
|
|
223
43
|
|
|
224
|
-
|
|
225
|
-
vcrRuntimeLayer,
|
|
226
|
-
ConfigProvider.layer(
|
|
227
|
-
ConfigProvider.fromUnknown({
|
|
228
|
-
CI: false,
|
|
229
|
-
ACK_DISABLE_VCR: "",
|
|
230
|
-
}),
|
|
231
|
-
),
|
|
232
|
-
);
|
|
233
|
-
|
|
234
|
-
const vcrLayer = VcrHttpClient.layer({
|
|
235
|
-
vcrName: "example",
|
|
236
|
-
mode: "auto",
|
|
237
|
-
}).pipe(Layer.provide(vcrTestRuntimeLayer));
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
### Use focused subpath imports
|
|
241
|
-
|
|
242
|
-
```ts
|
|
243
|
-
import * as VcrHttpClient from "@useairfoil/effect-vcr/vcr-http-client";
|
|
244
|
-
import * as FileSystemCassetteStore from "@useairfoil/effect-vcr/file-system-cassette-store";
|
|
245
|
-
```
|
|
44
|
+
## Configuration
|
|
246
45
|
|
|
247
|
-
|
|
46
|
+
| Variable | Required | Default |
|
|
47
|
+
| ----------------- | -------- | ------- |
|
|
48
|
+
| `CI` | no | `false` |
|
|
49
|
+
| `ACK_DISABLE_VCR` | no | empty |
|
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
import { n as CassetteFile } from "./types-
|
|
1
|
+
import { n as CassetteFile } from "./types-v6cSTgDp.mjs";
|
|
2
2
|
import { Context, Effect } from "effect";
|
|
3
|
-
import * as effect_Types0 from "effect/Types";
|
|
4
|
-
import * as effect_Cause0 from "effect/Cause";
|
|
5
|
-
|
|
6
|
-
//#region src/cassette-store.d.ts
|
|
7
3
|
declare namespace cassette_store_d_exports {
|
|
8
4
|
export { CassetteStore, CassetteStoreError, CassetteStoreOperation, CassetteStoreService, createEmptyCassette, createEmptyCassetteFile, make, parseCassette, toStoreError };
|
|
9
5
|
}
|
|
10
|
-
type CassetteStoreOperation = "exists" | "load" | "save" | "loadOrInit" | "resolveRoot";
|
|
6
|
+
export type CassetteStoreOperation = "exists" | "load" | "save" | "loadOrInit" | "resolveRoot";
|
|
11
7
|
/**
|
|
12
8
|
* Storage contract for VCR cassettes.
|
|
13
9
|
*
|
|
14
10
|
*/
|
|
15
|
-
interface CassetteStoreService {
|
|
11
|
+
export interface CassetteStoreService {
|
|
16
12
|
/** Returns true if a cassette with the given name exists. */
|
|
17
13
|
readonly exists: (name: string) => Effect.Effect<boolean, CassetteStoreError>;
|
|
18
14
|
/** Loads a cassette by name, returning a `CassetteFile` if found. */
|
|
@@ -26,11 +22,11 @@ declare const CassetteStore_base: Context.ServiceClass<CassetteStore, "@useairfo
|
|
|
26
22
|
/**
|
|
27
23
|
* Effect service tag for the cassette store.
|
|
28
24
|
*/
|
|
29
|
-
declare class CassetteStore extends CassetteStore_base {}
|
|
25
|
+
export declare class CassetteStore extends CassetteStore_base {}
|
|
30
26
|
/**
|
|
31
27
|
* Creates a new empty cassette with a timestamp and format version.
|
|
32
28
|
*/
|
|
33
|
-
declare const createEmptyCassette: () => Effect.Effect<{
|
|
29
|
+
export declare const createEmptyCassette: () => Effect.Effect<{
|
|
34
30
|
readonly meta: {
|
|
35
31
|
readonly createdAt: string;
|
|
36
32
|
readonly version: string;
|
|
@@ -55,8 +51,8 @@ declare const createEmptyCassette: () => Effect.Effect<{
|
|
|
55
51
|
};
|
|
56
52
|
};
|
|
57
53
|
}, never, never>;
|
|
58
|
-
declare const createEmptyCassetteFile: () => Effect.Effect<CassetteFile>;
|
|
59
|
-
declare const CassetteStoreError_base: new <A extends Record<string, any> = {}>(args:
|
|
54
|
+
export declare const createEmptyCassetteFile: () => Effect.Effect<CassetteFile>;
|
|
55
|
+
declare const CassetteStoreError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
60
56
|
readonly _tag: "CassetteStoreError";
|
|
61
57
|
} & Readonly<A>;
|
|
62
58
|
/**
|
|
@@ -65,19 +61,19 @@ declare const CassetteStoreError_base: new <A extends Record<string, any> = {}>(
|
|
|
65
61
|
* `operation` indicates which store function failed.
|
|
66
62
|
* `path` is the file or directory path that was targeted.
|
|
67
63
|
*/
|
|
68
|
-
declare class CassetteStoreError extends CassetteStoreError_base<{
|
|
64
|
+
export declare class CassetteStoreError extends CassetteStoreError_base<{
|
|
69
65
|
readonly operation: CassetteStoreOperation;
|
|
70
66
|
readonly path: string;
|
|
71
67
|
readonly message?: string;
|
|
72
68
|
readonly cause?: unknown;
|
|
73
69
|
}> {}
|
|
74
|
-
declare const toStoreError: (operation: CassetteStoreOperation, path: string, cause?: unknown, message?: string) => CassetteStoreError;
|
|
70
|
+
export declare const toStoreError: (operation: CassetteStoreOperation, path: string, cause?: unknown, message?: string) => CassetteStoreError;
|
|
75
71
|
/**
|
|
76
72
|
* Parses cassette JSON and maps invalid JSON or an invalid cassette shape to a store error.
|
|
77
73
|
*/
|
|
78
|
-
declare const parseCassette: (content: string, path: string) => Effect.Effect<CassetteFile, CassetteStoreError>;
|
|
74
|
+
export declare const parseCassette: (content: string, path: string) => Effect.Effect<CassetteFile, CassetteStoreError>;
|
|
79
75
|
/** Creates a `CassetteStore` implementation that uses the given `impl` object. */
|
|
80
|
-
declare const make: (impl: CassetteStoreService) => CassetteStoreService;
|
|
76
|
+
export declare const make: (impl: CassetteStoreService) => CassetteStoreService;
|
|
81
77
|
//#endregion
|
|
82
|
-
export { cassette_store_d_exports as
|
|
83
|
-
//# sourceMappingURL=cassette-store
|
|
78
|
+
export { cassette_store_d_exports as t };
|
|
79
|
+
//# sourceMappingURL=cassette-store.d.mts.map
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import {
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
+
import { CassetteFileSchema } from "./types.mjs";
|
|
3
3
|
import { Context, Data, DateTime, Effect, Schema } from "effect";
|
|
4
|
-
|
|
5
4
|
//#region src/cassette-store.ts
|
|
6
|
-
var cassette_store_exports = /* @__PURE__ */
|
|
5
|
+
var cassette_store_exports = /* @__PURE__ */ __exportAll({
|
|
7
6
|
CassetteStore: () => CassetteStore,
|
|
8
7
|
CassetteStoreError: () => CassetteStoreError,
|
|
9
8
|
createEmptyCassette: () => createEmptyCassette,
|
|
@@ -52,7 +51,7 @@ const parseCassette = (content, path) => Effect.try({
|
|
|
52
51
|
}).pipe(Effect.flatMap((parsed) => Schema.decodeUnknownEffect(CassetteFileSchema)(parsed).pipe(Effect.mapError((error) => toStoreError("load", path, error, "Invalid cassette file format")))));
|
|
53
52
|
/** Creates a `CassetteStore` implementation that uses the given `impl` object. */
|
|
54
53
|
const make = (impl) => CassetteStore.of({ ...impl });
|
|
55
|
-
|
|
56
54
|
//#endregion
|
|
57
|
-
export {
|
|
58
|
-
|
|
55
|
+
export { CassetteStore, CassetteStoreError, createEmptyCassette, createEmptyCassetteFile, make, parseCassette, cassette_store_exports as t, toStoreError };
|
|
56
|
+
|
|
57
|
+
//# sourceMappingURL=cassette-store.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cassette-store.mjs","names":[],"sources":["../src/cassette-store.ts"],"sourcesContent":["import { Context, Data, DateTime, Effect, Schema } from \"effect\";\n\nimport { CassetteFileSchema, type Cassette, type CassetteFile } from \"./types\";\n\nexport type CassetteStoreOperation = \"exists\" | \"load\" | \"save\" | \"loadOrInit\" | \"resolveRoot\";\n\n/**\n * Storage contract for VCR cassettes.\n *\n */\nexport interface CassetteStoreService {\n /** Returns true if a cassette with the given name exists. */\n readonly exists: (name: string) => Effect.Effect<boolean, CassetteStoreError>;\n\n /** Loads a cassette by name, returning a `CassetteFile` if found. */\n readonly load: (name: string) => Effect.Effect<CassetteFile, CassetteStoreError>;\n\n /** Saves a cassette by name, overwriting any existing cassette with the same name. */\n readonly save: (name: string, content: CassetteFile) => Effect.Effect<void, CassetteStoreError>;\n\n /** Loads a cassette by name, initializing a new empty cassette if not found. */\n readonly loadOrInit: (name: string) => Effect.Effect<CassetteFile, CassetteStoreError>;\n}\n\n/**\n * Effect service tag for the cassette store.\n */\nexport class CassetteStore extends Context.Service<CassetteStore, CassetteStoreService>()(\n \"@useairfoil/effect-vcr/CassetteStore\",\n) {}\n\n/**\n * Creates a new empty cassette with a timestamp and format version.\n */\nexport const createEmptyCassette = Effect.fnUntraced(function* (): Effect.fn.Return<Cassette> {\n const now = yield* DateTime.now;\n return {\n meta: {\n createdAt: DateTime.formatIso(now),\n version: \"1\",\n },\n entries: {},\n };\n});\n\nexport const createEmptyCassetteFile = (): Effect.Effect<CassetteFile> =>\n Effect.map(createEmptyCassette(), (cassette) => ({\n exports: { default: cassette },\n }));\n\n/**\n * Structured error for cassette persistence operations.\n *\n * `operation` indicates which store function failed.\n * `path` is the file or directory path that was targeted.\n */\nexport class CassetteStoreError extends Data.TaggedError(\"CassetteStoreError\")<{\n readonly operation: CassetteStoreOperation;\n readonly path: string;\n readonly message?: string;\n readonly cause?: unknown;\n}> {}\n\nexport const toStoreError = (\n operation: CassetteStoreOperation,\n path: string,\n cause?: unknown,\n message?: string,\n) =>\n new CassetteStoreError({\n operation,\n path,\n cause,\n message,\n });\n\n/**\n * Parses cassette JSON and maps invalid JSON or an invalid cassette shape to a store error.\n */\nexport const parseCassette = (\n content: string,\n path: string,\n): Effect.Effect<CassetteFile, CassetteStoreError> =>\n Effect.try({\n try: () => JSON.parse(content) as unknown,\n catch: (error) => toStoreError(\"load\", path, error, \"Invalid JSON\"),\n }).pipe(\n Effect.flatMap((parsed) =>\n Schema.decodeUnknownEffect(CassetteFileSchema)(parsed).pipe(\n Effect.mapError((error) =>\n toStoreError(\"load\", path, error, \"Invalid cassette file format\"),\n ),\n ),\n ),\n );\n\n/** Creates a `CassetteStore` implementation that uses the given `impl` object. */\nexport const make = (impl: CassetteStoreService): CassetteStoreService =>\n CassetteStore.of({ ...impl });\n"],"mappings":";;;;;;;;;;;;;;;;AA2BA,IAAa,gBAAb,cAAmC,QAAQ,QAA6C,CAAC,CACvF,sCACF,CAAC,CAAC,CAAC;;;;AAKH,MAAa,sBAAsB,OAAO,WAAW,aAAyC;CAC5F,MAAM,MAAM,OAAO,SAAS;CAC5B,OAAO;EACL,MAAM;GACJ,WAAW,SAAS,UAAU,GAAG;GACjC,SAAS;EACX;EACA,SAAS,CAAC;CACZ;AACF,CAAC;AAED,MAAa,gCACX,OAAO,IAAI,oBAAoB,IAAI,cAAc,EAC/C,SAAS,EAAE,SAAS,SAAS,EAC/B,EAAE;;;;;;;AAQJ,IAAa,qBAAb,cAAwC,KAAK,YAAY,oBAAoB,CAAC,CAK3E,CAAC;AAEJ,MAAa,gBACX,WACA,MACA,OACA,YAEA,IAAI,mBAAmB;CACrB;CACA;CACA;CACA;AACF,CAAC;;;;AAKH,MAAa,iBACX,SACA,SAEA,OAAO,IAAI;CACT,WAAW,KAAK,MAAM,OAAO;CAC7B,QAAQ,UAAU,aAAa,QAAQ,MAAM,OAAO,cAAc;AACpE,CAAC,CAAC,CAAC,KACD,OAAO,SAAS,WACd,OAAO,oBAAoB,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC,KACrD,OAAO,UAAU,UACf,aAAa,QAAQ,MAAM,OAAO,8BAA8B,CAClE,CACF,CACF,CACF;;AAGF,MAAa,QAAQ,SACnB,cAAc,GAAG,EAAE,GAAG,KAAK,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CassetteStore, CassetteStoreError, t as cassette_store_d_exports } from "./cassette-store.mjs";
|
|
2
|
+
import { FileSystem, Layer, Path } from "effect";
|
|
3
|
+
declare namespace file_system_cassette_store_d_exports {
|
|
4
|
+
export { FileSystemCassetteStoreConfig, layer };
|
|
5
|
+
}
|
|
6
|
+
export type FileSystemCassetteStoreConfig = {
|
|
7
|
+
readonly cassetteDir?: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* FileSystem-backed cassette store.
|
|
11
|
+
*
|
|
12
|
+
* Requires a platform FileSystem layer (Node/Bun) to be provided by the user.
|
|
13
|
+
*/
|
|
14
|
+
export declare const layer: (config?: FileSystemCassetteStoreConfig) => Layer.Layer<CassetteStore, CassetteStoreError, FileSystem.FileSystem | Path.Path>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { file_system_cassette_store_d_exports as t };
|
|
17
|
+
//# sourceMappingURL=file-system-cassette-store.d.mts.map
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import {
|
|
3
|
-
import { t as getVitestState } from "./vitest-state-
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
+
import { CassetteStore, createEmptyCassetteFile, make, parseCassette, toStoreError } from "./cassette-store.mjs";
|
|
3
|
+
import { t as getVitestState } from "./vitest-state-rX5XIlH6.mjs";
|
|
4
4
|
import { Effect, FileSystem, Layer, Path } from "effect";
|
|
5
|
-
|
|
6
5
|
//#region src/file-system-cassette-store.ts
|
|
7
|
-
var file_system_cassette_store_exports = /* @__PURE__ */
|
|
6
|
+
var file_system_cassette_store_exports = /* @__PURE__ */ __exportAll({ layer: () => layer });
|
|
8
7
|
/**
|
|
9
8
|
* FileSystem-backed cassette store.
|
|
10
9
|
*
|
|
@@ -36,7 +35,7 @@ const layer = (config = {}) => Layer.effect(CassetteStore)(Effect.gen(function*
|
|
|
36
35
|
loadOrInit
|
|
37
36
|
});
|
|
38
37
|
}));
|
|
39
|
-
|
|
40
38
|
//#endregion
|
|
41
|
-
export { layer
|
|
42
|
-
|
|
39
|
+
export { layer, file_system_cassette_store_exports as t };
|
|
40
|
+
|
|
41
|
+
//# sourceMappingURL=file-system-cassette-store.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-system-cassette-store.mjs","names":["CassetteStore.CassetteStore","CassetteStore.toStoreError","CassetteStore.parseCassette","CassetteStore.createEmptyCassetteFile","CassetteStore.make"],"sources":["../src/file-system-cassette-store.ts"],"sourcesContent":["import { Effect, Layer, FileSystem, Path } from \"effect\";\n\nimport type { CassetteFile } from \"./types\";\n\nimport * as CassetteStore from \"./cassette-store\";\nimport { getVitestState } from \"./vitest-state\";\n\nexport type FileSystemCassetteStoreConfig = {\n readonly cassetteDir?: string;\n};\n\n/**\n * FileSystem-backed cassette store.\n *\n * Requires a platform FileSystem layer (Node/Bun) to be provided by the user.\n */\nexport const layer = (config: FileSystemCassetteStoreConfig = {}) =>\n Layer.effect(CassetteStore.CassetteStore)(\n Effect.gen(function* () {\n const fs = yield* FileSystem.FileSystem;\n const path = yield* Path.Path;\n\n let rootDir: string;\n if (config.cassetteDir) {\n rootDir = config.cassetteDir;\n } else {\n const { testPath } = getVitestState();\n if (!testPath) {\n return yield* Effect.fail(\n CassetteStore.toStoreError(\n \"resolveRoot\",\n \"__cassettes__\",\n undefined,\n \"VCR cassette directory could not be inferred. Provide cassetteDir when not running in Vitest.\",\n ),\n );\n }\n const testFolder = path.dirname(testPath);\n rootDir = path.join(testFolder, \"__cassettes__\");\n }\n\n const fullPath = (name: string) => path.join(rootDir, name);\n\n const load = (name: string) =>\n fs.readFileString(fullPath(name)).pipe(\n Effect.mapError((error) => CassetteStore.toStoreError(\"load\", name, error)),\n Effect.flatMap((content) => CassetteStore.parseCassette(content, name)),\n );\n\n const save = (name: string, cassette: CassetteFile) => {\n const filePath = fullPath(name);\n const dir = path.dirname(filePath);\n const ensureDir =\n dir === \"\"\n ? Effect.void\n : fs\n .makeDirectory(dir, { recursive: true })\n .pipe(Effect.mapError((error) => CassetteStore.toStoreError(\"save\", dir, error)));\n return ensureDir.pipe(\n Effect.andThen(\n fs\n .writeFileString(filePath, JSON.stringify(cassette, null, 2))\n .pipe(Effect.mapError((error) => CassetteStore.toStoreError(\"save\", name, error))),\n ),\n );\n };\n\n const loadOrInit = (name: string) =>\n fs.exists(fullPath(name)).pipe(\n Effect.mapError((error) => CassetteStore.toStoreError(\"loadOrInit\", name, error)),\n Effect.flatMap((exists) =>\n exists\n ? load(name)\n : CassetteStore.createEmptyCassetteFile().pipe(\n Effect.tap((cassette) => save(name, cassette)),\n ),\n ),\n );\n\n return CassetteStore.make({\n exists: (name: string) =>\n fs\n .exists(fullPath(name))\n .pipe(Effect.mapError((error) => CassetteStore.toStoreError(\"exists\", name, error))),\n load,\n save,\n loadOrInit,\n });\n }),\n );\n"],"mappings":";;;;;;;;;;;AAgBA,MAAa,SAAS,SAAwC,CAAC,MAC7D,MAAM,OAAOA,aAA2B,CAAC,CACvC,OAAO,IAAI,aAAa;CACtB,MAAM,KAAK,OAAO,WAAW;CAC7B,MAAM,OAAO,OAAO,KAAK;CAEzB,IAAI;CACJ,IAAI,OAAO,aACT,UAAU,OAAO;MACZ;EACL,MAAM,EAAE,aAAa,eAAe;EACpC,IAAI,CAAC,UACH,OAAO,OAAO,OAAO,KACnBC,aACE,eACA,iBACA,KAAA,GACA,+FACF,CACF;EAEF,MAAM,aAAa,KAAK,QAAQ,QAAQ;EACxC,UAAU,KAAK,KAAK,YAAY,eAAe;CACjD;CAEA,MAAM,YAAY,SAAiB,KAAK,KAAK,SAAS,IAAI;CAE1D,MAAM,QAAQ,SACZ,GAAG,eAAe,SAAS,IAAI,CAAC,CAAC,CAAC,KAChC,OAAO,UAAU,UAAUA,aAA2B,QAAQ,MAAM,KAAK,CAAC,GAC1E,OAAO,SAAS,YAAYC,cAA4B,SAAS,IAAI,CAAC,CACxE;CAEF,MAAM,QAAQ,MAAc,aAA2B;EACrD,MAAM,WAAW,SAAS,IAAI;EAC9B,MAAM,MAAM,KAAK,QAAQ,QAAQ;EAOjC,QALE,QAAQ,KACJ,OAAO,OACP,GACG,cAAc,KAAK,EAAE,WAAW,KAAK,CAAC,CAAC,CACvC,KAAK,OAAO,UAAU,UAAUD,aAA2B,QAAQ,KAAK,KAAK,CAAC,CAAC,EAAA,CACvE,KACf,OAAO,QACL,GACG,gBAAgB,UAAU,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC,CAAC,CAC5D,KAAK,OAAO,UAAU,UAAUA,aAA2B,QAAQ,MAAM,KAAK,CAAC,CAAC,CACrF,CACF;CACF;CAEA,MAAM,cAAc,SAClB,GAAG,OAAO,SAAS,IAAI,CAAC,CAAC,CAAC,KACxB,OAAO,UAAU,UAAUA,aAA2B,cAAc,MAAM,KAAK,CAAC,GAChF,OAAO,SAAS,WACd,SACI,KAAK,IAAI,IACTE,wBAAsC,CAAC,CAAC,KACtC,OAAO,KAAK,aAAa,KAAK,MAAM,QAAQ,CAAC,CAC/C,CACN,CACF;CAEF,OAAOC,KAAmB;EACxB,SAAS,SACP,GACG,OAAO,SAAS,IAAI,CAAC,CAAC,CACtB,KAAK,OAAO,UAAU,UAAUH,aAA2B,UAAU,MAAM,KAAK,CAAC,CAAC;EACvF;EACA;EACA;CACF,CAAC;AACH,CAAC,CACH"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as VcrConfig, c as VcrMode, d as VcrRequestSchema, f as VcrResponse, i as CassetteSchema, l as VcrRedactedValue, n as CassetteFile, o as VcrEntry, p as VcrResponseSchema, r as CassetteFileSchema, s as VcrEntrySchema, t as Cassette, u as VcrRequest } from "./types-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { a as VcrConfig, c as VcrMode, d as VcrRequestSchema, f as VcrResponse, i as CassetteSchema, l as VcrRedactedValue, n as CassetteFile, o as VcrEntry, p as VcrResponseSchema, r as CassetteFileSchema, s as VcrEntrySchema, t as Cassette, u as VcrRequest } from "./types-v6cSTgDp.mjs";
|
|
2
|
+
import { t as cassette_store_d_exports } from "./cassette-store.mjs";
|
|
3
|
+
import { t as file_system_cassette_store_d_exports } from "./file-system-cassette-store.mjs";
|
|
4
|
+
import { t as vcr_http_client_d_exports } from "./vcr-http-client.mjs";
|
|
5
5
|
export { Cassette, CassetteFile, CassetteFileSchema, CassetteSchema, cassette_store_d_exports as CassetteStore, file_system_cassette_store_d_exports as FileSystemCassetteStore, VcrConfig, VcrEntry, VcrEntrySchema, vcr_http_client_d_exports as VcrHttpClient, VcrMode, VcrRedactedValue, VcrRequest, VcrRequestSchema, VcrResponse, VcrResponseSchema };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { CassetteFileSchema, CassetteSchema, VcrEntrySchema, VcrRequestSchema, VcrResponseSchema } from "./types.mjs";
|
|
2
|
+
import { t as cassette_store_exports } from "./cassette-store.mjs";
|
|
3
|
+
import { t as file_system_cassette_store_exports } from "./file-system-cassette-store.mjs";
|
|
4
|
+
import { r as vcr_http_client_exports } from "./vcr-http-client-5K20k6US.mjs";
|
|
5
|
+
export { CassetteFileSchema, CassetteSchema, cassette_store_exports as CassetteStore, file_system_cassette_store_exports as FileSystemCassetteStore, VcrEntrySchema, vcr_http_client_exports as VcrHttpClient, VcrRequestSchema, VcrResponseSchema };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
//#region
|
|
1
|
+
//#region \0rolldown/runtime.js
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
|
-
var
|
|
3
|
+
var __exportAll = (all, no_symbols) => {
|
|
4
4
|
let target = {};
|
|
5
5
|
for (var name in all) __defProp(target, name, {
|
|
6
6
|
get: all[name],
|
|
7
7
|
enumerable: true
|
|
8
8
|
});
|
|
9
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
9
10
|
return target;
|
|
10
11
|
};
|
|
11
|
-
|
|
12
12
|
//#endregion
|
|
13
|
-
export {
|
|
13
|
+
export { __exportAll as t };
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
|
-
|
|
3
2
|
//#region src/types.d.ts
|
|
4
|
-
|
|
5
3
|
/**
|
|
6
4
|
* VCR operating mode.
|
|
7
5
|
* - record: always call the live client and persist.
|
|
@@ -114,6 +112,8 @@ type VcrConfig = {
|
|
|
114
112
|
* Remove or replace sensitive data before writing to disk.
|
|
115
113
|
*/
|
|
116
114
|
readonly redact?: {
|
|
115
|
+
/** Removed from the recorded URL and ignored when matching. */
|
|
116
|
+
readonly requestQueryParams?: ReadonlyArray<string>;
|
|
117
117
|
readonly requestHeaders?: ReadonlyArray<string>;
|
|
118
118
|
readonly responseHeaders?: ReadonlyArray<string>;
|
|
119
119
|
readonly requestBodyKeys?: ReadonlyArray<string>;
|
|
@@ -135,4 +135,4 @@ type VcrConfig = {
|
|
|
135
135
|
};
|
|
136
136
|
//#endregion
|
|
137
137
|
export { VcrConfig as a, VcrMode as c, VcrRequestSchema as d, VcrResponse as f, CassetteSchema as i, VcrRedactedValue as l, CassetteFile as n, VcrEntry as o, VcrResponseSchema as p, CassetteFileSchema as r, VcrEntrySchema as s, Cassette as t, VcrRequest as u };
|
|
138
|
-
//# sourceMappingURL=types-
|
|
138
|
+
//# sourceMappingURL=types-v6cSTgDp.d.mts.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as VcrConfig, c as VcrMode, d as VcrRequestSchema, f as VcrResponse, i as CassetteSchema, l as VcrRedactedValue, n as CassetteFile, o as VcrEntry, p as VcrResponseSchema, r as CassetteFileSchema, s as VcrEntrySchema, t as Cassette, u as VcrRequest } from "./types-
|
|
1
|
+
import { a as VcrConfig, c as VcrMode, d as VcrRequestSchema, f as VcrResponse, i as CassetteSchema, l as VcrRedactedValue, n as CassetteFile, o as VcrEntry, p as VcrResponseSchema, r as CassetteFileSchema, s as VcrEntrySchema, t as Cassette, u as VcrRequest } from "./types-v6cSTgDp.mjs";
|
|
2
2
|
export { Cassette, CassetteFile, CassetteFileSchema, CassetteSchema, VcrConfig, VcrEntry, VcrEntrySchema, VcrMode, VcrRedactedValue, VcrRequest, VcrRequestSchema, VcrResponse, VcrResponseSchema };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Schema } from "effect";
|
|
2
|
-
|
|
3
2
|
//#region src/types.ts
|
|
4
3
|
/**
|
|
5
4
|
* Serialized request shape stored in a cassette.
|
|
@@ -39,7 +38,7 @@ const CassetteSchema = Schema.Struct({
|
|
|
39
38
|
* Cassette file format with multiple exports.
|
|
40
39
|
*/
|
|
41
40
|
const CassetteFileSchema = Schema.Struct({ exports: Schema.Record(Schema.String, CassetteSchema) });
|
|
42
|
-
|
|
43
41
|
//#endregion
|
|
44
|
-
export {
|
|
45
|
-
|
|
42
|
+
export { CassetteFileSchema, CassetteSchema, VcrEntrySchema, VcrRequestSchema, VcrResponseSchema };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=types.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.mjs","names":[],"sources":["../src/types.ts"],"sourcesContent":["import { Schema } from \"effect\";\n\n/**\n * VCR operating mode.\n * - record: always call the live client and persist.\n * - replay: serve only from cassette, fail if missing.\n * - auto: replay if cassette exists, otherwise record (fail in CI).\n */\nexport type VcrMode = \"record\" | \"replay\" | \"auto\";\n\n/**\n * Safe scalar value written in place of a sensitive body field.\n */\nexport type VcrRedactedValue = string | number | boolean | null;\n\n/**\n * Serialized request shape stored in a cassette.\n */\nexport const VcrRequestSchema = Schema.Struct({\n method: Schema.String,\n url: Schema.String,\n headers: Schema.optional(Schema.Record(Schema.String, Schema.String)),\n body: Schema.optional(Schema.String),\n});\nexport type VcrRequest = Schema.Schema.Type<typeof VcrRequestSchema>;\n\n/**\n * Serialized response shape stored in a cassette.\n */\nexport const VcrResponseSchema = Schema.Struct({\n status: Schema.Number,\n body: Schema.String,\n headers: Schema.optional(Schema.Record(Schema.String, Schema.String)),\n});\nexport type VcrResponse = Schema.Schema.Type<typeof VcrResponseSchema>;\n\n/**\n * A single request/response pair keyed in the cassette.\n */\nexport const VcrEntrySchema = Schema.Struct({\n request: VcrRequestSchema,\n response: VcrResponseSchema,\n});\nexport type VcrEntry = Schema.Schema.Type<typeof VcrEntrySchema>;\n\n/**\n * Cassette file format.\n */\nexport const CassetteSchema = Schema.Struct({\n meta: Schema.Struct({\n createdAt: Schema.String,\n version: Schema.String,\n }),\n entries: Schema.Record(Schema.String, VcrEntrySchema),\n});\nexport type Cassette = Schema.Schema.Type<typeof CassetteSchema>;\n\n/**\n * Cassette file format with multiple exports.\n */\nexport const CassetteFileSchema = Schema.Struct({\n exports: Schema.Record(Schema.String, CassetteSchema),\n});\nexport type CassetteFile = Schema.Schema.Type<typeof CassetteFileSchema>;\n\n/**\n * VCR configuration.\n */\nexport type VcrConfig = {\n readonly vcrName?: string;\n /**\n * Cassette file name or basename.\n *\n * `users` resolves to `users.cassette`.\n * `users.cassette` is preserved as-is.\n */\n readonly cassetteName?: string;\n readonly mode?: VcrMode;\n /**\n * Remove or replace sensitive data before writing to disk.\n */\n readonly redact?: {\n /** Removed from the recorded URL and ignored when matching. */\n readonly requestQueryParams?: ReadonlyArray<string>;\n readonly requestHeaders?: ReadonlyArray<string>;\n readonly responseHeaders?: ReadonlyArray<string>;\n readonly requestBodyKeys?: ReadonlyArray<string>;\n readonly responseBodyKeys?: ReadonlyArray<string>;\n readonly requestBodyReplacements?: Readonly<Record<string, VcrRedactedValue>>;\n readonly responseBodyReplacements?: Readonly<Record<string, VcrRedactedValue>>;\n };\n /**\n * Ignore fields when computing the request key for replay matching.\n */\n readonly matchIgnore?: {\n readonly requestHeaders?: ReadonlyArray<string>;\n readonly requestBodyKeys?: ReadonlyArray<string>;\n };\n /**\n * Custom matcher to override key-based lookup.\n */\n readonly match?: (request: VcrRequest, entry: VcrEntry) => boolean;\n};\n"],"mappings":";;;;;AAkBA,MAAa,mBAAmB,OAAO,OAAO;CAC5C,QAAQ,OAAO;CACf,KAAK,OAAO;CACZ,SAAS,OAAO,SAAS,OAAO,OAAO,OAAO,QAAQ,OAAO,MAAM,CAAC;CACpE,MAAM,OAAO,SAAS,OAAO,MAAM;AACrC,CAAC;;;;AAMD,MAAa,oBAAoB,OAAO,OAAO;CAC7C,QAAQ,OAAO;CACf,MAAM,OAAO;CACb,SAAS,OAAO,SAAS,OAAO,OAAO,OAAO,QAAQ,OAAO,MAAM,CAAC;AACtE,CAAC;;;;AAMD,MAAa,iBAAiB,OAAO,OAAO;CAC1C,SAAS;CACT,UAAU;AACZ,CAAC;;;;AAMD,MAAa,iBAAiB,OAAO,OAAO;CAC1C,MAAM,OAAO,OAAO;EAClB,WAAW,OAAO;EAClB,SAAS,OAAO;CAClB,CAAC;CACD,SAAS,OAAO,OAAO,OAAO,QAAQ,cAAc;AACtD,CAAC;;;;AAMD,MAAa,qBAAqB,OAAO,OAAO,EAC9C,SAAS,OAAO,OAAO,OAAO,QAAQ,cAAc,EACtD,CAAC"}
|