ng-afelio
Version:
Extended Angular CLI
208 lines (207 loc) • 9.47 kB
JavaScript
"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;