├── .husky ├── .gitignore └── commit-msg ├── commitlint.config.js ├── .prettierrc.json ├── .npmignore ├── src ├── builders │ └── build-schematics │ │ ├── schema.json │ │ └── index.ts ├── ng-generate │ ├── add-schematic │ │ ├── files │ │ │ └── ng-add │ │ │ │ ├── index.ts.template │ │ │ │ └── index.spec.ts.template │ │ ├── schema.json │ │ ├── index.ts │ │ └── index.spec.ts │ ├── init │ │ ├── schema.json │ │ ├── index.ts │ │ └── index.spec.ts │ ├── generate-schematic │ │ ├── files │ │ │ └── __name@dasherize__ │ │ │ │ ├── index.ts.template │ │ │ │ ├── schema.json.template │ │ │ │ └── index.spec.ts.template │ │ ├── schema.json │ │ ├── index.ts │ │ └── index.spec.ts │ └── update-schematic │ │ ├── files │ │ └── __name@dasherize__ │ │ │ ├── index.ts.template │ │ │ └── index.spec.ts.template │ │ ├── schema.json │ │ ├── index.ts │ │ └── index.spec.ts ├── builders.json ├── collection.json ├── ng-add │ ├── index.spec.ts │ └── index.ts └── utils │ └── utils.ts ├── smoke-tests ├── angular10 │ ├── projects │ │ └── lib1 │ │ │ ├── ng-package.json │ │ │ ├── src │ │ │ ├── public-api.ts │ │ │ └── lib │ │ │ │ ├── lib1.service.ts │ │ │ │ ├── lib1.module.ts │ │ │ │ └── lib1.component.ts │ │ │ ├── package.json │ │ │ ├── tsconfig.lib.prod.json │ │ │ ├── tslint.json │ │ │ ├── tsconfig.lib.json │ │ │ └── README.md │ ├── .editorconfig │ ├── package.json │ ├── tsconfig.json │ ├── .gitignore │ ├── README.md │ ├── angular.json │ └── tslint.json ├── angular11 │ ├── projects │ │ └── lib1 │ │ │ ├── ng-package.json │ │ │ ├── src │ │ │ ├── public-api.ts │ │ │ └── lib │ │ │ │ ├── lib1.service.ts │ │ │ │ ├── lib1.module.ts │ │ │ │ └── lib1.component.ts │ │ │ ├── package.json │ │ │ ├── tsconfig.lib.prod.json │ │ │ ├── tslint.json │ │ │ ├── tsconfig.spec.json │ │ │ ├── tsconfig.lib.json │ │ │ └── README.md │ ├── .editorconfig │ ├── package.json │ ├── tsconfig.json │ ├── .gitignore │ ├── README.md │ ├── angular.json │ └── tslint.json ├── angular12 │ ├── projects │ │ └── lib1 │ │ │ ├── ng-package.json │ │ │ ├── src │ │ │ ├── public-api.ts │ │ │ └── lib │ │ │ │ ├── lib1.service.ts │ │ │ │ ├── lib1.module.ts │ │ │ │ └── lib1.component.ts │ │ │ ├── package.json │ │ │ ├── tsconfig.lib.prod.json │ │ │ ├── tsconfig.lib.json │ │ │ └── README.md │ ├── .editorconfig │ ├── package.json │ ├── .gitignore │ ├── tsconfig.json │ ├── README.md │ └── angular.json └── angular9 │ ├── projects │ └── lib1 │ │ ├── ng-package.json │ │ ├── src │ │ ├── public-api.ts │ │ └── lib │ │ │ ├── lib1.service.ts │ │ │ ├── lib1.module.ts │ │ │ └── lib1.component.ts │ │ ├── package.json │ │ ├── tsconfig.lib.prod.json │ │ ├── tslint.json │ │ ├── tsconfig.spec.json │ │ ├── tsconfig.lib.json │ │ └── README.md │ ├── .editorconfig │ ├── package.json │ ├── tsconfig.json │ ├── .gitignore │ ├── README.md │ ├── angular.json │ └── tslint.json ├── .gitignore ├── .prettierignore ├── jest.config.js ├── tsconfig.json ├── LICENCE ├── package.json ├── .github └── workflows │ └── main.yml └── README.md /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { extends: ['@commitlint/config-conventional'] }; 2 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "tabWidth": 4, 4 | "printWidth": 120 5 | } 6 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install commitlint --edit "$1" 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Ignores TypeScript files, but keeps definitions. 2 | *.ts 3 | !*.d.ts 4 | 5 | # Ignore smoke tests 6 | smoke-tests/**/* 7 | -------------------------------------------------------------------------------- /src/builders/build-schematics/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "SchematicsBuilderSchema", 3 | "title": "Schematics builder", 4 | "description": "", 5 | "properties": { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /smoke-tests/angular10/projects/lib1/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/lib1", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } -------------------------------------------------------------------------------- /smoke-tests/angular10/projects/lib1/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of lib1 3 | */ 4 | 5 | export * from './lib/lib1.service'; 6 | export * from './lib/lib1.component'; 7 | export * from './lib/lib1.module'; 8 | -------------------------------------------------------------------------------- /smoke-tests/angular11/projects/lib1/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/lib1", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } -------------------------------------------------------------------------------- /smoke-tests/angular11/projects/lib1/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of lib1 3 | */ 4 | 5 | export * from './lib/lib1.service'; 6 | export * from './lib/lib1.component'; 7 | export * from './lib/lib1.module'; 8 | -------------------------------------------------------------------------------- /smoke-tests/angular12/projects/lib1/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/lib1", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } -------------------------------------------------------------------------------- /smoke-tests/angular12/projects/lib1/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of lib1 3 | */ 4 | 5 | export * from './lib/lib1.service'; 6 | export * from './lib/lib1.component'; 7 | export * from './lib/lib1.module'; 8 | -------------------------------------------------------------------------------- /smoke-tests/angular9/projects/lib1/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/lib1", 4 | "lib": { 5 | "entryFile": "src/public-api.ts" 6 | } 7 | } -------------------------------------------------------------------------------- /smoke-tests/angular9/projects/lib1/src/public-api.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of lib1 3 | */ 4 | 5 | export * from './lib/lib1.service'; 6 | export * from './lib/lib1.component'; 7 | export * from './lib/lib1.module'; 8 | -------------------------------------------------------------------------------- /smoke-tests/angular10/projects/lib1/src/lib/lib1.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root' 5 | }) 6 | export class Lib1Service { 7 | 8 | constructor() { } 9 | } 10 | -------------------------------------------------------------------------------- /smoke-tests/angular11/projects/lib1/src/lib/lib1.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root' 5 | }) 6 | export class Lib1Service { 7 | 8 | constructor() { } 9 | } 10 | -------------------------------------------------------------------------------- /smoke-tests/angular12/projects/lib1/src/lib/lib1.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root' 5 | }) 6 | export class Lib1Service { 7 | 8 | constructor() { } 9 | } 10 | -------------------------------------------------------------------------------- /smoke-tests/angular9/projects/lib1/src/lib/lib1.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root' 5 | }) 6 | export class Lib1Service { 7 | 8 | constructor() { } 9 | } 10 | -------------------------------------------------------------------------------- /src/ng-generate/add-schematic/files/ng-add/index.ts.template: -------------------------------------------------------------------------------- 1 | import { noop, Tree } from "@angular-devkit/schematics"; 2 | 3 | export function ngAdd(options: any) { 4 | return async (host: Tree) => { 5 | return noop(); 6 | }; 7 | } 8 | -------------------------------------------------------------------------------- /smoke-tests/angular10/projects/lib1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lib1", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^10.2.4", 6 | "@angular/core": "^10.2.4" 7 | }, 8 | "dependencies": { 9 | "tslib": "^2.0.0" 10 | } 11 | } -------------------------------------------------------------------------------- /smoke-tests/angular12/projects/lib1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lib1", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^12.0.2", 6 | "@angular/core": "^12.0.2" 7 | }, 8 | "dependencies": { 9 | "tslib": "^2.1.0" 10 | } 11 | } -------------------------------------------------------------------------------- /smoke-tests/angular9/projects/lib1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lib1", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^11.2.12", 6 | "@angular/core": "^11.2.12" 7 | }, 8 | "dependencies": { 9 | "tslib": "^2.0.0" 10 | } 11 | } -------------------------------------------------------------------------------- /smoke-tests/angular11/projects/lib1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lib1", 3 | "version": "0.0.1", 4 | "peerDependencies": { 5 | "@angular/common": "^11.2.14", 6 | "@angular/core": "^11.2.14" 7 | }, 8 | "dependencies": { 9 | "tslib": "^2.0.0" 10 | } 11 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Outputs 2 | src/**/*.js 3 | src/**/*.js.map 4 | src/**/*.d.ts 5 | 6 | # IDEs 7 | .idea/ 8 | jsconfig.json 9 | .vscode/ 10 | 11 | # Misc 12 | node_modules/ 13 | npm-debug.log* 14 | yarn-error.log* 15 | 16 | # Mac OSX Finder files. 17 | **/.DS_Store 18 | .DS_Store 19 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Outputs 2 | src/**/*.js 3 | src/**/*.js.map 4 | src/**/*.d.ts 5 | 6 | # IDEs 7 | .idea/ 8 | jsconfig.json 9 | .vscode/ 10 | 11 | # Misc 12 | node_modules/ 13 | npm-debug.log* 14 | yarn-error.log* 15 | *.json 16 | 17 | # Mac OSX Finder files. 18 | **/.DS_Store 19 | .DS_Store 20 | -------------------------------------------------------------------------------- /smoke-tests/angular10/projects/lib1/src/lib/lib1.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Lib1Component } from './lib1.component'; 3 | 4 | 5 | 6 | @NgModule({ 7 | declarations: [Lib1Component], 8 | imports: [ 9 | ], 10 | exports: [Lib1Component] 11 | }) 12 | export class Lib1Module { } 13 | -------------------------------------------------------------------------------- /smoke-tests/angular9/projects/lib1/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.lib.json", 4 | "compilerOptions": { 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "enableIvy": false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /smoke-tests/angular10/projects/lib1/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.lib.json", 4 | "compilerOptions": { 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "enableIvy": false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /smoke-tests/angular11/projects/lib1/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.lib.json", 4 | "compilerOptions": { 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "enableIvy": false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /smoke-tests/angular12/projects/lib1/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.lib.json", 4 | "compilerOptions": { 5 | "declarationMap": false 6 | }, 7 | "angularCompilerOptions": { 8 | "compilationMode": "partial" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/builders.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "@angular-devkit/architect/src/builders-schema.json", 3 | "builders": { 4 | "build-schematics": { 5 | "implementation": "./builders/build-schematics/index", 6 | "schema": "./builders/build-schematics/schema.json", 7 | "description": "Build schematics project" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /smoke-tests/angular11/projects/lib1/src/lib/lib1.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Lib1Component } from './lib1.component'; 3 | 4 | 5 | 6 | @NgModule({ 7 | declarations: [ 8 | Lib1Component 9 | ], 10 | imports: [ 11 | ], 12 | exports: [ 13 | Lib1Component 14 | ] 15 | }) 16 | export class Lib1Module { } 17 | -------------------------------------------------------------------------------- /smoke-tests/angular12/projects/lib1/src/lib/lib1.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Lib1Component } from './lib1.component'; 3 | 4 | 5 | 6 | @NgModule({ 7 | declarations: [ 8 | Lib1Component 9 | ], 10 | imports: [ 11 | ], 12 | exports: [ 13 | Lib1Component 14 | ] 15 | }) 16 | export class Lib1Module { } 17 | -------------------------------------------------------------------------------- /smoke-tests/angular9/projects/lib1/src/lib/lib1.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Lib1Component } from './lib1.component'; 3 | 4 | 5 | 6 | @NgModule({ 7 | declarations: [ 8 | Lib1Component 9 | ], 10 | imports: [ 11 | ], 12 | exports: [ 13 | Lib1Component 14 | ] 15 | }) 16 | export class Lib1Module { } 17 | -------------------------------------------------------------------------------- /src/ng-generate/init/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties": { 3 | "path": { 4 | "type": "string", 5 | "format": "path", 6 | "description": "", 7 | "visible": false 8 | }, 9 | "project": { 10 | "type": "string", 11 | "description": "Name of the Angular project", 12 | "minLength": 1 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /smoke-tests/angular10/projects/lib1/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json", 3 | "rules": { 4 | "directive-selector": [ 5 | true, 6 | "attribute", 7 | "lib", 8 | "camelCase" 9 | ], 10 | "component-selector": [ 11 | true, 12 | "element", 13 | "lib", 14 | "kebab-case" 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /smoke-tests/angular11/projects/lib1/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json", 3 | "rules": { 4 | "directive-selector": [ 5 | true, 6 | "attribute", 7 | "lib", 8 | "camelCase" 9 | ], 10 | "component-selector": [ 11 | true, 12 | "element", 13 | "lib", 14 | "kebab-case" 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /smoke-tests/angular9/projects/lib1/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tslint.json", 3 | "rules": { 4 | "directive-selector": [ 5 | true, 6 | "attribute", 7 | "lib", 8 | "camelCase" 9 | ], 10 | "component-selector": [ 11 | true, 12 | "element", 13 | "lib", 14 | "kebab-case" 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /smoke-tests/angular10/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /smoke-tests/angular11/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /smoke-tests/angular12/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /smoke-tests/angular9/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /smoke-tests/angular11/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular11", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng" 6 | }, 7 | "private": true, 8 | "dependencies": { 9 | "@angular/core": "~11.2.14" 10 | }, 11 | "devDependencies": { 12 | "@angular/cli": "~11.2.13", 13 | "ngx-cli-toolkit": "../../", 14 | "typescript": "~4.1.5" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/ng-generate/generate-schematic/files/__name@dasherize__/index.ts.template: -------------------------------------------------------------------------------- 1 | import { noop, Tree } from "@angular-devkit/schematics"; 2 | 3 | export interface <%= classify(name) %>Options { 4 | name: string; 5 | } 6 | 7 | export function <%= camelize(name) %>(options: <%= classify(name) %>Options) { 8 | return async (host: Tree) => { 9 | return noop(); 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /smoke-tests/angular10/projects/lib1/src/lib/lib1.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lib-lib1', 5 | template: ` 6 |

7 | lib1 works! 8 |

9 | `, 10 | styles: [ 11 | ] 12 | }) 13 | export class Lib1Component implements OnInit { 14 | 15 | constructor() { } 16 | 17 | ngOnInit(): void { 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /smoke-tests/angular11/projects/lib1/src/lib/lib1.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lib-lib1', 5 | template: ` 6 |

7 | lib1 works! 8 |

9 | `, 10 | styles: [ 11 | ] 12 | }) 13 | export class Lib1Component implements OnInit { 14 | 15 | constructor() { } 16 | 17 | ngOnInit(): void { 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /smoke-tests/angular12/projects/lib1/src/lib/lib1.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lib-lib1', 5 | template: ` 6 |

7 | lib1 works! 8 |

9 | `, 10 | styles: [ 11 | ] 12 | }) 13 | export class Lib1Component implements OnInit { 14 | 15 | constructor() { } 16 | 17 | ngOnInit(): void { 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /smoke-tests/angular9/projects/lib1/src/lib/lib1.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'lib-lib1', 5 | template: ` 6 |

7 | lib1 works! 8 |

9 | `, 10 | styles: [ 11 | ] 12 | }) 13 | export class Lib1Component implements OnInit { 14 | 15 | constructor() { } 16 | 17 | ngOnInit(): void { 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * For a detailed explanation regarding each configuration property and type check, visit: 3 | * https://jestjs.io/docs/en/configuration.html 4 | */ 5 | 6 | module.exports = { 7 | preset: 'ts-jest', 8 | clearMocks: true, 9 | coverageDirectory: 'coverage', 10 | collectCoverageFrom: ['src/**/*.ts'], 11 | coverageProvider: 'v8', 12 | testEnvironment: 'node', 13 | }; 14 | -------------------------------------------------------------------------------- /src/ng-generate/update-schematic/files/__name@dasherize__/index.ts.template: -------------------------------------------------------------------------------- 1 | import { noop, SchematicContext, Tree } from "@angular-devkit/schematics"; 2 | 3 | export interface <%= classify(name) %>Options { 4 | name: string; 5 | } 6 | 7 | export function <%= camelize(name) %>(options: <%= classify(name) %>Options) { 8 | return async (host: Tree, context: SchematicContext) => { 9 | return noop(); 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /smoke-tests/angular9/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular9", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng" 6 | }, 7 | "private": true, 8 | "dependencies": { 9 | "@angular/core": "~9.1.13", 10 | "rxjs": "^6.5.5", 11 | "zone.js": "~0.10.3" 12 | }, 13 | "devDependencies": { 14 | "@angular/cli": "~9.1.15", 15 | "ngx-cli-toolkit": "../../", 16 | "typescript": "~3.8.3" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /smoke-tests/angular9/projects/lib1/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "../../out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /smoke-tests/angular11/projects/lib1/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "../../out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "**/*.spec.ts", 15 | "**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /src/ng-generate/generate-schematic/files/__name@dasherize__/schema.json.template: -------------------------------------------------------------------------------- 1 | { 2 | "properties": { 3 | "name": { 4 | "type": "string", 5 | "description": "Name", 6 | "$default": { 7 | "$source": "argv", 8 | "index": 0 9 | } 10 | }, 11 | "path": { 12 | "type": "string", 13 | "format": "path", 14 | "description": "", 15 | "visible": false 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /smoke-tests/angular10/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular10", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "test": "ng test", 9 | "lint": "ng lint" 10 | }, 11 | "private": true, 12 | "dependencies": { 13 | "@angular/core": "~10.2.4", 14 | "zone.js": "~0.10.3" 15 | }, 16 | "devDependencies": { 17 | "@angular/cli": "~10.2.3", 18 | "ngx-cli-toolkit": "../../", 19 | "typescript": "~4.0.2" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /smoke-tests/angular12/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular12", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "watch": "ng build --watch --configuration development", 9 | "test": "ng test" 10 | }, 11 | "private": true, 12 | "dependencies": { 13 | "@angular/core": "~12.0.2" 14 | }, 15 | "devDependencies": { 16 | "@angular/cli": "~12.0.2", 17 | "ngx-cli-toolkit": "../../", 18 | "typescript": "~4.2.3" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /smoke-tests/angular12/projects/lib1/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "../../out-tsc/lib", 6 | "target": "es2015", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "inlineSources": true, 10 | "types": [], 11 | "lib": [ 12 | "dom", 13 | "es2018" 14 | ] 15 | }, 16 | "exclude": [ 17 | "src/test.ts", 18 | "**/*.spec.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/ng-generate/generate-schematic/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties": { 3 | "name": { 4 | "type": "string", 5 | "description": "Name of the schematic", 6 | "x-prompt": "Name of the schematic", 7 | "$default": { 8 | "$source": "argv", 9 | "index": 0 10 | } 11 | }, 12 | "description": { 13 | "type": "string", 14 | "x-prompt": "Schematic description" 15 | }, 16 | "path": { 17 | "type": "string", 18 | "format": "path", 19 | "description": "", 20 | "visible": false 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/ng-generate/add-schematic/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties": { 3 | "save": { 4 | "type": "string", 5 | "x-prompt": { 6 | "message": "Save package as", 7 | "type": "list", 8 | "multiselect": false, 9 | "items": [ 10 | { "value": "dependencies", "label": "dependency" }, 11 | { "value": "devDependencies", "label": "devDependency" } 12 | ] 13 | } 14 | }, 15 | "path": { 16 | "type": "string", 17 | "format": "path", 18 | "description": "", 19 | "visible": false 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /smoke-tests/angular10/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "downlevelIteration": true, 9 | "experimentalDecorators": true, 10 | "moduleResolution": "node", 11 | "importHelpers": true, 12 | "target": "es2015", 13 | "module": "es2020", 14 | "lib": [ 15 | "es2018", 16 | "dom" 17 | ], 18 | "paths": { 19 | "lib1": [ 20 | "dist/lib1/lib1", 21 | "dist/lib1" 22 | ] 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/builders/build-schematics/index.ts: -------------------------------------------------------------------------------- 1 | import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect'; 2 | import { Observable, of } from 'rxjs'; 3 | import { json } from '@angular-devkit/core'; 4 | 5 | interface SchematicsBuilderOptions { 6 | } 7 | 8 | export function buildSchematics( 9 | _options: SchematicsBuilderOptions, 10 | { logger }: BuilderContext 11 | ): Observable { 12 | logger.info('Noop'); 13 | return of({ 14 | success: true 15 | }); 16 | } 17 | 18 | export default createBuilder( 19 | buildSchematics 20 | ); 21 | -------------------------------------------------------------------------------- /src/ng-generate/update-schematic/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties": { 3 | "name": { 4 | "type": "string", 5 | "description": "Name of the schematic", 6 | "x-prompt": "Name of the schematic", 7 | "$default": { 8 | "$source": "argv", 9 | "index": 0 10 | } 11 | }, 12 | "description": { 13 | "type": "string", 14 | "x-prompt": "Schematic description" 15 | }, 16 | "version": { 17 | "type": "string", 18 | "x-prompt": "Update version" 19 | }, 20 | "path": { 21 | "type": "string", 22 | "format": "path", 23 | "description": "", 24 | "visible": false 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /smoke-tests/angular9/projects/lib1/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "../../out-tsc/lib", 6 | "target": "es2015", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "inlineSources": true, 10 | "types": [], 11 | "lib": [ 12 | "dom", 13 | "es2018" 14 | ] 15 | }, 16 | "angularCompilerOptions": { 17 | "skipTemplateCodegen": true, 18 | "strictMetadataEmit": true, 19 | "enableResourceInlining": true 20 | }, 21 | "exclude": [ 22 | "src/test.ts", 23 | "**/*.spec.ts" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /smoke-tests/angular10/projects/lib1/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "../../out-tsc/lib", 6 | "target": "es2015", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "inlineSources": true, 10 | "types": [], 11 | "lib": [ 12 | "dom", 13 | "es2018" 14 | ] 15 | }, 16 | "angularCompilerOptions": { 17 | "skipTemplateCodegen": true, 18 | "strictMetadataEmit": true, 19 | "enableResourceInlining": true 20 | }, 21 | "exclude": [ 22 | "src/test.ts", 23 | "**/*.spec.ts" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /smoke-tests/angular11/projects/lib1/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "../../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "../../out-tsc/lib", 6 | "target": "es2015", 7 | "declaration": true, 8 | "declarationMap": true, 9 | "inlineSources": true, 10 | "types": [], 11 | "lib": [ 12 | "dom", 13 | "es2018" 14 | ] 15 | }, 16 | "angularCompilerOptions": { 17 | "skipTemplateCodegen": true, 18 | "strictMetadataEmit": true, 19 | "enableResourceInlining": true 20 | }, 21 | "exclude": [ 22 | "src/test.ts", 23 | "**/*.spec.ts" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/ng-generate/add-schematic/files/ng-add/index.spec.ts.template: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { SchematicTestRunner } from '@angular-devkit/schematics/testing'; 3 | import * as path from 'path'; 4 | 5 | const collectionPath = path.join(__dirname, '../collection.json'); 6 | 7 | describe('ng-add', () => { 8 | let runner: SchematicTestRunner; 9 | let tree: Tree; 10 | 11 | beforeEach(() => { 12 | runner = new SchematicTestRunner('schematics', collectionPath); 13 | tree = Tree.empty(); 14 | }) 15 | 16 | it('noop', async () => { 17 | await runner.runSchematicAsync('ng-add', {}, tree).toPromise(); 18 | expect(true).toBe(true); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /smoke-tests/angular9/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "downlevelIteration": true, 9 | "experimentalDecorators": true, 10 | "paths": { 11 | "lib1": [ 12 | "dist/lib1/lib1", 13 | "dist/lib1" 14 | ] 15 | }, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "es2015", 20 | "lib": [ 21 | "es2018", 22 | "dom" 23 | ] 24 | }, 25 | "angularCompilerOptions": { 26 | "fullTemplateTypeCheck": true, 27 | "strictInjectionParameters": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/ng-generate/generate-schematic/files/__name@dasherize__/index.spec.ts.template: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { SchematicTestRunner } from '@angular-devkit/schematics/testing'; 3 | import * as path from 'path'; 4 | 5 | const collectionPath = path.join(__dirname, '<%= collectionJsonPath %>'); 6 | 7 | describe('<%= dasherize(name) %>', () => { 8 | let runner: SchematicTestRunner; 9 | let tree: Tree; 10 | 11 | beforeEach(() => { 12 | runner = new SchematicTestRunner('schematics', collectionPath); 13 | tree = Tree.empty(); 14 | }); 15 | 16 | it('noop', async () => { 17 | await runner.runSchematicAsync('<%= dasherize(name) %>', {}, tree).toPromise(); 18 | expect(true).toBe(true); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /src/ng-generate/update-schematic/files/__name@dasherize__/index.spec.ts.template: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { SchematicTestRunner } from '@angular-devkit/schematics/testing'; 3 | import * as path from 'path'; 4 | 5 | const migrationsPath = path.join(__dirname, '<%= migrationsJsonPath %>'); 6 | 7 | describe('<%= dasherize(name) %>', () => { 8 | let runner: SchematicTestRunner; 9 | let tree: Tree; 10 | 11 | beforeEach(() => { 12 | runner = new SchematicTestRunner('schematics', migrationsPath); 13 | tree = Tree.empty(); 14 | }); 15 | 16 | it('noop', async () => { 17 | await runner.runSchematicAsync('<%= dasherize(name) %>', {}, tree).toPromise(); 18 | expect(true).toBe(true); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /smoke-tests/angular11/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "sourceMap": true, 8 | "declaration": false, 9 | "downlevelIteration": true, 10 | "experimentalDecorators": true, 11 | "paths": { 12 | "lib1": [ 13 | "dist/lib1/lib1", 14 | "dist/lib1" 15 | ] 16 | }, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "es2015", 20 | "module": "es2020", 21 | "lib": [ 22 | "es2018", 23 | "dom" 24 | ] 25 | }, 26 | "angularCompilerOptions": { 27 | "enableI18nLegacyMessageIdFormat": false 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /smoke-tests/angular12/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | 16 | # IDEs and editors 17 | /.idea 18 | .project 19 | .classpath 20 | .c9/ 21 | *.launch 22 | .settings/ 23 | *.sublime-workspace 24 | 25 | # IDE - VSCode 26 | .vscode/* 27 | !.vscode/settings.json 28 | !.vscode/tasks.json 29 | !.vscode/launch.json 30 | !.vscode/extensions.json 31 | .history/* 32 | 33 | # misc 34 | /.sass-cache 35 | /connect.lock 36 | /coverage 37 | /libpeerconnection.log 38 | npm-debug.log 39 | yarn-error.log 40 | testem.log 41 | /typings 42 | 43 | # System Files 44 | .DS_Store 45 | Thumbs.db 46 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "tsconfig", 4 | "lib": [ 5 | "es2018", 6 | "dom" 7 | ], 8 | "declaration": true, 9 | "module": "commonjs", 10 | "moduleResolution": "node", 11 | "noEmitOnError": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "noImplicitAny": true, 14 | "noImplicitThis": true, 15 | "noUnusedParameters": true, 16 | "noUnusedLocals": true, 17 | "rootDir": "src/", 18 | "skipDefaultLibCheck": true, 19 | "skipLibCheck": true, 20 | "sourceMap": true, 21 | "strict": true, 22 | "target": "es6", 23 | "types": [ 24 | "jest", 25 | "node" 26 | ] 27 | }, 28 | "include": [ 29 | "src/**/*" 30 | ], 31 | "exclude": [ 32 | "src/*/files/**/*", 33 | "**/*.spec.ts", 34 | "smoke-tests/**/*" 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /smoke-tests/angular9/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | speed-measure-plugin*.json 16 | 17 | # IDEs and editors 18 | /.idea 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | 26 | # IDE - VSCode 27 | .vscode/* 28 | !.vscode/settings.json 29 | !.vscode/tasks.json 30 | !.vscode/launch.json 31 | !.vscode/extensions.json 32 | .history/* 33 | 34 | # misc 35 | /.sass-cache 36 | /connect.lock 37 | /coverage 38 | /libpeerconnection.log 39 | npm-debug.log 40 | yarn-error.log 41 | testem.log 42 | /typings 43 | 44 | # System Files 45 | .DS_Store 46 | Thumbs.db 47 | -------------------------------------------------------------------------------- /smoke-tests/angular10/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | speed-measure-plugin*.json 16 | 17 | # IDEs and editors 18 | /.idea 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | 26 | # IDE - VSCode 27 | .vscode/* 28 | !.vscode/settings.json 29 | !.vscode/tasks.json 30 | !.vscode/launch.json 31 | !.vscode/extensions.json 32 | .history/* 33 | 34 | # misc 35 | /.sass-cache 36 | /connect.lock 37 | /coverage 38 | /libpeerconnection.log 39 | npm-debug.log 40 | yarn-error.log 41 | testem.log 42 | /typings 43 | 44 | # System Files 45 | .DS_Store 46 | Thumbs.db 47 | -------------------------------------------------------------------------------- /smoke-tests/angular11/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | speed-measure-plugin*.json 16 | 17 | # IDEs and editors 18 | /.idea 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | 26 | # IDE - VSCode 27 | .vscode/* 28 | !.vscode/settings.json 29 | !.vscode/tasks.json 30 | !.vscode/launch.json 31 | !.vscode/extensions.json 32 | .history/* 33 | 34 | # misc 35 | /.sass-cache 36 | /connect.lock 37 | /coverage 38 | /libpeerconnection.log 39 | npm-debug.log 40 | yarn-error.log 41 | testem.log 42 | /typings 43 | 44 | # System Files 45 | .DS_Store 46 | Thumbs.db 47 | -------------------------------------------------------------------------------- /smoke-tests/angular12/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true, 11 | "sourceMap": true, 12 | "paths": { 13 | "lib1": [ 14 | "dist/lib1/lib1", 15 | "dist/lib1" 16 | ] 17 | }, 18 | "declaration": false, 19 | "downlevelIteration": true, 20 | "experimentalDecorators": true, 21 | "moduleResolution": "node", 22 | "importHelpers": true, 23 | "target": "es2017", 24 | "module": "es2020", 25 | "lib": [ 26 | "es2018", 27 | "dom" 28 | ] 29 | }, 30 | "angularCompilerOptions": { 31 | "enableI18nLegacyMessageIdFormat": false, 32 | "strictInjectionParameters": true, 33 | "strictInputAccessModifiers": true, 34 | "strictTemplates": true 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /smoke-tests/angular10/projects/lib1/README.md: -------------------------------------------------------------------------------- 1 | # Lib1 2 | 3 | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.2.4. 4 | 5 | ## Code scaffolding 6 | 7 | Run `ng generate component component-name --project lib1` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project lib1`. 8 | > Note: Don't forget to add `--project lib1` or else it will be added to the default project in your `angular.json` file. 9 | 10 | ## Build 11 | 12 | Run `ng build lib1` to build the project. The build artifacts will be stored in the `dist/` directory. 13 | 14 | ## Publishing 15 | 16 | After building your library with `ng build lib1`, go to the dist folder `cd dist/lib1` and run `npm publish`. 17 | 18 | ## Running unit tests 19 | 20 | Run `ng test lib1` to execute the unit tests via [Karma](https://karma-runner.github.io). 21 | 22 | ## Further help 23 | 24 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 25 | -------------------------------------------------------------------------------- /smoke-tests/angular11/projects/lib1/README.md: -------------------------------------------------------------------------------- 1 | # Lib1 2 | 3 | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 11.2.14. 4 | 5 | ## Code scaffolding 6 | 7 | Run `ng generate component component-name --project lib1` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project lib1`. 8 | > Note: Don't forget to add `--project lib1` or else it will be added to the default project in your `angular.json` file. 9 | 10 | ## Build 11 | 12 | Run `ng build lib1` to build the project. The build artifacts will be stored in the `dist/` directory. 13 | 14 | ## Publishing 15 | 16 | After building your library with `ng build lib1`, go to the dist folder `cd dist/lib1` and run `npm publish`. 17 | 18 | ## Running unit tests 19 | 20 | Run `ng test lib1` to execute the unit tests via [Karma](https://karma-runner.github.io). 21 | 22 | ## Further help 23 | 24 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 25 | -------------------------------------------------------------------------------- /smoke-tests/angular12/projects/lib1/README.md: -------------------------------------------------------------------------------- 1 | # Lib1 2 | 3 | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.0.2. 4 | 5 | ## Code scaffolding 6 | 7 | Run `ng generate component component-name --project lib1` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project lib1`. 8 | > Note: Don't forget to add `--project lib1` or else it will be added to the default project in your `angular.json` file. 9 | 10 | ## Build 11 | 12 | Run `ng build lib1` to build the project. The build artifacts will be stored in the `dist/` directory. 13 | 14 | ## Publishing 15 | 16 | After building your library with `ng build lib1`, go to the dist folder `cd dist/lib1` and run `npm publish`. 17 | 18 | ## Running unit tests 19 | 20 | Run `ng test lib1` to execute the unit tests via [Karma](https://karma-runner.github.io). 21 | 22 | ## Further help 23 | 24 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 25 | -------------------------------------------------------------------------------- /smoke-tests/angular9/projects/lib1/README.md: -------------------------------------------------------------------------------- 1 | # Lib1 2 | 3 | This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 11.2.12. 4 | 5 | ## Code scaffolding 6 | 7 | Run `ng generate component component-name --project lib1` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project lib1`. 8 | > Note: Don't forget to add `--project lib1` or else it will be added to the default project in your `angular.json` file. 9 | 10 | ## Build 11 | 12 | Run `ng build lib1` to build the project. The build artifacts will be stored in the `dist/` directory. 13 | 14 | ## Publishing 15 | 16 | After building your library with `ng build lib1`, go to the dist folder `cd dist/lib1` and run `npm publish`. 17 | 18 | ## Running unit tests 19 | 20 | Run `ng test lib1` to execute the unit tests via [Karma](https://karma-runner.github.io). 21 | 22 | ## Further help 23 | 24 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 25 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Kai Röder 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /smoke-tests/angular10/README.md: -------------------------------------------------------------------------------- 1 | # Angular10 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.2.3. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 28 | -------------------------------------------------------------------------------- /smoke-tests/angular11/README.md: -------------------------------------------------------------------------------- 1 | # Angular11 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 11.2.13. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 28 | -------------------------------------------------------------------------------- /smoke-tests/angular9/README.md: -------------------------------------------------------------------------------- 1 | # Angular9 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 9.1.15. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 28 | -------------------------------------------------------------------------------- /smoke-tests/angular12/README.md: -------------------------------------------------------------------------------- 1 | # Angular12 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 12.0.2. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. 24 | 25 | ## Further help 26 | 27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. 28 | -------------------------------------------------------------------------------- /src/collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json", 3 | "schematics": { 4 | "ng-add": { 5 | "save": "devDependencies", 6 | "description": "Add and bootstrap ngx-cli-toolkit", 7 | "factory": "./ng-add/index#ngAdd" 8 | }, 9 | "init": { 10 | "factory": "./ng-generate/init/index#initSchematicsProject", 11 | "description": "Initialize schematics project", 12 | "schema": "./ng-generate/init/schema.json" 13 | }, 14 | "add-schematic": { 15 | "factory": "./ng-generate/add-schematic/index#createAddSchematic", 16 | "description": "Create ng-add schematic", 17 | "schema": "./ng-generate/add-schematic/schema.json" 18 | }, 19 | "generate-schematic": { 20 | "factory": "./ng-generate/generate-schematic/index#createGenerateSchematic", 21 | "description": "Create ng-generate schematic", 22 | "schema": "./ng-generate/generate-schematic/schema.json" 23 | }, 24 | "update-schematic": { 25 | "factory": "./ng-generate/update-schematic/index#createUpdateSchematic", 26 | "description": "Create ng-update schematic", 27 | "schema": "./ng-generate/update-schematic/schema.json" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-cli-toolkit", 3 | "version": "0.4.0", 4 | "description": "A toolkit that helps with the setup and generation of schematics in projects.", 5 | "scripts": { 6 | "build": "tsc -p tsconfig.json", 7 | "build:watch": "tsc -p tsconfig.json --watch", 8 | "test": "jest", 9 | "release": "release-it" 10 | }, 11 | "keywords": [ 12 | "angular", 13 | "schematics", 14 | "utilities" 15 | ], 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/kroeder/ngx-cli-toolkit.git" 19 | }, 20 | "author": "Kai Roeder", 21 | "license": "MIT", 22 | "schematics": "./src/collection.json", 23 | "builders": "./src/builders.json", 24 | "dependencies": { 25 | "@angular-devkit/architect": "^0.1301.2", 26 | "@angular-devkit/core": "^13.1.2", 27 | "@angular-devkit/schematics": "^13.1.2", 28 | "@schematics/angular": "^13.1.2", 29 | "rxjs": "^7.4.0" 30 | }, 31 | "devDependencies": { 32 | "@commitlint/cli": "^12.1.1", 33 | "@commitlint/config-conventional": "^12.1.1", 34 | "@types/jest": "^26.0.23", 35 | "@types/node": "^14.18.2", 36 | "husky": "^6.0.0", 37 | "jest": "^26.6.3", 38 | "prettier": "2.2.1", 39 | "release-it": "^14.8.0", 40 | "ts-jest": "^26.5.5", 41 | "typescript": "~4.5.4" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /smoke-tests/angular12/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "cli": { 4 | "analytics": false 5 | }, 6 | "version": 1, 7 | "newProjectRoot": "projects", 8 | "projects": { 9 | "lib1": { 10 | "projectType": "library", 11 | "root": "projects/lib1", 12 | "sourceRoot": "projects/lib1/src", 13 | "prefix": "lib", 14 | "architect": { 15 | "build": { 16 | "builder": "@angular-devkit/build-angular:ng-packagr", 17 | "options": { 18 | "project": "projects/lib1/ng-package.json" 19 | }, 20 | "configurations": { 21 | "production": { 22 | "tsConfig": "projects/lib1/tsconfig.lib.prod.json" 23 | }, 24 | "development": { 25 | "tsConfig": "projects/lib1/tsconfig.lib.json" 26 | } 27 | }, 28 | "defaultConfiguration": "production" 29 | }, 30 | "test": { 31 | "builder": "@angular-devkit/build-angular:karma", 32 | "options": { 33 | "main": "projects/lib1/src/test.ts", 34 | "tsConfig": "projects/lib1/tsconfig.spec.json", 35 | "karmaConfig": "projects/lib1/karma.conf.js" 36 | } 37 | } 38 | } 39 | } 40 | }, 41 | "defaultProject": "lib1" 42 | } 43 | -------------------------------------------------------------------------------- /src/ng-add/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { SchematicTestRunner } from '@angular-devkit/schematics/testing'; 3 | import * as path from 'path'; 4 | 5 | const collectionPath = path.join(__dirname, '../collection.json'); 6 | 7 | describe('ng-add', () => { 8 | it('should add devDependencies', async () => { 9 | const angularJson = { 10 | dependencies: { 11 | '@angular/core': '~11.2.11', 12 | }, 13 | devDependencies: {}, 14 | }; 15 | 16 | const angularJsonExpected = { 17 | dependencies: { 18 | '@angular/core': '~11.2.11', 19 | }, 20 | devDependencies: { 21 | '@angular-devkit/architect': '~0.1102.0', 22 | '@angular-devkit/core': '~11.2.0', 23 | '@angular-devkit/schematics': '~11.2.0', 24 | '@schematics/angular': '~11.2.0', 25 | }, 26 | }; 27 | 28 | const runner = new SchematicTestRunner('schematics', collectionPath); 29 | const tree = Tree.empty(); 30 | tree.create('package.json', JSON.stringify(angularJson)); 31 | 32 | await runner.runSchematicAsync('ng-add', {}, tree).toPromise(); 33 | 34 | expect(JSON.parse(tree.read('package.json')!.toString())).toEqual(angularJsonExpected); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: push 3 | jobs: 4 | prepare-smoke-tests: 5 | runs-on: ubuntu-latest 6 | outputs: 7 | dir: ${{ steps.set-dirs.outputs.dir }} 8 | steps: 9 | - uses: actions/checkout@v2 10 | - id: set-dirs 11 | run: | 12 | cd smoke-tests && echo "::set-output name=dir::$(ls -d */ | jq -R -s -c 'split("\n")[:-1]')" 13 | jest: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Run tests 18 | run: | 19 | npm ci 20 | npm test 21 | smoke-test: 22 | runs-on: ubuntu-latest 23 | needs: [prepare-smoke-tests] # Depends on previous job 24 | strategy: 25 | matrix: 26 | dir: ${{fromJson(needs.prepare-smoke-tests.outputs.dir)}} # List matrix strategy from directories dynamically 27 | steps: 28 | - uses: actions/checkout@v2 29 | - name: Run tests 30 | run: | 31 | npm ci 32 | npm run build 33 | cd ./smoke-tests/${{matrix.dir}} 34 | npm install 35 | ./node_modules/.bin/ng generate ngx-cli-toolkit:ng-add 36 | cd ./projects/lib1 37 | ../../node_modules/.bin/ng generate ngx-cli-toolkit:init 38 | ../../node_modules/.bin/ng generate ngx-cli-toolkit:add-schematic --save dependencies 39 | ../../node_modules/.bin/ng generate ngx-cli-toolkit:update-schematic update1 --description foo --version 1.2.3 40 | ../../node_modules/.bin/ng generate ngx-cli-toolkit:generate-schematic generate1 --description foo 41 | -------------------------------------------------------------------------------- /smoke-tests/angular9/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "lib1": { 7 | "projectType": "library", 8 | "root": "projects/lib1", 9 | "sourceRoot": "projects/lib1/src", 10 | "prefix": "lib", 11 | "architect": { 12 | "build": { 13 | "builder": "@angular-devkit/build-angular:ng-packagr", 14 | "options": { 15 | "tsConfig": "projects/lib1/tsconfig.lib.json", 16 | "project": "projects/lib1/ng-package.json" 17 | }, 18 | "configurations": { 19 | "production": { 20 | "tsConfig": "projects/lib1/tsconfig.lib.prod.json" 21 | } 22 | } 23 | }, 24 | "test": { 25 | "builder": "@angular-devkit/build-angular:karma", 26 | "options": { 27 | "main": "projects/lib1/src/test.ts", 28 | "tsConfig": "projects/lib1/tsconfig.spec.json", 29 | "karmaConfig": "projects/lib1/karma.conf.js" 30 | } 31 | }, 32 | "lint": { 33 | "builder": "@angular-devkit/build-angular:tslint", 34 | "options": { 35 | "tsConfig": [ 36 | "projects/lib1/tsconfig.lib.json", 37 | "projects/lib1/tsconfig.spec.json" 38 | ], 39 | "exclude": [ 40 | "**/node_modules/**" 41 | ] 42 | } 43 | } 44 | } 45 | }}, 46 | "cli": { 47 | "analytics": false 48 | }, 49 | "defaultProject": "lib1" 50 | } -------------------------------------------------------------------------------- /smoke-tests/angular10/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "lib1": { 7 | "projectType": "library", 8 | "root": "projects/lib1", 9 | "sourceRoot": "projects/lib1/src", 10 | "prefix": "lib", 11 | "architect": { 12 | "build": { 13 | "builder": "@angular-devkit/build-angular:ng-packagr", 14 | "options": { 15 | "tsConfig": "projects/lib1/tsconfig.lib.json", 16 | "project": "projects/lib1/ng-package.json" 17 | }, 18 | "configurations": { 19 | "production": { 20 | "tsConfig": "projects/lib1/tsconfig.lib.prod.json" 21 | } 22 | } 23 | }, 24 | "test": { 25 | "builder": "@angular-devkit/build-angular:karma", 26 | "options": { 27 | "main": "projects/lib1/src/test.ts", 28 | "tsConfig": "projects/lib1/tsconfig.spec.json", 29 | "karmaConfig": "projects/lib1/karma.conf.js" 30 | } 31 | }, 32 | "lint": { 33 | "builder": "@angular-devkit/build-angular:tslint", 34 | "options": { 35 | "tsConfig": [ 36 | "projects/lib1/tsconfig.lib.json", 37 | "projects/lib1/tsconfig.spec.json" 38 | ], 39 | "exclude": [ 40 | "**/node_modules/**" 41 | ] 42 | } 43 | } 44 | } 45 | }}, 46 | "cli": { 47 | "analytics": false 48 | }, 49 | "defaultProject": "lib1" 50 | } -------------------------------------------------------------------------------- /smoke-tests/angular11/angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "cli": { 4 | "analytics": false 5 | }, 6 | "version": 1, 7 | "newProjectRoot": "projects", 8 | "projects": { 9 | "lib1": { 10 | "projectType": "library", 11 | "root": "projects/lib1", 12 | "sourceRoot": "projects/lib1/src", 13 | "prefix": "lib", 14 | "architect": { 15 | "build": { 16 | "builder": "@angular-devkit/build-angular:ng-packagr", 17 | "options": { 18 | "tsConfig": "projects/lib1/tsconfig.lib.json", 19 | "project": "projects/lib1/ng-package.json" 20 | }, 21 | "configurations": { 22 | "production": { 23 | "tsConfig": "projects/lib1/tsconfig.lib.prod.json" 24 | } 25 | } 26 | }, 27 | "test": { 28 | "builder": "@angular-devkit/build-angular:karma", 29 | "options": { 30 | "main": "projects/lib1/src/test.ts", 31 | "tsConfig": "projects/lib1/tsconfig.spec.json", 32 | "karmaConfig": "projects/lib1/karma.conf.js" 33 | } 34 | }, 35 | "lint": { 36 | "builder": "@angular-devkit/build-angular:tslint", 37 | "options": { 38 | "tsConfig": [ 39 | "projects/lib1/tsconfig.lib.json", 40 | "projects/lib1/tsconfig.spec.json" 41 | ], 42 | "exclude": [ 43 | "**/node_modules/**" 44 | ] 45 | } 46 | } 47 | } 48 | } 49 | }, 50 | "defaultProject": "lib1" 51 | } 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ngx-cli-toolkit - schematics for schematics 2 | 3 | This package provides schematics that can setup and generate schematics for your library. 4 | Creating `ng add`, `ng generate`, `ng update` or custom builders for the Angular CLI is 5 | not easy and often prevents you from solving your actual problems if you are not familiar with the 6 | bootstrapping process. 7 | 8 | **This package is in a very early stage, and most likely has bugs.** 9 | 10 | ## Support 11 | 12 | This package supports all LTS versions of Angular. ([Angular support policy and schedule](https://angular.io/guide/releases#support-policy-and-schedule)) 13 | 14 | ## Schematics 15 | 16 | ### Install 17 | 18 | Run `ng add` to add this package as well as useful, schematics related, dependencies that are 19 | useful for creating schematics. 20 | 21 | ```shell 22 | ng add ngx-cli-toolkit 23 | ``` 24 | 25 | ### Bootstrap schematics project 26 | 27 | The `init` schematic tries to discover the location of a package.json based on the directory the schematic was 28 | executed from. 29 | 30 | It will add the necessary schematic fields to the package.json as well as create json files that manage 31 | the `ng update` and `ng generate` schematics in your project. 32 | 33 | ```shell 34 | ng generate ngx-cli-toolkit:init 35 | ``` 36 | 37 | **Example for an Angular library project:** 38 | 39 | Inside Angular workspaces, the `--project` flag can be used to locate the root directory of a project. 40 | 41 | ```shell 42 | ng generate library awesome-library 43 | ng generate ngx-cli-toolkit:init --project awesome-library 44 | ``` 45 | 46 | ### Generating `ng-add` 47 | 48 | This creates a schematic that allows others to add your package using `ng add`. 49 | 50 | ```shell 51 | ng generate ngx-cli-toolkit:add-schematic 52 | ``` 53 | 54 | ### Generating `ng-generate` schematics 55 | 56 | This creates a `ng generate` schematic. 57 | 58 | ```shell 59 | ng generate ngx-cli-toolkit:generate-schematic name-of-your-schematic 60 | ``` 61 | 62 | ### Generating `ng-update` schematics 63 | 64 | This creates a `ng update` schematic. 65 | 66 | ```shell 67 | ng generate ngx-cli-toolkit:update-schematic name-of-your-schematic 68 | ``` 69 | -------------------------------------------------------------------------------- /src/ng-add/index.ts: -------------------------------------------------------------------------------- 1 | import { noop, Rule, SchematicContext, SchematicsException, Tree } from '@angular-devkit/schematics'; 2 | import { 3 | addPackageJsonDependency, 4 | getPackageJsonDependency, 5 | NodeDependencyType, 6 | } from '@schematics/angular/utility/dependencies'; 7 | import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks'; 8 | 9 | export function ngAdd(_options: any): Rule { 10 | return (host: Tree, context: SchematicContext) => { 11 | addDependencies(host); 12 | context.addTask(new NodePackageInstallTask()); 13 | return noop(); 14 | }; 15 | } 16 | 17 | const getCurrentInstalledAngularVersion = (host: Tree) => { 18 | const angularCore = getPackageJsonDependency(host, '@angular/core'); 19 | if (!angularCore) { 20 | throw new SchematicsException(`Could not find @angular/core in package.json dependencies`); 21 | } 22 | return angularCore.version; 23 | }; 24 | 25 | const addDependencies = (host: Tree) => { 26 | const angularVersion = getCurrentInstalledAngularVersion(host); 27 | 28 | const getVersion = (version: string) => { 29 | const versionSegments = version.split('.'); 30 | return `${versionSegments[0]}.${versionSegments[1]}.0`; 31 | }; 32 | 33 | const getDevBranchVersion = (version: string) => { 34 | const versionSegments = version.split('.'); 35 | versionSegments[0] = versionSegments[0].replace('~', '').replace('^', ''); 36 | return `~0.${versionSegments[0]}0${versionSegments[1]}.0`; 37 | }; 38 | 39 | const devDependencies: { [key: string]: string } = { 40 | '@angular-devkit/architect': getDevBranchVersion(angularVersion), 41 | '@angular-devkit/core': getVersion(angularVersion), 42 | '@angular-devkit/schematics': getVersion(angularVersion), 43 | '@schematics/angular': getVersion(angularVersion), 44 | }; 45 | 46 | for (const devDependenciesKey in devDependencies) { 47 | addPackageJsonDependency(host, { 48 | type: NodeDependencyType.Dev, 49 | name: devDependenciesKey, 50 | version: devDependencies[devDependenciesKey], 51 | }); 52 | } 53 | }; 54 | -------------------------------------------------------------------------------- /src/ng-generate/add-schematic/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | apply, 3 | applyTemplates, 4 | chain, 5 | mergeWith, 6 | move, 7 | noop, 8 | SchematicsException, 9 | Tree, 10 | url, 11 | } from '@angular-devkit/schematics'; 12 | import * as path from 'path'; 13 | import { getCollectionJsonPath, getParsedPath } from '../../utils/utils'; 14 | import { Location } from '@schematics/angular/utility/parse-name'; 15 | 16 | export interface InitSchematicsProjectOptions { 17 | path: string; 18 | save: 'dependencies' | 'devDependencies' | ''; 19 | } 20 | 21 | export function createAddSchematic(options: InitSchematicsProjectOptions) { 22 | return async (host: Tree) => { 23 | const parsedPath = getParsedPath(options.path, 'ng-add'); 24 | const templateSource = apply(url('./files'), [applyTemplates({}), move(parsedPath.path)]); 25 | 26 | return chain([mergeWith(templateSource), updateCollectionJson(host, parsedPath, options)]); 27 | }; 28 | } 29 | 30 | function updateCollectionJson(host: Tree, parsedPath: Location, options: InitSchematicsProjectOptions) { 31 | const collectionPath = getCollectionJsonPath(host, parsedPath); 32 | const collectionJsonBuffer = host.read(collectionPath); 33 | if (!collectionJsonBuffer) { 34 | throw new SchematicsException(`Could not read file '${collectionPath}'`); 35 | } 36 | 37 | const collectionJson = JSON.parse(collectionJsonBuffer.toString('utf8')); 38 | const relativePathToSchematic = path 39 | .relative( 40 | path.join(process.cwd(), path.dirname(collectionPath)), 41 | path.join(process.cwd(), parsedPath.path, 'ng-add', 'index') 42 | ) 43 | .replace(/\\/g, '/'); 44 | 45 | const updatedCollectionJson = { 46 | ...collectionJson, 47 | schematics: { 48 | 'ng-add': { 49 | save: options.save, 50 | description: 'Bootstrap package', 51 | factory: `${relativePathToSchematic}#ngAdd`, 52 | }, 53 | ...collectionJson.schematics, 54 | }, 55 | }; 56 | host.overwrite(collectionPath, JSON.stringify(updatedCollectionJson, null, 2)); 57 | 58 | return noop(); 59 | } 60 | -------------------------------------------------------------------------------- /src/utils/utils.ts: -------------------------------------------------------------------------------- 1 | import { SchematicsException, Tree } from '@angular-devkit/schematics'; 2 | import { ProjectDefinition, WorkspaceDefinition } from '@angular-devkit/core/src/workspace'; 3 | import * as path from 'path'; 4 | import { Location, parseName } from '@schematics/angular/utility/parse-name'; 5 | 6 | export function getParsedPath(path: string, dirName: string) { 7 | return parseName(path as string, dirName); 8 | } 9 | 10 | export function findPackageJson(host: Tree, parsedPath: Location) { 11 | const pathSegments = parsedPath.path.split('/'); 12 | let pathToPackageJson: string; 13 | for (let i = 0; i < pathSegments.length; i++) { 14 | pathToPackageJson = `${pathSegments.join('/')}/package.json`; 15 | if (host.exists(pathToPackageJson)) { 16 | return pathToPackageJson; 17 | } else { 18 | pathSegments.pop(); 19 | } 20 | } 21 | throw new SchematicsException(`Could not locate package.json based on path ${parsedPath.path}`); 22 | } 23 | 24 | export function readJson(host: Tree, path: string) { 25 | const jsonBuffer = host.read(path); 26 | if (!jsonBuffer) { 27 | throw new SchematicsException(`Could not read file '${path}'`); 28 | } 29 | return JSON.parse(jsonBuffer.toString('utf8')); 30 | } 31 | 32 | export function getMigrationsJsonPath(host: Tree, parsedPath: Location) { 33 | const packageJsonPath = findPackageJson(host, parsedPath); 34 | const packageJson = readJson(host, packageJsonPath); 35 | if (!packageJson?.['ng-update']?.migrations) { 36 | throw new SchematicsException(`Could not read 'ng-update.migrations' field from package.json. Try running 'ng g ngx-cli-toolkit:init'.`); 37 | } 38 | return path.join(removeLastSegmentOfPath(packageJsonPath), packageJson['ng-update'].migrations); 39 | } 40 | 41 | export function getCollectionJsonPath(host: Tree, parsedPath: Location) { 42 | const packageJsonPath = findPackageJson(host, parsedPath); 43 | const packageJson = readJson(host, packageJsonPath); 44 | if (!packageJson?.schematics) { 45 | throw new SchematicsException(`Could not read 'schematics' field from package.json. Try running 'ng g ngx-cli-toolkit:init'.`); 46 | } 47 | return path.join(removeLastSegmentOfPath(packageJsonPath), packageJson.schematics); 48 | } 49 | 50 | export async function getProject(workspace: WorkspaceDefinition, projectName: string) { 51 | if (workspace.projects.has(projectName)) { 52 | return workspace.projects.get(projectName) as ProjectDefinition; 53 | } else { 54 | throw new SchematicsException(`A project with the name '${projectName}' does not exists`); 55 | } 56 | } 57 | 58 | export function removeLastSegmentOfPath(path: string) { 59 | return path.substring(0, path.lastIndexOf('/')); 60 | } 61 | -------------------------------------------------------------------------------- /src/ng-generate/update-schematic/index.ts: -------------------------------------------------------------------------------- 1 | import { apply, applyTemplates, chain, mergeWith, move, noop, Tree, url } from '@angular-devkit/schematics'; 2 | import * as path from 'path'; 3 | import { camelize, dasherize } from '@angular-devkit/core/src/utils/strings'; 4 | import { strings } from '@angular-devkit/core'; 5 | import { getMigrationsJsonPath, getParsedPath, readJson } from '../../utils/utils'; 6 | import { Location } from '@schematics/angular/utility/parse-name'; 7 | 8 | export interface UpdateSchematicOptions { 9 | name: string; 10 | path: string; 11 | description: string; 12 | version: string; 13 | } 14 | 15 | export function createUpdateSchematic(options: UpdateSchematicOptions) { 16 | return async (host: Tree) => { 17 | const parsedPath = getParsedPath(options.path, options.name); 18 | 19 | const generatedSchematicDir = path.join(__dirname, parsedPath.path, dasherize(options.name)); 20 | const migrationsJson = path.join(__dirname, getMigrationsJsonPath(host, parsedPath)); 21 | const relativePathToMigrationsJson = path.relative(generatedSchematicDir, migrationsJson); 22 | 23 | const templateSource = apply(url('./files'), [ 24 | applyTemplates({ 25 | name: options.name, 26 | migrationsJsonPath: relativePathToMigrationsJson.replace(/\\/g, '/'), 27 | camelize: strings.camelize, 28 | classify: strings.classify, 29 | dasherize: strings.dasherize, 30 | }), 31 | move(parsedPath.path), 32 | ]); 33 | 34 | return chain([mergeWith(templateSource), updateMigrationsJson(host, parsedPath, options)]); 35 | }; 36 | } 37 | 38 | function updateMigrationsJson(host: Tree, parsedPath: Location, options: UpdateSchematicOptions) { 39 | const migrationsJsonPath = getMigrationsJsonPath(host, parsedPath); 40 | const migrationsJson = readJson(host, migrationsJsonPath); 41 | const schematicName = options.name; 42 | 43 | const relativePathToSchematic = path 44 | .relative( 45 | path.join(process.cwd(), path.dirname(migrationsJsonPath)), 46 | path.join(process.cwd(), parsedPath.path, schematicName, 'index') 47 | ) 48 | .replace(/\\/g, '/'); 49 | 50 | const updatedMigrationsJson = { 51 | ...migrationsJson, 52 | schematics: { 53 | ...migrationsJson.schematics, 54 | [dasherize(schematicName)]: { 55 | description: options.description, 56 | factory: `${relativePathToSchematic}#${camelize(options.name)}`, 57 | schema: `${relativePathToSchematic.replace('index', 'schema.json')}`, 58 | version: options.version, 59 | }, 60 | }, 61 | }; 62 | host.overwrite(migrationsJsonPath, JSON.stringify(updatedMigrationsJson, null, 2)); 63 | 64 | return noop(); 65 | } 66 | -------------------------------------------------------------------------------- /src/ng-generate/generate-schematic/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | apply, 3 | applyTemplates, 4 | chain, 5 | mergeWith, 6 | move, 7 | noop, 8 | SchematicsException, 9 | Tree, 10 | url, 11 | } from '@angular-devkit/schematics'; 12 | import * as path from 'path'; 13 | import { camelize, dasherize } from '@angular-devkit/core/src/utils/strings'; 14 | import { strings } from '@angular-devkit/core'; 15 | import { getCollectionJsonPath, getParsedPath } from '../../utils/utils'; 16 | import { Location } from '@schematics/angular/utility/parse-name'; 17 | 18 | export interface GenerateSchematicOptions { 19 | name: string; 20 | path: string; 21 | description: string; 22 | } 23 | 24 | export function createGenerateSchematic(options: GenerateSchematicOptions) { 25 | return async (host: Tree) => { 26 | const parsedPath = getParsedPath(options.path, options.name); 27 | 28 | const generatedSchematicDir = path.join(__dirname, parsedPath.path, dasherize(options.name)); 29 | const collectionJsonPath = path.join(__dirname, getCollectionJsonPath(host, parsedPath)); 30 | const relativePathToCollectionJson = path.relative(generatedSchematicDir, collectionJsonPath); 31 | 32 | const templateSource = apply(url('./files'), [ 33 | applyTemplates({ 34 | name: options.name, 35 | collectionJsonPath: relativePathToCollectionJson.replace(/\\/g, '/'), 36 | camelize: strings.camelize, 37 | classify: strings.classify, 38 | dasherize: strings.dasherize, 39 | }), 40 | move(parsedPath.path), 41 | ]); 42 | 43 | return chain([mergeWith(templateSource), updateCollectionJson(host, parsedPath, options)]); 44 | }; 45 | } 46 | 47 | function updateCollectionJson(host: Tree, parsedPath: Location, options: GenerateSchematicOptions) { 48 | const collectionPath = getCollectionJsonPath(host, parsedPath); 49 | const collectionJsonBuffer = host.read(collectionPath); 50 | const schematicName = options.name; 51 | if (!collectionJsonBuffer) { 52 | throw new SchematicsException(`Could not read file '${collectionPath}'`); 53 | } 54 | 55 | const collectionJson = JSON.parse(collectionJsonBuffer.toString('utf8')); 56 | const relativePathToSchematic = path 57 | .relative( 58 | path.join(process.cwd(), path.dirname(collectionPath)), 59 | path.join(process.cwd(), parsedPath.path, schematicName, 'index') 60 | ) 61 | .replace(/\\/g, '/'); 62 | 63 | const updatedCollectionJson = { 64 | ...collectionJson, 65 | schematics: { 66 | ...collectionJson.schematics, 67 | [dasherize(schematicName)]: { 68 | description: options.description, 69 | factory: `${relativePathToSchematic}#${camelize(options.name)}`, 70 | schema: `${relativePathToSchematic.replace('index', 'schema.json')}`, 71 | }, 72 | }, 73 | }; 74 | host.overwrite(collectionPath, JSON.stringify(updatedCollectionJson, null, 2)); 75 | 76 | return noop(); 77 | } 78 | -------------------------------------------------------------------------------- /smoke-tests/angular9/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:recommended", 3 | "rulesDirectory": [ 4 | "codelyzer" 5 | ], 6 | "rules": { 7 | "align": { 8 | "options": [ 9 | "parameters", 10 | "statements" 11 | ] 12 | }, 13 | "array-type": false, 14 | "arrow-return-shorthand": true, 15 | "curly": true, 16 | "deprecation": { 17 | "severity": "warning" 18 | }, 19 | "eofline": true, 20 | "import-blacklist": [ 21 | true, 22 | "rxjs/Rx" 23 | ], 24 | "import-spacing": true, 25 | "indent": { 26 | "options": [ 27 | "spaces" 28 | ] 29 | }, 30 | "max-classes-per-file": false, 31 | "max-line-length": [ 32 | true, 33 | 140 34 | ], 35 | "member-ordering": [ 36 | true, 37 | { 38 | "order": [ 39 | "static-field", 40 | "instance-field", 41 | "static-method", 42 | "instance-method" 43 | ] 44 | } 45 | ], 46 | "no-console": [ 47 | true, 48 | "debug", 49 | "info", 50 | "time", 51 | "timeEnd", 52 | "trace" 53 | ], 54 | "no-empty": false, 55 | "no-inferrable-types": [ 56 | true, 57 | "ignore-params" 58 | ], 59 | "no-non-null-assertion": true, 60 | "no-redundant-jsdoc": true, 61 | "no-switch-case-fall-through": true, 62 | "no-var-requires": false, 63 | "object-literal-key-quotes": [ 64 | true, 65 | "as-needed" 66 | ], 67 | "quotemark": [ 68 | true, 69 | "single" 70 | ], 71 | "semicolon": { 72 | "options": [ 73 | "always" 74 | ] 75 | }, 76 | "space-before-function-paren": { 77 | "options": { 78 | "anonymous": "never", 79 | "asyncArrow": "always", 80 | "constructor": "never", 81 | "method": "never", 82 | "named": "never" 83 | } 84 | }, 85 | "typedef-whitespace": { 86 | "options": [ 87 | { 88 | "call-signature": "nospace", 89 | "index-signature": "nospace", 90 | "parameter": "nospace", 91 | "property-declaration": "nospace", 92 | "variable-declaration": "nospace" 93 | }, 94 | { 95 | "call-signature": "onespace", 96 | "index-signature": "onespace", 97 | "parameter": "onespace", 98 | "property-declaration": "onespace", 99 | "variable-declaration": "onespace" 100 | } 101 | ] 102 | }, 103 | "variable-name": { 104 | "options": [ 105 | "ban-keywords", 106 | "check-format", 107 | "allow-pascal-case" 108 | ] 109 | }, 110 | "whitespace": { 111 | "options": [ 112 | "check-branch", 113 | "check-decl", 114 | "check-operator", 115 | "check-separator", 116 | "check-type", 117 | "check-typecast" 118 | ] 119 | }, 120 | "component-class-suffix": true, 121 | "contextual-lifecycle": true, 122 | "directive-class-suffix": true, 123 | "no-conflicting-lifecycle": true, 124 | "no-host-metadata-property": true, 125 | "no-input-rename": true, 126 | "no-inputs-metadata-property": true, 127 | "no-output-native": true, 128 | "no-output-on-prefix": true, 129 | "no-output-rename": true, 130 | "no-outputs-metadata-property": true, 131 | "template-banana-in-box": true, 132 | "template-no-negated-async": true, 133 | "use-lifecycle-interface": true, 134 | "use-pipe-transform-interface": true 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/ng-generate/init/index.ts: -------------------------------------------------------------------------------- 1 | import { chain, noop, SchematicsException, Tree } from '@angular-devkit/schematics'; 2 | import { getWorkspace, updateWorkspace } from '@schematics/angular/utility/workspace'; 3 | import { WorkspaceDefinition } from '@angular-devkit/core/src/workspace'; 4 | import * as path from 'path'; 5 | import { findPackageJson, getParsedPath, getProject, removeLastSegmentOfPath } from "../../utils/utils"; 6 | import { Location } from '@schematics/angular/utility/parse-name'; 7 | 8 | export interface InitSchematicsProjectOptions { 9 | path: string; 10 | project?: string; 11 | } 12 | 13 | export function initSchematicsProject(options: InitSchematicsProjectOptions) { 14 | return async (host: Tree) => { 15 | if(options.project) { 16 | const workspace = await getWorkspace(host); 17 | options.path = (await getProject(workspace, options.project)).root; 18 | } 19 | const parsedPath = getParsedPath(options.path, 'schematics'); 20 | const projectRoot = removeLastSegmentOfPath(findPackageJson(host, parsedPath)); 21 | const schematicsDir = path.join(projectRoot, parsedPath.name); 22 | const relativePathToNodeModules = path.relative(path.join(process.cwd(), projectRoot, 'schematics'), path.join(process.cwd(), 'node_modules')); 23 | 24 | return chain([ 25 | createSchematicsConfigurationFiles(host, schematicsDir, relativePathToNodeModules), 26 | // addBuilderToAngularJson(workspace, options.project), 27 | addSchematicsFieldsToPackageJson(host, parsedPath), 28 | ]); 29 | }; 30 | } 31 | 32 | function createSchematicsConfigurationFiles(host: Tree, targetDir: string, nodeModulesPath: string) { 33 | const schemaPath = path 34 | .join(nodeModulesPath, '@angular-devkit/schematics/collection-schema.json') 35 | .replace(/\\/g, '/'); 36 | host.create( 37 | path.join(targetDir, 'collection.json'), 38 | JSON.stringify( 39 | { 40 | $schema: schemaPath, 41 | schematics: {}, 42 | }, 43 | null, 44 | 2 45 | ) 46 | ); 47 | 48 | host.create( 49 | path.join(targetDir, 'migrations.json'), 50 | JSON.stringify( 51 | { 52 | $schema: schemaPath, 53 | schematics: {}, 54 | }, 55 | null, 56 | 2 57 | ) 58 | ); 59 | 60 | return noop(); 61 | } 62 | 63 | // todo: builder not yet implemented 64 | // @ts-ignore 65 | function addBuilderToAngularJson(workspace: WorkspaceDefinition, projectName: string) { 66 | workspace.projects.get(projectName)?.targets.set('build-schematics', { 67 | builder: 'ngx-cli-toolkit:build-schematics', 68 | }); 69 | return updateWorkspace(workspace); 70 | } 71 | 72 | function addSchematicsFieldsToPackageJson(host: Tree, parsedPath: Location) { 73 | const packageJsonPath = findPackageJson(host, parsedPath); 74 | const packageJsonBuffer = host.read(packageJsonPath); 75 | if (!packageJsonBuffer) { 76 | throw new SchematicsException(`Could not find package.json in '${packageJsonPath}'`); 77 | } 78 | 79 | const packageJson: object = JSON.parse(packageJsonBuffer.toString('utf8')); 80 | const updatedPackageJson = { 81 | ...packageJson, 82 | schematics: './schematics/collection.json', 83 | 'ng-update': { 84 | migrations: './schematics/migrations.json', 85 | packageGroup: [], 86 | }, 87 | }; 88 | 89 | host.overwrite(packageJsonPath, JSON.stringify(updatedPackageJson, null, 2)); 90 | 91 | return noop(); 92 | } 93 | -------------------------------------------------------------------------------- /src/ng-generate/add-schematic/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { SchematicTestRunner } from '@angular-devkit/schematics/testing'; 3 | import * as path from 'path'; 4 | import { PathLike } from 'fs'; 5 | import { InitSchematicsProjectOptions } from './index'; 6 | 7 | const testCollectionPath = path.join(__dirname, '../../collection.json'); 8 | 9 | describe('ng-generate', () => { 10 | let tree: Tree; 11 | let runner: SchematicTestRunner; 12 | 13 | const angularJson = { 14 | version: 1, 15 | projects: { 16 | ui: { 17 | projectType: 'library', 18 | root: 'projects/ui', 19 | sourceRoot: 'projects/ui/src', 20 | architect: { 21 | build: { 22 | builder: '@angular-devkit/build-angular:ng-packagr', 23 | options: { 24 | tsConfig: 'projects/ui/tsconfig.lib.json', 25 | project: 'projects/ui/ng-package.json', 26 | }, 27 | configurations: { 28 | production: { 29 | tsConfig: 'projects/ui/tsconfig.lib.prod.json', 30 | }, 31 | }, 32 | }, 33 | }, 34 | }, 35 | defaultProject: 'ui', 36 | }, 37 | }; 38 | 39 | const collectionJson = { 40 | schematics: {}, 41 | }; 42 | 43 | const packageJson = { 44 | schematics: './schematics/collection.json', 45 | }; 46 | 47 | const projectPath = 'projects/ui'; 48 | const schematicsPath = `${projectPath}/schematics`; 49 | 50 | beforeEach(async () => { 51 | runner = new SchematicTestRunner('schematics', testCollectionPath); 52 | tree = Tree.empty(); 53 | tree.create(path.join(projectPath, 'package.json'), JSON.stringify(packageJson)); 54 | }); 55 | 56 | it('should generate files', async () => { 57 | tree.create('angular.json', JSON.stringify(angularJson)); 58 | tree.create(path.join(schematicsPath, 'collection.json'), JSON.stringify(collectionJson)); 59 | const options: InitSchematicsProjectOptions = { 60 | save: 'dependencies', 61 | path: schematicsPath as string, 62 | }; 63 | 64 | await runner.runSchematicAsync('add-schematic', options, tree).toPromise(); 65 | 66 | expect(tree.exists(path.join(schematicsPath, 'ng-add', 'index.ts'))).toBe(true); 67 | expect(tree.exists(path.join(schematicsPath, 'ng-add', 'index.spec.ts'))).toBe(true); 68 | }); 69 | 70 | it('should add collection.json entry', async () => { 71 | tree.create('angular.json', JSON.stringify(angularJson)); 72 | tree.create(path.join(schematicsPath, 'collection.json'), JSON.stringify(collectionJson)); 73 | await runner 74 | .runSchematicAsync( 75 | 'add-schematic', 76 | { 77 | project: 'ui', 78 | save: 'dependencies', 79 | path: schematicsPath as PathLike, 80 | }, 81 | tree 82 | ) 83 | .toPromise(); 84 | 85 | const testCollectionJson = JSON.parse( 86 | tree.read(path.join(projectPath, packageJson.schematics))?.toString('utf8')! 87 | ); 88 | const ngAddEntry = testCollectionJson.schematics['ng-add']; 89 | 90 | expect(ngAddEntry.save).toStrictEqual('dependencies'); 91 | expect(ngAddEntry.factory).toStrictEqual('ng-add/index#ngAdd'); 92 | }); 93 | }); 94 | -------------------------------------------------------------------------------- /smoke-tests/angular10/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:recommended", 3 | "rulesDirectory": [ 4 | "codelyzer" 5 | ], 6 | "rules": { 7 | "align": { 8 | "options": [ 9 | "parameters", 10 | "statements" 11 | ] 12 | }, 13 | "array-type": false, 14 | "arrow-return-shorthand": true, 15 | "curly": true, 16 | "deprecation": { 17 | "severity": "warning" 18 | }, 19 | "eofline": true, 20 | "import-blacklist": [ 21 | true, 22 | "rxjs/Rx" 23 | ], 24 | "import-spacing": true, 25 | "indent": { 26 | "options": [ 27 | "spaces" 28 | ] 29 | }, 30 | "max-classes-per-file": false, 31 | "max-line-length": [ 32 | true, 33 | 140 34 | ], 35 | "member-ordering": [ 36 | true, 37 | { 38 | "order": [ 39 | "static-field", 40 | "instance-field", 41 | "static-method", 42 | "instance-method" 43 | ] 44 | } 45 | ], 46 | "no-console": [ 47 | true, 48 | "debug", 49 | "info", 50 | "time", 51 | "timeEnd", 52 | "trace" 53 | ], 54 | "no-empty": false, 55 | "no-inferrable-types": [ 56 | true, 57 | "ignore-params" 58 | ], 59 | "no-non-null-assertion": true, 60 | "no-redundant-jsdoc": true, 61 | "no-switch-case-fall-through": true, 62 | "no-var-requires": false, 63 | "object-literal-key-quotes": [ 64 | true, 65 | "as-needed" 66 | ], 67 | "quotemark": [ 68 | true, 69 | "single" 70 | ], 71 | "semicolon": { 72 | "options": [ 73 | "always" 74 | ] 75 | }, 76 | "space-before-function-paren": { 77 | "options": { 78 | "anonymous": "never", 79 | "asyncArrow": "always", 80 | "constructor": "never", 81 | "method": "never", 82 | "named": "never" 83 | } 84 | }, 85 | "typedef": [ 86 | true, 87 | "call-signature" 88 | ], 89 | "typedef-whitespace": { 90 | "options": [ 91 | { 92 | "call-signature": "nospace", 93 | "index-signature": "nospace", 94 | "parameter": "nospace", 95 | "property-declaration": "nospace", 96 | "variable-declaration": "nospace" 97 | }, 98 | { 99 | "call-signature": "onespace", 100 | "index-signature": "onespace", 101 | "parameter": "onespace", 102 | "property-declaration": "onespace", 103 | "variable-declaration": "onespace" 104 | } 105 | ] 106 | }, 107 | "variable-name": { 108 | "options": [ 109 | "ban-keywords", 110 | "check-format", 111 | "allow-pascal-case" 112 | ] 113 | }, 114 | "whitespace": { 115 | "options": [ 116 | "check-branch", 117 | "check-decl", 118 | "check-operator", 119 | "check-separator", 120 | "check-type", 121 | "check-typecast" 122 | ] 123 | }, 124 | "component-class-suffix": true, 125 | "contextual-lifecycle": true, 126 | "directive-class-suffix": true, 127 | "no-conflicting-lifecycle": true, 128 | "no-host-metadata-property": true, 129 | "no-input-rename": true, 130 | "no-inputs-metadata-property": true, 131 | "no-output-native": true, 132 | "no-output-on-prefix": true, 133 | "no-output-rename": true, 134 | "no-outputs-metadata-property": true, 135 | "template-banana-in-box": true, 136 | "template-no-negated-async": true, 137 | "use-lifecycle-interface": true, 138 | "use-pipe-transform-interface": true 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /smoke-tests/angular11/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:recommended", 3 | "rulesDirectory": [ 4 | "codelyzer" 5 | ], 6 | "rules": { 7 | "align": { 8 | "options": [ 9 | "parameters", 10 | "statements" 11 | ] 12 | }, 13 | "array-type": false, 14 | "arrow-return-shorthand": true, 15 | "curly": true, 16 | "deprecation": { 17 | "severity": "warning" 18 | }, 19 | "eofline": true, 20 | "import-blacklist": [ 21 | true, 22 | "rxjs/Rx" 23 | ], 24 | "import-spacing": true, 25 | "indent": { 26 | "options": [ 27 | "spaces" 28 | ] 29 | }, 30 | "max-classes-per-file": false, 31 | "max-line-length": [ 32 | true, 33 | 140 34 | ], 35 | "member-ordering": [ 36 | true, 37 | { 38 | "order": [ 39 | "static-field", 40 | "instance-field", 41 | "static-method", 42 | "instance-method" 43 | ] 44 | } 45 | ], 46 | "no-console": [ 47 | true, 48 | "debug", 49 | "info", 50 | "time", 51 | "timeEnd", 52 | "trace" 53 | ], 54 | "no-empty": false, 55 | "no-inferrable-types": [ 56 | true, 57 | "ignore-params" 58 | ], 59 | "no-non-null-assertion": true, 60 | "no-redundant-jsdoc": true, 61 | "no-switch-case-fall-through": true, 62 | "no-var-requires": false, 63 | "object-literal-key-quotes": [ 64 | true, 65 | "as-needed" 66 | ], 67 | "quotemark": [ 68 | true, 69 | "single" 70 | ], 71 | "semicolon": { 72 | "options": [ 73 | "always" 74 | ] 75 | }, 76 | "space-before-function-paren": { 77 | "options": { 78 | "anonymous": "never", 79 | "asyncArrow": "always", 80 | "constructor": "never", 81 | "method": "never", 82 | "named": "never" 83 | } 84 | }, 85 | "typedef": [ 86 | true, 87 | "call-signature" 88 | ], 89 | "typedef-whitespace": { 90 | "options": [ 91 | { 92 | "call-signature": "nospace", 93 | "index-signature": "nospace", 94 | "parameter": "nospace", 95 | "property-declaration": "nospace", 96 | "variable-declaration": "nospace" 97 | }, 98 | { 99 | "call-signature": "onespace", 100 | "index-signature": "onespace", 101 | "parameter": "onespace", 102 | "property-declaration": "onespace", 103 | "variable-declaration": "onespace" 104 | } 105 | ] 106 | }, 107 | "variable-name": { 108 | "options": [ 109 | "ban-keywords", 110 | "check-format", 111 | "allow-pascal-case" 112 | ] 113 | }, 114 | "whitespace": { 115 | "options": [ 116 | "check-branch", 117 | "check-decl", 118 | "check-operator", 119 | "check-separator", 120 | "check-type", 121 | "check-typecast" 122 | ] 123 | }, 124 | "component-class-suffix": true, 125 | "contextual-lifecycle": true, 126 | "directive-class-suffix": true, 127 | "no-conflicting-lifecycle": true, 128 | "no-host-metadata-property": true, 129 | "no-input-rename": true, 130 | "no-inputs-metadata-property": true, 131 | "no-output-native": true, 132 | "no-output-on-prefix": true, 133 | "no-output-rename": true, 134 | "no-outputs-metadata-property": true, 135 | "template-banana-in-box": true, 136 | "template-no-negated-async": true, 137 | "use-lifecycle-interface": true, 138 | "use-pipe-transform-interface": true 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/ng-generate/generate-schematic/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { SchematicTestRunner } from '@angular-devkit/schematics/testing'; 3 | import * as path from 'path'; 4 | import { camelize } from '@angular-devkit/core/src/utils/strings'; 5 | import { GenerateSchematicOptions } from './index'; 6 | 7 | const testCollectionPath = path.join(__dirname, '../../collection.json'); 8 | 9 | describe('ng-generate', () => { 10 | let tree: Tree; 11 | let runner: SchematicTestRunner; 12 | 13 | const angularJson = { 14 | version: 1, 15 | projects: { 16 | ui: { 17 | projectType: 'library', 18 | root: 'projects/ui', 19 | sourceRoot: 'projects/ui/src', 20 | architect: { 21 | build: { 22 | builder: '@angular-devkit/build-angular:ng-packagr', 23 | options: { 24 | tsConfig: 'projects/ui/tsconfig.lib.json', 25 | project: 'projects/ui/ng-package.json', 26 | }, 27 | configurations: { 28 | production: { 29 | tsConfig: 'projects/ui/tsconfig.lib.prod.json', 30 | }, 31 | }, 32 | }, 33 | }, 34 | }, 35 | defaultProject: 'ui', 36 | }, 37 | }; 38 | 39 | const collectionJson = { 40 | schematics: {}, 41 | }; 42 | 43 | const packageJson = { 44 | schematics: './schematics/collection.json', 45 | }; 46 | 47 | const projectPath = 'projects/ui'; 48 | const schematicsPath = `${projectPath}/schematics`; 49 | 50 | const newSchematicName = 'new-generate-schematic'; 51 | 52 | beforeEach(async () => { 53 | runner = new SchematicTestRunner('schematics', testCollectionPath); 54 | tree = Tree.empty(); 55 | tree.create(path.join(projectPath, 'package.json'), JSON.stringify(packageJson)); 56 | }); 57 | 58 | it('should generate files', async () => { 59 | tree.create('angular.json', JSON.stringify(angularJson)); 60 | tree.create(path.join(schematicsPath, 'collection.json'), JSON.stringify(collectionJson)); 61 | const options: GenerateSchematicOptions = { 62 | name: newSchematicName, 63 | description: 'A description', 64 | path: `${schematicsPath}/ng-generate` as string, 65 | }; 66 | await runner.runSchematicAsync('generate-schematic', options, tree).toPromise(); 67 | 68 | const pathToNewSchematic = path.join(schematicsPath, 'ng-generate', newSchematicName); 69 | 70 | expect(tree.exists(path.join(pathToNewSchematic, 'index.ts'))).toBe(true); 71 | expect(tree.exists(path.join(pathToNewSchematic, 'index.spec.ts'))).toBe(true); 72 | }); 73 | 74 | it('should add collection.json entry', async () => { 75 | tree.create('angular.json', JSON.stringify(angularJson)); 76 | tree.create(path.join(schematicsPath, 'collection.json'), JSON.stringify(collectionJson)); 77 | const options: GenerateSchematicOptions = { 78 | name: newSchematicName, 79 | description: 'A description', 80 | path: `${schematicsPath}/ng-generate` as string, 81 | }; 82 | await runner.runSchematicAsync('generate-schematic', options, tree).toPromise(); 83 | 84 | const testCollectionJson = JSON.parse( 85 | tree.read(path.join(projectPath, packageJson.schematics))?.toString('utf8')! 86 | ); 87 | const schematicsEntry = testCollectionJson.schematics[newSchematicName]; 88 | 89 | expect(schematicsEntry.factory).toStrictEqual( 90 | `ng-generate/${newSchematicName}/index#${camelize(newSchematicName)}` 91 | ); 92 | }); 93 | }); 94 | -------------------------------------------------------------------------------- /src/ng-generate/update-schematic/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { SchematicTestRunner } from '@angular-devkit/schematics/testing'; 3 | import * as path from 'path'; 4 | import { camelize } from '@angular-devkit/core/src/utils/strings'; 5 | import { UpdateSchematicOptions } from "./index"; 6 | 7 | const testCollectionPath = path.join(__dirname, '../../collection.json'); 8 | 9 | describe('ng-update', () => { 10 | let tree: Tree; 11 | let runner: SchematicTestRunner; 12 | 13 | const angularJson = { 14 | version: 1, 15 | projects: { 16 | ui: { 17 | projectType: 'library', 18 | root: 'projects/ui', 19 | sourceRoot: 'projects/ui/src', 20 | architect: { 21 | build: { 22 | builder: '@angular-devkit/build-angular:ng-packagr', 23 | options: { 24 | tsConfig: 'projects/ui/tsconfig.lib.json', 25 | project: 'projects/ui/ng-package.json', 26 | }, 27 | configurations: { 28 | production: { 29 | tsConfig: 'projects/ui/tsconfig.lib.prod.json', 30 | }, 31 | }, 32 | }, 33 | }, 34 | }, 35 | defaultProject: 'ui', 36 | }, 37 | }; 38 | 39 | const migrationsJson = { 40 | schematics: {}, 41 | }; 42 | 43 | const packageJson = { 44 | 'ng-update': { 45 | migrations: './schematics/migrations.json', 46 | }, 47 | }; 48 | 49 | const projectPath = angularJson.projects.ui.root; 50 | const schematicsPath = `projects/ui/schematics`; 51 | 52 | const newSchematicName = 'new-update-schematic'; 53 | 54 | beforeEach(async () => { 55 | runner = new SchematicTestRunner('schematics', testCollectionPath); 56 | tree = Tree.empty(); 57 | tree.create(path.join(projectPath, 'package.json'), JSON.stringify(packageJson)); 58 | }); 59 | 60 | it('should generate files', async () => { 61 | tree.create('angular.json', JSON.stringify(angularJson)); 62 | tree.create(path.join(schematicsPath, 'migrations.json'), JSON.stringify(migrationsJson)); 63 | const options: UpdateSchematicOptions = { 64 | name: newSchematicName, 65 | version: '1.2.3', 66 | description: 'A description', 67 | path: `${schematicsPath}/ng-update` as string, 68 | }; 69 | await runner 70 | .runSchematicAsync( 71 | 'update-schematic', 72 | options, 73 | tree 74 | ) 75 | .toPromise(); 76 | 77 | const pathToNewSchematic = path.join(schematicsPath, 'ng-update', newSchematicName); 78 | 79 | expect(tree.exists(path.join(pathToNewSchematic, 'index.ts'))).toBe(true); 80 | expect(tree.exists(path.join(pathToNewSchematic, 'index.spec.ts'))).toBe(true); 81 | }); 82 | 83 | it('should add migrations.json entry', async () => { 84 | tree.create('angular.json', JSON.stringify(angularJson)); 85 | tree.create(path.join(schematicsPath, 'migrations.json'), JSON.stringify(migrationsJson)); 86 | const options: UpdateSchematicOptions = { 87 | name: newSchematicName, 88 | version: '1.2.3', 89 | description: 'A description', 90 | path: `${schematicsPath}/ng-update` as string, 91 | }; 92 | await runner 93 | .runSchematicAsync( 94 | 'update-schematic', 95 | options, 96 | tree 97 | ) 98 | .toPromise(); 99 | 100 | const testCollectionJson = JSON.parse( 101 | tree.read(path.join(projectPath, packageJson['ng-update'].migrations))?.toString('utf8')! 102 | ); 103 | const schematicsEntry = testCollectionJson.schematics[newSchematicName]; 104 | 105 | expect(schematicsEntry.factory).toStrictEqual( 106 | `ng-update/${newSchematicName}/index#${camelize(newSchematicName)}` 107 | ); 108 | }); 109 | }); 110 | -------------------------------------------------------------------------------- /src/ng-generate/init/index.spec.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { SchematicTestRunner } from '@angular-devkit/schematics/testing'; 3 | import * as path from 'path'; 4 | import { InitSchematicsProjectOptions } from './index'; 5 | 6 | const collectionPath = path.join(__dirname, '../../collection.json'); 7 | 8 | describe('ng-generate', () => { 9 | const angularJson = { 10 | version: 1, 11 | projects: { 12 | ui: { 13 | projectType: 'library', 14 | root: 'projects/ui', 15 | sourceRoot: 'projects/ui/src', 16 | architect: { 17 | build: { 18 | builder: '@angular-devkit/build-angular:ng-packagr', 19 | options: { 20 | tsConfig: 'projects/ui/tsconfig.lib.json', 21 | project: 'projects/ui/ng-package.json', 22 | }, 23 | configurations: { 24 | production: { 25 | tsConfig: 'projects/ui/tsconfig.lib.prod.json', 26 | }, 27 | }, 28 | }, 29 | }, 30 | }, 31 | defaultProject: 'ui', 32 | }, 33 | }; 34 | 35 | // @ts-ignore 36 | const angularJsonExpected = { 37 | version: 1, 38 | projects: { 39 | ui: { 40 | projectType: 'library', 41 | root: 'projects/ui', 42 | sourceRoot: 'projects/ui/src', 43 | architect: { 44 | build: { 45 | builder: '@angular-devkit/build-angular:ng-packagr', 46 | options: { 47 | tsConfig: 'projects/ui/tsconfig.lib.json', 48 | project: 'projects/ui/ng-package.json', 49 | }, 50 | configurations: { 51 | production: { 52 | tsConfig: 'projects/ui/tsconfig.lib.prod.json', 53 | }, 54 | }, 55 | }, 56 | 'build-schematics': { 57 | builder: 'ngx-cli-toolkit:build-schematics', 58 | }, 59 | }, 60 | }, 61 | defaultProject: 'ui', 62 | }, 63 | }; 64 | 65 | const packageJson = { 66 | name: 'ui', 67 | version: '0.0.1', 68 | peerDependencies: { 69 | '@angular/common': '^11.2.13', 70 | '@angular/core': '^11.2.13', 71 | }, 72 | dependencies: { 73 | tslib: '^2.0.0', 74 | }, 75 | }; 76 | 77 | const packageJsonExpected = { 78 | name: 'ui', 79 | version: '0.0.1', 80 | schematics: './schematics/collection.json', 81 | 'ng-update': { 82 | migrations: './schematics/migrations.json', 83 | packageGroup: [], 84 | }, 85 | peerDependencies: { 86 | '@angular/common': '^11.2.13', 87 | '@angular/core': '^11.2.13', 88 | }, 89 | dependencies: { 90 | tslib: '^2.0.0', 91 | }, 92 | }; 93 | 94 | let tree: Tree; 95 | let runner: SchematicTestRunner; 96 | let options: InitSchematicsProjectOptions; 97 | const projectUiPackageJsonPath = path.join(angularJson.projects.ui.root, 'package.json'); 98 | const schematicsDirectoryPath = path.join(angularJson.projects.ui.root, 'schematics'); 99 | 100 | beforeEach(async () => { 101 | runner = new SchematicTestRunner('schematics', collectionPath); 102 | tree = Tree.empty(); 103 | tree.create('angular.json', JSON.stringify(angularJson)); 104 | tree.create(projectUiPackageJsonPath, JSON.stringify(packageJson)); 105 | 106 | options = { 107 | path: `${angularJson.projects.ui.root}/subdirectory` as string, 108 | }; 109 | }); 110 | 111 | it('should create migrations.json', async () => { 112 | await runner.runSchematicAsync('init', options, tree).toPromise(); 113 | const expectedMigrationsJson = { 114 | $schema: '../../../node_modules/@angular-devkit/schematics/collection-schema.json', 115 | schematics: {}, 116 | }; 117 | const migrationJson = tree.read(path.join(schematicsDirectoryPath, 'migrations.json'))?.toString('utf8')!; 118 | expect(JSON.parse(migrationJson)).toMatchObject(expectedMigrationsJson); 119 | }); 120 | 121 | it('should create collection.json', async () => { 122 | await runner.runSchematicAsync('init', options, tree).toPromise(); 123 | const expectedCollectionJson = { 124 | $schema: '../../../node_modules/@angular-devkit/schematics/collection-schema.json', 125 | schematics: {}, 126 | }; 127 | 128 | const collectionJson = tree.read(path.join(schematicsDirectoryPath, 'collection.json'))?.toString('utf8')!; 129 | expect(JSON.parse(collectionJson)).toMatchObject(expectedCollectionJson); 130 | }); 131 | 132 | // todo: enable after the implementation of the builder itself 133 | // it('should add `build-schematics` builder to angukar.json', () => { 134 | // expect(JSON.parse(tree.read('angular.json')?.toString('utf8')!)).toStrictEqual(angularJsonExpected); 135 | // }); 136 | 137 | it('should add schematics entries in package.json', async () => { 138 | await runner.runSchematicAsync('init', options, tree).toPromise(); 139 | expect(JSON.parse(tree.read(projectUiPackageJsonPath)?.toString('utf8')!)).toStrictEqual(packageJsonExpected); 140 | }); 141 | 142 | it('should init project with the --project flag', async () => { 143 | let _options = { project: 'ui', path: '/' as string }; 144 | await runner.runSchematicAsync('init', _options, tree).toPromise(); 145 | expect(JSON.parse(tree.read(projectUiPackageJsonPath)?.toString('utf8')!)).toStrictEqual(packageJsonExpected); 146 | }); 147 | }); 148 | --------------------------------------------------------------------------------