From 82e323fab0d2acffacff897d61f730f479a0b755 Mon Sep 17 00:00:00 2001 From: Mike Brocchi Date: Wed, 12 Jul 2017 13:40:38 -0400 Subject: [PATCH] feat(@schematics/angular): Add guard schematic --- packages/schematics/angular/collection.json | 5 ++ .../__path__/__name@dasherize__.guard.spec.ts | 15 ++++ .../__path__/__name@dasherize__.guard.ts | 12 +++ packages/schematics/angular/guard/index.ts | 83 +++++++++++++++++++ packages/schematics/angular/guard/schema.json | 36 ++++++++ 5 files changed, 151 insertions(+) create mode 100644 packages/schematics/angular/guard/files/__path__/__name@dasherize__.guard.spec.ts create mode 100644 packages/schematics/angular/guard/files/__path__/__name@dasherize__.guard.ts create mode 100644 packages/schematics/angular/guard/index.ts create mode 100644 packages/schematics/angular/guard/schema.json diff --git a/packages/schematics/angular/collection.json b/packages/schematics/angular/collection.json index 5c86460300..306815fa7b 100644 --- a/packages/schematics/angular/collection.json +++ b/packages/schematics/angular/collection.json @@ -20,6 +20,11 @@ "description": "Create an enumeration.", "schema": "./enum/schema.json" }, + "guard": { + "factory": "./guard", + "description": "Create an guard.", + "schema": "./guard/schema.json" + }, "interface": { "factory": "./interface", "description": "Create an interface.", diff --git a/packages/schematics/angular/guard/files/__path__/__name@dasherize__.guard.spec.ts b/packages/schematics/angular/guard/files/__path__/__name@dasherize__.guard.spec.ts new file mode 100644 index 0000000000..9a915c19b3 --- /dev/null +++ b/packages/schematics/angular/guard/files/__path__/__name@dasherize__.guard.spec.ts @@ -0,0 +1,15 @@ +import { TestBed, async, inject } from '@angular/core/testing'; + +import { <%= classify(name) %>Guard } from './<%= dasherize(name) %>.guard'; + +describe('<%= classify(name) %>Guard', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [<%= classify(name) %>Guard] + }); + }); + + it('should ...', inject([<%= classify(name) %>Guard], (guard: <%= classify(name) %>Guard) => { + expect(guard).toBeTruthy(); + })); +}); diff --git a/packages/schematics/angular/guard/files/__path__/__name@dasherize__.guard.ts b/packages/schematics/angular/guard/files/__path__/__name@dasherize__.guard.ts new file mode 100644 index 0000000000..781be9ea3f --- /dev/null +++ b/packages/schematics/angular/guard/files/__path__/__name@dasherize__.guard.ts @@ -0,0 +1,12 @@ +import { Injectable } from '@angular/core'; +import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; +import { Observable } from 'rxjs/Observable'; + +@Injectable() +export class <%= classify(name) %>Guard implements CanActivate { + canActivate( + next: ActivatedRouteSnapshot, + state: RouterStateSnapshot): Observable | Promise | boolean { + return true; + } +} diff --git a/packages/schematics/angular/guard/index.ts b/packages/schematics/angular/guard/index.ts new file mode 100644 index 0000000000..80d9668333 --- /dev/null +++ b/packages/schematics/angular/guard/index.ts @@ -0,0 +1,83 @@ +/** +* @license +* Copyright Google Inc. All Rights Reserved. +* +* Use of this source code is governed by an MIT-style license that can be +* found in the LICENSE file at https://angular.io/license +*/ +// TODO: replace `options: any` with an actual type generated from the schema. +// tslint:disable:no-any +import {addDeclarationToModule} from '../utility/ast-utils'; +import {InsertChange} from '../utility/change'; + +import { + Rule, + Tree, + apply, + branchAndMerge, + chain, + filter, + mergeWith, + move, + noop, + template, + url, +} from '@angular-devkit/schematics'; +import * as stringUtils from '../strings'; + +import 'rxjs/add/operator/merge'; +import * as ts from 'typescript'; +import {buildRelativePath} from '../utility/find-module'; + + +function addDeclarationToNgModule(options: any): Rule { + return (host: Tree) => { + if (!options.module) { + return host; + } + + if (!host.exists(options.module)) { + throw new Error(`Module specified (${options.module}) does not exist.`); + } + const modulePath = options.module; + + const sourceText = host.read(modulePath) !.toString('utf-8'); + const source = ts.createSourceFile(modulePath, sourceText, ts.ScriptTarget.Latest, true); + + const componentPath = `/${options.sourceDir}/${options.path}/` + + (options.flat ? '' : stringUtils.dasherize(options.name) + '/') + + stringUtils.dasherize(options.name) + + '.guard'; + const relativePath = buildRelativePath(modulePath, componentPath); + const changes = addDeclarationToModule(source, modulePath, + stringUtils.classify(`${options.name}Component`), + 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; + }; +} + +export default function (options: any): Rule { + const templateSource = apply(url('./files'), [ + options.spec ? noop() : filter(path => !path.endsWith('.spec.ts')), + template({ + ...stringUtils, + ...options, + }), + move(options.sourceDir), + ]); + + return chain([ + branchAndMerge(chain([ + addDeclarationToNgModule(options), + mergeWith(templateSource), + ])), + ]); +} diff --git a/packages/schematics/angular/guard/schema.json b/packages/schematics/angular/guard/schema.json new file mode 100644 index 0000000000..a07b5aa485 --- /dev/null +++ b/packages/schematics/angular/guard/schema.json @@ -0,0 +1,36 @@ +{ + "$schema": "http://json-schema.org/schema", + "id": "SchematicsAngularGuard", + "title": "Angular Guard Options Schema", + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "spec": { + "type": "boolean", + "default": true + }, + "flat": { + "type": "boolean", + "default": false + }, + "module": { + "type": "string", + "description": "Allows specification of the declaring module.", + "alias": "m", + "subtype": "filepath" + }, + "path": { + "type": "string", + "default": "app" + }, + "sourceDir": { + "type": "string", + "default": "src" + } + }, + "required": [ + "name" + ] +}