class-validator doesn't appear to do anything in NestJS application - nestjs

I'm setting up a new NestJS application, and I've just added class-validator in order to validate controller input, but it seems to be completely ignored. This is the DTO:
import {IsString} from 'class-validator';
export class CreateCompanyDto {
#IsString()
name: string | undefined;
}
This is the controller:
import {
Body,
Controller,
InternalServerErrorException,
Post,
Request,
UseGuards, ValidationPipe
} from '#nestjs/common';
import * as admin from 'firebase-admin';
import {User} from 'firebase';
import {AuthGuard} from '../auth/auth.guard';
import {CurrentUser} from '../auth/current-user.decorator';
import {CreateCompanyDto} from './dto/create-company.dto';
#Controller('vendor')
export class VendorController {
#Post()
#UseGuards(AuthGuard)
async create(#CurrentUser() user: User, #Request() req: any, #Body(new ValidationPipe({ transform: true })) company: CreateCompanyDto) {
console.log(JSON.stringify(company));
throw new InternalServerErrorException('meh?');
// irrelevant code
}
}
I would expect the code to throw a validation error and never hit the method itself, but instead it runs into the exception, and the object is logged exactly as it came in.
package.json:
{
"name": "functions",
"scripts": {
"lint": "tslint --project tsconfig.json",
"prebuild": "(cd src && rm settings.json && ln -s ../configs/prod.json settings.json)",
"build": "tsc",
"prebuild:dev": "(cd src && rm settings.json && ln -s ../configs/dev.json settings.json)",
"build:dev": "tsc",
"serve": "concurrently \"npm run build:dev -- --watch\" \"firebase emulators:start --only functions\"",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "8"
},
"main": "lib/functions/src/index.js",
"dependencies": {
"#elastic/elasticsearch": "^7.6.0",
"#nestjs/common": "^6.11.11",
"#nestjs/core": "^6.11.11",
"#nestjs/platform-express": "^6.11.11",
"#types/airtable": "^0.5.7",
"#types/nodemailer": "^6.4.0",
"airtable": "^0.8.1",
"class-transformer": "^0.2.3",
"class-validator": "^0.11.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"firebase": "^7.10.0",
"firebase-admin": "^8.9.2",
"firebase-functions": "^3.3.0",
"nodemailer": "^6.4.4",
"reflect-metadata": "^0.1.13",
"rxjs": "^6.5.4",
"slugify": "^1.4.0"
},
"devDependencies": {
"concurrently": "^5.1.0",
"tslint": "^6.0.0",
"typescript": "~3.7.5"
},
"private": true
}
What am I missing here?
Update
I did a little debugging, and I can tell where it's going wrong, even though I still don't know why.
In the ValidationPipe.transform method, it returns the raw input, because metatype is undefined:
async transform(value, metadata) {
const { metatype } = metadata;
if (!metatype || !this.toValidate(metadata)) {
return value;
}
// ...
}

in main.ts add app.useGlobalPipes(new ValidationPipe());:
import { ValidationPipe } from '#nestjs/common';
import { NestFactory } from '#nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors();
app.useGlobalPipes(new ValidationPipe());
await app.listen(process.env.PORT || 3000);
}
bootstrap();

Ok, the debugging gave me enough info to find the issue on Google, where I found this Github issue: https://github.com/nestjs/nest/issues/690
You need to enable "emitDecoratorMetadata": true in your tsconfig.json file for this to work.

In my case the validations did not work as I did not have the class-transformer dependency in my application. Hope this helps someone.
You need both class-validator and class-transformer
$ npm i --save class-validator class-transformer

Related

I am facing error while runing sveltekit app (Not found:/)

I am trying to run my sveltekit app, it was running fine few day's back but suddenly now when I run
"npm run build" it throw error Error: Not found: /, the way I understand is it is couldn't find entry file for app
// my vite.config file
// vite.config.js
import { sveltekit } from '#sveltejs/kit/vite';
/** #type {import('vite').UserConfig} */
const config = {
plugins: [sveltekit()]
};
export default config;
// my package.json
{
"name": "first-pwa",
"version": "0.0.1",
"scripts": {
"dev": "vite dev",
"build": "vite build",
"package": "vite package",
"preview": "vite preview",
"test": "playwright test",
"lint": "prettier --ignore-path .gitignore --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .",
"format": "prettier --ignore-path .gitignore --write --plugin-search-dir=. ."
},
"devDependencies": {
"#playwright/test": "^1.21.0",
"#sveltejs/adapter-auto": "^1.0.0-next.34",
"#sveltejs/adapter-static": "^1.0.0-next.29",
"#sveltejs/kit": "^1.0.0-next.314",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-svelte3": "^3.4.1",
"leaflet": "^1.8.0",
"prettier": "^2.6.2",
"prettier-plugin-svelte": "^2.7.0",
"sass": "^1.50.0",
"svelte": "^3.47.0",
"svelte-leafletjs": "^0.9.0",
"svelte-preprocess": "^4.10.6",
"svelte-range-slider-pips": "^2.0.3",
"svelte-simple-datatables": "^0.2.3",
"vanillajs-datepicker": "^1.2.0",
"vite": "^3.0.4"
},
"type": "module",
"dependencies": {
"#glidejs/glide": "^3.5.2",
"#sveltejs/adapter-node": "^1.0.0-next.73",
"bootstrap": "^5.1.3",
"bootstrap-icons": "^1.8.1",
"bootswatch": "^5.1.3",
"chartist": "^0.11.4",
"popper": "^1.0.1",
"svelte-loadable": "^2.0.1",
"svelte-speedometer": "^1.1.0",
"sveltestrap": "github:laxadev/sveltestrap",
"ua-parser-js": "^1.0.2"
}
}
I haven't migrated to the latest sveltekit changes yet I want my old app up running first,it would be very helpful if anyone could help me with this
I have tried adding entry path in vite.config.js but it didn't help
import { defineConfig } from 'vite';
import { sveltekit } from '#sveltejs/kit/vite';
/** #type {import('vite').UserConfig} */
export default defineConfig({
plugins: [sveltekit()]
build: {
lib: {
entry: 'src/routes/index.svelte'
}
}
});
Pages have been renamed from index.svelte to +page.svelte. When you rename your routes they should be detected without a custom entry file configuration.

Firebase When deploying Cloud Function with Typesense Type 'T' does not satisfy the constraint 'DocumentSchema'

I am having a problem when deploying my typesense cloud functions. I have installed the typesense npm package in my project.
I have the following for my cloud function, updateUserInfoInTypesense:
export const updateUserInfoInTypesense = functions
.region("us-central1")
.firestore
.document("users/{userId}")
.onUpdate(async (change) => {
const isPro = await isAtlistedPro(change.before.id);
const isRegular = await isRegularUser(change.before.id);
if (isRegular) {
const previousDocument = change.before.data() as UserInfo;
const document = change.after.data() as UserInfo;
if (!compareUserInfo(previousDocument, document)) {
return indexNormalUser(previousDocument, document).catch((error) => {
functions.logger.log(
"error in updateUserInfoInTypesense catch",
error
);
});
} else {
return {success: true, exit: 5};
}
} else if (isPro) {
const previousDocument = change.before.data() as ProUserInfo;
const document = change.after.data() as ProUserInfo;
if (!compareProUserInfo(previousDocument, document)) {
return indexProWithEvents(previousDocument, document).catch((error) => {
functions.logger.log(
"error in updateUserInfoInTypesense catch",
error
);
});
} else {
return {success: true, exit: 5};
}
} else {
return {success: false, exit: 8};
}
});
When I go to deploy this, I get the following errors:
node_modules/typesense/lib/Typesense/Documents.d.ts:113:92 - error TS2344: Type 'T' does not satisfy the constraint 'DocumentSchema'.
113 search(searchParameters: SearchParams, options: SearchOptions): Promise<SearchResponse<T>>;
~
node_modules/typesense/lib/Typesense/Documents.d.ts:112:38
112 export interface SearchableDocuments<T> {
~
This type parameter might need an `extends DocumentSchema` constraint.
node_modules/typesense/lib/Typesense/MultiSearch.d.ts:11:29 - error TS2344: Type 'T' does not satisfy the constraint 'DocumentSchema'.
11 results: SearchResponse<T>[];
~
node_modules/typesense/lib/Typesense/MultiSearch.d.ts:10:38
10 export interface MultiSearchResponse<T> {
~
This type parameter might need an `extends DocumentSchema` constraint.
node_modules/typesense/lib/Typesense/SearchOnlyDocuments.d.ts:12:131 - error TS2344: Type 'T' does not satisfy the constraint 'DocumentSchema'.
12 search(searchParameters: SearchParams, { cacheSearchResultsForSeconds, abortSignal }?: SearchOptions): Promise<SearchResponse<T>>;
~
node_modules/typesense/lib/Typesense/SearchOnlyDocuments.d.ts:5:42
5 export declare class SearchOnlyDocuments<T> implements SearchableDocuments<T> {
~
This type parameter might need an `extends DocumentSchema` constraint.
Found 3 errors in 3 files.
Errors Files
1 node_modules/typesense/lib/Typesense/Documents.d.ts:113
1 node_modules/typesense/lib/Typesense/MultiSearch.d.ts:11
1 node_modules/typesense/lib/Typesense/SearchOnlyDocuments.d.ts:12
These all seem to be problems in the libraries within Typesense and I have no errors pointing back to my original code. Has anyone seen this? I am a bit confused as to what I am doing wrong.
Here is my package.json, for your reference:
{
"name": "functions",
"scripts": {
"lint": "eslint --ext .ts .",
"build": "tsc",
"serve": "npm run build && firebase emulators:start --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"test": "mocha --reporter spec --timeout 10000",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "14"
},
"main": "lib/index.js",
"dependencies": {
"#babel/runtime": "^7.19.4",
"#firebase/app-compat": "^0.1.28",
"#types/rimraf": "^3.0.2",
"axios": "^0.27.2",
"chai": "^4.3.4",
"csv-parse": "^5.2.1",
"firebase-admin": "^9.8.0",
"firebase-functions": "^3.16.0",
"fs": "0.0.1-security",
"mocha": "^9.1.3",
"puppeteer": "^10.4.0",
"rimraf": "^3.0.2",
"typescript": "^4.7.4",
"typesense": "^1.4.1"
},
"devDependencies": {
"#typescript-eslint/eslint-plugin": "^4.33.0",
"#typescript-eslint/parser": "^4.33.0",
"eslint": "^7.6.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-import": "^2.22.0",
"firebase-functions-test": "^0.2.0"
},
"private": true
}

Typescript checking #current-cloud-backend with amplify and lambda

I am currently working on an app for which I am using amplify and lambda.
My lambda architecture is fairly simple. For now, I only have one lambda and one layer, this is more like a setup so far.
The lambda is using the layer just fine, the problem comes up when launching the app.
this is the error I get
ERROR in apps/eye-catcher-client/amplify/#current-cloud-backend/function/resetDB/src/index.ts:2:23
TS7016: Could not find a declaration file for module 'lodash'. '/home/bloverius/webdev/eye-catcher/node_modules/lodash/lodash.js' implicitly has an 'any' type.
Try `npm i --save-dev #types/lodash` if it exists or add a new declaration (.d.ts) file containing `declare module 'lodash';`
1 | import { APIGatewayProxyHandler } from 'aws-lambda';
> 2 | import { isNil } from 'lodash';
I know, it tells me I am missing the lodash module... problem is, I'm not. I am able to import it just fine in my index.ts file which looks like:
//This is my test lambda
import { APIGatewayProxyHandler } from 'aws-lambda';
import { isNil } from 'lodash'; //the is no error here.
export const handler: APIGatewayProxyHandler = async (event: any) => {
console.log(`EVENT: ${JSON.stringify(event)}`);
if (!isNil(event)) {
console.log('Seems to be working!');
}
console.log('testas');
return {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
};
This is my package.json file frim my layer
{
"version": "1.0.0",
"description": "",
"license": "UNLICENSED",
"main": "index.js",
"dependencies": {
"#formatjs/intl": "^1.15.1",
"atob": "^2.1.2",
"chrome-aws-lambda": "^10.1.0",
"date-fns": "^2.25.0",
"json2csv": "^5.0.6",
"lodash": "^4.17.21",
"node-fetch": "^2.6.7",
"nodemailer": "^6.6.1",
"pdf.js-extract": "^0.1.4",
"puppeteer-core": "^10.1.0",
"source-map-support": "^0.5.19",
"uuid": "^8.3.0"
},
"devDependencies": {
"#types/aws-lambda": "^8.10.59",
"#types/json2csv": "^5.0.3",
"#types/lodash": "^4.14.184",
"#types/node": "^14.0.27",
"#types/nodemailer": "^6.4.0",
"#types/uuid": "^8.0.0"
}
}
and here are the scripts from my front end app:
{
"scripts": {
"c": "cd ../.. && yarn c",
"amplify:eyecatcherclientLayer": "cd amplify/backend/function/eyecatcherclientLayer/opt/ && tsc -p tsconfig.json && cd -",
"preamplify:eyecatcherclientLayer": "cd amplify/backend/function/eyecatcherclientLayer/lib/nodejs && yarn --no-bin-links",
"amplify:resetDB": "cd amplify/backend/function/resetDB && tsc -p ./src/tsconfig.json && cd -"
}
}
whould anyone have the smallest idea on how to fix that error? I just dont get it :(

Nest js packaging hangs at build process of the serverless framework

So i did a fresh install of nestjs application and i am trying to add the serverless framework with it.I also added few of the packages to support the serverless framework
{
"name": "n1",
"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": {
"#hewmen/serverless-plugin-typescript": "^1.1.17",
"#nestjs/common": "^7.0.0",
"#nestjs/core": "^7.0.0",
"#nestjs/platform-express": "^7.0.0",
"aws-lambda": "^1.0.6",
"aws-serverless-express": "^3.3.8",
"express": "^4.17.1",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^6.5.4",
"serverless-offline": "^6.5.0",
"serverless-plugin-optimize": "^4.1.4-rc.1"
},
"devDependencies": {
"#nestjs/cli": "^7.0.0",
"#nestjs/schematics": "^7.0.0",
"#nestjs/testing": "^7.0.0",
"#types/express": "^4.17.3",
"#types/jest": "25.2.3",
"#types/node": "^13.9.1",
"#types/supertest": "^2.0.8",
"#typescript-eslint/eslint-plugin": "3.0.2",
"#typescript-eslint/parser": "3.0.2",
"eslint": "7.1.0",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-import": "^2.20.1",
"jest": "26.0.1",
"prettier": "^1.19.1",
"supertest": "^4.0.2",
"ts-jest": "26.1.0",
"ts-loader": "^6.2.1",
"ts-node": "^8.6.2",
"tsconfig-paths": "^3.9.0",
"typescript": "^3.7.4"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".spec.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
and i have also added the serverless.yml file which is pointing in to lambda.handler
serverless.yml file
service:
name: nest-serverless-framework
plugins:
- '#hewmen/serverless-plugin-typescript'
- serverless-plugin-optimize
- serverless-offline
provider:
name: aws
runtime: nodejs12.x
functions:
main:
handler: src/lambda.handler
events:
- http:
method: any
path: /{any+}
So the handler file is simple it just exported a module that can bootstrap the application
import { Handler, Context } from 'aws-lambda';
import { Server } from 'http';
import { createServer, proxy } from 'aws-serverless-express';
import { eventContext } from 'aws-serverless-express/middleware';
import { NestFactory } from '#nestjs/core';
import { ExpressAdapter } from '#nestjs/platform-express';
import { AppModule } from './app.module';
import express from 'express';
const binaryMimeTypes: string[] = [];
let cachedServer: Server;
// Create the Nest.js server and convert it into an Express.js server
async function bootstrapServer(): Promise<Server> {
if (!cachedServer) {
const expressApp = express();
const nestApp = await NestFactory.create(AppModule, new
ExpressAdapter(expressApp))
nestApp.use(eventContext());
await nestApp.init();
cachedServer = createServer(expressApp, undefined,
binaryMimeTypes);
}
return cachedServer;
}
// Export the handler : the entry point of the Lambda function
export const handler: Handler = async (event: any, context: Context) => {
cachedServer = await bootstrapServer();
return proxy(cachedServer, event, context, 'PROMISE').promise;
}
but when i now try to do sls offline start, the computer just hangs and nothing happen and i have to restart the computer forcefully.
Any help would be appreciated.
I had a similar issue with v8 crashing during the serverless build. Changing packages from #hewmen/serverless-plugin-typescript to the original serverless-plugin-typescript fixed it.
Please note that aws-serverless-express says:
On 11/30 [2022], the AWS Serverless Express library is moving to Vendia and will be rebranded to serverless-express [...]
has become obsolete.
Probably the same job, you wanted to achieve, does the following Vendina example:
vendia serveless basic-starter-nestjs

How to add NODE_PATH to webpack in package.json?

How do I add NODE_PATH to webpack in package.json?
Part of my packcage.json:
"dependencies": {
"axios": "^0.16.2",
"cross-env": "^5.0.1",
"koa": "^2.3.0",
"koa-mount": "^3.0.0",
"koa-static": "^4.0.1",
"koa-trie-router": "^2.1.5",
"mongodb": "^2.2.31",
"nuxt": "^1.0.0-rc3",
"socket.io": "^2.0.3"
},
"devDependencies": {
"babel-eslint": "^7.2.3",
"backpack-core": "^0.4.1"
},
"scripts": {
"test": "mocha --harmony",
"dev": "NODE_PATH=./app backpack dev",
"build": "nuxt build && backpack build",
"start": "cross-env NODE_ENV=production NODE_PATH=./app node build/main.js"
},
backpack.config.js:
module.exports = {
webpack: (config, options, webpack) => {
config.entry.main = './server/index.js'
return config
}
}
In my server.js:
import Koa from 'koa'
import { Nuxt, Builder } from 'nuxt'
import socket from 'socket.io'
import http from 'http'
import config from 'config' // this is './config' without NODE_PATH=./app
Error at npm run dev:
This dependency was not found:
* config in ./server/index.js
But if I run npm start, it is working fine.
Any ideas?
You should edit your webpack configuration to include the app directory for resolving modules.
Based on your code example, it would look like this:
module.exports = {
webpack: (config, options, webpack) => {
config.entry.main = './server/index.js'
config.resolve.modules = ['./app']
return config
}
}
See webpack documentation for details:
https://webpack.js.org/configuration/resolve/#resolve-modules

Resources