(command: unknown)
| 41 | // Methods called by the real S3 transport — minimal surface so the |
| 42 | // handler's call sites don't need rewriting under test. |
| 43 | async send(command: unknown): Promise<unknown> { |
| 44 | const op = command as { input: { Bucket: string; Key: string } } & { |
| 45 | constructor: { name: string }; |
| 46 | }; |
| 47 | const cmdName = op.constructor?.name ?? ""; |
| 48 | const uri = `s3://${op.input.Bucket}/${op.input.Key}`; |
| 49 | if (cmdName === "GetObjectCommand") { |
| 50 | const bytes = this.objects.get(uri) ?? Buffer.alloc(0); |
| 51 | this.ops.push({ kind: "download", uri, bytes: bytes.length }); |
| 52 | // Mock the AWS SDK stream contract just enough for pipeline() to |
| 53 | // pump bytes into a write stream. |
| 54 | const { Readable } = await import("node:stream"); |
| 55 | return { Body: Readable.from([bytes]) }; |
| 56 | } |
| 57 | if (cmdName === "PutObjectCommand") { |
| 58 | // Buffer the body so we can record how many bytes were uploaded; the |
| 59 | // handler's hot path streams from disk, but tests pin the count. |
| 60 | const body = (command as { input: { Body: NodeJS.ReadableStream | Buffer } }).input.Body; |
| 61 | let bytes = 0; |
| 62 | if (Buffer.isBuffer(body)) { |
| 63 | bytes = body.length; |
| 64 | } else if (body && typeof (body as NodeJS.ReadableStream).pipe === "function") { |
| 65 | for await (const chunk of body as NodeJS.ReadableStream) { |
| 66 | bytes += (chunk as Buffer).length; |
| 67 | } |
| 68 | } |
| 69 | this.ops.push({ kind: "upload", uri, bytes }); |
| 70 | this.objects.set(uri, Buffer.alloc(bytes)); |
| 71 | return {}; |
| 72 | } |
| 73 | return {}; |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | const tmpDirs: string[] = []; |
no test coverage detected