diff --git a/packages/specs/schema/src/components/open-spec/operationInQueryMapper.ts b/packages/specs/schema/src/components/open-spec/operationInQueryMapper.ts index 9c9c316f86c..f06065f9e31 100644 --- a/packages/specs/schema/src/components/open-spec/operationInQueryMapper.ts +++ b/packages/specs/schema/src/components/open-spec/operationInQueryMapper.ts @@ -1,9 +1,37 @@ import {cleanObject} from "@tsed/core"; +import {OS3Example} from "@tsed/openspec"; import {JsonSchemaOptions} from "../../interfaces/JsonSchemaOptions"; import {registerJsonSchemaMapper} from "../../registries/JsonSchemaMapperContainer"; import {createRefName} from "../../utils/ref"; import type {JsonParameterOptions} from "./operationInParameterMapper"; +function buildExamples(property: string, examples?: Record) { + if (!examples) { + return undefined; + } + + let hasKey = false; + + const newExamples = Object.entries(examples).reduce((acc, [key, {value, description, ...props}]) => { + if (value[property] === undefined) { + return acc; + } + + hasKey = true; + + return { + ...acc, + [key]: { + ...props, + value: value[property], + description + } + }; + }, {}); + + return hasKey ? newExamples : undefined; +} + function inlineReference(parameter: any, {jsonParameter, ...options}: JsonSchemaOptions) { const name = createRefName(jsonParameter.$schema.getName(), options); const schema = options.components?.schemas?.[name]; @@ -21,7 +49,8 @@ function inlineReference(parameter: any, {jsonParameter, ...options}: JsonSchema required: (schema?.required || []).includes(key), description, schema: prop, - style: prop.$ref ? "deepObject" : undefined + style: prop.$ref ? "deepObject" : undefined, + examples: buildExamples(key, parameter.examples) }) ]; }, []); diff --git a/packages/specs/schema/test/integrations/query-model-examples.spec.ts b/packages/specs/schema/test/integrations/query-model-examples.spec.ts new file mode 100644 index 00000000000..bc07320182d --- /dev/null +++ b/packages/specs/schema/test/integrations/query-model-examples.spec.ts @@ -0,0 +1,124 @@ +import { + Default, + Examples, + GenericOf, + Generics, + getSpec, + In, + Maximum, + Minimum, + OperationPath, + Path, + Property, + SpecTypes +} from "../../src/index"; +import {QueryParams} from "@tsed/platform-params"; + +class QueryParamModel { + @Property() + path: string; + + @Property() + condition: string; + + @Property() + value: string; +} + +@Path("/query") +class QueryModelCtrl { + @OperationPath("GET", "/") + async get( + @QueryParams() + @Examples({ + example1: { + description: "description1", + value: { + path: "path1", + condition: "condition1" + } + }, + example2: { + description: "description1", + value: { + path: "path2", + condition: "condition2" + } + } + }) + q: QueryParamModel + ) {} +} + +describe("Query Model example", () => { + it("should generate the spec for deep object", () => { + const spec = getSpec(QueryModelCtrl, {specType: SpecTypes.OPENAPI}); + + expect(spec).toEqual({ + paths: { + "/query": { + get: { + operationId: "queryModelCtrlGet", + parameters: [ + { + in: "query", + name: "path", + required: false, + examples: { + example1: { + description: "description1", + value: "path1" + }, + example2: { + description: "description1", + value: "path2" + } + }, + schema: { + type: "string" + } + }, + { + examples: { + example1: { + description: "description1", + value: "condition1" + }, + example2: { + description: "description1", + value: "condition2" + } + }, + in: "query", + name: "condition", + required: false, + schema: { + type: "string" + } + }, + { + in: "query", + name: "value", + required: false, + schema: { + type: "string" + } + } + ], + responses: { + "200": { + description: "Success" + } + }, + tags: ["QueryModelCtrl"] + } + } + }, + tags: [ + { + name: "QueryModelCtrl" + } + ] + }); + }); +});