Skip to content

Commit

Permalink
fix: ensure compatibility with Swagger response schema and fix the pa…
Browse files Browse the repository at this point in the history
…rsing of enum types (#4083)

* fix: swagger schema and enum value

* fix: build

* fix: test
  • Loading branch information
czy88840616 authored Sep 23, 2024
1 parent 898a6a7 commit 1dc6803
Show file tree
Hide file tree
Showing 10 changed files with 170 additions and 69 deletions.
2 changes: 1 addition & 1 deletion packages-legacy/cache/src/service/cache.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Config, Init, Provide, Scope, ScopeEnum } from '@midwayjs/core';
import * as cacheManager from 'cache-manager';
const cacheManager = require('cache-manager');

@Provide()
@Scope(ScopeEnum.Singleton)
Expand Down
1 change: 1 addition & 0 deletions packages/cache-manager/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"@midwayjs/core": "^3.18.0",
"@midwayjs/mock": "^3.18.0",
"@midwayjs/redis": "^3.18.0",
"cache-manager": "6.0.0",
"cache-manager-ioredis-yet": "2.1.1"
},
"dependencies": {
Expand Down
5 changes: 2 additions & 3 deletions packages/cache-manager/test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import * as path from 'path';
import * as assert from 'assert';
import { createLightApp, close } from '@midwayjs/mock';
import { caching } from 'cache-manager';
import { createCache } from 'cache-manager';
import { sleep } from '@midwayjs/core';

describe(`index.test.ts`, ()=>{

describe('cache manager', () => {
it('test cache manager wrap method', async () => {
const memoryCache = await caching('memory', {
max: 100,
const memoryCache = await createCache({
ttl: 10
});
let i = 0;
Expand Down
19 changes: 4 additions & 15 deletions packages/swagger/src/common/enum.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,11 @@ export function getEnumValues(enumType: SwaggerEnumType): string[] | number[] {
return [];
}

const values = [];
const uniqueValues = {};
const values = Object.keys(enumType)
.filter(key => isNaN(Number(key)))
.map(key => enumType[key]);

for (const key in enumType) {
const value = enumType[key];
/* eslint-disable no-prototype-builtins */
// filter out cases where enum key also becomes its value (A: B, B: A)
if (
!uniqueValues.hasOwnProperty(value) &&
!uniqueValues.hasOwnProperty(key)
) {
values.push(value);
uniqueValues[value] = value;
}
}
return values;
return Array.from(new Set(values));
}

export function getEnumType(values: (string | number)[]): 'string' | 'number' {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { saveClassMetadata } from '@midwayjs/core';
import { DECORATORS } from '../constants';

export function ApiExcludeController(disable = true): any {
export function ApiExcludeController(disable = true): ClassDecorator {
return (target: any) => {
saveClassMetadata(DECORATORS.API_EXCLUDE_CONTROLLER, { disable }, target);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ import { DECORATORS } from '../constants';
import { Type } from '../interfaces';
import { createMixedDecorator } from './helpers';

export function ApiExtraModel(models: Type | Type[]) {
export function ApiExtraModel(models: Type | Type[]): ClassDecorator {
return createMixedDecorator(DECORATORS.API_EXTRA_MODEL, models);
}
21 changes: 18 additions & 3 deletions packages/swagger/src/swaggerExplorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
SwaggerOptions,
} from './interfaces/';
import { BodyContentType } from '.';
import { getEnumValues } from './common/enum.utils';

@Provide()
@Scope(ScopeEnum.Singleton)
Expand Down Expand Up @@ -643,7 +644,16 @@ export class SwaggerExplorer {
for (const k of keys) {
// 这里是引用,赋值可以直接更改
const tt = resp[k];
if (tt.type) {

if (tt.schema) {
// response 的 schema 需要包含在 content 内
tt.content = {
'application/json': {
schema: this.formatType(tt.schema),
},
};
delete tt.schema;
} else if (tt.type) {
if (Types.isClass(tt.type)) {
this.parseClzz(tt.type);

Expand Down Expand Up @@ -856,8 +866,13 @@ export class SwaggerExplorer {

// 如果有枚举,单独处理
if (metadata.enum) {
// enum 不需要处理
metadata.enum.map(item => this.formatType(item));
if (Array.isArray(metadata.enum)) {
// enum 不需要处理
metadata.enum.map(item => this.formatType(item));
} else {
// 枚举类型需要处理
metadata.enum = getEnumValues(metadata.enum);
}
}

if (metadata.not) {
Expand Down
87 changes: 49 additions & 38 deletions packages/swagger/test/__snapshots__/parser.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2971,24 +2971,28 @@ exports[`test @ApiResponse should test use ApiOkResponse 1`] = `
"parameters": [],
"responses": {
"200": {
"description": "The record has been successfully created.",
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/Cat",
},
{
"properties": {
"age": {
"example": 1,
"type": "number",
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/Cat",
},
},
"type": "object",
{
"properties": {
"age": {
"example": 1,
"type": "number",
},
},
"type": "object",
},
],
"title": "response data",
},
],
"title": "response data",
},
},
"description": "The record has been successfully created.",
},
},
"summary": undefined,
Expand Down Expand Up @@ -3142,17 +3146,20 @@ exports[`test @ApiResponse should test with schema 1`] = `
"parameters": [],
"responses": {
"201": {
"description": "The record has been successfully created.",
"schema": {
"properties": {
"name": {
"description": "The name of the Cat",
"example": "Kitty",
"type": "string",
"content": {
"application/json": {
"schema": {
"properties": {
"age": {
"example": 1,
"type": "number",
},
},
"type": "object",
},
},
"type": "object",
},
"description": "The record has been successfully created.",
},
"403": {
"description": "Forbidden.",
Expand Down Expand Up @@ -3194,24 +3201,28 @@ exports[`test @ApiResponse should test with schema and set ref 1`] = `
"parameters": [],
"responses": {
"201": {
"description": "The record has been successfully created.",
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/Cat",
},
{
"properties": {
"age": {
"example": 1,
"type": "number",
"content": {
"application/json": {
"schema": {
"allOf": [
{
"$ref": "#/components/schemas/Cat",
},
},
"type": "object",
{
"properties": {
"age": {
"example": 1,
"type": "number",
},
},
"type": "object",
},
],
"title": "response data",
},
],
"title": "response data",
},
},
"description": "The record has been successfully created.",
},
"403": {
"description": "Forbidden.",
Expand Down
34 changes: 27 additions & 7 deletions packages/swagger/test/parser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1100,13 +1100,16 @@ describe('test @ApiResponse', () => {
@ApiResponse({
status: 201,
description: 'The record has been successfully created.',
schema: {
type: 'object',
properties: {
name: {
type: 'string',
description: 'The name of the Cat',
example: 'Kitty',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
age: {
type: 'number',
example: 1,
},
},
},
},
},
Expand Down Expand Up @@ -2144,6 +2147,23 @@ describe('test property metadata parse', () => {
});
});

it("should format enum with enum type", () => {
enum StatusEnum {
Disabled,
Enabled,
}

const result = swaggerExplorer.formatType({
type: 'enum',
enum: StatusEnum
});

expect(result).toEqual({
type: 'enum',
enum: [0, 1],
});
});

it('should format additionalProperties', () => {
const result = swaggerExplorer.formatType({
type: 'object',
Expand Down
66 changes: 66 additions & 0 deletions packages/swagger/test/util.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { getEnumValues } from "../src/common/enum.utils";

describe('/test/util.test.ts', () => {
it('test enum get values', () => {
enum StatusEnum {
Disabled,
Enabled,
}

expect(getEnumValues(StatusEnum)).toEqual([0, 1]);

enum StatusEnum2 {
Disabled = 'disabled',
Enabled = 'enabled',
}

expect(getEnumValues(StatusEnum2)).toEqual(['disabled', 'enabled']);

enum StatusEnum3 {
Disabled = 1,
Enabled = 2,
}

expect(getEnumValues(StatusEnum3)).toEqual([1, 2]);

enum StatusEnum4 {
Disabled = 'disabled',
Enabled = 2,
}

expect(getEnumValues(StatusEnum4)).toEqual(['disabled', 2]);

enum StatusEnum5 {
Disabled = 2,
Enabled = 'enabled',
}

expect(getEnumValues(StatusEnum5)).toEqual([2, 'enabled']);

enum StatusEnum6 {
Disabled = '1',
Enabled = 2,
}

expect(getEnumValues(StatusEnum6)).toEqual(['1', 2]);

enum StatusEnum7 {
Disabled = 3,
Enabled,
}

expect(getEnumValues(StatusEnum7)).toEqual([3, 4]);

enum StatusEnum8 {
Disabled = 1,
Enabled = 1,
}

expect(getEnumValues(StatusEnum8)).toEqual([1]);

expect(getEnumValues('test')).toEqual([]);
expect(getEnumValues([1])).toEqual([1]);
expect(getEnumValues([])).toEqual([]);
});

});

0 comments on commit 1dc6803

Please sign in to comment.