I am trying to access 2 classes in one dto class but when I check the schema in swagger, it shows only string instead of complete schema. I have gone through a lot of stackoverflow posts but i couldn't find any issue with my dto schema. Please help me in correcting the dto.
This is the schema visible in swagger
{
"originDestinations": [
"string"
],
"travelers": [
"string"
]
}
This is what I want.
{
"originDestinations": [
{
"originLocationCode": "string",
"destinationLocationCode": "string",
"departureDate": "string"
}
],
"travelers": [
{
"travelerType": "string",
"fareOptions": [
"string"
]
}
]
}
When I am running it in postman I am getting an error response where I am getting validations in message.
This is my dto
import { ApiProperty, ApiPropertyOptional } from "#nestjs/swagger";
import { Type } from "class-transformer";
import { IsNotEmpty, IsArray, ValidateNested, IsDateString, MinLength, MaxLength, } from "class-validator";
class Travelers{
#ApiProperty({ enum: [ "ADULT", "CHILD", "SENIOR", "YOUNG", "HELD_INFANT", "SEATED_INFANT", "STUDENT" ]})
travelerType:string;
#ApiProperty({ enum: [ "STANDARD", "INCLUSIVE_TOUR", "SPANISH_MELILLA_RESIDENT", "SPANISH_CEUTA_RESIDENT", "SPANISH_CANARY_RESIDENT", "SPANISH_BALEARIC_RESIDENT", "AIR_FRANCE_METROPOLITAN_DISCOUNT_PASS", "AIR_FRANCE_DOM_DISCOUNT_PASS", "AIR_FRANCE_COMBINED_DISCOUNT_PASS", "AIR_FRANCE_FAMILY", "ADULT_WITH_COMPANION", "COMPANION" ]})
fareOptions: string[];
}
class OriginDestinations {
#ApiProperty()
#IsNotEmpty()
#MinLength(3)
#MaxLength(3)
originLocationCode:string;
#ApiProperty()
#IsNotEmpty()
#MinLength(3)
#MaxLength(3)
destinationLocationCode:string;
#ApiProperty()
#IsDateString()
#IsNotEmpty()
departureDate:string;
// #ApiProperty()
// #IsNotEmpty()
// adults:string;
}
export class originDestinationsDto{
#IsArray()
#ApiProperty()
#IsNotEmpty()
#ValidateNested({ each: true })
#Type(() => OriginDestinations)
originDestinations:OriginDestinations[];
#ApiProperty()
#IsArray()
#IsNotEmpty()
#ValidateNested({ each: true })
#Type(() => Travelers)
travelers:Travelers[];
}
If I try to hit it with postman this is the response generate there
{
"statusCode": 400,
"message": [
"originLocationCode must be shorter than or equal to 3 characters",
"originLocationCode must be longer than or equal to 3 characters",
"originLocationCode should not be empty",
"destinationLocationCode must be shorter than or equal to 3 characters",
"destinationLocationCode must be longer than or equal to 3 characters",
"destinationLocationCode should not be empty",
"departureDate should not be empty",
"departureDate must be a valid ISO 8601 date string"
],
"error": "Bad Request"
}
Swagger cant automatically recognise, your params as objects, so you need to specify it by setting type param:
export class originDestinationsDto{
#ApiProperty({ type: [OriginDestinations] })
originDestinations:OriginDestinations[];
#ApiProperty({ type: [Travelers] })
travelers:Travelers[];
}
take a note, for array, type should be array with specific DTO { type: [Travelers] } while for single object it should be { type: Travelers }
Related
I am wondering if there's a way to create a dto to validate array of object?
Example array:
[
{
"name": "Tag 1",
"description": "This is the first tag"
},
{
"name": "Tag 2",
"description": "This is the second tag"
}
]
At the moment I have this, while it works, it isn't what I am after.
export class Tags {
#ApiProperty({
description: 'The name of the tag',
example: 'Tag 1',
required: true
})
#IsString()
#MaxLength(30)
#MinLength(1)
name: string;
#ApiProperty({
description: 'The description of the tag',
example: 'This is the first tag',
required: true
})
#IsString()
#MinLength(3)
description: string;
}
export class CreateTagDto {
#ApiProperty({ type: [Tags] })
#Type(() => Tags)
#ArrayMinSize(1)
#ValidateNested({ each: true })
tags: Tags[];
}
Just use ParseArrayPipe:
Update your Controller:
#Post()
createExample(#Body(new ParseArrayPipe({ items: Tags, whitelist: true })) body: Tags[]) {
...
}
Ensure to have items and whitelist set.
Update your DTO:
import { IsString, Length } from "class-validator";
export class Tags {
#IsString()
#Length(1, 30)
name: string;
#IsString()
#Length(3)
description: string;
}
I understand what the error is saying and tried debugging every possible solution.
The exact error in my case is:
{
"errors": [
{
"message": "Cannot return null for non-nullable field Order.total.",
"locations": [
{
"line": 5,
"column": 5
}
],
"path": [
"createOrder",
"total"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"Error: Cannot return null for non-nullable field Order.total.",
In my Type Definitions, I have made the Order.total field nullable and the problem still persists.
Order Type:
# Mutation
createOrder(orderInput: OrderInput!): Order!
# Custom Input
input OrderInput {
username: String!
total: Float
pizzas: [ID]!
collectAt: String!
createdAt: String!
}
The create order resolver has been set up just the same as all other resolvers which work perfectly.
Create Order Resolver:
createOrder: async (
_,
{ orderInput: { username, total, pizzas, collectAt, createdAt } }
) => {
try {
// console.log(pizzas);
const newOrder = Order({
username,
total,
pizzas,
collectAt,
createdAt
});
const res = await newOrder.save();
return res;
} catch (err) {
throw new Error("Caught An Error => " + err);
}
}
I know some people may request what ORM I'm using in this case, I'm using mongoose.
Here is the Order Model:
const orderSchema = new Schema({
username: String,
total: Number,
pizzas: [
{
type: Schema.Types.ObjectId,
ref: "pizzas"
}
],
collectAt: String,
createdAt: String
});
Thanks in advance.
I am trying to figure out how to wrap mutate a nested object with graphql mutations, if possible. For instance I have the following schema:
type Equipment{
assetId: ID
assetName: String
assetTag: String
createdAt: String
updatedAt: String
available: Boolean
category: Category
purchaseAt: String
purchaseCost: Float
serial: String
notes: String
}
type Category{
categoryId: ID,
name: String
}
type Mutation {
equipamento( e: EquipmentInput): Equipment
}
input EquipmentInput{
assetName: String
assetTag: String
available: Boolean
purchaseAt: String
category: CategoryInput
purchaseCost: Float
serial: String
notes: String
}
input CategoryInput{
categoryId: ID
name : String
}
This is the POST call on REST. This call works
{
"assetName": "Dell Laptop E5570",
"assetTag": "A0001",
"available": false,
"category":{
"categoryId": 1
} ,
"purchaseAt": "2018-09-10",
"purchaseCost": 1200.00,
"serial": "Serial",
"notes": "Novo"
}
I am trying to do a equivalent on GraphQL using graphql-yoga, but category is a nested object and the create call fail on REST service.
equipamento: (parent, args) => {
const equipment = {
assetName: args.e.assetName,
assetTag: args.e.assetTag,
available: args.e.available,
category: args.e.category.categoryId,
purchaseAt: args.e.purchaseAt,
purchaseCost: args.e.purchaseCost,
serial: args.e.serial,
notes: args.e.notes
}
return fetch(`${equipmentURL}/`, {
method: 'POST',
body: JSON.stringify(equipment),
headers: { 'Content-Type': 'application/json' }
}).then(res => res.json());
}```
Console Log for the GraphQL is
```{"assetName":"Dell Laptop E5570","assetTag":"A0001","available":false,"category":1,"purchaseAt":"2018-09-10","purchaseCost":1200,"serial":"Serial","notes":"Novo"}```
So the question is, how can i format my mutation to have nested object?
I'm trying to find documentation, to no avail, on how to create multi-field indexes in Mongoosejs. In particular I have two fields that need to be indexed and unique. What is an example mongoose schema that indexes two fields together?
You call the index method on your Schema object to do that as shown here. For your case it would be something like:
mySchema.index({field1: 1, field2: 1}, {unique: true});
Defining indexes at the schema level is necessary when creating compound indexes.
animalSchema.index({ name: 1, type: -1 });
Reference: http://mongoosejs.com/docs/guide.html#indexes
import { Schema, Document, model } from 'mongoose';
import { IUser } from './User';
import { IMood } from './Mood';
import { ILocation } from './Location';
export interface IUserMoodLocation extends Document {
userId?: IUser['_id'];
moodId?: IMood['_id'];
locationId?: ILocation['_id'];
}
const UserMoodLocationSchema: Schema = new Schema({
userId: {
type: Schema.Types.ObjectId,
required: true,
ref: 'User'
},
moodId: {
type: Schema.Types.ObjectId,
required: true,
ref: 'Mood'
},
locationId: {
type: Schema.Types.ObjectId,
required: true,
ref: 'Location'
}
});
UserMoodLocationSchema.index(
{ userId: 1, moodId: 1, locationId: 1 },
{ unique: true }
);
export const UserMoodLocation = model<IUserMoodLocation>(
'UserMoodLocation',
UserMoodLocationSchema
);
Following command can be used to create compound index for nested json:
db.ACCOUNT_collection.createIndex({"account.id":1,"account.customerId":1},{unique:1})
Mongo json structure is like :
{"_id":"648738"
"account": {
"id": "123",
"customerId": 7879,
"name": "test"
..
..
}
}
I have tested with sample data it is perfectly working as expected.
By the way, the accepted answer is wrong, as per https://stackoverflow.com/a/52553550/129300 you should wrap the field names in single quotes, ie:
mySchema.index({'field1': 1, 'field2': 1}, {unique: true});
Happy Day!
I should create a js class respecting a json format
{
"rows": [{
"value": {
"comments": ${dInfo.description},
"Tags": [],
"metadataList": {
"names": [],
"metadata": {}
},
}]
}
I would like to know how to declare metadata.
I'm declaring like this actually.
export class Value {
comments: string;
Tags:string[];
metadataList:{
name:string[],
metadata: Object
}
}
Here metadataList is not typed which is not a best practice I think.
how could I declare metadataList with it's type ?
If metadata is a key/value store, you can make the type a little narrower than Object or {} by tightening up the value types:
class Value {
comments: string;
Tags:string[];
metadataList:{
name:string[],
metadata: { [key: string]: string }
}
}
const val = new Value();
val.metadataList = {
name: ['Example'],
metadata: {
key: 'value',
key2: 'value'
}
};
If you have more information about your metadata, I may be able to make it even narrower.