Skip to content

FastifyAdapter can't take a FastifyInstance due to a type error #12979

Closed
@toptal-dave

Description

@toptal-dave

Is there an existing issue for this?

  • I have searched the existing issues

Current behavior

I am following some example code (that needed adapting) to deploy a Nest.js application using Fastify on AWS Lambda. The code is found in this issue and this PR.

When I adapt the code to be error free, I get a type error at the point where I create the FastifyAdapter using a FastifyInstance:

Argument of type 'FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault>' is not assignable to parameter of type 'FastifyHttp2Options<any, FastifyBaseLogger> | FastifyHttp2SecureOptions<any, FastifyBaseLogger> | FastifyHttpsOptions<...> | FastifyInstance<...> | FastifyServerOptions<...>'.
  Type 'FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProviderDefault>' is not assignable to type 'FastifyInstance<any, any, any, FastifyBaseLogger, FastifyTypeProviderDefault>'.
    The types of 'withTypeProvider().decorate' are incompatible between these types.
      Type 'DecorationMethod<FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, Provider>, FastifyInstance<...>>' is not assignable to type 'DecorationMethod<FastifyInstance<any, any, any, FastifyBaseLogger, Provider>, FastifyInstance<any, any, any, FastifyBaseLogger, Provider>>'.
        Target signature provides too few arguments. Expected 2 or more, but got 1.

Fastify type error

Minimum reproduction code

https://github.com/toptal-dave/fastify-adapter-type-error

Steps to reproduce

All I did was replace the original code with the following code in the main.ts:

import { NestFactory } from '@nestjs/core';
import {
  FastifyAdapter,
  NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { AppModule } from './app.module';
import awsLambdaFastify, { PromiseHandler } from '@fastify/aws-lambda';
import fastify, { FastifyInstance, FastifyServerOptions } from 'fastify';
import { Context, APIGatewayProxyEvent } from 'aws-lambda';
import { Logger } from '@nestjs/common';

interface NestApp {
  app: NestFastifyApplication;
  instance: FastifyInstance;
}

let cachedNestApp;

async function bootstrap(): Promise<NestApp> {
  const serverOptions: FastifyServerOptions = {
    logger: (process.env.LOGGER || '0') == '1',
  };
  const instance: FastifyInstance = fastify(serverOptions);
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter(instance),
    {
      logger: !process.env.AWS_EXECUTION_ENV ? new Logger() : console,
    },
  );

  const CORS_OPTIONS = {
    origin: '*',
    allowedHeaders: '*',
    exposedHeaders: '*',
    credentials: false,
    methods: ['GET', 'PUT', 'OPTIONS', 'POST', 'DELETE'],
  };

  app.register(require('fastify-cors'), CORS_OPTIONS);

  app.setGlobalPrefix(process.env.API_PREFIX);

  await app.init();

  return {
    app,
    instance,
  };
}

export const handler = async (
  event: APIGatewayProxyEvent,
  context: Context,
): Promise<PromiseHandler> => {
  if (!cachedNestApp) {
    const nestApp: NestApp = await bootstrap();
    cachedNestApp = awsLambdaFastify(nestApp.instance, {
      decorateRequest: true,
    });
  }

  return cachedNestApp(event, context);
};

Expected behavior

It should be possible to pass a FastifyInstance into FastifyAdapter without causing a type error because it looks like FastifyAdapter takes either options or an instance by the typing:

FastifyAdapter argument types

Package

  • I don't know. Or some 3rd-party package
  • @nestjs/common
  • @nestjs/core
  • @nestjs/microservices
  • @nestjs/platform-express
  • @nestjs/platform-fastify
  • @nestjs/platform-socket.io
  • @nestjs/platform-ws
  • @nestjs/testing
  • @nestjs/websockets
  • Other (see below)

Other package

@fastify/aws-lambda

NestJS version

10.3.0

Packages versions

{
  "name": "@iluvcoffee/application",
  "version": "0.0.1",
  "description": "",
  "author": "",
  "private": true,
  "license": "UNLICENSED",
  "scripts": {
    "build": "nest build",
    "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
    "start": "nest start",
    "start:dev": "nest start --watch",
    "start:debug": "nest start --debug --watch",
    "start:prod": "node dist/main",
    "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:cov": "jest --coverage",
    "test:watch:cov": "jest --watch --coverage",
    "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
    "test:e2e": "jest --config ./test/jest-e2e.json"
  },
  "dependencies": {
    "@fastify/aws-lambda": "^3.5.0",
    "@nestjs/common": "^10.0.0",
    "@nestjs/core": "^10.0.0",
    "@nestjs/mapped-types": "^2.0.4",
    "@nestjs/platform-express": "^10.0.0",
    "@nestjs/platform-fastify": "^10.3.0",
    "@nestjs/typeorm": "^10.0.1",
    "aws-lambda": "^1.0.7",
    "class-transformer": "^0.5.1",
    "class-validator": "^0.14.0",
    "fastify": "^4.25.2",
    "fastify-cors": "^6.1.0",
    "pg": "^8.11.3",
    "reflect-metadata": "^0.1.13",
    "rxjs": "^7.8.1",
    "typeorm": "^0.3.17"
  },
  "devDependencies": {
    "@nestjs/cli": "^10.0.0",
    "@nestjs/schematics": "^10.0.0",
    "@nestjs/testing": "^10.0.0",
    "@types/express": "^4.17.17",
    "@types/jest": "^29.5.2",
    "@types/node": "^20.3.1",
    "@types/supertest": "^2.0.12",
    "@typescript-eslint/eslint-plugin": "^6.0.0",
    "@typescript-eslint/parser": "^6.0.0",
    "eslint": "^8.42.0",
    "eslint-config-prettier": "^9.0.0",
    "eslint-plugin-prettier": "^5.0.0",
    "jest": "^29.5.0",
    "prettier": "^3.0.0",
    "source-map-support": "^0.5.21",
    "supertest": "^6.3.3",
    "ts-jest": "^29.1.0",
    "ts-loader": "^9.4.3",
    "ts-node": "^10.9.1",
    "tsconfig-paths": "^4.2.0",
    "typescript": "^5.1.3"
  },
  "jest": {
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "rootDir": "src",
    "testRegex": ".*\\.spec\\.ts$",
    "transform": {
      "^.+\\.(t|j)s$": "ts-jest"
    },
    "collectCoverageFrom": [
      "**/*.(t|j)s"
    ],
    "coverageDirectory": "../coverage",
    "testEnvironment": "node"
  }
}

Also, the output of npx nest info:


 _   _             _      ___  _____  _____  _     _____
| \ | |           | |    |_  |/  ___|/  __ \| |   |_   _|
|  \| |  ___  ___ | |_     | |\ `--. | /  \/| |     | |
| . ` | / _ \/ __|| __|    | | `--. \| |    | |     | |
| |\  ||  __/\__ \| |_ /\__/ //\__/ /| \__/\| |_____| |_
\_| \_/ \___||___/ \__|\____/ \____/  \____/\_____/\___/


[System Information]
OS Version     : Linux 6.6
NodeJS Version : v18.19.0
NPM Version    : 10.2.3 

[Nest CLI]
Nest CLI Version : 10.2.1 

[Nest Platform Information]
platform-express version : 10.3.0
platform-fastify version : 10.3.0
mapped-types version     : 2.0.4
schematics version       : 10.0.3
typeorm version          : 10.0.1
testing version          : 10.3.0
common version           : 10.3.0
core version             : 10.3.0
cli version              : 10.2.1

Node.js version

18.19.0

In which operating systems have you tested?

  • macOS
  • Windows
  • Linux

Other

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs triageThis issue has not been looked into

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions