From fc567d2fbbe49105dfb53d7bbe77f4d0979585ef Mon Sep 17 00:00:00 2001 From: vabene1111 Date: Mon, 23 Sep 2024 14:05:27 +0200 Subject: [PATCH] added some test code and python script for openapi generation --- generate_api_client.py | 33 ++++ vue3/src/openapi/openapitools.json | 2 +- .../templates/customModelFunctions.mustache | 12 ++ .../openapi/templates/modelGeneric.mustache | 172 ++++++++++++++++++ vue3/src/openapi/update.bat | 1 - 5 files changed, 218 insertions(+), 2 deletions(-) create mode 100644 generate_api_client.py create mode 100644 vue3/src/openapi/templates/customModelFunctions.mustache create mode 100644 vue3/src/openapi/templates/modelGeneric.mustache delete mode 100755 vue3/src/openapi/update.bat diff --git a/generate_api_client.py b/generate_api_client.py new file mode 100644 index 000000000..e0b3eba19 --- /dev/null +++ b/generate_api_client.py @@ -0,0 +1,33 @@ +import json +import os +import sys +from urllib.request import urlretrieve + + +os.chdir('vue3/src/openapi') + +# generate base API client for all models +os.system('openapi-generator-cli generate -g typescript-fetch -i http://127.0.0.1:8000/openapi/') + +sys.exit(0) + +# TODO this code was written as a test and commited for archiving +# TODO it is currently not used because the generator creates interfaces not classes, thus cannot be annotated by functions + +# get the latest template from openapi generator and tell it to include the custom model functions +with open('openapitools.json','r') as f: + openapi_tools_config = json.loads(f.read()) + +TEMPLATE_URL = f'https://raw.githubusercontent.com/OpenAPITools/openapi-generator/refs/tags/v{openapi_tools_config['generator-cli']['version']}/modules/openapi-generator/src/main/resources/typescript-fetch/modelGeneric.mustache' +TEMPLATE_FILE_NAME = 'templates/modelGeneric.mustache' +OVERRIDE_FILE_NAME = 'templates/customModelFunctions.mustache' + +urlretrieve(TEMPLATE_URL, TEMPLATE_FILE_NAME) + +with open(TEMPLATE_FILE_NAME, 'a') as template_file, open(OVERRIDE_FILE_NAME, 'r') as override_file: + template_file.write(override_file.read()) + +# generate API client with custom template for specified models +MODELS = ['Keyword', 'Food'] + +os.system(f'openapi-generator-cli generate -g typescript-fetch -t templates -i http://127.0.0.1:8000/openapi/ --global-property models={':'.join(MODELS)}') \ No newline at end of file diff --git a/vue3/src/openapi/openapitools.json b/vue3/src/openapi/openapitools.json index 557168821..2f4612ced 100644 --- a/vue3/src/openapi/openapitools.json +++ b/vue3/src/openapi/openapitools.json @@ -2,6 +2,6 @@ "$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json", "spaces": 2, "generator-cli": { - "version": "7.4.0" + "version": "7.8.0" } } diff --git a/vue3/src/openapi/templates/customModelFunctions.mustache b/vue3/src/openapi/templates/customModelFunctions.mustache new file mode 100644 index 000000000..cf17f265f --- /dev/null +++ b/vue3/src/openapi/templates/customModelFunctions.mustache @@ -0,0 +1,12 @@ +// ---------------------------------------------------------------------- +// Custom model functions added by custom openapi-generator template +// ---------------------------------------------------------------------- +import {ApiApi, Api{{classname}}ListRequest, Paginated{{classname}}List} from "@/openapi"; + +/** + * query list endpoint using the provided request parameters + */ +export function list(requestParameters: Api{{classname}}ListRequest = {}): Promise { + const api = new ApiApi() + return api.api{{classname}}List(requestParameters) +} \ No newline at end of file diff --git a/vue3/src/openapi/templates/modelGeneric.mustache b/vue3/src/openapi/templates/modelGeneric.mustache new file mode 100644 index 000000000..321e1593c --- /dev/null +++ b/vue3/src/openapi/templates/modelGeneric.mustache @@ -0,0 +1,172 @@ +import { mapValues } from '../runtime{{importFileExtension}}'; +{{#hasImports}} +{{#tsImports}} +import type { {{{classname}}} } from './{{filename}}{{importFileExtension}}'; +import { + {{classname}}FromJSON, + {{classname}}FromJSONTyped, + {{classname}}ToJSON, +} from './{{filename}}{{importFileExtension}}'; +{{/tsImports}} + +{{/hasImports}} +{{#discriminator}} +{{#discriminator.mappedModels}} +import { {{modelName}}FromJSONTyped } from './{{modelName}}{{importFileExtension}}'; +{{/discriminator.mappedModels}} +{{/discriminator}} +{{>modelGenericInterfaces}} + +/** + * Check if a given object implements the {{classname}} interface. + */ +export function instanceOf{{classname}}(value: object): value is {{classname}} { + {{#vars}} + {{#required}} + if (!('{{name}}' in value) || value['{{name}}'] === undefined) return false; + {{/required}} + {{/vars}} + return true; +} + +export function {{classname}}FromJSON(json: any): {{classname}} { + return {{classname}}FromJSONTyped(json, false); +} + +export function {{classname}}FromJSONTyped(json: any, ignoreDiscriminator: boolean): {{classname}} { + {{#hasVars}} + if (json == null) { + return json; + } +{{#discriminator}} + if (!ignoreDiscriminator) { +{{#discriminator.mappedModels}} + if (json['{{discriminator.propertyBaseName}}'] === '{{mappingName}}') { + return {{modelName}}FromJSONTyped(json, true); + } +{{/discriminator.mappedModels}} + } +{{/discriminator}} + return { + {{#parent}}...{{{.}}}FromJSONTyped(json, ignoreDiscriminator),{{/parent}} + {{#additionalPropertiesType}} + ...json, + {{/additionalPropertiesType}} + {{#vars}} + {{#isPrimitiveType}} + {{#isDateType}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}json['{{baseName}}'] == null ? null : {{/isNullable}}{{/required}}new Date(json['{{baseName}}'])), + {{/isDateType}} + {{#isDateTimeType}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}json['{{baseName}}'] == null ? null : {{/isNullable}}{{/required}}new Date(json['{{baseName}}'])), + {{/isDateTimeType}} + {{^isDateType}} + {{^isDateTimeType}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}json['{{baseName}}'], + {{/isDateTimeType}} + {{/isDateType}} + {{/isPrimitiveType}} + {{^isPrimitiveType}} + {{#isArray}} + {{#uniqueItems}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}json['{{baseName}}'] == null ? null : {{/isNullable}}{{/required}}new Set((json['{{baseName}}'] as Array).map({{#items}}{{datatype}}{{/items}}FromJSON))), + {{/uniqueItems}} + {{^uniqueItems}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}json['{{baseName}}'] == null ? null : {{/isNullable}}{{/required}}(json['{{baseName}}'] as Array).map({{#items}}{{datatype}}{{/items}}FromJSON)), + {{/uniqueItems}} + {{/isArray}} + {{#isMap}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}json['{{baseName}}'] == null ? null : {{/isNullable}}{{/required}}mapValues(json['{{baseName}}'], {{#items}}{{datatype}}{{/items}}FromJSON)), + {{/isMap}} + {{^isArray}} + {{^isMap}} + {{^isFreeFormObject}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}{{datatype}}FromJSON(json['{{baseName}}']), + {{/isFreeFormObject}} + {{#isFreeFormObject}} + '{{name}}': {{^required}}json['{{baseName}}'] == null ? undefined : {{/required}}json['{{baseName}}'], + {{/isFreeFormObject}} + {{/isMap}} + {{/isArray}} + {{/isPrimitiveType}} + {{/vars}} + }; + {{/hasVars}} + {{^hasVars}} + return json; + {{/hasVars}} +} + +export function {{classname}}ToJSON(value?: {{#hasReadOnly}}Omit<{{classname}}, {{#readOnlyVars}}'{{baseName}}'{{^-last}}|{{/-last}}{{/readOnlyVars}}>{{/hasReadOnly}}{{^hasReadOnly}}{{classname}}{{/hasReadOnly}} | null): any { + {{#hasVars}} + if (value == null) { + return value; + } + return { + {{#parent}}...{{{.}}}ToJSON(value),{{/parent}} + {{#additionalPropertiesType}} + ...value, + {{/additionalPropertiesType}} + {{#vars}} + {{^isReadOnly}} + {{#isPrimitiveType}} + {{#isDateType}} + '{{baseName}}': {{^required}}value['{{name}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}value['{{name}}'] == null ? null : {{/isNullable}}{{/required}}(value['{{name}}']{{#isNullable}} as any{{/isNullable}}).toISOString().substring(0,10)), + {{/isDateType}} + {{#isDateTimeType}} + '{{baseName}}': {{^required}}value['{{name}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}value['{{name}}'] == null ? null : {{/isNullable}}{{/required}}(value['{{name}}']{{#isNullable}} as any{{/isNullable}}).toISOString()), + {{/isDateTimeType}} + {{#isArray}} + '{{baseName}}': {{#uniqueItems}}{{^required}}value['{{name}}'] == null ? undefined : {{/required}}{{#required}}{{#isNullable}}value['{{name}}'] == null ? null : {{/isNullable}}{{/required}}Array.from(value['{{name}}'] as Set){{/uniqueItems}}{{^uniqueItems}}value['{{name}}']{{/uniqueItems}}, + {{/isArray}} + {{^isDateType}} + {{^isDateTimeType}} + {{^isArray}} + '{{baseName}}': value['{{name}}'], + {{/isArray}} + {{/isDateTimeType}} + {{/isDateType}} + {{/isPrimitiveType}} + {{^isPrimitiveType}} + {{#isArray}} + {{#uniqueItems}} + '{{baseName}}': {{^required}}value['{{name}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}value['{{name}}'] == null ? null : {{/isNullable}}{{/required}}Array.from(value['{{name}}'] as Set).map({{#items}}{{datatype}}{{/items}}ToJSON)), + {{/uniqueItems}} + {{^uniqueItems}} + '{{baseName}}': {{^required}}value['{{name}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}value['{{name}}'] == null ? null : {{/isNullable}}{{/required}}(value['{{name}}'] as Array).map({{#items}}{{datatype}}{{/items}}ToJSON)), + {{/uniqueItems}} + {{/isArray}} + {{#isMap}} + '{{baseName}}': {{^required}}value['{{name}}'] == null ? undefined : {{/required}}({{#required}}{{#isNullable}}value['{{name}}'] == null ? null : {{/isNullable}}{{/required}}mapValues(value['{{name}}'], {{#items}}{{datatype}}{{/items}}ToJSON)), + {{/isMap}} + {{^isArray}} + {{^isMap}} + {{^isFreeFormObject}} + '{{baseName}}': {{datatype}}ToJSON(value['{{name}}']), + {{/isFreeFormObject}} + {{#isFreeFormObject}} + '{{baseName}}': value['{{name}}'], + {{/isFreeFormObject}} + {{/isMap}} + {{/isArray}} + {{/isPrimitiveType}} + {{/isReadOnly}} + {{/vars}} + }; + {{/hasVars}} + {{^hasVars}} + return value; + {{/hasVars}} +} +// ---------------------------------------------------------------------- +// Custom model functions added by custom openapi-generator template +// ---------------------------------------------------------------------- +import {ApiApi, Api{{classname}}ListRequest, Paginated{{classname}}List} from "@/openapi"; + +/** + * query list endpoint using the provided request parameters + */ +export function list(requestParameters: Api{{classname}}ListRequest = {}): Promise { + const api = new ApiApi() + return api.api{{classname}}List(requestParameters) +} \ No newline at end of file diff --git a/vue3/src/openapi/update.bat b/vue3/src/openapi/update.bat deleted file mode 100755 index 9f2f164d5..000000000 --- a/vue3/src/openapi/update.bat +++ /dev/null @@ -1 +0,0 @@ -openapi-generator-cli generate -g typescript-fetch -i http://127.0.0.1:8000/openapi/