aws-sdk-vitest-mock 0.3.1 → 0.4.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 +136 -86
- package/index.cjs +1 -1
- package/index.js +32 -32
- package/lib/utils/paginator-helpers.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,6 +43,8 @@ pnpm add -D aws-sdk-vitest-mock
|
|
|
43
43
|
|
|
44
44
|
### Basic Usage
|
|
45
45
|
|
|
46
|
+
> **Note:** `mockClient()` mocks **all instances** of a client class. Use `mockClientInstance()` when you need to mock a specific instance.
|
|
47
|
+
|
|
46
48
|
```typescript
|
|
47
49
|
import { describe, test, expect, beforeEach, afterEach } from "vitest";
|
|
48
50
|
import { mockClient } from "aws-sdk-vitest-mock";
|
|
@@ -65,10 +67,10 @@ describe("DocumentService", () => {
|
|
|
65
67
|
let documentService: DocumentService;
|
|
66
68
|
|
|
67
69
|
beforeEach(() => {
|
|
68
|
-
// Mock
|
|
70
|
+
// Mock all instances of S3Client
|
|
69
71
|
s3Mock = mockClient(S3Client);
|
|
70
72
|
|
|
71
|
-
//
|
|
73
|
+
// Any S3Client instance created after this will be mocked
|
|
72
74
|
const s3Client = new S3Client({ region: "us-east-1" });
|
|
73
75
|
documentService = new DocumentService(s3Client);
|
|
74
76
|
});
|
|
@@ -93,6 +95,18 @@ describe("DocumentService", () => {
|
|
|
93
95
|
});
|
|
94
96
|
```
|
|
95
97
|
|
|
98
|
+
## 🎯 Key Concepts
|
|
99
|
+
|
|
100
|
+
Understanding these concepts will help you use the library effectively:
|
|
101
|
+
|
|
102
|
+
- **`mockClient(ClientClass)`** - Mocks **all instances** of a client class. Use this in most test scenarios where you control client creation.
|
|
103
|
+
- **`mockClientInstance(instance)`** - Mocks a **specific client instance**. Use when the client is created outside your test (e.g., in application bootstrap).
|
|
104
|
+
- **Command Matching** - Commands are matched by constructor. Optionally match by input properties (partial matching by default, strict matching available).
|
|
105
|
+
- **Sequential Responses** - Use `resolvesOnce()` / `rejectsOnce()` for one-time behaviors that fall back to permanent handlers set with `resolves()` / `rejects()`.
|
|
106
|
+
- **Chainable API** - All mock configuration methods return the stub, allowing method chaining for cleaner test setup.
|
|
107
|
+
|
|
108
|
+
## 📖 Usage Guide
|
|
109
|
+
|
|
96
110
|
### Request Matching
|
|
97
111
|
|
|
98
112
|
```typescript
|
|
@@ -121,56 +135,66 @@ s3Mock
|
|
|
121
135
|
// All other calls return 'subsequent calls'
|
|
122
136
|
```
|
|
123
137
|
|
|
124
|
-
###
|
|
125
|
-
|
|
126
|
-
Load mock responses from files for easier test data management:
|
|
138
|
+
### Error Handling
|
|
127
139
|
|
|
128
140
|
```typescript
|
|
129
|
-
|
|
130
|
-
s3Mock.on(GetObjectCommand).resolvesFromFile("./fixtures/s3-response.json");
|
|
141
|
+
s3Mock.on(GetObjectCommand).rejects(new Error("Not found"));
|
|
131
142
|
|
|
132
|
-
//
|
|
133
|
-
s3Mock
|
|
143
|
+
// Or with rejectsOnce
|
|
144
|
+
s3Mock
|
|
145
|
+
.on(GetObjectCommand)
|
|
146
|
+
.rejectsOnce(new Error("Temporary failure"))
|
|
147
|
+
.resolves({ Body: "success" });
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Custom Handlers
|
|
134
151
|
|
|
135
|
-
|
|
136
|
-
|
|
152
|
+
```typescript
|
|
153
|
+
s3Mock.on(GetObjectCommand).callsFake(async (input, getClient) => {
|
|
154
|
+
const client = getClient();
|
|
155
|
+
console.log("Bucket:", input.Bucket);
|
|
156
|
+
return { Body: `Dynamic response for ${input.Key}` };
|
|
157
|
+
});
|
|
137
158
|
```
|
|
138
159
|
|
|
139
|
-
###
|
|
160
|
+
### Mocking Existing Instances
|
|
140
161
|
|
|
141
|
-
|
|
162
|
+
Use `mockClientInstance()` when you need to mock a client that's already been created:
|
|
142
163
|
|
|
143
164
|
```typescript
|
|
144
|
-
//
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}));
|
|
165
|
+
// Your application service that uses an injected S3 client
|
|
166
|
+
class FileUploadService {
|
|
167
|
+
constructor(private s3Client: S3Client) {}
|
|
148
168
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
}
|
|
169
|
+
async uploadFile(bucket: string, key: string, data: string) {
|
|
170
|
+
return await this.s3Client.send(
|
|
171
|
+
new PutObjectCommand({ Bucket: bucket, Key: key, Body: data }),
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
154
175
|
|
|
155
|
-
|
|
156
|
-
//
|
|
157
|
-
|
|
176
|
+
test("should mock existing S3 client instance", async () => {
|
|
177
|
+
// Client is already created (e.g., in application bootstrap)
|
|
178
|
+
const s3Client = new S3Client({ region: "us-east-1" });
|
|
179
|
+
const service = new FileUploadService(s3Client);
|
|
158
180
|
|
|
159
|
-
// Mock
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
}));
|
|
181
|
+
// Mock the specific client instance
|
|
182
|
+
const mock = mockClientInstance(s3Client);
|
|
183
|
+
mock.on(PutObjectCommand).resolves({ ETag: "mock-etag" });
|
|
163
184
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
185
|
+
// Test your service
|
|
186
|
+
const result = await service.uploadFile("bucket", "key", "data");
|
|
187
|
+
|
|
188
|
+
expect(result.ETag).toBe("mock-etag");
|
|
189
|
+
expect(mock).toHaveReceivedCommand(PutObjectCommand);
|
|
168
190
|
});
|
|
169
191
|
```
|
|
170
192
|
|
|
193
|
+
## 🔧 AWS Service Examples
|
|
194
|
+
|
|
171
195
|
### DynamoDB with Marshal/Unmarshal
|
|
172
196
|
|
|
173
|
-
Mock DynamoDB operations using
|
|
197
|
+
Mock DynamoDB operations using marshal/unmarshal utilities for type-safe data handling:
|
|
174
198
|
|
|
175
199
|
```typescript
|
|
176
200
|
import { describe, test, expect, beforeEach, afterEach } from "vitest";
|
|
@@ -265,7 +289,9 @@ describe("UserService with DynamoDB", () => {
|
|
|
265
289
|
});
|
|
266
290
|
```
|
|
267
291
|
|
|
268
|
-
|
|
292
|
+
## 🚀 Advanced Features
|
|
293
|
+
|
|
294
|
+
### Stream Mocking (S3)
|
|
269
295
|
|
|
270
296
|
Mock S3 operations that return streams with automatic environment detection:
|
|
271
297
|
|
|
@@ -283,21 +309,70 @@ s3Mock
|
|
|
283
309
|
.resolvesStream("Subsequent calls");
|
|
284
310
|
```
|
|
285
311
|
|
|
286
|
-
###
|
|
312
|
+
### Paginator Support
|
|
287
313
|
|
|
288
|
-
|
|
314
|
+
Mock AWS SDK v3 pagination with automatic token handling:
|
|
289
315
|
|
|
290
316
|
```typescript
|
|
291
|
-
//
|
|
292
|
-
|
|
317
|
+
// Mock DynamoDB scan with pagination
|
|
318
|
+
// DynamoDB uses different keys for input (ExclusiveStartKey) and output (LastEvaluatedKey)
|
|
319
|
+
const items = Array.from({ length: 25 }, (_, i) => ({
|
|
320
|
+
id: { S: `item-${i + 1}` },
|
|
321
|
+
}));
|
|
293
322
|
|
|
294
|
-
|
|
295
|
-
|
|
323
|
+
dynamoMock.on(ScanCommand).resolvesPaginated(items, {
|
|
324
|
+
pageSize: 10,
|
|
325
|
+
itemsKey: "Items",
|
|
326
|
+
tokenKey: "LastEvaluatedKey", // Token key in response
|
|
327
|
+
inputTokenKey: "ExclusiveStartKey", // Token key in request (when different from response)
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
// First call returns items 1-10 with LastEvaluatedKey
|
|
331
|
+
const result1 = await client.send(new ScanCommand({ TableName: "test" }));
|
|
332
|
+
// result1.LastEvaluatedKey = "token-10"
|
|
333
|
+
|
|
334
|
+
// Second call with ExclusiveStartKey returns items 11-20
|
|
335
|
+
const result2 = await client.send(
|
|
336
|
+
new ScanCommand({
|
|
337
|
+
TableName: "test",
|
|
338
|
+
ExclusiveStartKey: result1.LastEvaluatedKey,
|
|
339
|
+
}),
|
|
340
|
+
);
|
|
341
|
+
// result2.LastEvaluatedKey = "token-20"
|
|
342
|
+
|
|
343
|
+
// Third call returns items 21-25 without LastEvaluatedKey
|
|
344
|
+
const result3 = await client.send(
|
|
345
|
+
new ScanCommand({
|
|
346
|
+
TableName: "test",
|
|
347
|
+
ExclusiveStartKey: result2.LastEvaluatedKey,
|
|
348
|
+
}),
|
|
349
|
+
);
|
|
350
|
+
// result3.LastEvaluatedKey = undefined (no more pages)
|
|
351
|
+
|
|
352
|
+
// Mock S3 list objects with pagination
|
|
353
|
+
// S3 uses the same key for input and output, so inputTokenKey is optional
|
|
354
|
+
const objects = Array.from({ length: 15 }, (_, i) => ({
|
|
355
|
+
Key: `file-${i + 1}.txt`,
|
|
356
|
+
}));
|
|
357
|
+
|
|
358
|
+
s3Mock.on(ListObjectsV2Command).resolvesPaginated(objects, {
|
|
359
|
+
pageSize: 10,
|
|
360
|
+
itemsKey: "Contents",
|
|
361
|
+
tokenKey: "NextContinuationToken", // Used for both input and output
|
|
362
|
+
});
|
|
296
363
|
```
|
|
297
364
|
|
|
365
|
+
**Pagination Options:**
|
|
366
|
+
|
|
367
|
+
- `pageSize` - Number of items per page (default: 10)
|
|
368
|
+
- `itemsKey` - Property name for items array in response (default: "Items")
|
|
369
|
+
- `tokenKey` - Property name for pagination token in response (default: "NextToken")
|
|
370
|
+
- `inputTokenKey` - Property name for pagination token in request (default: same as `tokenKey`)
|
|
371
|
+
- Use this when AWS service uses different names for input/output tokens (e.g., DynamoDB's `ExclusiveStartKey` vs `LastEvaluatedKey`)
|
|
372
|
+
|
|
298
373
|
### AWS Error Simulation
|
|
299
374
|
|
|
300
|
-
Convenient methods for common AWS errors:
|
|
375
|
+
Convenient helper methods for common AWS errors:
|
|
301
376
|
|
|
302
377
|
```typescript
|
|
303
378
|
// S3 Errors
|
|
@@ -314,61 +389,34 @@ s3Mock.on(GetObjectCommand).rejectsWithThrottling();
|
|
|
314
389
|
s3Mock.on(GetObjectCommand).rejectsWithInternalServerError();
|
|
315
390
|
```
|
|
316
391
|
|
|
317
|
-
###
|
|
392
|
+
### Delay/Latency Simulation
|
|
393
|
+
|
|
394
|
+
Simulate network delays for testing timeouts and race conditions:
|
|
318
395
|
|
|
319
396
|
```typescript
|
|
320
|
-
|
|
397
|
+
// Resolve with delay
|
|
398
|
+
s3Mock.on(GetObjectCommand).resolvesWithDelay({ Body: "data" }, 1000);
|
|
321
399
|
|
|
322
|
-
//
|
|
323
|
-
s3Mock
|
|
324
|
-
.on(GetObjectCommand)
|
|
325
|
-
.rejectsOnce(new Error("Temporary failure"))
|
|
326
|
-
.resolves({ Body: "success" });
|
|
400
|
+
// Reject with delay
|
|
401
|
+
s3Mock.on(GetObjectCommand).rejectsWithDelay("Network timeout", 500);
|
|
327
402
|
```
|
|
328
403
|
|
|
329
|
-
###
|
|
330
|
-
|
|
331
|
-
```typescript
|
|
332
|
-
s3Mock.on(GetObjectCommand).callsFake(async (input, getClient) => {
|
|
333
|
-
const client = getClient();
|
|
334
|
-
console.log("Bucket:", input.Bucket);
|
|
335
|
-
return { Body: `Dynamic response for ${input.Key}` };
|
|
336
|
-
});
|
|
337
|
-
```
|
|
404
|
+
### Fixture Loading
|
|
338
405
|
|
|
339
|
-
|
|
406
|
+
Load mock responses from files for easier test data management:
|
|
340
407
|
|
|
341
408
|
```typescript
|
|
342
|
-
//
|
|
343
|
-
|
|
344
|
-
constructor(private s3Client: S3Client) {}
|
|
345
|
-
|
|
346
|
-
async uploadFile(bucket: string, key: string, data: string) {
|
|
347
|
-
return await this.s3Client.send(
|
|
348
|
-
new PutObjectCommand({ Bucket: bucket, Key: key, Body: data }),
|
|
349
|
-
);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
test("should mock existing S3 client instance", async () => {
|
|
354
|
-
// Create the client your application will use
|
|
355
|
-
const s3Client = new S3Client({ region: "us-east-1" });
|
|
356
|
-
const service = new FileUploadService(s3Client);
|
|
357
|
-
|
|
358
|
-
// Mock the existing client instance
|
|
359
|
-
const mock = mockClientInstance(s3Client);
|
|
360
|
-
mock.on(PutObjectCommand).resolves({ ETag: "mock-etag" });
|
|
361
|
-
|
|
362
|
-
// Test your service
|
|
363
|
-
const result = await service.uploadFile("bucket", "key", "data");
|
|
409
|
+
// Load JSON response from file (automatically parsed)
|
|
410
|
+
s3Mock.on(GetObjectCommand).resolvesFromFile("./fixtures/s3-response.json");
|
|
364
411
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
});
|
|
412
|
+
// Load text response from file (returned as string)
|
|
413
|
+
s3Mock.on(GetObjectCommand).resolvesFromFile("./fixtures/response.txt");
|
|
368
414
|
```
|
|
369
415
|
|
|
370
416
|
### Debug Mode
|
|
371
417
|
|
|
418
|
+
Enable debug logging to troubleshoot mock configurations when they're not matching as expected:
|
|
419
|
+
|
|
372
420
|
Enable debug logging to troubleshoot mock configurations and see detailed information about command matching:
|
|
373
421
|
|
|
374
422
|
```typescript
|
|
@@ -543,9 +591,11 @@ bun nx build
|
|
|
543
591
|
|
|
544
592
|
See [CONTRIBUTING.md](./CONTRIBUTING.md) for the complete guide.
|
|
545
593
|
|
|
546
|
-
##
|
|
594
|
+
## Acknowledgements
|
|
595
|
+
|
|
596
|
+
This library is based on the core ideas and API patterns introduced by [aws-sdk-client-mock](https://github.com/m-radzikowski/aws-sdk-client-mock), which is no longer actively maintained.
|
|
547
597
|
|
|
548
|
-
|
|
598
|
+
It reimagines those concepts for Vitest, while extending them with additional features, improved ergonomics, and ongoing maintenance.
|
|
549
599
|
|
|
550
600
|
## 📝 License
|
|
551
601
|
|
package/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=require("vitest"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=require("vitest"),R=require("node:fs"),N=require("node:path"),C=require("node:stream"),W=require("./matchers-Rq18z2C7.cjs");class d extends Error{constructor(e,s,c,n){super(e),this.name="AwsError",this.code=s,this.statusCode=c,this.retryable=n}}const M=t=>{const e=t?`The specified key does not exist. Key: ${t}`:"The specified key does not exist.";return new d(e,"NoSuchKey",404,!1)},T=t=>{const e=t?`The specified bucket does not exist. Bucket: ${t}`:"The specified bucket does not exist.";return new d(e,"NoSuchBucket",404,!1)},$=t=>{const e=t?`Access Denied for resource: ${t}`:"Access Denied";return new d(e,"AccessDenied",403,!1)},D=t=>{const e=t?`Requested resource not found: ${t}`:"Requested resource not found";return new d(e,"ResourceNotFoundException",400,!1)},I=()=>new d("The conditional request failed","ConditionalCheckFailedException",400,!1),O=()=>new d("Rate exceeded","Throttling",400,!0),F=()=>new d("We encountered an internal error. Please try again.","InternalServerError",500,!0);function k(){return{enabled:!1,log(t,e){this.enabled&&(e===void 0?console.log(`[aws-sdk-vitest-mock](Debug) ${t}`):console.log(`[aws-sdk-vitest-mock](Debug) ${t}`,e))}}}function y(t){t.enabled=!0}function v(t){t.enabled=!1}function L(t){const e=N.resolve(t),s=R.readFileSync(e,"utf8");return t.endsWith(".json")?JSON.parse(s):s}function K(t,e={}){const{pageSize:s=10,tokenKey:c="NextToken",itemsKey:n="Items"}=e;if(t.length===0)return[{[n]:[]}];const o=[];for(let r=0;r<t.length;r+=s){const u=t.slice(r,r+s),i=r+s<t.length,l={[n]:u};if(i){const a=l;a[c]=`token-${r+s}`}o.push(l)}return o}function A(){return typeof process<"u"&&process.versions?.node?"node":typeof process<"u"&&process.versions?.bun?"bun":"browser"}function q(t){const e=typeof t=="string"?Buffer.from(t,"utf8"):Buffer.from(t);let s=!1;return new C.Readable({read(){s||(this.push(e),this.push(null),s=!0)}})}function B(t){let e;return typeof t=="string"?e=new TextEncoder().encode(t):t instanceof Buffer?e=new Uint8Array(t):e=t,new ReadableStream({start(s){s.enqueue(e),s.close()}})}function h(t){const e=A();return e==="node"||e==="bun"?q(t):B(t)}function w(t,e){return Object.keys(e).every(s=>{const c=e[s],n=t[s];return c&&typeof c=="object"&&!Array.isArray(c)?typeof n!="object"||n===null?!1:w(n,c):n===c})}function j(t,e){if(t===e)return!0;if(typeof t!="object"||t===null||typeof e!="object"||e===null)return t===e;const s=Object.keys(t),c=Object.keys(e);return s.length!==c.length?!1:c.every(n=>{if(!Object.prototype.hasOwnProperty.call(t,n))return!1;const o=t,r=e,u=o[n],i=r[n];return typeof u=="object"&&u!==null&&typeof i=="object"&&i!==null?j(u,i):u===i})}function S(t){return async function(e){const s=()=>this;t.debugLogger.log(`Received command: ${e.constructor.name}`,e.input);const c=t.map.get(e.constructor);if(c){t.debugLogger.log(`Found ${c.length} mock(s) for ${e.constructor.name}`);const n=c.findIndex(o=>o.strict?o.matcher&&j(e.input,o.matcher):!o.matcher||w(e.input,o.matcher));if(n===-1)t.debugLogger.log(`No matching mock found for ${e.constructor.name}`,e.input);else{const o=c[n];if(!o)throw new Error(`Mock at index ${n} not found`);return t.debugLogger.log(`Using mock at index ${n} for ${e.constructor.name}`),o.once&&(c.splice(n,1),t.debugLogger.log(`Removed one-time mock for ${e.constructor.name}`)),o.handler(e.input,s())}}else t.debugLogger.log(`No mocks configured for ${e.constructor.name}`);throw new Error(`No mock configured for command: ${e.constructor.name}`)}}function x(t,e,s,c={}){const n=(r,u)=>{const i={matcher:s,handler:r,once:u,strict:!!c.strict},l=t.map.get(e)??[];if(u){const a=l.findIndex(f=>!f.once);a===-1?l.push(i):l.splice(a,0,i),t.map.set(e,l)}else{const a=l.filter(f=>f.once||JSON.stringify(f.matcher)!==JSON.stringify(s));a.push(i),t.map.set(e,a)}},o={resolves(r){return n(()=>Promise.resolve(r),!1),o},rejects(r){return n(()=>{const u=typeof r=="string"?new Error(r):r;return Promise.reject(u)},!1),o},callsFake(r){return n(r,!1),o},resolvesOnce(r){return n(()=>Promise.resolve(r),!0),o},rejectsOnce(r){return n(()=>{const u=typeof r=="string"?new Error(r):r;return Promise.reject(u)},!0),o},callsFakeOnce(r){return n(r,!0),o},resolvesStream(r){return n(()=>Promise.resolve({Body:h(r)}),!1),o},resolvesStreamOnce(r){return n(()=>Promise.resolve({Body:h(r)}),!0),o},resolvesWithDelay(r,u){const i=l=>{setTimeout(()=>l(r),u)};return n(()=>new Promise(i),!1),o},rejectsWithDelay(r,u){const i=typeof r=="string"?new Error(r):r,l=(a,f)=>{setTimeout(()=>f(i),u)};return n(()=>new Promise(l),!1),o},rejectsWithNoSuchKey(r){return n(()=>Promise.reject(M(r)),!1),o},rejectsWithNoSuchBucket(r){return n(()=>Promise.reject(T(r)),!1),o},rejectsWithAccessDenied(r){return n(()=>Promise.reject($(r)),!1),o},rejectsWithResourceNotFound(r){return n(()=>Promise.reject(D(r)),!1),o},rejectsWithConditionalCheckFailed(){return n(()=>Promise.reject(I()),!1),o},rejectsWithThrottling(){return n(()=>Promise.reject(O()),!1),o},rejectsWithInternalServerError(){return n(()=>Promise.reject(F()),!1),o},resolvesPaginated(r,u={}){const i=K(r,u);let l=0;return n(a=>{const f=u.tokenKey||"NextToken",E=u.inputTokenKey||f,p=a[E];if(p){const g=/token-(\d+)/.exec(p);if(g&&g[1]){const P=g[1];l=Math.floor(Number.parseInt(P,10)/(u.pageSize||10))}}else l=0;const m=i[l]||i[i.length-1]||i[0];if(!m)throw new Error("No paginated responses available");return l=Math.min(l+1,i.length-1),Promise.resolve(m)},!1),o},resolvesFromFile(r){return n(()=>{const u=L(r);return Promise.resolve(u)},!1),o}};return o}const _=t=>{const e={map:new WeakMap,debugLogger:k()},s=t.prototype,c=b.vi.spyOn(s,"send").mockImplementation(S(e));return{client:void 0,on:(o,r,u)=>x(e,o,r,u),reset:()=>{c.mockClear(),e.map=new WeakMap},restore:()=>{c.mockRestore(),e.map=new WeakMap},calls:()=>c.mock.calls.map(o=>o[0]),__rawCalls:()=>c.mock.calls,enableDebug:()=>{y(e.debugLogger)},disableDebug:()=>{v(e.debugLogger)}}},V=t=>{const e={map:new WeakMap,debugLogger:k()},s=b.vi.spyOn(t,"send").mockImplementation(S(e));return{client:t,on:(n,o,r)=>x(e,n,o,r),reset:()=>{s.mockClear(),e.map=new WeakMap},restore:()=>{s.mockRestore(),e.map=new WeakMap},calls:()=>s.mock.calls.map(n=>n[0]),__rawCalls:()=>s.mock.calls,enableDebug:()=>{y(e.debugLogger)},disableDebug:()=>{v(e.debugLogger)}}};exports.matchers=W.matchers;exports.mockClient=_;exports.mockClientInstance=V;
|
package/index.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
import { vi as b } from "vitest";
|
|
2
|
-
import { readFileSync as
|
|
3
|
-
import
|
|
4
|
-
import { Readable as
|
|
5
|
-
import { m as
|
|
2
|
+
import { readFileSync as R } from "node:fs";
|
|
3
|
+
import N from "node:path";
|
|
4
|
+
import { Readable as W } from "node:stream";
|
|
5
|
+
import { m as Y } from "./matchers-C6AtmwWz.js";
|
|
6
6
|
class d extends Error {
|
|
7
7
|
constructor(e, s, c, n) {
|
|
8
8
|
super(e), this.name = "AwsError", this.code = s, this.statusCode = c, this.retryable = n;
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
|
-
const
|
|
11
|
+
const C = (t) => {
|
|
12
12
|
const e = t ? `The specified key does not exist. Key: ${t}` : "The specified key does not exist.";
|
|
13
13
|
return new d(e, "NoSuchKey", 404, !1);
|
|
14
|
-
},
|
|
14
|
+
}, $ = (t) => {
|
|
15
15
|
const e = t ? `The specified bucket does not exist. Bucket: ${t}` : "The specified bucket does not exist.";
|
|
16
16
|
return new d(e, "NoSuchBucket", 404, !1);
|
|
17
|
-
},
|
|
17
|
+
}, D = (t) => {
|
|
18
18
|
const e = t ? `Access Denied for resource: ${t}` : "Access Denied";
|
|
19
19
|
return new d(e, "AccessDenied", 403, !1);
|
|
20
|
-
},
|
|
20
|
+
}, M = (t) => {
|
|
21
21
|
const e = t ? `Requested resource not found: ${t}` : "Requested resource not found";
|
|
22
22
|
return new d(e, "ResourceNotFoundException", 400, !1);
|
|
23
|
-
},
|
|
23
|
+
}, T = () => new d(
|
|
24
24
|
"The conditional request failed",
|
|
25
25
|
"ConditionalCheckFailedException",
|
|
26
26
|
400,
|
|
@@ -45,11 +45,11 @@ function y(t) {
|
|
|
45
45
|
function w(t) {
|
|
46
46
|
t.enabled = !1;
|
|
47
47
|
}
|
|
48
|
-
function
|
|
49
|
-
const e =
|
|
48
|
+
function F(t) {
|
|
49
|
+
const e = N.resolve(t), s = R(e, "utf8");
|
|
50
50
|
return t.endsWith(".json") ? JSON.parse(s) : s;
|
|
51
51
|
}
|
|
52
|
-
function
|
|
52
|
+
function L(t, e = {}) {
|
|
53
53
|
const { pageSize: s = 10, tokenKey: c = "NextToken", itemsKey: n = "Items" } = e;
|
|
54
54
|
if (t.length === 0)
|
|
55
55
|
return [{ [n]: [] }];
|
|
@@ -64,19 +64,19 @@ function F(t, e = {}) {
|
|
|
64
64
|
}
|
|
65
65
|
return o;
|
|
66
66
|
}
|
|
67
|
-
function
|
|
67
|
+
function K() {
|
|
68
68
|
return typeof process < "u" && process.versions?.node ? "node" : typeof process < "u" && process.versions?.bun ? "bun" : "browser";
|
|
69
69
|
}
|
|
70
70
|
function A(t) {
|
|
71
71
|
const e = typeof t == "string" ? Buffer.from(t, "utf8") : Buffer.from(t);
|
|
72
72
|
let s = !1;
|
|
73
|
-
return new
|
|
73
|
+
return new W({
|
|
74
74
|
read() {
|
|
75
75
|
s || (this.push(e), this.push(null), s = !0);
|
|
76
76
|
}
|
|
77
77
|
});
|
|
78
78
|
}
|
|
79
|
-
function
|
|
79
|
+
function B(t) {
|
|
80
80
|
let e;
|
|
81
81
|
return typeof t == "string" ? e = new TextEncoder().encode(t) : t instanceof Buffer ? e = new Uint8Array(t) : e = t, new ReadableStream({
|
|
82
82
|
start(s) {
|
|
@@ -85,8 +85,8 @@ function K(t) {
|
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
87
|
function h(t) {
|
|
88
|
-
const e =
|
|
89
|
-
return e === "node" || e === "bun" ? A(t) :
|
|
88
|
+
const e = K();
|
|
89
|
+
return e === "node" || e === "bun" ? A(t) : B(t);
|
|
90
90
|
}
|
|
91
91
|
function v(t, e) {
|
|
92
92
|
return Object.keys(e).every((s) => {
|
|
@@ -223,23 +223,23 @@ function S(t, e, s, c = {}) {
|
|
|
223
223
|
return n(() => new Promise(l), !1), o;
|
|
224
224
|
},
|
|
225
225
|
rejectsWithNoSuchKey(r) {
|
|
226
|
-
return n(() => Promise.reject(
|
|
226
|
+
return n(() => Promise.reject(C(r)), !1), o;
|
|
227
227
|
},
|
|
228
228
|
rejectsWithNoSuchBucket(r) {
|
|
229
|
-
return n(() => Promise.reject(
|
|
229
|
+
return n(() => Promise.reject($(r)), !1), o;
|
|
230
230
|
},
|
|
231
231
|
rejectsWithAccessDenied(r) {
|
|
232
|
-
return n(() => Promise.reject(
|
|
232
|
+
return n(() => Promise.reject(D(r)), !1), o;
|
|
233
233
|
},
|
|
234
234
|
rejectsWithResourceNotFound(r) {
|
|
235
235
|
return n(
|
|
236
|
-
() => Promise.reject(
|
|
236
|
+
() => Promise.reject(M(r)),
|
|
237
237
|
!1
|
|
238
238
|
), o;
|
|
239
239
|
},
|
|
240
240
|
rejectsWithConditionalCheckFailed() {
|
|
241
241
|
return n(
|
|
242
|
-
() => Promise.reject(
|
|
242
|
+
() => Promise.reject(T()),
|
|
243
243
|
!1
|
|
244
244
|
), o;
|
|
245
245
|
},
|
|
@@ -250,16 +250,16 @@ function S(t, e, s, c = {}) {
|
|
|
250
250
|
return n(() => Promise.reject(O()), !1), o;
|
|
251
251
|
},
|
|
252
252
|
resolvesPaginated(r, u = {}) {
|
|
253
|
-
const i =
|
|
253
|
+
const i = L(r, u);
|
|
254
254
|
let l = 0;
|
|
255
255
|
return n((a) => {
|
|
256
|
-
const f = u.tokenKey || "NextToken", p = a[
|
|
256
|
+
const f = u.tokenKey || "NextToken", E = u.inputTokenKey || f, p = a[E];
|
|
257
257
|
if (p) {
|
|
258
258
|
const g = /token-(\d+)/.exec(p);
|
|
259
259
|
if (g && g[1]) {
|
|
260
|
-
const
|
|
260
|
+
const P = g[1];
|
|
261
261
|
l = Math.floor(
|
|
262
|
-
Number.parseInt(
|
|
262
|
+
Number.parseInt(P, 10) / (u.pageSize || 10)
|
|
263
263
|
);
|
|
264
264
|
}
|
|
265
265
|
} else
|
|
@@ -276,14 +276,14 @@ function S(t, e, s, c = {}) {
|
|
|
276
276
|
},
|
|
277
277
|
resolvesFromFile(r) {
|
|
278
278
|
return n(() => {
|
|
279
|
-
const u =
|
|
279
|
+
const u = F(r);
|
|
280
280
|
return Promise.resolve(u);
|
|
281
281
|
}, !1), o;
|
|
282
282
|
}
|
|
283
283
|
};
|
|
284
284
|
return o;
|
|
285
285
|
}
|
|
286
|
-
const
|
|
286
|
+
const G = (t) => {
|
|
287
287
|
const e = {
|
|
288
288
|
map: /* @__PURE__ */ new WeakMap(),
|
|
289
289
|
debugLogger: k()
|
|
@@ -311,7 +311,7 @@ const U = (t) => {
|
|
|
311
311
|
w(e.debugLogger);
|
|
312
312
|
}
|
|
313
313
|
};
|
|
314
|
-
},
|
|
314
|
+
}, H = (t) => {
|
|
315
315
|
const e = {
|
|
316
316
|
map: /* @__PURE__ */ new WeakMap(),
|
|
317
317
|
debugLogger: k()
|
|
@@ -341,7 +341,7 @@ const U = (t) => {
|
|
|
341
341
|
};
|
|
342
342
|
};
|
|
343
343
|
export {
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
344
|
+
Y as matchers,
|
|
345
|
+
G as mockClient,
|
|
346
|
+
H as mockClientInstance
|
|
347
347
|
};
|