ng-alain
Version:
Schematics specific to NG-ALAIN
225 lines (224 loc) • 11.6 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = default_1;
const core_1 = require("@angular-devkit/core");
const schematics_1 = require("@angular-devkit/schematics");
const colors = require("ansi-colors");
const fs_1 = require("fs");
const jsonc_parser_1 = require("jsonc-parser");
const path_1 = require("path");
const swagger_typescript_api_1 = require("swagger-typescript-api");
const json_1 = require("../utils/json");
const workspace_1 = require("../utils/workspace");
let project;
let projectName;
const filePrefix = `/* eslint-disable */
/*
* Automatically generated by 'ng g ng-alain:sta'
* @see https://ng-alain.com/cli/sta
*
* Inspired by: https://github.com/acacode/swagger-typescript-api
*/
`;
function addPathInTsConfig(name) {
return (tree) => {
const mulitProject = (0, workspace_1.isMulitProject)(tree);
const commandPrefix = mulitProject ? `projects/${projectName}/` : '';
const tsConfigPath = 'tsconfig.json';
const basePath = ['compilerOptions', 'paths'];
(0, json_1.modifyJSON)(tree, tsConfigPath, {
path: [...basePath, `@${name}`],
value: [`${commandPrefix}src/app/_${name}/index`]
});
(0, json_1.modifyJSON)(tree, tsConfigPath, {
path: [...basePath, `@${name}/*`],
value: [`${commandPrefix}src/app/_${name}/*`]
});
return tree;
};
}
function cleanOutput(p) {
try {
(0, fs_1.rmSync)(p, { recursive: true });
(0, fs_1.mkdirSync)(p);
}
catch (_a) { }
}
function tagsMapping(res, config) {
var _a;
if (config.tagsMapping != null && Object.keys(config.tagsMapping).length <= 0)
return;
(_a = res.configuration.routes.combined) === null || _a === void 0 ? void 0 : _a.forEach(v => {
const newModuleName = config.tagsMapping[v.moduleName];
if (newModuleName != null) {
v.moduleName = newModuleName;
v.routes.forEach(route => {
route.raw.moduleName = newModuleName;
});
}
});
}
function fix(output, res, tree, context, config) {
tagsMapping(res, config);
const indexList = [`models`, `_base.service`];
const basePath = (0, core_1.normalize)((0, path_1.join)(project.root, output.replace(process.cwd(), '')));
try {
// definitions
const dataTpl = res.getTemplate({ name: 'dataContracts', fileName: 'data-contracts.eta' });
const dataContent = res.renderTemplate(dataTpl, Object.assign({}, res.configuration));
tree.create(`${basePath}/models.ts`, filePrefix + res.formatTSContent(dataContent));
// Base Service
const baseServiceTpl = res.getTemplate({ name: 'baseService', fileName: 'base.service.eta' });
const baseServiceContent = res.renderTemplate(baseServiceTpl, Object.assign({}, res.configuration));
tree.create(`${basePath}/_base.service.ts`, filePrefix + res.formatTSContent(baseServiceContent));
// Tag Service
const dtoTypeTpl = res.getTemplate({ name: 'dto-type', fileName: 'dto-type.eta' });
const serviceTpl = res.getTemplate({ name: 'service', fileName: 'service.eta' });
res.configuration.routes.combined.forEach(route => {
const routeIndex = [];
// dto
const dtoContent = res.formatTSContent(res.renderTemplate(dtoTypeTpl, Object.assign(Object.assign({}, res.configuration), { route })));
if (dtoContent.trim().length > 10) {
tree.create(`${basePath}/${route.moduleName}/dtos.ts`, filePrefix + dtoContent);
routeIndex.push(`dtos`);
}
// service
const serviceContent = res.renderTemplate(serviceTpl, Object.assign(Object.assign({}, res.configuration), { route }));
tree.create(`${basePath}/${route.moduleName}/service.ts`, filePrefix + res.formatTSContent(serviceContent));
routeIndex.push(`service`);
// index.ts
tree.create(`${basePath}/${route.moduleName}/index.ts`, filePrefix + routeIndex.map(name => `export * from './${name}';`).join('\n'));
indexList.push(`${route.moduleName}/index`);
});
// Index
tree.create(`${basePath}/index.ts`, filePrefix + indexList.map(name => `export * from './${name}';`).join('\n'));
}
catch (ex) {
throw new schematics_1.SchematicsException(`Parse error: ${ex}`);
}
}
function genProxy(config) {
return (tree, context) => {
var _a;
context.logger.info(colors.blue(`- Name: ${config.name}`));
const output = (config.output = (0, path_1.resolve)(process.cwd(), (_a = config.output) !== null && _a !== void 0 ? _a : `./src/app/_${config.name}`));
const templates = (0, path_1.resolve)(__dirname, './templates');
if (config.url) {
context.logger.info(colors.blue(`- Using url data: ${config.url}`));
}
else if (config.filePath) {
context.logger.info(colors.blue(`- Using file data: ${config.filePath}`));
}
context.logger.info(colors.blue(`- Output: ${output}`));
return new Promise(resolve => {
context.logger.info(colors.blue(`Start generating...`));
const options = Object.assign({ name: `${config.name}.ts`, url: config.url, input: config.filePath, spec: config.spec, output,
templates, toJS: false, modular: true, cleanOutput: true, generateUnionEnums: true, generateClient: true, extractRequestParams: false, generateResponses: false, generateRouteTypes: true, generateApi: true, silent: true, disableStrictSSL: true, moduleNameFirstTag: true, defaultResponseType: 'any', typePrefix: config.modelTypePrefix, hooks: {
onInit: (c) => {
c.httpClientType = config.httpClientType;
return c;
},
onPrepareConfig: c => {
var _a;
if (!config.responseDataField)
return c;
const getDeepDataType = (ref) => {
var _a, _b;
let typeData = (_a = c.utils.getComponentByRef(ref)) === null || _a === void 0 ? void 0 : _a.typeData;
while (typeData != null && Array.isArray(typeData.allOf) && typeData.allOf.length > 0) {
typeData = (_b = c.utils.getComponentByRef(typeData.allOf[0].$ref)) === null || _b === void 0 ? void 0 : _b.typeData;
}
return typeData;
};
(_a = c.routes.combined) === null || _a === void 0 ? void 0 : _a.forEach(moduleInfo => {
moduleInfo.routes.forEach((routeInfo) => {
var _a, _b, _c;
if (!routeInfo.responseBodySchema)
return;
try {
const responseBodyContentFirstType = Object.keys((_a = routeInfo.responseBodySchema) === null || _a === void 0 ? void 0 : _a.content).pop();
if (!responseBodyContentFirstType)
return;
const ref = routeInfo.responseBodySchema.content[responseBodyContentFirstType].schema.$ref;
const resDataType = getDeepDataType(ref);
if (!resDataType)
return;
const fieldProperty = (_b = resDataType.properties) === null || _b === void 0 ? void 0 : _b[config.responseDataField];
if (!fieldProperty)
return;
routeInfo.response.type = (_c = fieldProperty.$parsed.content) !== null && _c !== void 0 ? _c : 'any';
}
catch (ex) {
throw new schematics_1.SchematicsException(`Parse data field error: ${ex}`);
}
});
});
return c;
},
onFormatTypeName: formattedModelName => {
if (!config.modelTypePrefix)
return formattedModelName;
if (formattedModelName.startsWith(config.modelTypePrefix + config.modelTypePrefix)) {
return formattedModelName.substring(config.modelTypePrefix.length);
}
return formattedModelName;
}
} }, config.generateApiOptions);
(0, swagger_typescript_api_1.generateApi)(options)
.then((res) => {
cleanOutput(output);
fix(output, res, tree, context, config);
resolve();
})
.catch(ex => {
throw new schematics_1.SchematicsException(`Generate error: ${ex}`);
});
});
};
}
function finished() {
return (_, context) => {
context.logger.info(colors.green(`✓ Finished, refer to: https://ng-alain.com/cli/sta`));
};
}
function tryLoadConfig(context, configPath) {
if (!configPath || configPath.length <= 0)
return null;
try {
const configFile = (0, path_1.resolve)(process.cwd(), configPath);
context.logger.info(colors.blue(`- Use config file: ${configFile}`));
if ((0, fs_1.existsSync)(configFile)) {
return (0, jsonc_parser_1.parse)((0, fs_1.readFileSync)(configFile).toString('utf8'));
}
}
catch (err) {
throw new schematics_1.SchematicsException(`Invalid config file ${err}`);
}
}
function default_1(options) {
return (tree, context) => __awaiter(this, void 0, void 0, function* () {
const res = yield (0, workspace_1.getProject)(tree, options.project);
project = res.project;
projectName = res.name;
const config = Object.assign(Object.assign({ name: 'sta' }, options), tryLoadConfig(context, options.config));
if (typeof config.generateApiOptions === 'string') {
try {
config.generateApiOptions = JSON.parse(config.generateApiOptions);
}
catch (ex) {
throw new schematics_1.SchematicsException(`Parse generateApiParams error: '${config.generateApiOptions}' => ${ex}`);
}
}
return (0, schematics_1.chain)([addPathInTsConfig(config.name), genProxy(config), finished()]);
});
}
//# sourceMappingURL=index.js.map
;