From 6b6ac2bc0d6969f298e254bddff1d972eab84c78 Mon Sep 17 00:00:00 2001 From: Tony133 Date: Tue, 28 Apr 2026 11:41:03 +0200 Subject: [PATCH 1/3] refactor(types): migrate from tsd to tstyche --- package.json | 9 +-- types/{index.test-d.ts => index.tst.ts} | 87 +++++++++++++------------ 2 files changed, 48 insertions(+), 48 deletions(-) rename types/{index.test-d.ts => index.tst.ts} (64%) diff --git a/package.json b/package.json index aa890833..90417724 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "noop-stream": "^0.1.0", "pump": "^3.0.0", "readable-stream": "^4.5.2", - "tsd": "^0.33.0" + "tstyche": "^7.0.0" }, "scripts": { "climem": "climem 8999 localhost", @@ -36,7 +36,7 @@ "lint:fix": "eslint --fix", "start": "CLIMEM=8999 node -r climem ./examples/example", "test": "npm run test:unit && npm run test:typescript", - "test:typescript": "tsd", + "test:typescript": "tstyche", "test:unit": "c8 --100 node --test" }, "repository": { @@ -84,10 +84,7 @@ } ], "license": "MIT", - "tsd": { - "directory": "test" - }, "publishConfig": { "access": "public" } -} +} \ No newline at end of file diff --git a/types/index.test-d.ts b/types/index.tst.ts similarity index 64% rename from types/index.test-d.ts rename to types/index.tst.ts index 9562213d..33e810b4 100644 --- a/types/index.test-d.ts +++ b/types/index.tst.ts @@ -1,10 +1,10 @@ /* eslint-disable @typescript-eslint/no-unused-expressions */ import fastify from 'fastify' -import fastifyMultipart, { MultipartValue, MultipartFields, MultipartFile } from '..' +import fastifyMultipart, { MultipartValue, MultipartFields, MultipartFile } from '.' import * as util from 'node:util' import { pipeline } from 'node:stream' import * as fs from 'node:fs' -import { expectError, expectType } from 'tsd' +import { expect } from 'tstyche' import { FastifyErrorConstructor } from '@fastify/error' import { BusboyConfig, BusboyFileStream } from '@fastify/busboy' @@ -26,18 +26,18 @@ const runServer = async () => { // usage app.post('/', async (req, reply) => { - expectType>(req.formData()) + expect(req.formData()).type.toBe>() const data = await req.file() if (data == null) throw new Error('missing file') - expectType<'file'>(data.type) - expectType(data.file) - expectType(data.file.truncated) - expectType(data.fields) - expectType(data.fieldname) - expectType(data.filename) - expectType(data.encoding) - expectType(data.mimetype) + expect(data.type).type.toBe<'file'>() + expect(data.file).type.toBeAssignableTo() + expect(data.file.truncated).type.toBe() + expect(data.fields).type.toBeAssignableTo() + expect(data.fieldname).type.toBe() + expect(data.filename).type.toBe() + expect(data.encoding).type.toBe() + expect(data.mimetype).type.toBe() const field = data.fields.myField if (field === undefined) { @@ -59,22 +59,24 @@ const runServer = async () => { // Multiple fields including scalar values app.post<{ Body: { file: MultipartFile, foo: MultipartValue } }>('/upload/stringvalue', async (req, reply) => { - expectError(req.body.foo.file) - expectType<'field'>(req.body.foo.type) - expectType(req.body.foo.value) + // @ts-expect-error! + req.body.foo.file - expectType(req.body.file.file) - expectType<'file'>(req.body.file.type) + expect(req.body.foo.type).type.toBe<'field'>() + expect(req.body.foo.value).type.toBe() + + expect(req.body.file.file).type.toBeAssignableTo() + expect(req.body.file.type).type.toBe<'file'>() reply.send() }) app.post<{ Body: { file: MultipartFile, num: MultipartValue } }>('/upload/stringvalue', async (req, reply) => { - expectType(req.body.num.value) + expect(req.body.num.value).type.toBe() reply.send() - // file is a file - expectType(req.body.file.file) - expectError(req.body.file.value) + expect(req.body.file.file).type.toBeAssignableTo() + // @ts-expect-error! + req.body.file.value }) // busboy @@ -84,9 +86,9 @@ const runServer = async () => { throwFileSizeLimit: true, sharedSchemaId: 'schemaId', isPartAFile: (fieldName, contentType, fileName) => { - expectType(fieldName) - expectType(contentType) - expectType(fileName) + expect(fieldName).type.toBe() + expect(contentType).type.toBe() + expect(fileName).type.toBe() return true } }) @@ -102,9 +104,9 @@ const runServer = async () => { throwFileSizeLimit: true, sharedSchemaId: 'schemaId', isPartAFile: (fieldName, contentType, fileName) => { - expectType(fieldName) - expectType(contentType) - expectType(fileName) + expect(fieldName).type.toBe() + expect(contentType).type.toBe() + expect(fileName).type.toBe() return true } }) @@ -131,7 +133,7 @@ const runServer = async () => { app.post('/upload/raw/any', async function (req, reply) { const data = await req.file() if (!data) throw new Error('missing file') - expectType(await data.toBuffer()) + expect(await data.toBuffer()).type.toBe() // upload to S3 reply.send() }) @@ -140,13 +142,13 @@ const runServer = async () => { app.post('/upload/files', async function (req, reply) { // stores files to tmp dir and return files + values const { files, values } = await req.saveRequestFiles() - files[0].type // "file" - files[0].filepath - files[0].fieldname - files[0].filename - files[0].encoding - files[0].mimetype - files[0].fields // other parsed parts + files[0]!.type // "file" + files[0]!.filepath + files[0]!.fieldname + files[0]!.filename + files[0]!.encoding + files[0]!.mimetype + files[0]!.fields // other parsed parts values.foo reply.send() @@ -164,12 +166,12 @@ const runServer = async () => { app.post('/upload/files', async function (_req, reply) { const { FilesLimitError } = app.multipartErrors - expectType(app.multipartErrors.FieldsLimitError) - expectType(app.multipartErrors.FilesLimitError) - expectType(app.multipartErrors.InvalidMultipartContentTypeError) - expectType(app.multipartErrors.PartsLimitError) - expectType(app.multipartErrors.PrototypeViolationError) - expectType(app.multipartErrors.RequestFileTooLargeError) + expect(app.multipartErrors.FieldsLimitError).type.toBe() + expect(app.multipartErrors.FilesLimitError).type.toBe() + expect(app.multipartErrors.InvalidMultipartContentTypeError).type.toBe() + expect(app.multipartErrors.PartsLimitError).type.toBe() + expect(app.multipartErrors.PrototypeViolationError).type.toBe() + expect(app.multipartErrors.RequestFileTooLargeError).type.toBe() // test instanceof Error const a = new FilesLimitError() @@ -185,12 +187,13 @@ const runServer = async () => { multipartOptions: {} } }, async function (req, reply) { - expectType>(req.routeOptions.config.multipartOptions) + expect(req.routeOptions.config.multipartOptions).type.toBeAssignableTo>() reply.send() }) app.post('/upload/files', async function (req, reply) { - expectError>(req.routeOptions.config?.multipartOptions) + // @ts-expect-error! + req.routeOptions.config.multipartOptions satisfies Omit reply.send() }) From 3e09556cf0c700ec2057e5689a2836309ec8176a Mon Sep 17 00:00:00 2001 From: Tony133 Date: Tue, 28 Apr 2026 15:49:58 +0200 Subject: [PATCH 2/3] chore: updated --- types/index.tst.ts | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/types/index.tst.ts b/types/index.tst.ts index 33e810b4..949de7bf 100644 --- a/types/index.tst.ts +++ b/types/index.tst.ts @@ -31,9 +31,9 @@ const runServer = async () => { if (data == null) throw new Error('missing file') expect(data.type).type.toBe<'file'>() - expect(data.file).type.toBeAssignableTo() + expect(data.file).type.toBe() expect(data.file.truncated).type.toBe() - expect(data.fields).type.toBeAssignableTo() + expect(data.fields).type.toBe() expect(data.fieldname).type.toBe() expect(data.filename).type.toBe() expect(data.encoding).type.toBe() @@ -59,13 +59,11 @@ const runServer = async () => { // Multiple fields including scalar values app.post<{ Body: { file: MultipartFile, foo: MultipartValue } }>('/upload/stringvalue', async (req, reply) => { - // @ts-expect-error! - req.body.foo.file - + expect(req.body.foo).type.not.toHaveProperty('file') expect(req.body.foo.type).type.toBe<'field'>() expect(req.body.foo.value).type.toBe() - expect(req.body.file.file).type.toBeAssignableTo() + expect(req.body.file.file).type.toBe() expect(req.body.file.type).type.toBe<'file'>() reply.send() }) @@ -74,9 +72,8 @@ const runServer = async () => { expect(req.body.num.value).type.toBe() reply.send() - expect(req.body.file.file).type.toBeAssignableTo() - // @ts-expect-error! - req.body.file.value + expect(req.body.file.file).type.toBe() + expect(req.body.file).type.not.toHaveProperty('value') }) // busboy @@ -187,13 +184,12 @@ const runServer = async () => { multipartOptions: {} } }, async function (req, reply) { - expect(req.routeOptions.config.multipartOptions).type.toBeAssignableTo>() + expect(req.routeOptions.config.multipartOptions).type.toBe>() reply.send() }) app.post('/upload/files', async function (req, reply) { - // @ts-expect-error! - req.routeOptions.config.multipartOptions satisfies Omit + expect(req.routeOptions.config.multipartOptions).type.toBe | undefined>() reply.send() }) From 3cee7fe4fc4dbd0ec2c36c32dd79a9e60f13dc3d Mon Sep 17 00:00:00 2001 From: Tony133 Date: Tue, 28 Apr 2026 18:29:46 +0200 Subject: [PATCH 3/3] chore: updated --- types/avj-plugin.test-d.ts | 13 ------------- types/avj-plugin.tst.ts | 6 ++++++ .../{named-import.test-d.ts => named-import.tst.ts} | 0 3 files changed, 6 insertions(+), 13 deletions(-) delete mode 100644 types/avj-plugin.test-d.ts create mode 100644 types/avj-plugin.tst.ts rename types/{named-import.test-d.ts => named-import.tst.ts} (100%) diff --git a/types/avj-plugin.test-d.ts b/types/avj-plugin.test-d.ts deleted file mode 100644 index 22f999a9..00000000 --- a/types/avj-plugin.test-d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import fastify from 'fastify' -import { fastifyMultipart, ajvFilePlugin } from '..' - -const app = fastify({ - ajv: { - plugins: [ - ajvFilePlugin, - (await import('..')).ajvFilePlugin - ] - } -}) - -app.register(fastifyMultipart) diff --git a/types/avj-plugin.tst.ts b/types/avj-plugin.tst.ts new file mode 100644 index 00000000..efd30c29 --- /dev/null +++ b/types/avj-plugin.tst.ts @@ -0,0 +1,6 @@ +import * as fastifyMultipart from '..' +import { ajvFilePlugin } from '..' +import { expect } from 'tstyche' + +expect(ajvFilePlugin).type.toBeAssignableTo() +expect(fastifyMultipart.ajvFilePlugin).type.toBe(ajvFilePlugin) diff --git a/types/named-import.test-d.ts b/types/named-import.tst.ts similarity index 100% rename from types/named-import.test-d.ts rename to types/named-import.tst.ts