UNPKG

ngx-spec

Version:

A missing schematics for creating missing / recreating Angular 6+ specs

105 lines (83 loc) 3.36 kB
import { basename, dirname, normalize, Path, strings } from '@angular-devkit/core'; import { WorkspaceSchema } from '@angular-devkit/core/src/workspace'; import { apply, applyTemplates, filter, mergeWith, move, Rule, SchematicContext, SchematicsException, Tree, url } from '@angular-devkit/schematics'; import * as nodePath from 'path'; import { SupportedTypes } from '../utils/supported-types'; import { Schema as Options } from './schema'; export function getWorkspacePath(host: Tree): string { const possibleFiles = ['/angular.json', '/.angular.json']; const path = possibleFiles.filter(path => host.exists(path))[0]; return path; } export function getWorkspace(host: Tree): WorkspaceSchema { const path = getWorkspacePath(host); const configBuffer = host.read(path); if (configBuffer === null) { throw new SchematicsException(`Could not find (${path})`); } const config = configBuffer.toString(); return JSON.parse(config); } interface Location { name: string; path: Path; } function parseName(path: string, name: string): Location { const nameWithoutPath = basename(name as Path); const namePath = dirname((path + '/' + name) as Path); return { name: nameWithoutPath, path: normalize('/' + namePath), }; } export default function (options: Options): Rule { return (host: Tree, context: SchematicContext) => { const workspace = getWorkspace(host); if (!options.project) { throw new SchematicsException('Option (project) is required.'); } const project = workspace.projects[options.project]; if (options.path === undefined) { const projectDirName = project.projectType === 'application' ? 'app' : 'lib'; options.path = `/${project.root}/src/${projectDirName}`; } const parsedPath = parseName(options.path, options.name); const [, name, type] = parsedPath.name.replace(/\.ts$/, '').match(/(.*)\.([^.]+)$/) || [ null, null, null, ]; if (!name || !type) { throw new SchematicsException( 'The provided name / file should look like name.type (e.g. component-name.component)' + ' or name.type.ts (e.g. component-name.component.ts).', ); } if (!SupportedTypes.includes(type)) { const ex = `The type "${type}" is not supported. Please use one of [${ SupportedTypes.join(', ') }].`; throw new SchematicsException(ex); } options.name = name; options.type = type; options.path = parsedPath.path; const schematicsPath = require.resolve(`@schematics/angular/${type}/index`).replace(/index\.js$/, 'files'); const targetPath = `${parsedPath.path}/${name}.${type}.ts`; if (!host.exists(targetPath) && !options.ignoreTargetNotFound) { throw new SchematicsException(`Target file ${targetPath} is not existing`); } // important for windows to get the relative path, otherwise schematics becomes crazy when sees C:\bla\bla things const relativeSchematicsPath = nodePath.relative(__dirname, schematicsPath); const templateSource = apply(url(relativeSchematicsPath), [ filter(path => path.endsWith('.spec.ts.template')), applyTemplates({ ...strings, 'if-flat': () => '', ...options, }), move(parsedPath.path), ]); return mergeWith(templateSource)(host, context); }; }