UNPKG

swagger-to-typescript-client

Version:

Generate TypeScript axios client from Swagger & OpenAPI specification

214 lines 10.2 kB
#!/usr/bin/env node "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const yargs_1 = __importDefault(require("yargs")); const path_1 = require("path"); const child_process_1 = require("child_process"); const openapi_client_axios_typegen_1 = require("openapi-client-axios-typegen"); const fs_1 = require("fs"); const input_1 = require("./src/input"); const types_1 = require("./src/types"); const utils_1 = require("./src/utils"); function camelCase(str) { return str.replace(/-([a-z])/g, (g) => g[1].toUpperCase()); } process .on('unhandledRejection', (reason, promise) => { console.error(`✖ ${reason.message}`); if (reason.stack.includes('validator')) { console.log(''); yargs_1.default.showHelp(); } process.exit(1); }) .on('uncaughtException', (error) => { console.error(`✖ ${error.message}`); if (error.stack.includes('validator')) { console.log(''); yargs_1.default.showHelp(); } process.exit(1); }); ////////////////////////////////////////// // Paths for the templates ////////////////////////////////////////// const staticsDirPath = (0, path_1.resolve)(`${__dirname}/template/static`); const sdkTypesTemplatePath = (0, path_1.resolve)(`${__dirname}/template/types.tmpl`); const clientMethodTemplatePath = (0, path_1.resolve)(`${__dirname}/template/client-method.tmpl`); const clientTemplatePath = (0, path_1.resolve)(`${__dirname}/template/client.tmpl`); const indexTemplatePath = (0, path_1.resolve)(`${__dirname}/template/index.tmpl`); ////////////////////////////////////////// // Reads the command line arguments ////////////////////////////////////////// const argv = yargs_1.default .option(types_1.ARG_NAMES.PKG, { alias: 'p', description: 'Name of the package e.g. @websitecom/my-api-sdk', type: 'string', }) .option(types_1.ARG_NAMES.OUTPUT, { alias: 'o', description: 'Output path for the generated SDK', type: 'string', }) .option(types_1.ARG_NAMES.SWAGGER, { alias: 's', description: 'Path to the swagger file', type: 'string', }) .option(types_1.ARG_NAMES.PKG_VERSION, { alias: 'e', description: 'Version to set for the npm package (defaults to npm', default: '', }) .option(types_1.ARG_NAMES.INTERACTIVE, { alias: 'i', type: 'boolean', description: 'Runs the interactive version', default: false, }) .help() .alias('help', 'h').argv; const isInteractive = argv[types_1.ARG_NAMES.INTERACTIVE]; (async () => { var _a, _b; const cliArgs = isInteractive ? await (0, input_1.askArguments)() : await (0, input_1.argvToArguments)(argv); const outputPath = cliArgs.givenOutputPath; const swaggerPath = cliArgs.givenSwaggerPath; const publishPkgName = cliArgs.packageNameWithOrg; const initialVersion = cliArgs.initialVersion; const projectName = publishPkgName.replace(/@.+\//, '').replace('-sdk', ''); const underscoredProjectName = projectName.replace(/-/g, '_'); const outputPathSrc = (0, path_1.join)(outputPath, '/src'); ////////////////////////////////////////// // Codebase for the SDK generator ////////////////////////////////////////// // Create the directory for sdk (0, fs_1.mkdirSync)(outputPathSrc, { recursive: true }); console.info('✔ Created output path'); // @todo change to node copy (0, child_process_1.execSync)(`cp -rf ${staticsDirPath}/* ${outputPath}`); ///////////////////////////////////////////////////////////////////////// // Reads the typing template, replaces the values and dumps to the SDK ///////////////////////////////////////////////////////////////////////// const typingTemplate = (0, fs_1.readFileSync)(sdkTypesTemplatePath).toString('utf8'); // replace params as first function param with body and move it the end because we will use all API's as POST unless its needed to be get const clientTypingStringReplaced = (await (0, openapi_client_axios_typegen_1.generateTypesForDocument)(swaggerPath, { transformOperationName: function (operation) { return operation; }, })) .join('') // .replace(/parameters\?: Parameters<UnknownParamsObject>,/gi, '') // .replace(/config\?: AxiosRequestConfig/gi, 'config?: AxiosRequestConfig, parameters?: Parameters<UnknownParamsObject>') .replace(/\.Responses\.(\d+)/gi, '.Responses.$$$1'); const typingCode = (0, utils_1.replaceInTemplate)(typingTemplate, { '{@client_typings@}': clientTypingStringReplaced, '{@project_name_underscored@}': underscoredProjectName.toLowerCase(), }); const typingDestPath = (0, path_1.join)(outputPathSrc, `types.ts`); (0, fs_1.writeFileSync)(typingDestPath, typingCode); console.info('✔ Typings file generated.'); ///////////////////////////////////////////////////////////////////////// // Copy swagger file to sdk ///////////////////////////////////////////////////////////////////////// (0, fs_1.copyFileSync)(swaggerPath, (0, path_1.join)(outputPathSrc, `/swagger.json`)); console.info('✔ Copied swagger file to sdk.'); ///////////////////////////////////////////////////////////////////////// // Generate and write the client for SDK ///////////////////////////////////////////////////////////////////////// // eslint-disable-next-line @typescript-eslint/no-var-requires const swaggerObj = require(swaggerPath); const methodTemplate = (0, fs_1.readFileSync)(clientMethodTemplatePath).toString('utf8'); const methodDefinitions = Object.keys(swaggerObj.paths).map((endpoint) => { const endpointDetail = swaggerObj.paths[endpoint]; const method = Object.keys(endpointDetail)[0]; const operationId = endpointDetail[method].operationId; const summary = endpointDetail[method].summary; const description = endpointDetail[method].description; return (0, utils_1.replaceInTemplate)(methodTemplate, { '{@operation_id@}': operationId, '{@method@}': method, '{@endpoint@}': endpoint, '{@summary@}': summary, '{@description@}': description, }).trimRight(); }); const serversObj = swaggerObj.servers || []; let local_server = ''; let local_path = ''; let dev_server = ''; let dev_path = ''; let stage_server = ''; let stage_path = ''; let prod_server = ''; let prod_path = ''; serversObj.forEach((server) => { const { pathname, host, protocol } = new URL(server.url); const urlLink = `${protocol}//${host}`; switch (server.description) { case 'local_server': local_server = urlLink; local_path = pathname; break; case 'dev_server': dev_server = urlLink; dev_path = pathname; break; case 'stage_server': stage_server = urlLink; stage_path = pathname; break; case 'prod_server': prod_server = urlLink; prod_path = pathname; break; } }); const clientTemplate = (0, fs_1.readFileSync)(clientTemplatePath).toString('utf8'); const clientFileCode = (0, utils_1.replaceInTemplate)(clientTemplate, { '{@api_local_server@}': local_server, '{@api_local_path@}': local_path, '{@api_dev_server@}': dev_server, '{@api_dev_path@}': dev_path, '{@api_stage_server@}': stage_server, '{@api_stage_path@}': stage_path, '{@api_prod_server@}': prod_server, '{@api_prod_path@}': prod_path, '{@project_name_camel@}': camelCase(projectName), '{@project_name_lower@}': underscoredProjectName.toLowerCase(), '{@project_name_upper@}': underscoredProjectName.toUpperCase(), '{@method_definitions@}': methodDefinitions.join(',\n\n'), }); (0, fs_1.writeFileSync)((0, path_1.join)(outputPathSrc, `/client.ts`), clientFileCode); const gitIgnoreFileCode = `node_modules .git .idea .DS_Store `; (0, fs_1.writeFileSync)((0, path_1.join)(outputPathSrc, `/../.gitignore`), gitIgnoreFileCode); console.info('✔ Create client index file.'); ///////////////////////////////////////////////////////////////////////// // Generate and write the index file for SDK ///////////////////////////////////////////////////////////////////////// const indexFileCode = (0, fs_1.readFileSync)(indexTemplatePath).toString('utf8'); (0, fs_1.writeFileSync)((0, path_1.join)(outputPathSrc, `/index.ts`), indexFileCode); console.info('✔ Export sdk and typings from sdk.'); ///////////////////////////////////////////////////////////////////////// // Update package.json with correct version and name ///////////////////////////////////////////////////////////////////////// const outputPackageJsonPath = (0, path_1.join)(outputPath, 'package.json'); const outputPackageJson = JSON.parse((0, fs_1.readFileSync)(outputPackageJsonPath, { encoding: 'utf8' })); outputPackageJson.name = publishPkgName; outputPackageJson.version = initialVersion || ((_a = swaggerObj === null || swaggerObj === void 0 ? void 0 : swaggerObj.info) === null || _a === void 0 ? void 0 : _a.version) || '0.0.1'; outputPackageJson.description = ((_b = swaggerObj === null || swaggerObj === void 0 ? void 0 : swaggerObj.info) === null || _b === void 0 ? void 0 : _b.description) || ''; (0, fs_1.writeFileSync)(outputPackageJsonPath, JSON.stringify(outputPackageJson, null, 2)); console.info('✔ Updated sdk package version.'); console.info(`✔ Package successfully generated ${outputPath}`); console.info(`✔ Installing dependencies and building ${outputPath}`); (0, child_process_1.execSync)(`cd ${outputPath} && yarn install --check-files && yarn build`); })(); //# sourceMappingURL=index.js.map