fix: swagger recursive type not working

This commit is contained in:
Methapon2001 2024-01-17 11:46:14 +07:00
parent ce22f77b32
commit c1eaeb5c64
No known key found for this signature in database
GPG key ID: 849924FEF46BD132
4 changed files with 114 additions and 57 deletions

View file

@ -1,9 +1,10 @@
import { Body, Controller, Post, Route, Security, SuccessResponse, Tags } from "tsoa";
import HttpStatusCode from "../interfaces/http-status";
import esClient from "../elasticsearch";
import { Search, SearchInfo, SearchOperator } from "../interfaces/search";
import { Search, SearchInfo, SearchOperator, SearchOptions } from "../interfaces/search";
import { StorageFile } from "../interfaces/storage-fs";
import { QueryDslQueryContainer } from "@elastic/elasticsearch/lib/api/types";
import HttpError from "../interfaces/http-error";
const DEFAULT_INDEX = process.env.ELASTICSEARCH_INDEX;
@ -15,7 +16,26 @@ export class SearchController extends Controller {
@Tags("Search")
@Security("bearerAuth")
@SuccessResponse(HttpStatusCode.OK, "สำเร็จ")
public async searchFile(@Body() search: Search): Promise<StorageFile[]> {
public async searchFile(
@Body()
body: {
AND?: (
| SearchInfo
| {
AND?: unknown;
OR?: unknown;
}
)[];
OR?: (
| SearchInfo
| {
AND?: unknown;
OR?: unknown;
}
)[];
} & SearchOptions,
): Promise<StorageFile[]> {
const search = body as Search;
const type = ["match", "match_phrase"] as const;
const searchMapCallback = (v: SearchInfo | SearchOperator): QueryDslQueryContainer => {
@ -23,9 +43,16 @@ export class SearchController extends Controller {
return { [type[search.exact || v.exact ? 1 : 0]]: { [v.field]: v.value } };
}
return {
bool: { must: v.AND?.map(searchMapCallback), should: v.OR?.map(searchMapCallback) },
};
if ("AND" in v || "OR" in v) {
return {
bool: { must: v.AND?.map(searchMapCallback), should: v.OR?.map(searchMapCallback) },
};
}
throw new HttpError(
HttpStatusCode.UNPROCESSABLE_ENTITY,
"ข้อมูลค้นหาไม่ถูกต้อง กรุณาตรวจสอบอีกครั้ง",
);
};
const result = await esClient.search<StorageFile & { attachment: Record<string, string> }>({

View file

@ -1,5 +1,11 @@
import { QueryDslQueryContainer } from "@elastic/elasticsearch/lib/api/types";
export interface SearchOptions {
recursive?: boolean;
path?: string[];
exact?: boolean;
}
export interface SearchInfo {
field: string;
value: string;
@ -11,11 +17,7 @@ export interface SearchOperator {
OR?: (SearchInfo | SearchOperator)[];
}
export interface Search extends SearchOperator {
recursive?: boolean;
path?: string[];
exact?: boolean;
}
export type Search = SearchOperator & SearchOptions;
export function mapCallback(exact: boolean) {
const type = ["match", "match_phrase"] as const;

View file

@ -45,14 +45,22 @@ const models: TsoaRoute.Models = {
"additionalProperties": false,
},
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
"Search": {
"SearchInfo": {
"dataType": "refObject",
"properties": {
"AND": {"dataType":"array","array":{"dataType":"nestedObjectLiteral","nestedProperties":{"exact":{"dataType":"boolean"},"value":{"dataType":"string","required":true},"field":{"dataType":"string","required":true}}}},
"OR": {"dataType":"array","array":{"dataType":"nestedObjectLiteral","nestedProperties":{"exact":{"dataType":"boolean"},"value":{"dataType":"string","required":true},"field":{"dataType":"string","required":true}}}},
"field": {"dataType":"string","required":true},
"value": {"dataType":"string","required":true},
"exact": {"dataType":"boolean"},
},
"additionalProperties": false,
},
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa
"SearchOptions": {
"dataType": "refObject",
"properties": {
"recursive": {"dataType":"boolean"},
"path": {"dataType":"array","array":{"dataType":"string"}},
"exact": {"dataType":"boolean"},
},
"additionalProperties": false,
},
@ -177,7 +185,7 @@ export function RegisterRoutes(app: Router) {
function SearchController_searchFile(request: any, response: any, next: any) {
const args = {
search: {"in":"body","name":"search","required":true,"ref":"Search"},
body: {"in":"body","name":"body","required":true,"dataType":"intersection","subSchemas":[{"dataType":"nestedObjectLiteral","nestedProperties":{"OR":{"dataType":"array","array":{"dataType":"union","subSchemas":[{"ref":"SearchInfo"},{"dataType":"nestedObjectLiteral","nestedProperties":{"OR":{"dataType":"any"},"AND":{"dataType":"any"}}}]}},"AND":{"dataType":"array","array":{"dataType":"union","subSchemas":[{"ref":"SearchInfo"},{"dataType":"nestedObjectLiteral","nestedProperties":{"OR":{"dataType":"any"},"AND":{"dataType":"any"}}}]}}}},{"ref":"SearchOptions"}]},
};
// WARNING: This file was auto-generated with tsoa. Please do not modify it. Re-run tsoa to re-generate this file: https://github.com/lukeautry/tsoa

View file

@ -110,53 +110,27 @@
"type": "object",
"additionalProperties": false
},
"Search": {
"SearchInfo": {
"properties": {
"AND": {
"items": {
"properties": {
"exact": {
"type": "boolean"
},
"value": {
"type": "string"
},
"field": {
"type": "string"
}
},
"required": [
"value",
"field"
],
"type": "object"
},
"type": "array"
"field": {
"type": "string"
},
"OR": {
"items": {
"properties": {
"exact": {
"type": "boolean"
},
"value": {
"type": "string"
},
"field": {
"type": "string"
}
},
"required": [
"value",
"field"
],
"type": "object"
},
"type": "array"
"value": {
"type": "string"
},
"exact": {
"type": "boolean"
},
}
},
"required": [
"field",
"value"
],
"type": "object",
"additionalProperties": false
},
"SearchOptions": {
"properties": {
"recursive": {
"type": "boolean"
},
@ -165,6 +139,9 @@
"type": "string"
},
"type": "array"
},
"exact": {
"type": "boolean"
}
},
"type": "object",
@ -617,7 +594,50 @@
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Search"
"allOf": [
{
"properties": {
"OR": {
"items": {
"anyOf": [
{
"$ref": "#/components/schemas/SearchInfo"
},
{
"properties": {
"OR": {},
"AND": {}
},
"type": "object"
}
]
},
"type": "array"
},
"AND": {
"items": {
"anyOf": [
{
"$ref": "#/components/schemas/SearchInfo"
},
{
"properties": {
"OR": {},
"AND": {}
},
"type": "object"
}
]
},
"type": "array"
}
},
"type": "object"
},
{
"$ref": "#/components/schemas/SearchOptions"
}
]
}
}
}