import * as ts from 'typescript'; import { normalize, strings } from '@angular-devkit/core'; import { apply, chain, mergeWith, move, renameTemplateFiles, Rule, SchematicContext, SchematicsException, template, Tree, url } from '@angular-devkit/schematics'; import { addImportToModule } from '../utility/ast-utils'; import { InsertChange } from '../utility/change'; import { createComment } from '../utility/comment'; import { buildRelativePath, findModuleFromOptions, ModuleOptions } from '../utility/find-module'; import { parseName } from '../utility/parse-name'; import { buildDefaultPath } from '../utility/project'; export function module(options: any): Rule { return (tree: Tree, _context: SchematicContext) => { const angularJsonBuffer = tree.read('angular.json'); if (!angularJsonBuffer) { throw new SchematicsException('not an angular project'); } const angularJsonObject = JSON.parse(angularJsonBuffer.toString()); const projectName = options.project || angularJsonObject.defaultProject; const project = angularJsonObject.projects[projectName]; const appPath = buildDefaultPath(project); if(options.path === undefined){ options.path = appPath; } if(options.module) { options.module = findModuleFromOptions(tree, options); } const parsedPath = parseName(options.path, options.name); const { name, path } = parsedPath; options.path = path; options.name = name; const modulePath = normalize(`/${path}/${strings.dasherize(name)}/${strings.dasherize(name)}.module`); const sharedModulePath = normalize(`/${appPath}/app-shared/app-shared.module`); const relativePath = buildRelativePath(modulePath, sharedModulePath); const src = url('./files'); const processedSource = apply(src, [ template({ ...options, ...strings, relativePath, comment: createComment(), }), renameTemplateFiles(), move(path) ]); return chain([ mergeWith(processedSource), addDeclarationToNgModule(options), ]); }; } function addDeclarationToNgModule(options: ModuleOptions): Rule { return (host: Tree) => { if (!options.module) { return host; } const modulePath = options.module; const text = host.read(modulePath); if (text === null) { throw new SchematicsException(`File ${modulePath} does not exist.`); } const sourceText = text.toString('utf-8'); const source = ts.createSourceFile(modulePath, sourceText, ts.ScriptTarget.Latest, true); const importModulePath = normalize( `/${options.path}/` + (options.flat ? '' : strings.dasherize(options.name) + '/') + strings.dasherize(options.name) + '.module', ); const relativePath = buildRelativePath(modulePath, importModulePath); const changes = addImportToModule(source, modulePath, strings.classify(`${options.name}Module`), relativePath); const recorder = host.beginUpdate(modulePath); for (const change of changes) { if (change instanceof InsertChange) { recorder.insertLeft(change.pos, change.toAdd); } } host.commitUpdate(recorder); return host; }; }