diff --git a/index.d.ts b/index.d.ts index 70a99c8..71086cf 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,14 +1,22 @@ /// import { IncomingMessage, ServerResponse, Server } from 'http'; -import { FastifyRequest, FastifyPluginCallback, RawServerBase, RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, RequestGenericInterface, ContextConfigDefault, FastifyInstance} from 'fastify'; +import { FastifyRequest, FastifyPluginCallback, RawServerBase, RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, RequestGenericInterface, ContextConfigDefault, FastifyInstance, FastifySchema, FastifyTypeProvider, FastifyTypeProviderDefault, FastifyBaseLogger } from 'fastify'; import * as fastify from 'fastify'; import * as WebSocket from 'ws'; import { Duplex, DuplexOptions } from 'stream'; import { FastifyReply } from 'fastify/types/reply'; import { RouteGenericInterface } from 'fastify/types/route'; -interface WebsocketRouteOptions = RawRequestDefaultExpression, RequestGeneric extends RequestGenericInterface = RequestGenericInterface> { - wsHandler?: WebsocketHandler; +interface WebsocketRouteOptions< + RawServer extends RawServerBase = RawServerDefault, + RawRequest extends RawRequestDefaultExpression = RawRequestDefaultExpression, + RequestGeneric extends RequestGenericInterface = RequestGenericInterface, + ContextConfig = ContextConfigDefault, + SchemaCompiler extends FastifySchema = FastifySchema, + TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, + Logger extends FastifyBaseLogger = FastifyBaseLogger +> { + wsHandler?: WebsocketHandler; } declare module 'fastify' { @@ -31,29 +39,43 @@ declare module 'fastify' { RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression = RawRequestDefaultExpression, RawReply extends RawReplyDefaultExpression = RawReplyDefaultExpression, + TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, > { - ( + ( path: string, - opts: RouteShorthandOptions & { websocket: true }, // this creates an overload that only applies these different types if the handler is for websockets - handler?: WebsocketHandler - ): FastifyInstance; + opts: RouteShorthandOptions & { websocket: true }, // this creates an overload that only applies these different types if the handler is for websockets + handler?: WebsocketHandler + ): FastifyInstance; } - interface RouteOptions = RawRequestDefaultExpression, RawReply extends RawReplyDefaultExpression = RawReplyDefaultExpression, RouteGeneric extends RouteGenericInterface = RouteGenericInterface, ContextConfig = ContextConfigDefault,SchemaCompiler = fastify.FastifySchema> extends WebsocketRouteOptions {} + interface RouteOptions< + RawServer extends RawServerBase = RawServerDefault, + RawRequest extends RawRequestDefaultExpression = RawRequestDefaultExpression, + RawReply extends RawReplyDefaultExpression = RawReplyDefaultExpression, + RouteGeneric extends RouteGenericInterface = RouteGenericInterface, + ContextConfig = ContextConfigDefault, + SchemaCompiler = fastify.FastifySchema, + TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, + Logger extends FastifyBaseLogger = FastifyBaseLogger + > extends WebsocketRouteOptions { } } declare const websocketPlugin: FastifyPluginCallback; -interface WebSocketServerOptions extends Omit {} +interface WebSocketServerOptions extends Omit { } export type WebsocketHandler< RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression = RawRequestDefaultExpression, - RequestGeneric extends RequestGenericInterface = RequestGenericInterface + RequestGeneric extends RequestGenericInterface = RequestGenericInterface, + ContextConfig = ContextConfigDefault, + SchemaCompiler extends FastifySchema = FastifySchema, + TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, + Logger extends FastifyBaseLogger = FastifyBaseLogger > = ( this: FastifyInstance, connection: SocketStream, - request: FastifyRequest, + request: FastifyRequest ) => void | Promise; export interface SocketStream extends Duplex { @@ -66,6 +88,15 @@ export interface WebsocketPluginOptions { connectionOptions?: DuplexOptions; } -export interface RouteOptions = RawRequestDefaultExpression, RawReply extends RawReplyDefaultExpression = RawReplyDefaultExpression, RouteGeneric extends RouteGenericInterface = RouteGenericInterface, ContextConfig = ContextConfigDefault, SchemaCompiler extends fastify.FastifySchema = fastify.FastifySchema> extends fastify.RouteOptions, WebsocketRouteOptions {} +export interface RouteOptions< + RawServer extends RawServerBase = RawServerDefault, + RawRequest extends RawRequestDefaultExpression = RawRequestDefaultExpression, + RawReply extends RawReplyDefaultExpression = RawReplyDefaultExpression, + RouteGeneric extends RouteGenericInterface = RouteGenericInterface, + ContextConfig = ContextConfigDefault, + SchemaCompiler extends fastify.FastifySchema = fastify.FastifySchema, + TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, + Logger extends FastifyBaseLogger = FastifyBaseLogger +> extends fastify.RouteOptions, WebsocketRouteOptions { } export default websocketPlugin; diff --git a/package.json b/package.json index b00e3d6..e3cb266 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,8 @@ "homepage": "https://github.com/fastify/fastify-websocket#readme", "devDependencies": { "@fastify/pre-commit": "^2.0.2", + "@fastify/type-provider-typebox": "^2.3.0", + "@sinclair/typebox": "^0.24.44", "@types/ws": "^8.2.2", "fastify": "^4.0.0-rc.2", "snazzy": "^9.0.0", diff --git a/test/types/index.test-d.ts b/test/types/index.test-d.ts index 597a89f..32cd1ad 100644 --- a/test/types/index.test-d.ts +++ b/test/types/index.test-d.ts @@ -1,9 +1,12 @@ import wsPlugin, { WebsocketHandler, SocketStream } from '../..'; -import type {IncomingMessage} from "http"; -import fastify, { RouteOptions, FastifyRequest, FastifyInstance, FastifyReply, RequestGenericInterface } from 'fastify'; +import type { IncomingMessage } from "http"; +import fastify, { RouteOptions, FastifyRequest, FastifyInstance, FastifyReply, RequestGenericInterface, FastifyBaseLogger, RawServerDefault, FastifySchema, RawRequestDefaultExpression, RawServerBase, ContextConfigDefault, RawReplyDefaultExpression } from 'fastify'; import { expectType } from 'tsd'; import { Server } from 'ws'; import { RouteGenericInterface } from 'fastify/types/route'; +import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox'; +import { Static, Type } from '@sinclair/typebox' +import { ResolveFastifyRequestType } from 'fastify/types/type-provider'; const app: FastifyInstance = fastify(); app.register(wsPlugin); @@ -105,3 +108,91 @@ app.route<{ Params: { foo: string }, Body: { bar: string }, Querystring: { searc expectType(request.headers); }, }); + + +const schema = { + params: Type.Object({ + foo: Type.String() + }), + querystring: Type.Object({ + search: Type.String() + }), + body: Type.Object({ + bar: Type.String() + }), + headers: Type.Object({ + auth: Type.String() + }) +}; +type SchemaType = { + params: Static; + querystring: Static; + body: Static; + headers: Static; +}; + +const server = app.withTypeProvider(); + +server.route({ + method: 'GET', + url: '/longhand-type-inference', + schema, + handler: (request, _reply) => { + expectType<{ foo: string }>(request.params); + expectType<{ bar: string }>(request.body); + expectType<{ search: string }>(request.query); + expectType(request.headers); + }, + wsHandler: (connection, request) => { + expectType(connection); + expectType<{ foo: string }>(request.params); + expectType<{ bar: string }>(request.body); + expectType<{ search: string }>(request.query); + expectType(request.headers); + }, +}); + +server.get('/websockets-type-inference', + { + websocket: true, + schema + }, + async function (connection, request) { + expectType(this); + expectType(connection); + expectType(app.websocketServer); + expectType>(request); + expectType(request.ws); + expectType<{ foo: string }>(request.params); + expectType<{ bar: string }>(request.body); + expectType<{ search: string }>(request.query); + expectType(request.headers); + }); + +server.get('/not-websockets-type-inference', + { + websocket: false, + schema + }, + async (request, reply) => { + expectType>>(request); + expectType>(reply); + expectType<{ foo: string }>(request.params); + expectType<{ bar: string }>(request.body); + expectType<{ search: string }>(request.query); + expectType(request.headers); + }); + +server.get('/websockets-no-type-inference', + { websocket: true }, + async function (connection, request) { + expectType(this); + expectType(connection); + expectType(app.websocketServer); + expectType>(request); + expectType(request.ws); + expectType(request.params); + expectType(request.body); + expectType(request.query); + expectType(request.headers); + }); \ No newline at end of file