Skip to content

Commit

Permalink
feat: ng-add schematics implementation (#16)
Browse files Browse the repository at this point in the history
Closes #9
  • Loading branch information
santoshyadavdev committed Jul 23, 2020
1 parent b0e67ba commit 54e728b
Show file tree
Hide file tree
Showing 15 changed files with 1,405 additions and 19 deletions.
80 changes: 64 additions & 16 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"sourceRoot": "libs/angular-routing/src",
"prefix": "reactiveangular",
"architect": {
"build": {
"build-package": {
"builder": "@nrwl/angular:package",
"options": {
"tsConfig": "libs/angular-routing/tsconfig.lib.json",
Expand All @@ -19,14 +19,31 @@
}
}
},
"build": {
"builder": "@nrwl/workspace:run-commands",
"options": {
"parallel": false,
"commands": [
{
"command": "ng run angular-routing:build-package"
},
{
"command": "yarn tsc -p libs/angular-routing/tsconfig.schematics.json"
}
]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"libs/angular-routing/tsconfig.lib.json",
"libs/angular-routing/tsconfig.spec.json"
],
"exclude": ["**/node_modules/**", "!libs/angular-routing/**/*"]
"exclude": [
"**/node_modules/**",
"!libs/angular-routing/**/*"
]
}
},
"test": {
Expand Down Expand Up @@ -61,7 +78,9 @@
"apps/getting-started/src/favicon.ico",
"apps/getting-started/src/assets"
],
"styles": ["apps/getting-started/src/styles.css"],
"styles": [
"apps/getting-started/src/styles.css"
],
"scripts": []
},
"configurations": {
Expand Down Expand Up @@ -119,7 +138,10 @@
"apps/getting-started/tsconfig.app.json",
"apps/getting-started/tsconfig.spec.json"
],
"exclude": ["**/node_modules/**", "!apps/getting-started/**/*"]
"exclude": [
"**/node_modules/**",
"!apps/getting-started/**/*"
]
}
},
"test": {
Expand Down Expand Up @@ -154,8 +176,13 @@
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": ["apps/getting-started-e2e/tsconfig.e2e.json"],
"exclude": ["**/node_modules/**", "!apps/getting-started-e2e/**/*"]
"tsConfig": [
"apps/getting-started-e2e/tsconfig.e2e.json"
],
"exclude": [
"**/node_modules/**",
"!apps/getting-started-e2e/**/*"
]
}
}
}
Expand All @@ -180,7 +207,9 @@
"apps/example-app/src/favicon.ico",
"apps/example-app/src/assets"
],
"styles": ["apps/example-app/src/styles.css"],
"styles": [
"apps/example-app/src/styles.css"
],
"scripts": []
},
"configurations": {
Expand Down Expand Up @@ -238,7 +267,10 @@
"apps/example-app/tsconfig.app.json",
"apps/example-app/tsconfig.spec.json"
],
"exclude": ["**/node_modules/**", "!apps/example-app/**/*"]
"exclude": [
"**/node_modules/**",
"!apps/example-app/**/*"
]
}
},
"test": {
Expand Down Expand Up @@ -273,8 +305,13 @@
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": ["apps/example-app-e2e/tsconfig.e2e.json"],
"exclude": ["**/node_modules/**", "!apps/example-app-e2e/**/*"]
"tsConfig": [
"apps/example-app-e2e/tsconfig.e2e.json"
],
"exclude": [
"**/node_modules/**",
"!apps/example-app-e2e/**/*"
]
}
}
}
Expand All @@ -299,7 +336,9 @@
"apps/tour-of-heroes/src/favicon.ico",
"apps/tour-of-heroes/src/assets"
],
"styles": ["apps/tour-of-heroes/src/styles.css"],
"styles": [
"apps/tour-of-heroes/src/styles.css"
],
"scripts": []
},
"configurations": {
Expand Down Expand Up @@ -357,7 +396,10 @@
"apps/tour-of-heroes/tsconfig.app.json",
"apps/tour-of-heroes/tsconfig.spec.json"
],
"exclude": ["**/node_modules/**", "!apps/tour-of-heroes/**/*"]
"exclude": [
"**/node_modules/**",
"!apps/tour-of-heroes/**/*"
]
}
},
"test": {
Expand Down Expand Up @@ -392,15 +434,21 @@
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": ["apps/tour-of-heroes-e2e/tsconfig.e2e.json"],
"exclude": ["**/node_modules/**", "!apps/tour-of-heroes-e2e/**/*"]
"tsConfig": [
"apps/tour-of-heroes-e2e/tsconfig.e2e.json"
],
"exclude": [
"**/node_modules/**",
"!apps/tour-of-heroes-e2e/**/*"
]
}
}
}
}
},
"cli": {
"defaultCollection": "@nrwl/angular"
"defaultCollection": "@nrwl/angular",
"analytics": false
},
"schematics": {
"@nrwl/angular:application": {
Expand All @@ -411,5 +459,5 @@
"unitTestRunner": "jest"
}
},
"defaultProject": "router"
"defaultProject": "angular-routing"
}
7 changes: 5 additions & 2 deletions libs/angular-routing/ng-package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/libs/angular-routing",
"assets": ["**/*.md"],
"whitelistedNonPeerDependencies": ["path-to-regexp", "query-string"],
"assets": ["**/*.md", "./schematics/**/*.json"],
"whitelistedNonPeerDependencies": [
"path-to-regexp",
"query-string"
],
"lib": {
"entryFile": "src/index.ts"
}
Expand Down
4 changes: 4 additions & 0 deletions libs/angular-routing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
"name": "angular-routing",
"version": "0.2.0",
"description": "A declarative router for Angular applications",
"schematics": "./schematics/collection.json",
"ng-add": {
"save": "dependencies"
},
"repository": {
"type": "git",
"url": "https://github.com/brandonroberts/angular-routing.git"
Expand Down
10 changes: 10 additions & 0 deletions libs/angular-routing/schematics/collection.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"schematics": {
"ng-add": {
"aliases": ["init"],
"factory": "./ng-add",
"schema": "./ng-add/schema.json",
"description": "Add angular-routing to application"
}
}
}
62 changes: 62 additions & 0 deletions libs/angular-routing/schematics/ng-add/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {
SchematicTestRunner,
UnitTestTree,
} from '@angular-devkit/schematics/testing';
import * as path from 'path';
import { RouterOptions } from './schema';

export const workspaceOptions = {
name: 'workspace',
newProjectRoot: 'projects',
version: '6.0.0',
defaultProject: 'bar',
};

export const defaultAppOptions = {
name: 'bar',
inlineStyle: false,
inlineTemplate: false,
viewEncapsulation: 'Emulated',
routing: false,
style: 'css',
skipTests: false,
};


const collectionPath = path.join(__dirname, '../collection.json');

describe('ng add function', () => {
let appTree: UnitTestTree;
let schematicRunner: SchematicTestRunner;

const defaultOptions: RouterOptions = {
project: 'bar',
module: 'app'
};

beforeEach(async () => {

schematicRunner = new SchematicTestRunner('angular-routing', collectionPath);

appTree = await schematicRunner.runExternalSchematicAsync(
'@schematics/angular',
'workspace',
workspaceOptions
).toPromise();

appTree = await schematicRunner.runExternalSchematicAsync(
'@schematics/angular',
'application',
defaultAppOptions,
appTree
).toPromise();
});

it('should import RouterModule a specified module', () => {
const options = { ...defaultOptions };

const tree = schematicRunner.runSchematic('ng-add', options, appTree);
const content = tree.readContent(`/projects/bar/src/app/app.module.ts`);
expect(content).toContain('RoutingModule.forRoot()');
});
});
67 changes: 67 additions & 0 deletions libs/angular-routing/schematics/ng-add/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import {
chain, Rule,
Tree, SchematicsException
} from '@angular-devkit/schematics';
import * as ts from 'typescript';
import { addImportToModule, insertImport } from '../utils/ast-utils';
import { commitChanges } from '../utils/change';
import { RouterOptions } from './schema';
import { findModuleFromOptions } from '../utils/find-module';
import { getProjectPath } from '../utils/project';

function addImportToNgModule(options: RouterOptions): Rule {
return (host: Tree) => {
options.path = getProjectPath(host, options);
const modulePath = findModuleFromOptions(host, options);

if (!modulePath) {
return host;
}

if (!host.exists(modulePath)) {
throw new Error('Specified module does not exist');
}


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 importChanges = addImportToModule(
source,
modulePath,
'RoutingModule.forRoot()',
'angular-routing',
).shift();


let changes = [
insertImport(source, modulePath, 'RoutingModule', 'angular-routing'),
importChanges
];

commitChanges(host, source.fileName, changes);

return host;
};
}

// Just return the tree
export default function (options: RouterOptions): Rule {

return chain([
addImportToNgModule(options)
]);
}



28 changes: 28 additions & 0 deletions libs/angular-routing/schematics/ng-add/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"$schema": "http://json-schema.org/schema",
"id": "SchematicsAddRouting",
"title": "Angular Routing ng-add Options Schema",
"type": "object",
"properties": {
"project": {
"type": "string",
"description": "The name of the project.",
"aliases": [
"p"
]
},
"module": {
"type": "string",
"default": "app",
"description": "Allows specification of the declaring module.",
"alias": "m",
"subtype": "filepath"
},
"path": {
"type": "string",
"format": "path",
"description": "The path to create the state.",
"visible": false
}
}
}
5 changes: 5 additions & 0 deletions libs/angular-routing/schematics/ng-add/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface RouterOptions {
project: string;
module?: string;
path?: string;
}

0 comments on commit 54e728b

Please sign in to comment.