Spaces:
Running
Running
Commit
·
f402448
1
Parent(s):
532c8f0
update(swagger-request): read nested
Browse files- src/common/models/exercise.model.ts +2 -0
- src/common/serializers/exercise.serialization.ts +5 -1
- src/common/serializers/exercisePopulate.serialization.ts +4 -0
- src/lib/decorators/swagger-request.decorator.ts +23 -6
- src/lib/decorators/swagger-response.decorator.ts +9 -4
- src/modules/console/modules/exercises/controllers/exercises.controller.ts +1 -1
- src/modules/console/modules/exercises/validations/create-excercise.validation.ts +5 -1
- src/modules/console/modules/exercises/validations/update-excercise.validation.ts +19 -4
src/common/models/exercise.model.ts
CHANGED
@@ -18,6 +18,7 @@ export interface IExercise {
|
|
18 |
secondary: ObjectId;
|
19 |
}
|
20 |
equipments: ObjectId[];
|
|
|
21 |
media: {
|
22 |
type: "image" | "video";
|
23 |
url: string;
|
@@ -41,6 +42,7 @@ const exerciseSchema = new Schema({
|
|
41 |
secondary: { type: Schema.Types.ObjectId, ref: "muscles" },
|
42 |
},
|
43 |
equipments: [{ type: Schema.Types.ObjectId, ref: "equipments" }],
|
|
|
44 |
media: {
|
45 |
type: {
|
46 |
type: String,
|
|
|
18 |
secondary: ObjectId;
|
19 |
}
|
20 |
equipments: ObjectId[];
|
21 |
+
coverImage: string;
|
22 |
media: {
|
23 |
type: "image" | "video";
|
24 |
url: string;
|
|
|
42 |
secondary: { type: Schema.Types.ObjectId, ref: "muscles" },
|
43 |
},
|
44 |
equipments: [{ type: Schema.Types.ObjectId, ref: "equipments" }],
|
45 |
+
coverImage: { type: String, required: true },
|
46 |
media: {
|
47 |
type: {
|
48 |
type: String,
|
src/common/serializers/exercise.serialization.ts
CHANGED
@@ -77,9 +77,13 @@ export class ExerciseSerialization {
|
|
77 |
@Expose()
|
78 |
@SwaggerResponseProperty({ type: ["string"] })
|
79 |
equipments: any;
|
|
|
|
|
|
|
|
|
80 |
|
81 |
@Expose({ name: "media" })
|
82 |
@SwaggerResponseProperty({ type: Media })
|
83 |
@Transform(({ value }) => serialize(value, Media))
|
84 |
-
media:
|
85 |
}
|
|
|
77 |
@Expose()
|
78 |
@SwaggerResponseProperty({ type: ["string"] })
|
79 |
equipments: any;
|
80 |
+
|
81 |
+
@Expose()
|
82 |
+
@SwaggerResponseProperty('string')
|
83 |
+
coverImage: string;
|
84 |
|
85 |
@Expose({ name: "media" })
|
86 |
@SwaggerResponseProperty({ type: Media })
|
87 |
@Transform(({ value }) => serialize(value, Media))
|
88 |
+
media: Media;
|
89 |
}
|
src/common/serializers/exercisePopulate.serialization.ts
CHANGED
@@ -80,6 +80,10 @@ export class ExercisePopulateSerialization {
|
|
80 |
@SwaggerResponseProperty({ type: [EquipmentSerialization] })
|
81 |
equipments: any;
|
82 |
|
|
|
|
|
|
|
|
|
83 |
@Expose({ name: "media" })
|
84 |
@SwaggerResponseProperty({ type: MediaPopulate })
|
85 |
@Transform(({ value }) => serialize(value, MediaPopulate))
|
|
|
80 |
@SwaggerResponseProperty({ type: [EquipmentSerialization] })
|
81 |
equipments: any;
|
82 |
|
83 |
+
@Expose()
|
84 |
+
@SwaggerResponseProperty('string')
|
85 |
+
coverImage: string;
|
86 |
+
|
87 |
@Expose({ name: "media" })
|
88 |
@SwaggerResponseProperty({ type: MediaPopulate })
|
89 |
@Transform(({ value }) => serialize(value, MediaPopulate))
|
src/lib/decorators/swagger-request.decorator.ts
CHANGED
@@ -1,6 +1,28 @@
|
|
1 |
import { swaggerRegistry } from "@lib/swagger/swagger";
|
2 |
import { getCallingFileName } from "@lib/utils/calling-file.helper";
|
3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
export const SwaggerRequest = (joiSchema: any) => {
|
5 |
return (target: any, propertyKey: string) => {
|
6 |
const schema: any = {
|
@@ -8,12 +30,7 @@ export const SwaggerRequest = (joiSchema: any) => {
|
|
8 |
properties: {},
|
9 |
};
|
10 |
|
11 |
-
|
12 |
-
properties.forEach((property) => {
|
13 |
-
schema.properties[property] = {
|
14 |
-
type: joiSchema.describe().keys[property].type,
|
15 |
-
};
|
16 |
-
});
|
17 |
|
18 |
target.constructor['targetName'] = target.constructor.name + getCallingFileName();
|
19 |
swaggerRegistry.updateRoute(target.constructor['targetName'], {
|
|
|
1 |
import { swaggerRegistry } from "@lib/swagger/swagger";
|
2 |
import { getCallingFileName } from "@lib/utils/calling-file.helper";
|
3 |
|
4 |
+
const parseToSchema = (schema: any, joiSchema: any) => {
|
5 |
+
joiSchema = joiSchema.describe && joiSchema.describe().keys || joiSchema.keys || joiSchema;
|
6 |
+
let properties: any;
|
7 |
+
try {
|
8 |
+
properties = Object.getOwnPropertyNames(joiSchema);
|
9 |
+
} catch (error) {
|
10 |
+
console.log(joiSchema)
|
11 |
+
}
|
12 |
+
properties.forEach((property) => {
|
13 |
+
const type = joiSchema[property].type;
|
14 |
+
if (type === "object") {
|
15 |
+
schema.properties[property] = {
|
16 |
+
type: "object",
|
17 |
+
properties: {},
|
18 |
+
};
|
19 |
+
parseToSchema(schema.properties[property], joiSchema[property]);
|
20 |
+
} else {
|
21 |
+
schema.properties[property] = {type};
|
22 |
+
}
|
23 |
+
});
|
24 |
+
}
|
25 |
+
|
26 |
export const SwaggerRequest = (joiSchema: any) => {
|
27 |
return (target: any, propertyKey: string) => {
|
28 |
const schema: any = {
|
|
|
30 |
properties: {},
|
31 |
};
|
32 |
|
33 |
+
parseToSchema(schema, joiSchema)
|
|
|
|
|
|
|
|
|
|
|
34 |
|
35 |
target.constructor['targetName'] = target.constructor.name + getCallingFileName();
|
36 |
swaggerRegistry.updateRoute(target.constructor['targetName'], {
|
src/lib/decorators/swagger-response.decorator.ts
CHANGED
@@ -54,10 +54,15 @@ const responseToSwaggerSchema = (response: any) => {
|
|
54 |
);
|
55 |
schema.properties[property].type = "array";
|
56 |
} else {
|
57 |
-
schema.properties[property].
|
58 |
-
|
59 |
-
|
60 |
-
|
|
|
|
|
|
|
|
|
|
|
61 |
}
|
62 |
}
|
63 |
|
|
|
54 |
);
|
55 |
schema.properties[property].type = "array";
|
56 |
} else {
|
57 |
+
if(Array.isArray(schema.properties[property].type[0])){
|
58 |
+
schema.properties[property].enum = schema.properties[property].type[0]
|
59 |
+
schema.properties[property].type = "string";
|
60 |
+
}else{
|
61 |
+
schema.properties[property].items = {
|
62 |
+
type: schema.properties[property].type[0],
|
63 |
+
};
|
64 |
+
schema.properties[property].type = "array";
|
65 |
+
}
|
66 |
}
|
67 |
}
|
68 |
|
src/modules/console/modules/exercises/controllers/exercises.controller.ts
CHANGED
@@ -63,7 +63,7 @@ export class ExercisesController extends BaseController {
|
|
63 |
populateArray: [
|
64 |
{ path: "targetMuscles.primary" },
|
65 |
{ path: "targetMuscles.secondary" },
|
66 |
-
{ path: "
|
67 |
],
|
68 |
}
|
69 |
);
|
|
|
63 |
populateArray: [
|
64 |
{ path: "targetMuscles.primary" },
|
65 |
{ path: "targetMuscles.secondary" },
|
66 |
+
{ path: "equipments" },
|
67 |
],
|
68 |
}
|
69 |
);
|
src/modules/console/modules/exercises/validations/create-excercise.validation.ts
CHANGED
@@ -13,8 +13,12 @@ export interface ICreateExercise {
|
|
13 |
sets: number;
|
14 |
instructions: string;
|
15 |
benefits: string;
|
16 |
-
targetMuscles:
|
|
|
|
|
|
|
17 |
equipments: string[]; // refs
|
|
|
18 |
media: {
|
19 |
type: "image" | "video";
|
20 |
url: string;
|
|
|
13 |
sets: number;
|
14 |
instructions: string;
|
15 |
benefits: string;
|
16 |
+
targetMuscles: {
|
17 |
+
primary: string;
|
18 |
+
secondary: string;
|
19 |
+
};
|
20 |
equipments: string[]; // refs
|
21 |
+
coverImage: string,
|
22 |
media: {
|
23 |
type: "image" | "video";
|
24 |
url: string;
|
src/modules/console/modules/exercises/validations/update-excercise.validation.ts
CHANGED
@@ -13,8 +13,12 @@ export interface IUpdateExercise {
|
|
13 |
sets?: number;
|
14 |
instructions?: string;
|
15 |
benefits?: string;
|
16 |
-
targetMuscles?:
|
|
|
|
|
|
|
17 |
equipments?: string[]; // refs
|
|
|
18 |
media?: {
|
19 |
type: "image" | "video";
|
20 |
url: string;
|
@@ -63,14 +67,25 @@ export const updateExerciseSchema = createSchema<IUpdateExercise>({
|
|
63 |
"any.required": "benefits is required",
|
64 |
"string.empty": "benefits can not be empty",
|
65 |
}),
|
66 |
-
targetMuscles: joi.
|
67 |
-
|
68 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
69 |
}),
|
70 |
equipments: joi.array().items(joi.string()).empty().optional().messages({
|
71 |
"array.base": "please enter a valid equipments",
|
72 |
"any.required": "equipments is required",
|
73 |
}),
|
|
|
|
|
|
|
|
|
|
|
74 |
media: joi.object().keys({
|
75 |
type: joi.string().valid("image", "video").optional().messages({
|
76 |
"string.base": "please enter a valid media type",
|
|
|
13 |
sets?: number;
|
14 |
instructions?: string;
|
15 |
benefits?: string;
|
16 |
+
targetMuscles?: {
|
17 |
+
primary: string;
|
18 |
+
secondary: string;
|
19 |
+
};
|
20 |
equipments?: string[]; // refs
|
21 |
+
coverImage?: string,
|
22 |
media?: {
|
23 |
type: "image" | "video";
|
24 |
url: string;
|
|
|
67 |
"any.required": "benefits is required",
|
68 |
"string.empty": "benefits can not be empty",
|
69 |
}),
|
70 |
+
targetMuscles: joi.object().keys({
|
71 |
+
primary: joi.string().empty().optional().messages({
|
72 |
+
"string.base": "please enter a valid primary muscle",
|
73 |
+
"any.required": "primary muscle is required",
|
74 |
+
}),
|
75 |
+
secondary: joi.string().empty().optional().messages({
|
76 |
+
"string.base": "please enter a valid secondary muscle",
|
77 |
+
"any.required": "secondary muscle is required",
|
78 |
+
}),
|
79 |
}),
|
80 |
equipments: joi.array().items(joi.string()).empty().optional().messages({
|
81 |
"array.base": "please enter a valid equipments",
|
82 |
"any.required": "equipments is required",
|
83 |
}),
|
84 |
+
coverImage: joi.string().empty().optional().messages({
|
85 |
+
"string.base": "please enter a valid cover image",
|
86 |
+
"any.required": "cover image is required",
|
87 |
+
"string.empty": "cover image can not be empty",
|
88 |
+
}),
|
89 |
media: joi.object().keys({
|
90 |
type: joi.string().valid("image", "video").optional().messages({
|
91 |
"string.base": "please enter a valid media type",
|