I am getting an error everytime I run SendGrid.setApiKey
with serverless architecture, let me explain...
So when I run sendgrid.service.ts
locally (code below) It works perfectly fine and runs how I expect it to; It sends an email and sets my API key. But when I try running it on AWS lambda using this tutorial I get this error: SendGrid.setApiKey is not a function
. I thought It was a one-off error, and just did not work with lambda, so I also tried using Vercel with this tutorial , and I got the exact same error. I am not sure why I'm getting this error, my code seems to work fine not in serverless architecture, but every time I try running it in serverless architecture (how I deploy it) I keep getting this error, so I know it is something with my code is incorrect.
I've been stuck on this problem for a couple of days and still have not found a solution, so any help or suggestions would be greatly appreciated.
I know i had similar issue with the package bcrypt
because that does not work in serverless environments either, so I might just try using another emailing service, and see if that works.
sendgrid.service.ts (path: src/auth/services):
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as SendGrid from '@sendgrid/mail';
@Injectable()
export class SendgridService {
constructor() {
SendGrid.setApiKey(process.env.SEND_GRID_KEY);
}
async send(mail: SendGrid.MailDataRequired) {
const transport = await SendGrid.send(mail);
return transport;
}
}
package.json:
{
"name": "api",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"prebuild": "rimraf dist",
"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: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": {
"@nestjs/common": "^9.4.0",
"@nestjs/config": "^2.3.1",
"@nestjs/core": "^9.4.0",
"@nestjs/jwt": "^10.0.3",
"@nestjs/passport": "^9.0.3",
"@nestjs/platform-express": "^9.4.0",
"@nestjs/platform-socket.io": "^9.4.0",
"@nestjs/schedule": "^2.2.1",
"@nestjs/typeorm": "^9.0.1",
"@nestjs/websockets": "^9.4.0",
"@sendgrid/mail": "^7.7.0",
"@vendia/serverless-express": "^4.10.1",
"aws-lambda": "^1.0.7",
"aws-sdk": "^2.1362.0",
"bcryptjs": "^2.4.3",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"cookie-parser": "^1.4.6",
"dotenv": "^16.0.3",
"file-type": "^18.2.1",
"jimp": "^0.22.7",
"morgan": "^1.10.0",
"nodemailer": "^6.9.1",
"passport": "^0.6.0",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"pg": "^8.10.0",
"postmark": "^3.0.15",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.0",
"sharp": "^0.32.0",
"socket.io": "^4.6.1",
"stripe": "^12.2.0",
"typeorm": "^0.3.15",
"uuid": "^9.0.0"
},
"devDependencies": {
"@nestjs/cli": "^9.4.0",
"@nestjs/schematics": "^9.1.0",
"@nestjs/testing": "^9.4.0",
"@types/aws-lambda": "^8.10.114",
"@types/express": "^4.17.17",
"@types/jest": "^29.5.1",
"@types/multer": "^1.4.7",
"@types/node": "^18.15.12",
"@types/passport-jwt": "^3.0.8",
"@types/supertest": "^2.0.12",
"@typescript-eslint/eslint-plugin": "^5.59.0",
"@typescript-eslint/parser": "^5.59.0",
"eslint": "^8.38.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^29.5.0",
"node-mocks-http": "^1.12.2",
"prettier": "^2.8.7",
"rimraf": "^5.0.0",
"serverless-offline": "^12.0.4",
"supertest": "^6.3.3",
"ts-jest": "^29.1.0",
"ts-loader": "^9.4.2",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
"typescript": "^5.0.4"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
tsconfig.json:
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "es2017",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"skipLibCheck": true,
"strictNullChecks": false,
"noImplicitAny": false,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false,
"esModuleInterop": true
}
}
serverless.yaml:
service: SERVICE-NAME
useDotenv: true
plugins:
- serverless-offline
provider:
name: aws
runtime: nodejs12.x
environment:
POSTGRES_HOST: ${env:POSTGRES_HOST}
PORT_OF_POSTGRES: ${env:PORT_OF_POSTGRES}
POSTGRES_USER: ${env:POSTGRES_USER}
POSTGRES_PASSWORD: ${env:POSTGRES_PASSWORD}
POSTGRES_DATABASE: ${env:POSTGRES_DATABASE}
JWT_SECRET: ${env:JWT_SECRET}
TIMEZONE: ${env:TIMEZONE}
ACCESS_KEY_ID: ${env:ACCESS_KEY_ID}
SECRET_ACCESS_KEY: ${env:SECRET_ACCESS_KEY}
BUCKET_NAME_FOR_SUMMARY: ${env:BUCKET_NAME_FOR_SUMMARY}
SEND_GRID_KEY: ${env:SEND_GRID_KEY}
STRIPE_SECRET_KEY: ${env:STRIPE_SECRET_KEY}
STRIPE_PUBLIC_KEY: ${env:STRIPE_PUBLIC_KEY}
functions:
main:
handler: dist/serverless.handler
events:
- http:
method: ANY
path: /
- http:
method: ANY
path: '{proxy+}'