Skip to content

Instantly share code, notes, and snippets.

@andresgutgon
Last active March 14, 2022 14:59
Show Gist options
  • Save andresgutgon/36e01c91acb7a0c2dc7509b2b046a6cc to your computer and use it in GitHub Desktop.
Save andresgutgon/36e01c91acb7a0c2dc7509b2b046a6cc to your computer and use it in GitHub Desktop.
Create File in Disk and validate size with `Meter`
import type { TransformCallback } from "stream"
import { Transform } from "stream"
export class Meter extends Transform {
public bytes: number
constructor(
public field: string,
public maxBytes: number
) {
super()
this.bytes = 0
}
_transform(chunk: unknown, _: BufferEncoding, callback: TransformCallback) {
this.bytes += (chunk as Buffer).length
this.push(chunk)
if (typeof this.maxBytes === "number" && this.bytes > this.maxBytes) {
return callback(new MeterError(this.field, this.maxBytes))
}
callback()
}
}
export class MeterError extends Error {
constructor(public field: string, public maxBytes: number) {
super(`Field "${field}" exceeded upload size of ${maxBytes} bytes.`)
}
}
import z from "zod"
import type { Readable } from "stream"
import { createWriteStream } from "fs"
import { rm, mkdir } from "fs/promises"
import { dirname } from "path"
import { FileValidationOptions } from "./zod/file/types"
import { makeFile } from "./files/makeFile"
import { Meter } from "./files/meter"
import { NodeFile } from "./files/file"
export type FileResult = {
name: string
success: boolean
data: NodeFile | null
errors: string[]
}
export type Props = {
shape: z.input<z.ZodTypeAny>
tmpdir: string
fileValidation: FileValidationOptions | null
name: string
filestream: Readable
filename: string
encoding: string
mimeType: string
}
exp
export async function validateFile({ │ 214| elephant_file: ["Only PDFs please"]
shape, │ ❯ runTest ../../node_modules/.pnpm/vitest@0.2.8/node_modules/vitest/src/
fileValidation, │runtime/run.ts:101:1
tmpdir, │ ❯ runSuite ../../node_modules/.pnpm/vitest@0.2.8/node_modules/vitest/src
name, │/runtime/run.ts:165:6
filestream, │ ❯ runSuite ../../node_modules/.pnpm/vitest@0.2.8/node_modules/vitest/src
filename, │/runtime/run.ts:165:6
mimeType │ ❯ runSuites ../../node_modules/.pnpm/vitest@0.2.8/node_modules/vitest/sr
}: Props): Promise<FileResult | undefined> { │c/runtime/entry.ts:4:8
if (!shape) return undefined │ ❯ startTests ../../node_modules/.pnpm/vitest@0.2.8/node_modules/vitest/s
const filepath = await makeFile(tmpdir, filename, mimeType) │rc/runtime/entry.ts:9:1
// Make the dir │ ❯ withEnv ../../node_modules/.pnpm/vitest@0.2.8/node_modules/vitest/src/
await mkdir(dirname(filepath), { recursive: true }).catch(() => null) │runtime/error.ts:9:3
const maxFileSize = 1048576 // 1MB │
const meter = new Meter(name, maxFileSize) │⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/3]⎯
await new Promise<void>((resolve, reject) => { │
const writeFileStream = createWriteStream(filepath) │ FAIL src/index.test.ts > bodyparser > Validate file mimeType custom fun
│ction message
let aborted = false │AssertionError: expected true to be falsy
async function abort(error: Error) { │ ❯ src/index.test.ts:237:27
if (aborted) return │ 235| }
aborted = true │ 236| })
│ 237| expect(result.success).toBeFalsy()
filestream.unpipe() │ | ^
meter.unpipe() │ 238| expect(result.fieldErrors).toEqual({
filestream.removeAllListeners() │ 239| elephant_file: [
meter.removeAllListeners() │ ❯ runTest ../../node_modules/.pnpm/vitest@0.2.8/node_modules/vitest/src/
writeFileStream.removeAllListeners() │runtime/run.ts:101:1
│ ❯ runSuite ../../node_modules/.pnpm/vitest@0.2.8/node_modules/vitest/src
await rm(filepath, { force: true }).catch(() => null) │/runtime/run.ts:165:6
│ ❯ runSuite ../../node_modules/.pnpm/vitest@0.2.8/node_modules/vitest/src
reject(error) │/runtime/run.ts:165:6
} │ ❯ runSuites ../../node_modules/.pnpm/vitest@0.2.8/node_modules/vitest/sr
│c/runtime/entry.ts:4:8
filestream.on("error", abort) │ ❯ startTests ../../node_modules/.pnpm/vitest@0.2.8/node_modules/vitest/s
meter.on("error", abort) │rc/runtime/entry.ts:9:1
writeFileStream.on("error", abort) │ ❯ withEnv ../../node_modules/.pnpm/vitest@0.2.8/node_modules/vitest/src/
writeFileStream.on("finish", resolve) │runtime/error.ts:9:3
filestream.pipe(meter).pipe(writeFileStream) │
}) │
│⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/3]⎯
const file = new NodeFile(filepath, meter.bytes, mimeType) │
return { │Test Files 1 failed | 1 skipped (2)
name, │ Tests 3 failed | 7 passed | 1 skipped | 6 todo (17)
success: true, │ Time 47ms
data: file, │
errors: [] │
} │ FAIL Tests failed. Watching for file changes...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment