diff --git a/package.json b/package.json index 13d82c3..79f2ded 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "@fastify/pre-commit": "^2.1.0", "@fastify/type-provider-typebox": "^5.0.0-pre.fv5.1", "@types/node": "^22.0.0", - "fastify": "^5.0.0-alpha.2", + "fastify": "git+https://github.com/livingspec/fastify.git#type-improvements", "proxyquire": "^2.1.3", "standard": "^17.1.0", "tap": "^18.7.0", diff --git a/types/plugin.d.ts b/types/plugin.d.ts index 02d874b..c7a7d24 100644 --- a/types/plugin.d.ts +++ b/types/plugin.d.ts @@ -1,14 +1,13 @@ /// import { + FastifyPluginOptions, + AnyFastifyInstance, + UnEncapsulatedPlugin, FastifyPluginCallback, FastifyPluginAsync, - FastifyPluginOptions, - RawServerBase, - RawServerDefault, - FastifyTypeProvider, - FastifyTypeProviderDefault, - FastifyBaseLogger, + ApplyDependencies, + FastifyDependencies } from 'fastify' type FastifyPlugin = typeof fastifyPlugin @@ -36,6 +35,18 @@ declare namespace fastifyPlugin { export const fastifyPlugin: FastifyPlugin export { fastifyPlugin as default } + + export function createPlugin< + TPlugin extends FastifyPluginCallback, + TDependencies extends FastifyDependencies, + TEnhanced extends ApplyDependencies = ApplyDependencies + > (plugin: TEnhanced, options?: { dependencies?: TDependencies }): UnEncapsulatedPlugin + + export function createPlugin< + TPlugin extends FastifyPluginAsync, + TDependencies extends FastifyDependencies, + TEnhanced extends ApplyDependencies = ApplyDependencies + > (plugin: TEnhanced, options?: { dependencies?: TDependencies }): UnEncapsulatedPlugin } /** @@ -49,13 +60,16 @@ declare namespace fastifyPlugin { declare function fastifyPlugin< Options extends FastifyPluginOptions = Record, - RawServer extends RawServerBase = RawServerDefault, - TypeProvider extends FastifyTypeProvider = FastifyTypeProviderDefault, - Logger extends FastifyBaseLogger = FastifyBaseLogger, - Fn extends FastifyPluginCallback | FastifyPluginAsync = FastifyPluginCallback ->( - fn: Fn extends unknown ? Fn extends (...args: any) => Promise ? FastifyPluginAsync : FastifyPluginCallback : Fn, + Plugin extends FastifyPluginCallback = FastifyPluginCallback>( + fn: Plugin, + options?: fastifyPlugin.PluginMetadata | string +): UnEncapsulatedPlugin>; + +declare function fastifyPlugin< + Options extends FastifyPluginOptions = Record, + Plugin extends FastifyPluginAsync = FastifyPluginAsync>( + fn: Plugin, options?: fastifyPlugin.PluginMetadata | string -): Fn; +): UnEncapsulatedPlugin>; export = fastifyPlugin diff --git a/types/plugin.test-d.ts b/types/plugin.test-d.ts index 70ec5a7..0c8fae8 100644 --- a/types/plugin.test-d.ts +++ b/types/plugin.test-d.ts @@ -1,31 +1,38 @@ import fastifyPlugin from '..'; -import fastify, { FastifyPluginCallback, FastifyPluginAsync, FastifyError, FastifyInstance, FastifyPluginOptions, RawServerDefault, FastifyTypeProviderDefault, FastifyBaseLogger } from 'fastify'; +import fastify, { + FastifyPluginCallback, + FastifyPluginAsync, + FastifyError, + FastifyInstance, + FastifyPluginOptions, + UnEncapsulatedPlugin, +} from 'fastify'; import { expectAssignable, expectError, expectNotType, expectType } from 'tsd' import { Server } from "node:https" import { TypeBoxTypeProvider } from "@fastify/type-provider-typebox" import fastifyExampleCallback from './example-callback.test-d'; import fastifyExampleAsync from './example-async.test-d'; -interface Options { - foo: string +interface Options extends FastifyPluginOptions { + foo?: string } const testSymbol = Symbol('foobar') // Callback -const pluginCallback: FastifyPluginCallback = (fastify, options, next) => { } -expectType(fastifyPlugin(pluginCallback)) +const pluginCallback = fastifyPlugin((fastify, options, next) => fastify) +expectAssignable>(pluginCallback) -const pluginCallbackWithTypes = (fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void): void => { } -expectAssignable(fastifyPlugin(pluginCallbackWithTypes)) -expectNotType(fastifyPlugin(pluginCallbackWithTypes)) +const pluginCallbackWithTypes = fastifyPlugin((fastify: FastifyInstance, options: FastifyPluginOptions, next) => fastify) +expectType>>(pluginCallbackWithTypes) +expectNotType(pluginCallbackWithTypes) -expectAssignable(fastifyPlugin((fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void): void => { })) -expectNotType(fastifyPlugin((fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void): void => { })) +expectAssignable(fastifyPlugin((fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void) => fastify)) +expectNotType(fastifyPlugin((fastify: FastifyInstance, options: FastifyPluginOptions, next: (error?: FastifyError) => void) => fastify)) -expectType(fastifyPlugin(pluginCallback, '')) -expectType(fastifyPlugin(pluginCallback, { +expectAssignable>(fastifyPlugin(pluginCallback, '')) +expectAssignable>(fastifyPlugin(pluginCallback, { fastify: '', name: '', decorators: { @@ -37,33 +44,39 @@ expectType(fastifyPlugin(pluginCallback, { encapsulate: true })) -const pluginCallbackWithOptions: FastifyPluginCallback = (fastify, options, next) => { - expectType(options.foo) -} - -expectType>(fastifyPlugin(pluginCallbackWithOptions)) +const pluginCallbackWithOptions = fastifyPlugin((fastify, options: Options, next) => { + expectType(options.foo) + return fastify +}) +expectAssignable>>(pluginCallbackWithOptions) -const pluginCallbackWithServer: FastifyPluginCallback = (fastify, options, next) => { +const pluginCallbackWithServer = fastifyPlugin((fastify: FastifyInstance, options, next) => { expectType(fastify.server) -} - -expectType>(fastifyPlugin(pluginCallbackWithServer)) - -const pluginCallbackWithTypeProvider: FastifyPluginCallback = (fastify, options, next) => { } - -expectType>(fastifyPlugin(pluginCallbackWithTypeProvider)) + return fastify +}) +expectAssignable, FastifyInstance>>>(pluginCallbackWithServer) + +const pluginCallbackWithTypeProvider = fastifyPlugin((fastify: FastifyInstance, options: Options, next) => fastify.withTypeProvider()) +expectAssignable< + UnEncapsulatedPlugin< + FastifyPluginCallback< + Options, + FastifyInstance, + FastifyInstance + > + > +>(pluginCallbackWithTypeProvider) // Async -const pluginAsync: FastifyPluginAsync = async (fastify, options) => { } -expectType(fastifyPlugin(pluginAsync)) +const pluginAsync = fastifyPlugin(async (fastify, options) => fastify) +expectAssignable>(pluginAsync) -const pluginAsyncWithTypes = async (fastify: FastifyInstance, options: FastifyPluginOptions): Promise => { } -expectType>(fastifyPlugin(pluginAsyncWithTypes)) +const pluginAsyncWithTypes = fastifyPlugin(async (fastify: FastifyInstance, options: FastifyPluginOptions) => fastify) +expectType>>(pluginAsyncWithTypes) -expectType>(fastifyPlugin(async (fastify: FastifyInstance, options: FastifyPluginOptions): Promise => { })) -expectType(fastifyPlugin(pluginAsync, '')) -expectType(fastifyPlugin(pluginAsync, { +expectAssignable>(fastifyPlugin(pluginAsync, '')) +expectAssignable>(fastifyPlugin(pluginAsync, { fastify: '', name: '', decorators: { @@ -75,92 +88,117 @@ expectType(fastifyPlugin(pluginAsync, { encapsulate: true })) -const pluginAsyncWithOptions: FastifyPluginAsync = async (fastify, options) => { - expectType(options.foo) -} - -expectType>(fastifyPlugin(pluginAsyncWithOptions)) +const pluginAsyncWithOptions = fastifyPlugin(async (fastify, options: Options) => { + expectType(options.foo) + return fastify +}) +expectAssignable>>(pluginAsyncWithOptions) -const pluginAsyncWithServer: FastifyPluginAsync = async (fastify, options) => { +const pluginAsyncWithServer = fastifyPlugin(async (fastify: FastifyInstance, options) => { expectType(fastify.server) -} - -expectType>(fastifyPlugin(pluginAsyncWithServer)) - -const pluginAsyncWithTypeProvider: FastifyPluginAsync = async (fastify, options) => { } - -expectType>(fastifyPlugin(pluginAsyncWithTypeProvider)) + return fastify +}) +expectAssignable, FastifyInstance>>>(pluginAsyncWithServer) + +const pluginAsyncWithTypeProvider = fastifyPlugin(async (fastify: FastifyInstance, options: Options) => fastify.withTypeProvider()) +expectAssignable< + UnEncapsulatedPlugin< + FastifyPluginAsync< + Options, + FastifyInstance, + FastifyInstance + > + > +>(pluginAsyncWithTypeProvider) // Fastify register const server = fastify() -server.register(fastifyPlugin(pluginCallback)) -server.register(fastifyPlugin(pluginCallbackWithTypes)) -server.register(fastifyPlugin(pluginCallbackWithOptions)) -server.register(fastifyPlugin(pluginCallbackWithServer)) -server.register(fastifyPlugin(pluginCallbackWithTypeProvider)) -server.register(fastifyPlugin(pluginAsync)) -server.register(fastifyPlugin(pluginAsyncWithTypes)) -server.register(fastifyPlugin(pluginAsyncWithOptions)) -server.register(fastifyPlugin(pluginAsyncWithServer)) -server.register(fastifyPlugin(pluginAsyncWithTypeProvider)) +server.register(pluginCallback) +server.register(pluginCallbackWithTypes) +server.register(pluginCallbackWithOptions) +// TODO +// server.register(pluginCallbackWithServer) +server.register(pluginCallbackWithTypeProvider) +server.register(pluginAsync) +server.register(pluginAsyncWithTypes) +server.register(pluginAsyncWithOptions) +// TODO +// server.register(pluginAsyncWithServer) +server.register(pluginAsyncWithTypeProvider) // properly handling callback and async fastifyPlugin(function (fastify, options, next) { - expectType(fastify) + expectAssignable(fastify) expectType>(options) expectType<(err?: Error) => void>(next) + return fastify }) fastifyPlugin(function (fastify, options, next) { - expectType(fastify) + expectAssignable(fastify) expectType(options) expectType<(err?: Error) => void>(next) + return fastify }) fastifyPlugin(async function (fastify, options) { - expectType(fastify) + expectAssignable(fastify) expectType(options) + return fastify }) -expectAssignable>(fastifyPlugin(async function (fastify: FastifyInstance, options: Options) { })) -expectNotType(fastifyPlugin(async function (fastify: FastifyInstance, options: Options) { })) +expectAssignable>(fastifyPlugin(async function (fastify: FastifyInstance, options: Options) { + return fastify +})) +expectNotType(fastifyPlugin(async function (fastify: FastifyInstance, options: Options) { + return fastify +})) fastifyPlugin(async function (fastify, options: Options) { - expectType(fastify) + expectAssignable(fastify) expectType(options) + return fastify }) fastifyPlugin(async function (fastify, options) { - expectType(fastify) + expectAssignable(fastify) expectType>(options) + return fastify }) expectError( fastifyPlugin(async function (fastify, options: Options, next) { - expectType(fastify) + expectAssignable(fastify) expectType(options) + return fastify }) ) -expectAssignable>(fastifyPlugin(function (fastify, options, next) { })) -expectNotType(fastifyPlugin(function (fastify, options, next) { })) +expectAssignable>(fastifyPlugin(function (fastify, options, next) { + return fastify +})) +expectNotType(fastifyPlugin(function (fastify, options, next) { + return fastify +})) fastifyPlugin(function (fastify, options: Options, next) { - expectType(fastify) + expectAssignable(fastify) expectType(options) expectType<(err?: Error) => void>(next) + + return fastify }) expectError( fastifyPlugin(function (fastify, options: Options, next) { - expectType(fastify) + expectAssignable(fastify) expectType(options) - return Promise.resolve() + return Promise.resolve(fastify) }) ) -server.register(fastifyExampleCallback, { foo: 'bar' }) +server.register(fastifyExampleCallback, { foo: 'bar' } as const) expectError(server.register(fastifyExampleCallback, { foo: 'baz' })) -server.register(fastifyExampleAsync, { foo: 'bar' }) +server.register(fastifyExampleAsync, { foo: 'bar' } as const) expectError(server.register(fastifyExampleAsync, { foo: 'baz' }))