From 37537c45d074263b5975313abfd588b86f538967 Mon Sep 17 00:00:00 2001 From: Vasilis Kefallinos Date: Thu, 25 Jul 2024 17:04:09 +0300 Subject: [PATCH] feat: add extra-templates modular approach --- src/code-gen-process.js | 44 ++++++++++--- src/util/file-system.js | 5 +- .../__snapshots__/basic.test.js.snap | 51 +++++++++++++++ tests/spec/extra-templates/basic.test.js | 65 +++++++++++++++++++ tests/spec/extra-templates/schema.json | 36 ++++++++++ .../extra-templates/templates/test-route.ejs | 20 ++++++ tests/spec/extra-templates/templates/test.ejs | 18 +++++ 7 files changed, 228 insertions(+), 11 deletions(-) create mode 100644 tests/spec/extra-templates/__snapshots__/basic.test.js.snap create mode 100644 tests/spec/extra-templates/basic.test.js create mode 100644 tests/spec/extra-templates/schema.json create mode 100644 tests/spec/extra-templates/templates/test-route.ejs create mode 100644 tests/spec/extra-templates/templates/test.ejs diff --git a/src/code-gen-process.js b/src/code-gen-process.js index 712fe256..96d3b4b6 100644 --- a/src/code-gen-process.js +++ b/src/code-gen-process.js @@ -324,17 +324,41 @@ class CodeGenProcess { if (!_.isEmpty(configuration.extraTemplates)) { for (const extraTemplate of configuration.extraTemplates) { - const content = this.templatesWorker.renderTemplate( - this.fileSystem.getFileContent(extraTemplate.path), - configuration, - ); - output.push( - ...(await this.createOutputFileInfo( + if(extraTemplate.modular){ + for (const route of configuration.routes.combined) { + const extraTemplateContent = this.templatesWorker.renderTemplate( + this.fileSystem.getFileContent(extraTemplate.path), + { + ...configuration, + route, + }, + ); + + output.push( + ...(await this.createOutputFileInfo( + configuration, + extraTemplate.name({ + ...configuration, + route, + }), + extraTemplateContent, + )), + ); + } + }else{ + const content = this.templatesWorker.renderTemplate( + this.fileSystem.getFileContent(extraTemplate.path), configuration, - extraTemplate.name, - content, - )), - ); + ); + output.push( + ...(await this.createOutputFileInfo( + configuration, + extraTemplate.name, + content, + )), + ); + } + } } diff --git a/src/util/file-system.js b/src/util/file-system.js index dfb1d472..f86bc2b9 100644 --- a/src/util/file-system.js +++ b/src/util/file-system.js @@ -87,7 +87,10 @@ class FileSystem { const __dirname = dirname(url.fileURLToPath(import.meta.url)); const absolutePath = resolve(__dirname, path, `./${fileName}`); const fileContent = `${withPrefix ? FILE_PREFIX : ""}${content}`; - + const dirPath = dirname(absolutePath); + if (!this.pathIsExist(dirPath)) { + this.createDir(dirPath); + } return fs.writeFileSync(absolutePath, fileContent, _.noop); }; } diff --git a/tests/spec/extra-templates/__snapshots__/basic.test.js.snap b/tests/spec/extra-templates/__snapshots__/basic.test.js.snap new file mode 100644 index 00000000..d8b20753 --- /dev/null +++ b/tests/spec/extra-templates/__snapshots__/basic.test.js.snap @@ -0,0 +1,51 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`basic > --extra-templates 1`] = ` +"/* eslint-disable */ +/* tslint:disable */ +/* + * --------------------------------------------------------------- + * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ## + * ## ## + * ## AUTHOR: acacode ## + * ## SOURCE: https://github.com/acacode/swagger-typescript-api ## + * --------------------------------------------------------------- + */ + +/** + Swagger Petstore + 1.0.0 + A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification +*/ +export class Api { + private request(params: Record) { + return fetch(params as any); + } +} +" +`; + +exports[`basic > --extra-templates-route 1`] = ` +"/* eslint-disable */ +/* tslint:disable */ +/* + * --------------------------------------------------------------- + * ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ## + * ## ## + * ## AUTHOR: acacode ## + * ## SOURCE: https://github.com/acacode/swagger-typescript-api ## + * --------------------------------------------------------------- + */ + +/** + Swagger Petstore + 1.0.0 + A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification +*/ +export class WrongPathParams1 { + private request(params: Record) { + return fetch(params as any); + } +} +" +`; diff --git a/tests/spec/extra-templates/basic.test.js b/tests/spec/extra-templates/basic.test.js new file mode 100644 index 00000000..c4180039 --- /dev/null +++ b/tests/spec/extra-templates/basic.test.js @@ -0,0 +1,65 @@ +import * as fs from "node:fs/promises"; +import * as os from "node:os"; +import * as path from "node:path"; + +import { afterAll, beforeAll, describe, expect, test } from "vitest"; + +import { generateApi } from "../../../src/index.js"; + +describe("basic", async () => { + let tmpdir = ""; + + beforeAll(async () => { + tmpdir = await fs.mkdtemp(path.join(os.tmpdir(), "swagger-typescript-api")); + }); + + afterAll(async () => { + await fs.rm(tmpdir, { recursive: true }); + }); + + test("--extra-templates", async () => { + await generateApi({ + name: "schema", + input: path.resolve(import.meta.dirname, "schema.json"), + output: tmpdir, + silent: true, + extraTemplates: [ + { + name: "external-template-name", + path: path.resolve(import.meta.dirname, "./templates/test.ejs") + }, + ], + }); + + const content = await fs.readFile(path.join(tmpdir, "external-template-name.ts"), { + encoding: "utf8", + }); + + expect(content).toMatchSnapshot(); + }); + + test("--extra-templates-route", async () => { + await generateApi({ + name: "schema", + input: path.resolve(import.meta.dirname, "schema.json"), + output: tmpdir, + silent: true, + extraTemplates: [ + { + name: (config)=>{ + console.log(config.route.moduleName) + return `contexts/${config.route.moduleName}Context` + }, + path: path.resolve(import.meta.dirname, "./templates/test-route.ejs"), + modular: true + }, + ], + }); + + const content = await fs.readFile(path.join(tmpdir, "contexts/wrongPathParams1Context.ts"), { + encoding: "utf8", + }); + + expect(content).toMatchSnapshot(); + }); +}); diff --git a/tests/spec/extra-templates/schema.json b/tests/spec/extra-templates/schema.json new file mode 100644 index 00000000..35baa3a5 --- /dev/null +++ b/tests/spec/extra-templates/schema.json @@ -0,0 +1,36 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0.0", + "title": "Swagger Petstore", + "description": "A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification", + "termsOfService": "http://swagger.io/terms/", + "contact": { + "name": "Swagger API Team" + }, + "license": { + "name": "MIT" + } + }, + "host": "petstore.swagger.io", + "basePath": "/api", + "schemes": ["http"], + "consumes": ["application/json"], + "produces": ["application/json"], + "paths": { + "/wrong-path-params1/{pathParam1}/{path_param2}/{path_param3}/:pathParam4": { + "delete": { + "description": "DDD", + "operationId": "wrong-path-params1", + "parameters": [], + "produces": ["application/json"], + "responses": { + "200": { "description": "Successfully deleted" } + }, + "tags": ["key", "delete"] + } + } + }, + "definitions": { + } +} diff --git a/tests/spec/extra-templates/templates/test-route.ejs b/tests/spec/extra-templates/templates/test-route.ejs new file mode 100644 index 00000000..f7ccd89c --- /dev/null +++ b/tests/spec/extra-templates/templates/test-route.ejs @@ -0,0 +1,20 @@ +<% +const { utils, route, config, modelTypes } = it; +const { _, pascalCase, require } = utils; +const apiClassName = pascalCase(route.moduleName); +%> + +/** + <%= it.apiConfig.info.title %> + + <%= it.apiConfig.info.version %> + + <%= it.apiConfig.info.description %> + +*/ +export class <%= apiClassName %> { + private request(params: Record) { + return fetch(params as any) + } +} + diff --git a/tests/spec/extra-templates/templates/test.ejs b/tests/spec/extra-templates/templates/test.ejs new file mode 100644 index 00000000..89772c6d --- /dev/null +++ b/tests/spec/extra-templates/templates/test.ejs @@ -0,0 +1,18 @@ +<% +// console.info(it) +%> + +/** + <%= it.apiConfig.info.title %> + + <%= it.apiConfig.info.version %> + + <%= it.apiConfig.info.description %> + +*/ +export class <%= it.config.apiClassName %> { + private request(params: Record) { + return fetch(params as any) + } +} +