swagger-typescript-api
/
index.js
350 строк · 10.8 Кб
1#!/usr/bin/env node
2
3// Copyright (c) 2019-present acacode
4// Node module: swagger-typescript-api
5// This file is licensed under the MIT License.
6// License text available at https://opensource.org/licenses/MIT
7// Repository https://github.com/acacode/swagger-typescript-api
8
9const { version, name } = require('./package.json');10const { cli } = require('./cli');11const { generateApi, generateTemplates } = require('./src');12const { HTTP_CLIENT } = require('./src/constants');13const { resolve } = require('path');14const { CodeGenConfig } = require('./src/configuration');15const {16TemplatesGenConfig,17} = require('./src/commands/generate-templates/configuration');18
19const codeGenBaseConfig = new CodeGenConfig({});20const templateGenBaseConfig = new TemplatesGenConfig({});21
22const program = cli({23name: name,24alias: 'sta',25version: version,26description:27'Generate api via swagger scheme.\nSupports OA 3.0, 2.0, JSON, yaml.',28options: [29{30flags: '-p, --path <string>',31description: 'path/url to swagger scheme',32required: true,33},34{35flags: '-o, --output <string>',36description: 'output path of typescript api file',37default: './',38},39{40flags: '-n, --name <string>',41description: 'name of output typescript api file',42default: codeGenBaseConfig.fileName,43},44{45flags: '-t, --templates <string>',46description: 'path to folder containing templates',47},48{49flags: '-d, --default-as-success',50description:51'use "default" response status code as success response too.\n' +52'some swagger schemas use "default" response status code as success response type by default.',53default: codeGenBaseConfig.defaultResponseAsSuccess,54internal: { name: 'defaultResponseAsSuccess' },55},56{57flags: '-r, --responses',58description:59'generate additional information about request responses\n' +60'also add typings for bad responses',61default: codeGenBaseConfig.generateResponses,62internal: { name: 'generateResponses' },63},64{65flags: '--union-enums',66description: 'generate all "enum" types as union types (T1 | T2 | TN)',67default: codeGenBaseConfig.generateUnionEnums,68internal: { name: 'generateUnionEnums' },69},70{71flags: '--add-readonly',72description: 'generate readonly properties',73default: codeGenBaseConfig.addReadonly,74},75{76flags: '--route-types',77description: 'generate type definitions for API routes',78default: codeGenBaseConfig.generateRouteTypes,79internal: { name: 'generateRouteTypes' },80},81{82flags: '--no-client',83description: 'do not generate an API class',84default: codeGenBaseConfig.generateClient,85},86{87flags: '--enum-names-as-values',88description:89"use values in 'x-enumNames' as enum values (not only as keys)",90default: codeGenBaseConfig.enumNamesAsValues,91},92{93flags: '--extract-request-params',94description:95'extract request params to data contract (Also combine path params and query params into one object)',96default: codeGenBaseConfig.extractRequestParams,97internal: { formatter: Boolean },98},99{100flags: '--extract-request-body',101description: 'extract request body type to data contract',102default: codeGenBaseConfig.extractRequestBody,103internal: { formatter: Boolean },104},105{106flags: '--extract-response-body',107description: 'extract response body type to data contract',108default: codeGenBaseConfig.extractResponseBody,109internal: { formatter: Boolean },110},111{112flags: '--extract-response-error',113description: 'extract response error type to data contract',114default: codeGenBaseConfig.extractResponseError,115internal: { formatter: Boolean },116},117{118flags: '--extract-responses',119description: 'extract all responses described in /components/responses',120default: codeGenBaseConfig.extractResponses,121internal: { formatter: Boolean },122},123{124flags: '--modular',125description:126'generate separated files for http client, data contracts, and routes',127default: codeGenBaseConfig.modular,128internal: { formatter: Boolean },129},130{131flags: '--js',132description: 'generate js api module with declaration file',133default: codeGenBaseConfig.toJS,134internal: { formatter: Boolean, name: 'toJS' },135},136{137flags: '--module-name-index <number>',138description:139'determines which path index should be used for routes separation (example: GET:/fruites/getFruit -> index:0 -> moduleName -> fruites)',140default: codeGenBaseConfig.moduleNameIndex,141internal: { formatter: (moduleNameIndex) => +moduleNameIndex || 0 },142},143{144flags: '--module-name-first-tag',145description: 'splits routes based on the first tag',146default: codeGenBaseConfig.moduleNameFirstTag,147},148{149flags: '--disableStrictSSL',150description: 'disabled strict SSL',151default: codeGenBaseConfig.disableStrictSSL,152internal: { formatter: Boolean },153},154{155flags: '--disableProxy',156description: 'disabled proxy',157default: codeGenBaseConfig.disableProxy,158internal: { formatter: Boolean },159},160{161flags: '--axios',162description: 'generate axios http client',163default: codeGenBaseConfig.httpClientType === HTTP_CLIENT.AXIOS,164},165{166flags: '--unwrap-response-data',167description: 'unwrap the data item from the response',168default: codeGenBaseConfig.unwrapResponseData,169},170{171flags: '--disable-throw-on-error',172description: 'Do not throw an error when response.ok is not true',173default: codeGenBaseConfig.disableThrowOnError,174},175{176flags: '--single-http-client',177description: 'Ability to send HttpClient instance to Api constructor',178default: codeGenBaseConfig.singleHttpClient,179internal: { formatter: Boolean },180},181{182flags: '--silent',183description: 'Output only errors to console',184default: codeGenBaseConfig.silent,185internal: { formatter: Boolean },186},187{188flags: '--default-response <type>',189description: 'default type for empty response schema',190default: codeGenBaseConfig.defaultResponseType,191internal: { name: 'defaultResponseType' },192},193{194flags: '--type-prefix <string>',195description: 'data contract name prefix',196default: codeGenBaseConfig.typePrefix,197},198{199flags: '--type-suffix <string>',200description: 'data contract name suffix',201default: codeGenBaseConfig.typeSuffix,202},203{204flags: '--clean-output',205description:206'clean output folder before generate api. WARNING: May cause data loss',207default: codeGenBaseConfig.cleanOutput,208internal: { formatter: Boolean },209},210{211flags: '--api-class-name <string>',212description: 'name of the api class',213default: codeGenBaseConfig.apiClassName,214},215{216flags: '--patch',217description: 'fix up small errors in the swagger source definition',218default: codeGenBaseConfig.patch,219internal: { formatter: Boolean },220},221{222flags: '--debug',223description: 'additional information about processes inside this tool',224default: codeGenBaseConfig.debug,225},226{227flags: '--another-array-type',228description: 'generate array types as Array<Type> (by default Type[])',229default: codeGenBaseConfig.anotherArrayType,230},231{232flags: '--sort-types',233description: 'sort fields and types',234default: codeGenBaseConfig.sortTypes,235},236{237flags: '--extract-enums',238description:239'extract all enums from inline interface\\type content to typescript enum construction',240default: codeGenBaseConfig.extractEnums,241},242{243flags: '--sort-routes',244description: 'sort routes in alphabetical order',245default: codeGenBaseConfig.sortRoutes,246},247{248flags: '--custom-config <string>',249description: 'custom config: primitiveTypeConstructs, hooks, ... ',250default: '',251},252],253});254
255program.addCommand({256name: 'generate-templates',257description: `Generate ".ejs" templates needed for generate api`,258options: [259{260flags: '-o, --output <string>',261description: 'output path of generated templates',262default: templateGenBaseConfig.output,263},264{265flags: '-m, --modular',266description:267'generate templates needed to separate files for http client, data contracts, and routes',268default: templateGenBaseConfig.modular,269internal: { formatter: Boolean },270},271{272flags: '--http-client <string>',273description: `http client type (possible values: ${Object.values(274HTTP_CLIENT,275)276.map((v) => `"${v}"`)277.join(', ')})`,278default: templateGenBaseConfig.httpClientType,279internal: { name: 'httpClientType' },280},281{282flags: '-c, --clean-output',283description:284'clean output folder before generate template. WARNING: May cause data loss',285default: templateGenBaseConfig.cleanOutput,286internal: { formatter: Boolean },287},288{289flags: '-r, --rewrite',290description: 'rewrite content in existing templates',291default: templateGenBaseConfig.rewrite,292internal: { formatter: Boolean },293},294{295flags: '--silent',296description: 'Output only errors to console',297default: templateGenBaseConfig.silent,298internal: { formatter: Boolean },299},300],301});302
303const main = async () => {304const { command, options } = await program.execute({ args: process.argv });305
306let customConfig = null;307
308if (options.customConfig) {309try {310const customConfigPath = resolve(process.cwd(), options.customConfig);311console.log(`✨ found custom config at: ${customConfigPath}`);312customConfig = require(customConfigPath);313} catch (e) {314/* empty */315}316}317
318try {319switch (command) {320case null: {321await generateApi({322...options,323name: options.name,324url: options.path,325generateRouteTypes: options.routeTypes,326generateClient: !!(options.axios || options.client),327httpClientType: options.axios ? HTTP_CLIENT.AXIOS : HTTP_CLIENT.FETCH,328input: resolve(process.cwd(), options.path),329output: resolve(process.cwd(), options.output || '.'),330...customConfig,331});332break;333}334case 'generate-templates': {335await generateTemplates(options);336break;337}338default: {339break;340}341}342} catch (e) {343console.error(e);344process.exit(1);345return;346}347process.exit(0);348};349
350main();351