Skip to content

Commit 66b70eb

Browse files
authored
Added SchemaCompiler, TypeProvider, and Logger to types. (#225)
* Added SchemaCompiler, TypeProvider, and Logger to types. * Added tests for schema based type inference. * Fixed type specifications in tests and added contextconfig to request types.
1 parent 7566a9e commit 66b70eb

File tree

3 files changed

+138
-14
lines changed

3 files changed

+138
-14
lines changed

index.d.ts

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
/// <reference types="node" />
22
import { IncomingMessage, ServerResponse, Server } from 'http';
3-
import { FastifyRequest, FastifyPluginCallback, RawServerBase, RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, RequestGenericInterface, ContextConfigDefault, FastifyInstance} from 'fastify';
3+
import { FastifyRequest, FastifyPluginCallback, RawServerBase, RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, RequestGenericInterface, ContextConfigDefault, FastifyInstance, FastifySchema, FastifyTypeProvider, FastifyTypeProviderDefault, FastifyBaseLogger } from 'fastify';
44
import * as fastify from 'fastify';
55
import * as WebSocket from 'ws';
66
import { Duplex, DuplexOptions } from 'stream';
77
import { FastifyReply } from 'fastify/types/reply';
88
import { RouteGenericInterface } from 'fastify/types/route';
99

10-
interface WebsocketRouteOptions<RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>, RequestGeneric extends RequestGenericInterface = RequestGenericInterface> {
11-
wsHandler?: WebsocketHandler<RawServer, RawRequest, RequestGeneric>;
10+
interface WebsocketRouteOptions<
11+
RawServer extends RawServerBase = RawServerDefault,
12+
RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,
13+
RequestGeneric extends RequestGenericInterface = RequestGenericInterface,
14+
ContextConfig = ContextConfigDefault,
15+
SchemaCompiler extends FastifySchema = FastifySchema,
16+
TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault,
17+
Logger extends FastifyBaseLogger = FastifyBaseLogger
18+
> {
19+
wsHandler?: WebsocketHandler<RawServer, RawRequest, RequestGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>;
1220
}
1321

1422
declare module 'fastify' {
@@ -31,29 +39,43 @@ declare module 'fastify' {
3139
RawServer extends RawServerBase = RawServerDefault,
3240
RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,
3341
RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>,
42+
TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault,
3443
> {
35-
<RequestGeneric extends RequestGenericInterface = RequestGenericInterface, ContextConfig = ContextConfigDefault>(
44+
<RequestGeneric extends RequestGenericInterface = RequestGenericInterface, ContextConfig = ContextConfigDefault, SchemaCompiler extends FastifySchema = FastifySchema, Logger extends FastifyBaseLogger = FastifyBaseLogger>(
3645
path: string,
37-
opts: RouteShorthandOptions<RawServer, RawRequest, RawReply, RequestGeneric, ContextConfig> & { websocket: true }, // this creates an overload that only applies these different types if the handler is for websockets
38-
handler?: WebsocketHandler<RawServer, RawRequest, RequestGeneric>
39-
): FastifyInstance<RawServer, RawRequest, RawReply>;
46+
opts: RouteShorthandOptions<RawServer, RawRequest, RawReply, RequestGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> & { websocket: true }, // this creates an overload that only applies these different types if the handler is for websockets
47+
handler?: WebsocketHandler<RawServer, RawRequest, RequestGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>
48+
): FastifyInstance<RawServer, RawRequest, RawReply, Logger, TypeProvider>;
4049
}
4150

42-
interface RouteOptions<RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>, RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>, RouteGeneric extends RouteGenericInterface = RouteGenericInterface, ContextConfig = ContextConfigDefault,SchemaCompiler = fastify.FastifySchema> extends WebsocketRouteOptions<RawServer, RawRequest, RouteGeneric> {}
51+
interface RouteOptions<
52+
RawServer extends RawServerBase = RawServerDefault,
53+
RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,
54+
RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>,
55+
RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
56+
ContextConfig = ContextConfigDefault,
57+
SchemaCompiler = fastify.FastifySchema,
58+
TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault,
59+
Logger extends FastifyBaseLogger = FastifyBaseLogger
60+
> extends WebsocketRouteOptions<RawServer, RawRequest, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> { }
4361
}
4462

4563
declare const websocketPlugin: FastifyPluginCallback<WebsocketPluginOptions>;
4664

47-
interface WebSocketServerOptions extends Omit<WebSocket.ServerOptions, "path"> {}
65+
interface WebSocketServerOptions extends Omit<WebSocket.ServerOptions, "path"> { }
4866

4967
export type WebsocketHandler<
5068
RawServer extends RawServerBase = RawServerDefault,
5169
RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,
52-
RequestGeneric extends RequestGenericInterface = RequestGenericInterface
70+
RequestGeneric extends RequestGenericInterface = RequestGenericInterface,
71+
ContextConfig = ContextConfigDefault,
72+
SchemaCompiler extends FastifySchema = FastifySchema,
73+
TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault,
74+
Logger extends FastifyBaseLogger = FastifyBaseLogger
5375
> = (
5476
this: FastifyInstance<Server, IncomingMessage, ServerResponse>,
5577
connection: SocketStream,
56-
request: FastifyRequest<RequestGeneric, RawServer, RawRequest>,
78+
request: FastifyRequest<RequestGeneric, RawServer, RawRequest, SchemaCompiler, TypeProvider, ContextConfig, Logger>
5779
) => void | Promise<any>;
5880

5981
export interface SocketStream extends Duplex {
@@ -66,6 +88,15 @@ export interface WebsocketPluginOptions {
6688
connectionOptions?: DuplexOptions;
6789
}
6890

69-
export interface RouteOptions<RawServer extends RawServerBase = RawServerDefault, RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>, RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>, RouteGeneric extends RouteGenericInterface = RouteGenericInterface, ContextConfig = ContextConfigDefault, SchemaCompiler extends fastify.FastifySchema = fastify.FastifySchema> extends fastify.RouteOptions<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler>, WebsocketRouteOptions<RawServer, RawRequest, RouteGeneric> {}
91+
export interface RouteOptions<
92+
RawServer extends RawServerBase = RawServerDefault,
93+
RawRequest extends RawRequestDefaultExpression<RawServer> = RawRequestDefaultExpression<RawServer>,
94+
RawReply extends RawReplyDefaultExpression<RawServer> = RawReplyDefaultExpression<RawServer>,
95+
RouteGeneric extends RouteGenericInterface = RouteGenericInterface,
96+
ContextConfig = ContextConfigDefault,
97+
SchemaCompiler extends fastify.FastifySchema = fastify.FastifySchema,
98+
TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault,
99+
Logger extends FastifyBaseLogger = FastifyBaseLogger
100+
> extends fastify.RouteOptions<RawServer, RawRequest, RawReply, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger>, WebsocketRouteOptions<RawServer, RawRequest, RouteGeneric, ContextConfig, SchemaCompiler, TypeProvider, Logger> { }
70101

71102
export default websocketPlugin;

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
"homepage": "https://github.com/fastify/fastify-websocket#readme",
3131
"devDependencies": {
3232
"@fastify/pre-commit": "^2.0.2",
33+
"@fastify/type-provider-typebox": "^2.3.0",
34+
"@sinclair/typebox": "^0.24.44",
3335
"@types/ws": "^8.2.2",
3436
"fastify": "^4.0.0-rc.2",
3537
"snazzy": "^9.0.0",

test/types/index.test-d.ts

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import wsPlugin, { WebsocketHandler, SocketStream } from '../..';
2-
import type {IncomingMessage} from "http";
3-
import fastify, { RouteOptions, FastifyRequest, FastifyInstance, FastifyReply, RequestGenericInterface } from 'fastify';
2+
import type { IncomingMessage } from "http";
3+
import fastify, { RouteOptions, FastifyRequest, FastifyInstance, FastifyReply, RequestGenericInterface, FastifyBaseLogger, RawServerDefault, FastifySchema, RawRequestDefaultExpression, RawServerBase, ContextConfigDefault, RawReplyDefaultExpression } from 'fastify';
44
import { expectType } from 'tsd';
55
import { Server } from 'ws';
66
import { RouteGenericInterface } from 'fastify/types/route';
7+
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox';
8+
import { Static, Type } from '@sinclair/typebox'
9+
import { ResolveFastifyRequestType } from 'fastify/types/type-provider';
710

811
const app: FastifyInstance = fastify();
912
app.register(wsPlugin);
@@ -105,3 +108,91 @@ app.route<{ Params: { foo: string }, Body: { bar: string }, Querystring: { searc
105108
expectType<IncomingMessage['headers'] & { auth: string }>(request.headers);
106109
},
107110
});
111+
112+
113+
const schema = {
114+
params: Type.Object({
115+
foo: Type.String()
116+
}),
117+
querystring: Type.Object({
118+
search: Type.String()
119+
}),
120+
body: Type.Object({
121+
bar: Type.String()
122+
}),
123+
headers: Type.Object({
124+
auth: Type.String()
125+
})
126+
};
127+
type SchemaType = {
128+
params: Static<typeof schema.params>;
129+
querystring: Static<typeof schema.querystring>;
130+
body: Static<typeof schema.body>;
131+
headers: Static<typeof schema.headers>;
132+
};
133+
134+
const server = app.withTypeProvider<TypeBoxTypeProvider>();
135+
136+
server.route({
137+
method: 'GET',
138+
url: '/longhand-type-inference',
139+
schema,
140+
handler: (request, _reply) => {
141+
expectType<{ foo: string }>(request.params);
142+
expectType<{ bar: string }>(request.body);
143+
expectType<{ search: string }>(request.query);
144+
expectType<IncomingMessage['headers'] & { auth: string }>(request.headers);
145+
},
146+
wsHandler: (connection, request) => {
147+
expectType<SocketStream>(connection);
148+
expectType<{ foo: string }>(request.params);
149+
expectType<{ bar: string }>(request.body);
150+
expectType<{ search: string }>(request.query);
151+
expectType<IncomingMessage['headers'] & { auth: string }>(request.headers);
152+
},
153+
});
154+
155+
server.get('/websockets-type-inference',
156+
{
157+
websocket: true,
158+
schema
159+
},
160+
async function (connection, request) {
161+
expectType<FastifyInstance>(this);
162+
expectType<SocketStream>(connection);
163+
expectType<Server>(app.websocketServer);
164+
expectType<FastifyRequest<RequestGenericInterface, RawServerDefault, IncomingMessage, SchemaType, TypeBoxTypeProvider, unknown, FastifyBaseLogger>>(request);
165+
expectType<boolean>(request.ws);
166+
expectType<{ foo: string }>(request.params);
167+
expectType<{ bar: string }>(request.body);
168+
expectType<{ search: string }>(request.query);
169+
expectType<IncomingMessage['headers'] & { auth: string }>(request.headers);
170+
});
171+
172+
server.get('/not-websockets-type-inference',
173+
{
174+
websocket: false,
175+
schema
176+
},
177+
async (request, reply) => {
178+
expectType<FastifyRequest<RouteGenericInterface, RawServerDefault, IncomingMessage, SchemaType, TypeBoxTypeProvider, unknown, FastifyBaseLogger, ResolveFastifyRequestType<TypeBoxTypeProvider, FastifySchema, RouteGenericInterface>>>(request);
179+
expectType<FastifyReply<RawServerDefault, RawRequestDefaultExpression, RawReplyDefaultExpression, RouteGenericInterface, ContextConfigDefault, SchemaType, TypeBoxTypeProvider>>(reply);
180+
expectType<{ foo: string }>(request.params);
181+
expectType<{ bar: string }>(request.body);
182+
expectType<{ search: string }>(request.query);
183+
expectType<IncomingMessage['headers'] & { auth: string }>(request.headers);
184+
});
185+
186+
server.get('/websockets-no-type-inference',
187+
{ websocket: true },
188+
async function (connection, request) {
189+
expectType<FastifyInstance>(this);
190+
expectType<SocketStream>(connection);
191+
expectType<Server>(app.websocketServer);
192+
expectType<FastifyRequest<RequestGenericInterface, RawServerDefault, RawRequestDefaultExpression, FastifySchema, TypeBoxTypeProvider, unknown, FastifyBaseLogger>>(request);
193+
expectType<boolean>(request.ws);
194+
expectType<unknown>(request.params);
195+
expectType<unknown>(request.body);
196+
expectType<unknown>(request.query);
197+
expectType<IncomingMessage['headers']>(request.headers);
198+
});

0 commit comments

Comments
 (0)