Cannot return null for non-nullable field GraphQL Nestjs - mongodb

im getting this error Cannot return null for non-nullable field CityBoundaries.city_name. from mongoDB, but if im using static json data, i get my response fine. Here's my code. Any help will be appreciated :)
city-boundries.model.ts
import { ObjectType, Field, ID, Int, Float } from '#nestjs/graphql';
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose';
import { Document } from 'mongoose';
import 'dotenv/config';
import { CityBoundiresFeatures } from 'src/types/city-boundries-features';
import mongoose from 'mongoose';
export type CityBoundriesDocument = CityBoundaries & Document;
#Schema()
#ObjectType()
export class CityBoundaries extends Document {
#Field(() => ID, { nullable: true })
_id: string | number;
#Prop()
#Field()
readonly city_admin_level: number;
#Prop({ required: true })
#Field()
readonly city_name: string;
#Prop({ required: true })
#Field(() => Float)
readonly city_id: number;
#Prop({ required: true })
#Field(() => Float)
readonly city_osm_id: number;
#Prop({
required: true,
type: mongoose.Schema.Types.ObjectId,
ref: 'CityBoundiresFeatures',
})
#Field(() => [CityBoundiresFeatures], { nullable: true })
features: CityBoundiresFeatures[];
#Prop({ required: true })
#Field({ nullable: true })
type: string;
}
export const CityBoundriesSchema = SchemaFactory.createForClass(CityBoundaries);
city-boundries.module.ts
import { Module } from '#nestjs/common';
import { MongooseModule } from '#nestjs/mongoose';
import {
CityBoundaries,
CityBoundriesSchema,
} from 'src/models/city-boundries.model';
import { CityBoundriesService } from 'src/services/city-boundries.service';
import { CityBoundriesResolvers } from 'src/resolvers/city-boundries.resolver';
import { Bop500_City, CitiesSchema } from 'src/models/cities.model';
import { CitiesService } from 'src/services/cities.service';
#Module({
imports: [
MongooseModule.forFeature([
{
name: CityBoundaries.name,
schema: CityBoundriesSchema,
},
{ name: Bop500_City.name, schema: CitiesSchema },
]),
],
providers: [CityBoundriesService, CityBoundriesResolvers, CitiesService],
})
export class CityBoundriesModule {}
cities.resolver.ts
import { Resolver, Query, Args, ResolveField, Parent } from '#nestjs/graphql';
import { Bop500_City } from 'src/models/cities.model';
import { CityBoundaries } from 'src/models/city-boundries.model';
import { CitiesService } from 'src/services/cities.service';
import { CityBoundriesService } from 'src/services/city-boundries.service';
#Resolver(() => Bop500_City)
export class CitiesResolvers {
constructor(
private readonly citiesService: CitiesService,
private readonly cityBoundariesService: CityBoundriesService,
) {}
#Query(() => [Bop500_City])
/**
* #returns list of all cities
*/
async getAllCities() {
return this.citiesService.findMany();
}
#Query(() => [Bop500_City], { nullable: true })
/**
* #param {string} value take city name as argument from user
* #returns detail of city
*/
async getCity(#Args('city') value: string) {
const res = await this.citiesService.findOneByName(value);
console.log('Response: ', res);
return res;
}
#ResolveField(() => CityBoundaries)
async getBoundries(#Parent() parent: Bop500_City) {
const res = await this.cityBoundariesService.findOneByCityName(
parent.city_name,
);
console.log('Response: ', res);
return res;
}
}
city-boundries.service.ts
import { Injectable } from '#nestjs/common';
import { Model } from 'mongoose';
import { InjectModel } from '#nestjs/mongoose';
import {
CityBoundaries,
CityBoundriesDocument,
} from 'src/models/city-boundries.model';
import * as cityBoundriesData from '../static/City_boundaries.json';
#Injectable()
export class CityBoundriesService {
constructor(
#InjectModel(CityBoundaries.name)
private cityBoundriesModel: Model<CityBoundriesDocument>,
) {}
/**
* #param {string} cityName take city name as argument from user
* #returns boundries of city
*/
async findOneByCityName(cityName: string) {
const res = await this.cityBoundriesModel.find({ city_name: cityName });
return res;
}
}
app.module.ts
import { Module } from '#nestjs/common';
import { GraphQLModule } from '#nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '#nestjs/apollo';
import { MongooseModule } from '#nestjs/mongoose';
import { CitiesModule } from './module/cities.module';
import 'dotenv/config';
import { CityBoundriesModule } from './module/city-boundries.module';
#Module({
imports: [
MongooseModule.forRoot(process.env.MONGODB_DB_URI, {
dbName: process.env.DB_NAME,
}),
GraphQLModule.forRoot<ApolloDriverConfig>({
driver: ApolloDriver,
autoSchemaFile: 'src/schema/schema.gql',
introspection: true,
playground: true,
}),
CitiesModule,
CityBoundriesModule,
],
})
export class AppModule {}

Related

JWT not expiring in nestjs application even after setting expiresIn value

This is what my auth.module.ts looks like:
import { Module } from "#nestjs/common";
import { ConfigModule, ConfigService } from "#nestjs/config";
import { JwtModule } from "#nestjs/jwt";
import { PassportModule } from "#nestjs/passport";
import { TypeOrmModule } from "#nestjs/typeorm";
import appConfig from "src/config/app.config";
import devConfig from "src/config/dev.config";
import stagConfig from "src/config/stag.config";
import { User } from "src/entities/entity/user.entity";
import { AuthService } from "./auth.service";
import { JwtStrategy } from "./passport-strategies/jwt-strategy";
import { LocalStrategy } from "./passport-strategies/local-strategy";
#Module({
imports: [
PassportModule,
ConfigModule.forRoot({
load: [appConfig, devConfig, stagConfig],
ignoreEnvFile: true,
isGlobal: true,
}),
TypeOrmModule.forFeature([
User
]),
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
// secret: configService.get<string>('jwt.secret'),
secret: process.env.TOKEN_KEY,
signOptions: { expiresIn: 30 }
}),
inject: [ConfigService]
}),
],
providers: [
AuthService,
LocalStrategy,
JwtStrategy
],
exports: [AuthService],
})
export class AuthModule {}
As you can see I have set signOptions: { expiresIn: 30 } but when I analyze the token it has no expiration parameter and does not expire.
I am using https://jwt.io/#encoded-jwt to analyze the token:
You have to pass the expiresIn value as string and mention s for seconds like this
JwtModule.register({
secret: jwtConstants.secret,
signOptions: { expiresIn: '60s' },
}),
Do let me know if this works!
The same problem. search ignoreExpiration flag. Here's my problem
e:
#Injectable()
export class JWTStrategy extends PassportStrategy(Strategy) {
constructor(
readonly configService: ConfigService,
private userService: UserService,
) {
super({
jwtFromRequest: ExtractJwt.fromHeader(
configService.get('API_ACCESS_TOKEN_HEADER'),
),
ignoreExpiration: true, // *** FIXME: here
secretOrKey: configService.get('API_ACCESS_TOKEN_SECRET'),
});
}
...
Here is type:
export interface StrategyOptions {
secretOrKey?: string | Buffer | undefined;
secretOrKeyProvider?: SecretOrKeyProvider | undefined;
jwtFromRequest: JwtFromRequestFunction;
issuer?: string | undefined;
audience?: string | undefined;
algorithms?: string[] | undefined;
ignoreExpiration?: boolean | undefined;
passReqToCallback?: boolean | undefined;
jsonWebTokenOptions?: VerifyOptions | undefined;
}
The ignoreExpiration used, https://github.com/auth0/node-jsonwebtoken/blob/master/verify.js#L147
Hope it will help you

How to accept multiple objects into an array NestJS

I have a feedbackQuestion schema which takes (title: string, subtitle: string, types: enum, values: enum)
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose'
import { Document } from 'mongoose'
import { Types, Value } from 'src/common/enum/types.enum'
export type FeedbackQuestionDocument = FeedbackQuestion & Document
#Schema({ timestamps: true, id: true })
export class FeedbackQuestion {
#Prop()
title: string
#Prop()
subtitle: string
#Prop()
types: Types
#Prop()
value: Value
}
export const FeedbackQuestionSchema =
SchemaFactory.createForClass(FeedbackQuestion)
The feedbackQuestion schema serves as a subdocument in my feedback schema for the key question
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose'
import mongoose, { Document, ObjectId } from 'mongoose'
import { User } from './user.schema'
import { Transform, Type } from 'class-transformer'
import { FeedbackQuestion } from './feedback-question.schema'
import { distributionChannels } from 'src/common/enum/distributionChannels.enum'
export type FeedbackDocument = Feedback & Document
#Schema({ timestamps: true, id: true })
export class Feedback {
#Transform(({ value }) => value.toString())
_id: ObjectId
#Prop()
label: string
#Prop({ default: false })
status: boolean
#Prop()
question: [FeedbackQuestion]
#Prop()
comment: string
#Prop()
thankYouMessage: string
#Prop()
distributionChannels: distributionChannels
#Prop({ type: mongoose.Schema.Types.ObjectId, ref: 'User' })
#Type(() => User)
user: User
}
export const FeedbackSchema = SchemaFactory.createForClass(Feedback)
when creating my create-feedbackDto, I assigned question to be an array of type feedbackQuestion
import { Type } from 'class-transformer'
import { FeedbackQuestion } from '../../schemas/feedback-question.schema'
import { IsArray, IsEnum, IsNotEmpty, ValidateNested } from 'class-validator'
import { Types, Value } from '../enum/types.enum'
import { distributionChannels } from '../enum/distributionChannels.enum'
export class CreateFeedbackDto {
#IsNotEmpty()
label: string
status: boolean
#IsArray()
#ValidateNested({ each: true })
#Type(() => FeedbackQuestion)
question: FeedbackQuestion[]
#IsNotEmpty()
comment: string
#IsNotEmpty()
thankYouMessage: string
#IsNotEmpty()
title: string
#IsNotEmpty()
subtitle: string
#IsEnum(Types)
#IsNotEmpty()
types: Types
#IsEnum(Value)
#IsNotEmpty()
value: Value
#IsEnum(distributionChannels)
#IsNotEmpty()
distributionChannels: distributionChannels
}
In my feedback services, I want to work on questions such that I can pass in multiple objects of feedbackQuestion into the question array when creating a feedback. Please How can I do that?
The current code only takes one FeedbackQuestion object in the array
import { Injectable } from '#nestjs/common'
import { InjectModel } from '#nestjs/mongoose'
import { Model } from 'mongoose'
import { Feedback, FeedbackDocument } from '../../schemas/feedback.schema'
import {
FeedbackQuestion,
FeedbackQuestionDocument,
} from '../../schemas/feedback-question.schema'
import { IServiceResponse } from '../../common/interfaces/service.interface'
import { CreateFeedbackDto } from 'src/common/dto/create-feedback.dto'
#Inject#5406able()
export class FeedbackService {
constructor(
#Inject#5406Model(Feedback.name)
private feedbackDocumentModel: Model<FeedbackDocument>,
#Inject#5406Model(FeedbackQuestion.name)
private feedbackQuestionDocumentModel: Model<FeedbackQuestionDocument>,
) {}
async createFeedback(payload: CreateFeedbackDto): Promise<IServiceResponse> {
const feedbackQuestion = await this.feedbackQuestionDocumentModel.create({
title: payload.title,
subtitle: payload.subtitle,
type: payload.types,
value: payload.value,
})
const feedback = await this.feedbackDocumentModel.create({
label: payload.label,
status: payload.status,
question: [feedbackQuestion],
comment: payload.comment,
thankYouMesage: payload.thankYouMessage,
distributionChannels: payload.distributionChannels,
})
// feedback.question.push(feedbackQuestion)
await feedback.save()
return {
data: {
user: feedback,
},
}
}
}
This is the current response I get
"label": "Yearly Feedback",
"status": false,
"question": [
{
"title": "Yearly Feedback",
"subtitle": "Rating the Yearly performance of the organization",
"value": 1,
"_id": "627fa9b915d31bbbc0fe6908",
"createdAt": "2022-05-14T13:08:09.180Z",
"updatedAt": "2022-05-14T13:08:09.180Z",
"__v": 0
}
],
Thanks

MissingDriverError while using postgres

Errors
Error during migration generation:
MissingDriverError: Wrong driver: "undefined" given. Supported drivers are: "aurora-data-api", "aurora-data-api-pg", "better-sqlite3", "capacitor", "cockroachdb", "cordova", "expo", "mariadb", "mongodb", "mssql", "mysql", "nativescript", "oracle", "postgres", "react-native", "sap", "sqlite", "sqljs".
at MissingDriverError.TypeORMError [as constructor] (D:\Projects\Mark1\api2\src\error\TypeORMError.ts:7:9)
at new MissingDriverError (D:\Projects\Mark1\api2\src\error\MissingDriverError.ts:8:9)
at DriverFactory.create (D:\Projects\Mark1\api2\src\driver\DriverFactory.ts:70:23)
at new Connection (D:\Projects\Mark1\api2\src\connection\Connection.ts:122:43)
at ConnectionManager.create (D:\Projects\Mark1\api2\src\connection\ConnectionManager.ts:61:28)
at D:\Projects\Mark1\api2\src\globals.ts:77:35
at step (D:\Projects\Mark1\api2\node_modules\tslib\tslib.js:143:27)
at Object.next (D:\Projects\Mark1\api2\node_modules\tslib\tslib.js:124:57)
at D:\Projects\Mark1\api2\node_modules\tslib\tslib.js:117:75
at new Promise ()
ormConfig.ts
import { TypeOrmModuleOptions } from '#nestjs/typeorm';
import { join } from 'path';
require('dotenv').config();
class ConfigService {
constructor(private env: { [k: string]: string | undefined }) { }
private getValue(key: string, throwOnMissing = true): string {
const value = this.env[key];
if (!value && throwOnMissing) {
throw new Error(`config error - missing env.${key}`);
}
return value;
}
public ensureValues(keys: string[]) {
keys.forEach(k => this.getValue(k, true));
return this;
}
public getPort() {
return this.getValue('PORT', true);
}
public isProduction() {
const mode = this.getValue('MODE', false);
return mode != 'DEV';
}
public getTypeOrmConfig(): TypeOrmModuleOptions {
return {
type: 'postgres',
host: this.getValue('POSTGRES_HOST'),
port: parseInt(this.getValue('POSTGRES_PORT')),
username: this.getValue('POSTGRES_USER'),
password: this.getValue('POSTGRES_PASSWORD'),
database: this.getValue('POSTGRES_DATABASE'),
entities: [join(__dirname, '**', '*.entity.{ts,js}')],
migrationsTableName: 'migration',
migrations: ['src/migration/*.ts'],
cli: {
migrationsDir: 'src/migration',
},
};
}
}
const configService = new ConfigService(process.env)
.ensureValues([
'POSTGRES_HOST',
'POSTGRES_PORT',
'POSTGRES_USER',
'POSTGRES_PASSWORD',
'POSTGRES_DATABASE'
]);
export = configService ;
appmodule.ts
import { Module } from '#nestjs/common';
import { TypeOrmModule } from '#nestjs/typeorm';
import configService from 'ormConfig';
import { AppController } from './app.controller';
import { AppService } from './app.service';
#Module({
imports: [TypeOrmModule.forRoot(configService.getTypeOrmConfig())],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {
}
.env file
POSTGRES_HOST=localhost
POSTGRES_PORT=8080
POSTGRES_USER=postgres
POSTGRES_PASSWORD=saad2113
POSTGRES_DATABASE=mark1
PORT=3000
MODE=DEV
RUN_MIGRATIONS=true

MissingSchemaError in Nestjs

hello everyone i'm not able specify relation to another model. when i add a relation it's showing me this error
Book Model
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose';
import { Document } from 'mongoose';
export type BookDocument = Book & Document;
#Schema({ timestamps: true, collection: 'books' })
export class Book {
#Prop({ type: String, required: true })
name: string;
#Prop({ type: String, required: true })
author: string;
#Prop({ type: String, required: true })
bookType: string;
}
export const BooksSchema = SchemaFactory.createForClass(Book);
BookLend Model
import { Prop, Schema, SchemaFactory } from '#nestjs/mongoose';
import { Schema as mongooseSchema, Document } from 'mongoose';
import { Book } from '../../books/enitiy/book.model';
import { IsNotEmpty } from 'class-validator';
export type BookLendDocument = BookLend & Document;
#Schema({ timestamps: true })
export class BookLend {
#IsNotEmpty()
#Prop({ type: mongooseSchema.Types.ObjectId, ref: 'books', required: true })
bookId: Book;
#IsNotEmpty()
#Prop({ type: String, required: true })
name: string;
#IsNotEmpty()
#Prop({ type: String, required: true })
returnDate: string;
#Prop({ type: String })
returnedOn: string;
#IsNotEmpty()
#Prop({ type: String, required: true })
status: string;
}
export const BookLendSchema = SchemaFactory.createForClass(BookLend);
i'm referring the books objectID to booklend booksID , when i use below code i'm getting error MissingSchemaError: Schema hasn't been registered for model "books".
const allBookLendDetails = await this.bookLend
.find()
.populate('bookId')
.exec();
hi guy's I fixed it by importing the BooksSchema into BookLend Module file
here ref code:-
import { Module } from '#nestjs/common';
import { BookLendService } from './book-lend.service';
import { BookLendController } from './book-lend.controller';
import { MongooseModule } from '#nestjs/mongoose';
import { BookLendSchema } from './entities/book-lend.entity';
import { CommonService } from '../common-service/common-service.service';
import { BooksSchema } from '../books/enitiy/book.model';
#Module({
imports: [
MongooseModule.forFeature([
{ name: 'booklend', schema: BookLendSchema },
{ name: 'books', schema: BooksSchema },
]),
],
controllers: [BookLendController],
providers: [BookLendService, CommonService],
})
export class BookLendModule {}
In the service file, you need to inject the model
constructor(
#InjectModel('booklend') private readonly bookLend: Model<BookLend>,
#InjectModel('books') private readonly books: Model<Book>
) {}

Nest JS, Mongoose: Inject service into model

I'm having a problem with Nest Js and mongoose, Im trying to make a seed for my database,
And the main problem I'm having is I cannot import service from my module, into other module.
And it constantly gives me error:
Nest can't resolve dependencies of the CategoryModel (?). Please make sure that the argument at index [0] is available in the MongooseModule context.
the main thing I'm trying to do is to create seed for my categories.
Here is my Category Module:
import { Module } from '#nestjs/common';
import { CategoryController } from './category.controller';
import { CategoryService } from './category.service';
import { MongooseModule } from '#nestjs/mongoose';
import { CategorySchema } from 'src/models/category.schema';
#Module({
imports: [MongooseModule.forFeature([{ name: 'Category', schema: CategorySchema }])],
controllers: [CategoryController],
providers: [CategoryService]
})
export class CategoryModule {}
My Category service:
import { Model } from 'mongoose';
import { Injectable, Inject } from '#nestjs/common';
import { CategoryInterface } from '../interfaces/category.interface';
import { InjectModel } from '#nestjs/mongoose';
#Injectable()
export class CategoryService {
constructor(#InjectModel('Category') private categoryModel: Model<CategoryInterface>) {}
async create(category){
const createdQuestion = new this.categoryModel(category);
return createdQuestion.save();
}
async getMainCategories() {
return this.categoryModel.find( { parent: null } );
}
}
My Category Controller:
import { Controller, Post, Get, Body, HttpCode } from '#nestjs/common';
import { CategoryService } from './category.service';
#Controller('category')
export class CategoryController {
constructor(private categoryService: CategoryService) { }
#Post()
#HttpCode(204)
async createCategory(#Body() category) {
console.log('evo je kategorija ', category);
const data = await this.categoryService.create(category);
}
#Get('/main')
async getAllCategories() {
const data = await this.categoryService.getMainCategories();
return data;
}
}
My Seeder module where I'm having provider that seed database:
import { Module } from '#nestjs/common';
import { Seeder } from './seeder';
#Module({
providers: [Seeder],
})
export class SeederModule {}
and my seeder.ts
import { Injectable } from '#nestjs/common';
import { CategoryService } from 'src/category/category.service';
#Injectable()
export class Seeder {
constructor(private categoryService: CategoryService) { }
async seed() {
}
async categories() {
// const data = await this.categoryService.createMultiple(categories);
}
}
My App.module
import { Module } from '#nestjs/common';
import { MongooseModule } from '#nestjs/mongoose';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CategoryModule } from './category/category.module';
import { QuizModule } from './quiz/quiz.module';
import { ConfigModule } from '#nestjs/config';
import config from './config/config';
#Module({
imports: [
MongooseModule.forRoot('mongodb://localhost:27017'),
ConfigModule.forRoot({ load: [config], isGlobal: true }),
CategoryModule,
QuizModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Category Model:
import * as mongoose from 'mongoose';
export const CategorySchema = new mongoose.Schema({
name: { type:String, required:true, unique: true },
slug: { type:String, required:true, unique: true },
});
And for some reason it is not working, even If I import whole
GitHub Repository of Project: https://github.com/HunterJS-bit/react-quiz-app
CategoryModule, or CategoryService into Seeder.module ??
Note: To reproduce error try running npm run seed from
server/package.json
Thanks for the help :)
You need to have the CategoryModule add exports: [CategoryService] to allow for other modules to import the module and make use to the CategoryService. This is how you share providers in NestJS. The, you need to add imports: [CategoryModule] to the SeederModule to allow the providers of the SeederModule to use the exports of the CategoryModule. Then, everything should load up just fine.