Well, basically I get this error when I try to serverless deploy
or serverless offline
:
PS C:\Users\joaov\Desktop\lambda-ts> serverless offline
Running "serverless" from node_modules
X [ERROR] Could not resolve "mock-aws-s3"
node_modules/@mapbox/node-pre-gyp/lib/util/s3_setup.js:43:28:
43 │ const AWSMock = require('mock-aws-s3');
╵ ~~~~~~~~~~~~~
You can mark the path "mock-aws-s3" as external to exclude it from the bundle, which will remove
this error. You can also surround this "require" call with a try/catch block to handle this
failure at run-time instead of bundle-time.
X [ERROR] Could not resolve "nock"
node_modules/@mapbox/node-pre-gyp/lib/util/s3_setup.js:112:23:
112 │ const nock = require('nock');
╵ ~~~~~~
You can mark the path "nock" as external to exclude it from the bundle, which will remove this
error. You can also surround this "require" call with a try/catch block to handle this failure at
run-time instead of bundle-time.
X [ERROR] Could not resolve "pg-native"
node_modules/pg/lib/native/client.js:4:21:
4 │ var Native = require('pg-native')
╵ ~~~~~~~~~~~
You can mark the path "pg-native" as external to exclude it from the bundle, which will remove
this error. You can also surround this "require" call with a try/catch block to handle this
failure at run-time instead of bundle-time.
Environment: win32, node 16.14.0, framework 3.14.0 (local) 3.14.0v (global), plugin 6.2.1, SDK 4.3.2
Docs: docs.serverless.com
Support: forum.serverless.com
Bugs: github.com/serverless/serverless/issues
Error:
Error: Build failed with 3 errors:
node_modules/@mapbox/node-pre-gyp/lib/util/s3_setup.js:43:28: ERROR: Could not resolve "mock-aws-s3"
node_modules/@mapbox/node-pre-gyp/lib/util/s3_setup.js:112:23: ERROR: Could not resolve "nock"
node_modules/pg/lib/native/client.js:4:21: ERROR: Could not resolve "pg-native"
at failureErrorWithLog (C:\Users\joaov\Desktop\lambda-ts\node_modules\esbuild\lib\main.js:1603:15)
at C:\Users\joaov\Desktop\lambda-ts\node_modules\esbuild\lib\main.js:1249:28
at runOnEndCallbacks (C:\Users\joaov\Desktop\lambda-ts\node_modules\esbuild\lib\main.js:1162:65)
at buildResponseToResult (C:\Users\joaov\Desktop\lambda-ts\node_modules\esbuild\lib\main.js:1247:7)
at C:\Users\joaov\Desktop\lambda-ts\node_modules\esbuild\lib\main.js:1356:14
at C:\Users\joaov\Desktop\lambda-ts\node_modules\esbuild\lib\main.js:666:9
at handleIncomingPacket (C:\Users\joaov\Desktop\lambda-ts\node_modules\esbuild\lib\main.js:763:9)
at Socket.readFromStdout (C:\Users\joaov\Desktop\lambda-ts\node_modules\esbuild\lib\main.js:632:7)
at Socket.emit (node:events:520:28)
at Socket.emit (node:domain:475:12)
at addChunk (node:internal/streams/readable:315:12)
at readableAddChunk (node:internal/streams/readable:289:9)
at Socket.Readable.push (node:internal/streams/readable:228:10)
at Pipe.onStreamRead (node:internal/stream_base_commons:190:23)
PS C:\Users\joaov\Desktop\lambda-ts>
This is the code:
package.json
dependencies:
"dependencies": {
"aws-lambda": "^1.0.7",
"bcrypt": "^5.0.1",
"dotenv": "^16.0.0",
"pg": "^8.7.3",
"reflect-metadata": "^0.1.13",
"typeorm": "^0.3.6",
"uuid": "^8.3.2",
"yup": "^0.32.11"
},
"devDependencies": {
"@serverless/typescript": "^3.8.0",
"@types/aws-lambda": "^8.10.93",
"@types/bcrypt": "^5.0.0",
"@types/node": "^17.0.25",
"@types/pg": "^8.6.5",
"@types/uuid": "^8.3.4",
"esbuild": "^0.14.36",
"serverless": "^3.14.0",
"serverless-esbuild": "^1.26.2",
"serverless-offline": "^8.7.0",
"ts-node": "^10.7.0",
"typescript": "^4.6.3"
}
// src/configs/consts.ts
import {
AWS_RDS_POSTGRES,
AWS_RDS_POSTGRES_DB,
AWS_RDS_POSTGRES_PASSWORD,
AWS_RDS_POSTGRES_PORT,
AWS_RDS_POSTGRES_USER
} from '@configs/env_vars';
export const HOST = AWS_RDS_POSTGRES;
export const PORT = AWS_RDS_POSTGRES_PORT;
export const DATABASE = AWS_RDS_POSTGRES_DB;
export const USER = AWS_RDS_POSTGRES_USER;
export const PASSWORD = AWS_RDS_POSTGRES_PASSWORD;
// src/database/config.ts
import { DataSource } from 'typeorm';
import { User } from '@entities/User';
import { HOST, PORT, DATABASE, USER, PASSWORD } from '@configs/consts';
export const connConfig = new DataSource({
type: 'postgres',
host: HOST,
port: Number(PORT),
database: DATABASE,
username: USER,
password: PASSWORD,
synchronize: false,
entities: [User],
migrations: []
});
// src/entities/User.ts
import { BaseEntity, Column, PrimaryGeneratedColumn } from 'typeorm';
export class User extends BaseEntity {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
name: string;
@Column()
age: number;
@Column()
password: string;
}
// src/lambdas/CreateUser
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
import { handle } from '@services/CreateUser';
import { connConfig } from '@database/config';
import { userSchema } from '@validations/UserSchema';
export const handler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
try {
const { body } = event;
const parsedBody = JSON.parse(body);
userSchema.isValid(parsedBody).catch(() => {
throw Error('Invalid user data.');
});
const user = await handle(connConfig, parsedBody);
if (!user) {
return {
statusCode: 400,
body: JSON.stringify({
message: "Couldn't create user."
})
};
}
return {
statusCode: 200,
body: JSON.stringify({
message: 'User created successfully.',
user
})
};
} catch (error) {
return {
statusCode: 500,
body: JSON.stringify({
error: (error as Error).message
})
};
}
};
// src/services/CreateUser
import 'reflect-metadata';
import { DataSource } from 'typeorm';
import { hash } from 'bcrypt';
import { User } from '@entities/User';
export const handle = async (dataSource: DataSource, userData: User): Promise<User | undefined> => {
try {
await dataSource.initialize();
const user = new User();
const { name, password, age } = userData;
user.name = name;
user.age = age;
const hashedPassword = await hash(password, 10);
user.password = hashedPassword;
const savedUser = await dataSource.manager.save(user);
return savedUser;
} catch (error) {
throw Error("Couldn't connect to database.");
}
};
// src/validations/UserSchema
import * as yup from 'yup';
export const userSchema = yup.object().shape({
name: yup.string().required(),
age: yup.number().required(),
password: yup.string().required()
});
What should I do in order to fix that and get a working aws-lambda + typeorm?
Looks like you're using esbuild to bundle your lambdas? Some node modules don't like being bundled with esbuild and you have to add them as externals. Try adding to esbuild config:
external:
- pg-native
- mock-aws-s3
- nock