UNPKG

ng-afelio

Version:
208 lines (207 loc) 9.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const core_1 = require("@angular-devkit/core"); const schematics_1 = require("@angular-devkit/schematics"); const find_module_1 = require("@schematics/angular/utility/find-module"); const parse_name_1 = require("@schematics/angular/utility/parse-name"); const workspace_1 = require("@schematics/angular/utility/workspace"); const ts = require("typescript"); const colors = require("colors"); const ast_util_1 = require("../util/ast-util"); const change_1 = require("../util/change"); const validation_1 = require("../util/validation"); const barrel_1 = require("../util/barrel"); function getMocksNode(source) { const keywords = (0, ast_util_1.findNodes)(source, ts.SyntaxKind.VariableStatement); for (const keyword of keywords) { if (ts.isVariableStatement(keyword)) { const [declaration] = keyword.declarationList.declarations; if (ts.isVariableDeclaration(declaration) && declaration.initializer && declaration.name.getText() === 'mocks') { return declaration.initializer.getChildAt(1); } } } } function includesIntoProject(path, options) { return host => { if (options.includes) { const changes = []; const mockListPath = (0, core_1.join)(path, 'mocks.ts'); const text = host.read(mockListPath); if (!text) { throw new schematics_1.SchematicsException(`Can not add to mock list, ${mockListPath} does not exist.`); } const sourceText = text.toString('utf8'); const source = ts.createSourceFile(mockListPath, sourceText, ts.ScriptTarget.Latest, true); // Add Store to ts import const mockPath = (0, core_1.join)(path, options.file.replace('.ts', '')); const relativeMockPath = (0, find_module_1.buildRelativePath)(mockListPath, `${mockPath}.ts`).slice(0, -3); const nameExtraction = options.file.match(/(\w*).mock.ts/); if (nameExtraction) { const mocksToAdd = `${nameExtraction[1]}Mocks`; changes.push((0, ast_util_1.insertImport)(source, mockListPath, `listeners as ${mocksToAdd}`, relativeMockPath)); // Add Store to Barrel array const node = getMocksNode(source); if (node) { const commat = node.getChildCount() > 0 ? ',' : ''; changes.push(new change_1.InsertChange(mockListPath, node.getEnd(), `${commat}\n ...${mocksToAdd}`)); } } else { throw new schematics_1.SchematicsException(`Can not extract name from file name ${options.file}`); } // Save changes (0, change_1.applyChangesToHost)(host, mockListPath, changes); } return host; }; } function getEnvironmentNode(source) { const keywords = (0, ast_util_1.findNodes)(source, ts.SyntaxKind.VariableStatement); for (const keyword of keywords) { if (ts.isVariableStatement(keyword)) { const [declaration] = keyword.declarationList.declarations; if (ts.isVariableDeclaration(declaration) && declaration.initializer && declaration.name.getText() === 'environment') { return declaration.initializer.getChildAt(1); } } } } function getEnvServiceMocksNode(source) { let mockServices; const services = (0, ast_util_1.findNode)(source, ts.SyntaxKind.PropertyAssignment, /^services:/, true); if (services && ts.isPropertyAssignment(services)) { mockServices = services.initializer.getChildAt(1); } return mockServices; } function addProperty(projectEnvPath, node, mockName) { const commat = node.getChildCount() > 0 ? ',' : ''; const position = node.getChildCount() > 0 ? node.getChildren()[node.getChildCount() - 1].getEnd() : node.getStart(); return new change_1.InsertChange(projectEnvPath, position, `${commat}\n ${mockName}: true`); } function addIntoEnvironment(projectAppPath, projectName, options) { const projectEnvPath = (0, core_1.join)(projectAppPath, '../environments/environment.ts'); return host => { if (options.environment) { const text = host.read(projectEnvPath); if (!text) { throw new schematics_1.SchematicsException(`Environment file in ${projectName} project does not exist.`); } const sourceText = text.toString('utf8'); const source = ts.createSourceFile(projectEnvPath, sourceText, ts.ScriptTarget.Latest, true); const envNode = getEnvironmentNode(source); const changes = []; if (envNode) { const serviceMockList = getEnvServiceMocksNode(envNode); if (serviceMockList) { changes.push(addProperty(projectEnvPath, serviceMockList, core_1.strings.camelize(options.name))); } else { throw new schematics_1.SchematicsException(`Can not find mock.services in ${projectName} project. Did you already add the mock system "${colors.cyan('ng-afelio install mocks')}" ?`); } } (0, change_1.applyChangesToHost)(host, projectEnvPath, changes); } return host; }; } function getListenersNode(source) { var _a; let listeners; const listenNode = (0, ast_util_1.findNode)(source, ts.SyntaxKind.VariableDeclaration, /^listeners/, false); if (listenNode && ts.isVariableDeclaration(listenNode)) { listeners = (_a = listenNode.initializer) === null || _a === void 0 ? void 0 : _a.getChildAt(1); } return listeners; } function addListener(mockPath, node, mockName) { const commat = node.getChildCount() > 0 ? ',' : ''; const position = node.getChildCount() > 0 ? node.getChildren()[node.getChildCount() - 1].getEnd() : node.getStart(); return new change_1.InsertChange(mockPath, position, `${commat}\n { url: '/store/inventory', methods: 'GET', name: '${mockName}', response: ${mockName}Mock }`); } function addMockFunction(mockPath, node, mockName) { const position = node.getStart() - 1; const toInsert = ` const ${mockName}Mock = (request: HttpRequest<any>) => new HttpResponse({ status: 200, body: { url: 'https://www.wikipedia.org' } }); `; return new change_1.InsertChange(mockPath, position, toInsert); } function addMockIntoExistingFile(mockPath, options) { return host => { const text = host.read(mockPath); if (!text) { throw new schematics_1.SchematicsException(`Can not find mock file ${mockPath} in the current path.`); } const sourceText = text.toString('utf8'); const source = ts.createSourceFile(mockPath, sourceText, ts.ScriptTarget.Latest, true); const listeners = getListenersNode(source); if (listeners) { const changes = []; const camelizedName = core_1.strings.camelize(options.name); changes.push(addMockFunction(mockPath, listeners.parent.parent.parent.parent, camelizedName)); // final parent = VariableStatement changes.push(addListener(mockPath, listeners, camelizedName)); (0, change_1.applyChangesToHost)(host, mockPath, changes); } }; } function default_1(options) { return async (host) => { if (!options.project) { throw new schematics_1.SchematicsException('Option (project) is required.'); } const workspace = await (0, workspace_1.getWorkspace)(host); const project = workspace.projects.get(options.project); let projectAppPath; if (project) { projectAppPath = (0, workspace_1.buildDefaultPath)(project); } else { throw new schematics_1.SchematicsException(`Project "${options.project}" not found.`); } if (project && options.path === undefined) { options.path = projectAppPath; } const parsedPath = (0, parse_name_1.parseName)(options.path, options.name); options.name = parsedPath.name; options.path = (0, barrel_1.relativeCwdFromRelativeProjectPath)(parsedPath.path); (0, validation_1.validateName)(options.name); const templateSource = (0, schematics_1.apply)((0, schematics_1.url)('./files'), [ (0, schematics_1.template)({ ...core_1.strings, ...options, }), (0, schematics_1.move)(parsedPath.path), ]); let steps = []; const mockPath = (0, core_1.join)(options.path, options.file); const fileExists = !!host.read(mockPath); if (fileExists) { steps = [ addMockIntoExistingFile(mockPath, options) ]; } else { steps = [ (0, schematics_1.mergeWith)(templateSource), includesIntoProject(options.path, options) ]; } return (0, schematics_1.chain)([ (0, schematics_1.branchAndMerge)((0, schematics_1.chain)([ ...steps, addIntoEnvironment(projectAppPath, options.project, options) ])), ]); }; } exports.default = default_1;