diff --git a/package.json b/package.json index 6cd7cb1d..c2882a6d 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "lint:fix": "eslint --fix", "test": "npm run test:unit && npm run test:typescript", "test:unit": "c8 node --test --test-timeout=30000", - "test:typescript": "tsd" + "test:typescript": "tstyche" }, "repository": { "type": "git", @@ -72,7 +72,7 @@ "proxy": "^4.0.0", "proxyquire": "^2.1.3", "split2": "^4.2.0", - "tsd": "^0.33.0" + "tstyche": "^7.0.0" }, "dependencies": { "@fastify/error": "^4.0.0", @@ -86,4 +86,4 @@ "publishConfig": { "access": "public" } -} +} \ No newline at end of file diff --git a/types/index.test-d.ts b/types/index.test-d.ts deleted file mode 100644 index 7458860a..00000000 --- a/types/index.test-d.ts +++ /dev/null @@ -1,194 +0,0 @@ -import fastify, { FastifyReply, FastifyRequest, RawServerBase, RequestGenericInterface, RouteGenericInterface } from 'fastify' -import * as http from 'node:http' -import { IncomingHttpHeaders } from 'node:http2' -import * as https from 'node:https' -import { AddressInfo } from 'node:net' -import { expectType } from 'tsd' -import { Agent, Client, Dispatcher, Pool } from 'undici' -import replyFrom, { FastifyReplyFromOptions, RawServerResponse } from '..' -// @ts-ignore -import tap from 'tap' - -const fullOptions: FastifyReplyFromOptions = { - base: 'http://example2.com', - http: { - agentOptions: { - keepAliveMsecs: 60 * 1000, - maxFreeSockets: 2048, - maxSockets: 2048 - }, - requestOptions: { - timeout: 1000 - }, - agents: { - 'http:': new http.Agent({}), - 'https:': new https.Agent({}) - } - }, - http2: { - sessionTimeout: 1000, - requestTimeout: 1000, - sessionOptions: { - rejectUnauthorized: true - }, - requestOptions: { - endStream: true - } - }, - cacheURLs: 100, - disableCache: false, - undici: { - connections: 100, - pipelining: 10, - proxy: 'http://example2.com:8080' - }, - contentTypesToEncode: ['application/x-www-form-urlencoded'], - retryMethods: ['GET', 'HEAD', 'OPTIONS', 'TRACE'], - maxRetriesOn503: 10, - disableRequestLogging: false, - globalAgent: false, - destroyAgent: true -} - -async function main () { - const server = fastify() - - server.register(replyFrom) - - server.register(replyFrom, {}) - - server.register(replyFrom, { http2: true }) - - server.register(replyFrom, fullOptions) - - server.register(replyFrom, { undici: { proxy: new URL('http://example2.com:8080') } }) - - server.register(replyFrom, { undici: { proxy: { uri: 'http://example2.com:8080' } } }) - - server.get('/v1', (_request, reply) => { - expectType(reply.from()) - }) - server.get('/v3', (_request, reply) => { - reply.from('/v3', { - timeout: 1000, - body: { hello: 'world' }, - rewriteRequestHeaders (req, headers) { - expectType>(req) - return headers - }, - getUpstream (req, base) { - expectType>(req) - return base - }, - onResponse (request, reply, res) { - expectType>(request) - expectType>(reply) - expectType>(res) - expectType(res.statusCode) - } - }) - }) - - // http2 - const instance = fastify({ http2: true }) - // @ts-ignore - tap.tearDown(instance.close.bind(instance)) - const target = fastify({ http2: true }) - // @ts-ignore - tap.tearDown(target.close.bind(target)) - instance.get('/', (_request, reply) => { - reply.from() - }) - - instance.get('/http2', (_request, reply) => { - reply.from('/', { - method: 'POST', - retryDelay: ({ req, res, err, attempt, getDefaultDelay }) => { - const defaultDelay = getDefaultDelay(req, res, err, attempt) - if (defaultDelay) return defaultDelay - - if (res && res.statusCode === 500 && req.method === 'GET') { - return 300 - } - return null - }, - rewriteHeaders (headers) { - return headers - }, - rewriteRequestHeaders (_req, headers: IncomingHttpHeaders) { - return headers - }, - getUpstream (_req, base) { - return base - }, - onError (reply: FastifyReply, error) { - return reply.send(error.error) - }, - queryString (search, reqUrl, request) { - expectType(search) - expectType(reqUrl) - expectType>(request) - return '' - }, - }) - }) - - await target.listen({ port: 0 }) - const port = (target.server.address() as AddressInfo).port - instance.register(replyFrom, { - base: `http://localhost:${port}`, - http2: { - sessionOptions: { - rejectUnauthorized: false, - }, - }, - }) - instance.register(replyFrom, { - base: `http://localhost:${port}`, - http2: true, - }) - await instance.listen({ port: 0 }) - - const undiciInstance = fastify() - undiciInstance.register(replyFrom, { - base: 'http://example2.com', - undici: { - pipelining: 10, - connections: 10 - } - }) - await undiciInstance.ready() - - const undiciInstanceAgent = fastify() - undiciInstance.register(replyFrom, { - base: 'http://example2.com', - undici: new Agent() - }) - await undiciInstanceAgent.ready() - - const undiciInstancePool = fastify() - undiciInstance.register(replyFrom, { - base: 'http://example2.com', - undici: new Pool('http://example2.com') - }) - await undiciInstancePool.ready() - - const undiciInstanceClient = fastify() - undiciInstance.register(replyFrom, { - base: 'http://example2.com', - undici: new Client('http://example2.com') - }) - await undiciInstanceClient.ready() - - const undiciInstanceDispatcher = fastify() - undiciInstance.register(replyFrom, { - base: 'http://example2.com', - undici: new Dispatcher() - }) - await undiciInstanceDispatcher.ready() - - tap.pass('done') - tap.end() -} - -main() diff --git a/types/index.tst.ts b/types/index.tst.ts new file mode 100644 index 00000000..5e2bf6f8 --- /dev/null +++ b/types/index.tst.ts @@ -0,0 +1,123 @@ +import { expect } from 'tstyche' +import fastify, { + type FastifyReply, + type FastifyRequest, + type RawServerBase, + type RequestGenericInterface, + type RouteGenericInterface +} from 'fastify' +import * as http from 'node:http' +import { type IncomingHttpHeaders } from 'node:http2' +import * as https from 'node:https' +import { Agent, Client, Dispatcher, Pool } from 'undici' +import replyFrom, { + type FastifyReplyFromOptions, + type RawServerResponse +} from '.' + +const fullOptions: FastifyReplyFromOptions = { + base: 'http://example2.com', + http: { + agentOptions: { + keepAliveMsecs: 60 * 1000, + maxFreeSockets: 2048, + maxSockets: 2048 + }, + requestOptions: { timeout: 1000 }, + agents: { + 'http:': new http.Agent({}), + 'https:': new https.Agent({}) + } + }, + http2: { + sessionTimeout: 1000, + requestTimeout: 1000, + sessionOptions: { rejectUnauthorized: true }, + requestOptions: { endStream: true } + }, + cacheURLs: 100, + disableCache: false, + undici: { + connections: 100, + pipelining: 10, + proxy: 'http://example2.com:8080' + }, + contentTypesToEncode: ['application/x-www-form-urlencoded'], + retryMethods: ['GET', 'HEAD', 'OPTIONS', 'TRACE'], + maxRetriesOn503: 10, + disableRequestLogging: false, + globalAgent: false, + destroyAgent: true +} + +const app = fastify() + +app.register(replyFrom) +app.register(replyFrom, {}) +app.register(replyFrom, { http2: true }) +app.register(replyFrom, fullOptions) +app.register(replyFrom, { undici: { proxy: new URL('http://example2.com:8080') } }) +app.register(replyFrom, { undici: { proxy: { uri: 'http://example2.com:8080' } } }) + +app.register(replyFrom, { base: 'http://example.com', undici: new Agent() }) +app.register(replyFrom, { base: 'http://example.com', undici: new Pool('http://example.com') }) +app.register(replyFrom, { base: 'http://example.com', undici: new Client('http://example.com') }) +app.register(replyFrom, { base: 'http://example.com', undici: new Dispatcher() }) + +app.get('/v1', (_request, reply) => { + expect(reply.from()).type.toBe() +}) + +app.get('/v3', (_request, reply) => { + reply.from('/v3', { + timeout: 1000, + body: { hello: 'world' }, + rewriteRequestHeaders (req, headers) { + expect(req).type.toBe>() + return headers + }, + getUpstream (req, base) { + expect(req).type.toBe>() + return base + }, + onResponse (request, reply, res) { + expect(request).type.toBe>() + expect(reply).type.toBe>() + expect(res).type.toBe>() + expect(res.statusCode).type.toBe() + } + }) +}) + +app.get('/http2', (_request, reply) => { + reply.from('/', { + method: 'POST', + retryDelay: ({ req, res, err, attempt, getDefaultDelay }) => { + const defaultDelay = getDefaultDelay(req, res, err, attempt) + expect(defaultDelay).type.toBe() + + if (res && res.statusCode === 500 && req.method === 'GET') { + return 300 + } + return null + }, + rewriteHeaders (headers) { + return headers + }, + rewriteRequestHeaders (_req, headers: IncomingHttpHeaders) { + return headers + }, + onError (reply: FastifyReply, error) { + return reply.send(error.error) + }, + queryString (search, reqUrl, request) { + expect(search).type.toBe() + expect(reqUrl).type.toBe() + expect(request).type.toBe>() + return '' + }, + }) +}) + +expect().type.toBeAssignableFrom(fullOptions) +expect().type.toBeAssignableFrom({ http2: true })