├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ ├── ---docs.md │ ├── ---feature-request.md │ └── --bug-report.md └── workflows │ └── nodejs.yml ├── .gitignore ├── .npmignore ├── .prettierignore ├── .prettierrc ├── .vscode └── settings.json ├── CHANGELOG.md ├── DEVELOPMENT.md ├── LICENSE ├── README.md ├── assets ├── commitizen-vscode.png ├── commitizen.svg └── commitlint.svg ├── commitlint.config.js ├── package-lock.json ├── package.json ├── src ├── collection.json ├── migration.json ├── ng-add │ ├── defaults.ts │ ├── index.ts │ ├── index_spec.ts │ ├── schema.json │ └── schema.ts ├── ng-update │ ├── migration-01 │ │ ├── index.ts │ │ └── index_spec.ts │ ├── migration-02 │ │ ├── index.ts │ │ └── index_spec.ts │ ├── migration-03 │ │ ├── index.ts │ │ └── index_spec.ts │ └── migration-04 │ │ ├── index.ts │ │ └── index_spec.ts ├── test-utils.ts └── utils.ts └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = false 8 | insert_final_newline = false -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/---docs.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F4D7 Docs" 3 | about: Shortly describe how the docs will be improved 4 | title: "[docs]" 5 | labels: documentation 6 | assignees: '' 7 | 8 | --- 9 | 10 | # 📗 Docs 11 | 12 | ## Description 13 | 14 | A short description of the docs improvement 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/---feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F9E9 Feature request" 3 | about: Suggest an idea for this project 4 | title: "[feature]" 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | # 🧩 Feature 11 | 12 | ## What feature / part will be affected 13 | 14 | 15 | 16 | 17 | ```text 18 | - [ ] commitlint 19 | - [ ] husky 20 | - [ ] commitizen 21 | - [ ] standard-version 22 | ``` 23 | 24 | ## Description 25 | 26 | A clear and concise description of the feature 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/--bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41EBug Report" 3 | about: Report a bug 4 | title: "[bug]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | # 🐞 Bug report 11 | 12 | ## What feature is affected 13 | 14 | 15 | 16 | ```text 17 | - [ ] commitlint 18 | - [ ] husky 19 | - [ ] commitizen 20 | - [ ] standard-version 21 | ``` 22 | 23 | ## Description 24 | 25 | A clear and concise description of the problem... 26 | 27 | ## Reproduction 28 | 29 | Simply describe how to reproduce the bug situation 30 | 31 | ## Error message 32 | 33 |

34 |  
35 | 
36 | 37 | ## 🌍 Your Environment 38 | 39 |

40 |  
41 | 
42 | -------------------------------------------------------------------------------- /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | strategy: 11 | matrix: 12 | node-version: [12.x] 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Use Node.js ${{ matrix.node-version }} 17 | uses: actions/setup-node@v1 18 | with: 19 | node-version: ${{ matrix.node-version }} 20 | - run: npm install 21 | - run: npm test 22 | env: 23 | CI: true 24 | 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Outputs 2 | src/**/*.js 3 | src/**/*.js.map 4 | src/**/*.d.ts 5 | 6 | # IDEs 7 | .idea/ 8 | jsconfig.json 9 | 10 | # Misc 11 | node_modules/ 12 | npm-debug.log* 13 | yarn-error.log* 14 | 15 | # Mac OSX Finder files. 16 | **/.DS_Store 17 | .DS_Store 18 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Ignores TypeScript files, but keeps definitions. 2 | *.ts 3 | !*.d.ts 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.js 2 | *.js.map 3 | *.d.ts 4 | *.md 5 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "singleQuote": true, 4 | "trailingComma": "all" 5 | } 6 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.wordWrapColumn": 100, 3 | "editor.rulers": [100], 4 | "workbench.colorCustomizations": { 5 | "activityBar.background": "#f5ac4d", 6 | "activityBar.activeBorder": "#077947", 7 | "activityBar.foreground": "#15202b", 8 | "activityBar.inactiveForeground": "#15202b99", 9 | "activityBarBadge.background": "#077947", 10 | "activityBarBadge.foreground": "#e7e7e7", 11 | "titleBar.activeBackground": "#f2961d", 12 | "titleBar.inactiveBackground": "#f2961d99", 13 | "titleBar.activeForeground": "#15202b", 14 | "titleBar.inactiveForeground": "#15202b99", 15 | "statusBar.background": "#f2961d", 16 | "statusBarItem.hoverBackground": "#d07b0c", 17 | "statusBar.foreground": "#15202b", 18 | "activityBar.activeBackground": "#f5ac4d" 19 | }, 20 | "peacock.color": "#f2961d" 21 | } 22 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ## [2.3.0](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v2.2.0...v2.3.0) (2020-11-12) 6 | 7 | 8 | ### Features 9 | 10 | * update workspace and packages ([494a229](https://github.com/d-koppenhagen/ngx-semantic-version/commit/494a229da7ee79b2b51bae7b76c5c81eb20d7e6b)) 11 | 12 | ## [2.2.0](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v2.1.0...v2.2.0) (2020-08-20) 13 | 14 | 15 | ### Features 16 | 17 | * add mirgation for new package versions ([7fe59ae](https://github.com/d-koppenhagen/ngx-semantic-version/commit/7fe59ae83f01de646be3996ca25205b7ead93347)) 18 | * use latest tooling versions ([74d7d85](https://github.com/d-koppenhagen/ngx-semantic-version/commit/74d7d85b32f0a1b64548ada21b8fa46b12e4a1e0)) 19 | 20 | ## [2.1.0](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v2.0.0...v2.1.0) (2020-06-25) 21 | 22 | 23 | ### Features 24 | 25 | * add latest package versions ([659cedc](https://github.com/d-koppenhagen/ngx-semantic-version/commit/659cedc003ea07313353206bb95c87e6d341230c)) 26 | 27 | ## [2.0.0](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v2.0.0-beta.5...v2.0.0) (2020-06-25) 28 | 29 | ## [2.0.0-beta.5](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v2.0.0-beta.4...v2.0.0-beta.5) (2020-02-11) 30 | 31 | 32 | ### Features 33 | 34 | * update default versions ([27c77c5](https://github.com/d-koppenhagen/ngx-semantic-version/commit/27c77c5d0b76ac86cdf8a3c77b1334f522ccf50c)) 35 | 36 | ## [2.0.0-beta.4](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v2.0.0-beta.3...v2.0.0-beta.4) (2020-01-06) 37 | 38 | ## [2.0.0-beta.3](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v2.0.0-beta.2...v2.0.0-beta.3) (2019-12-11) 39 | 40 | 41 | ### Features 42 | 43 | * warning when missing 'repository' or 'bugs' fields ([25815db](https://github.com/d-koppenhagen/ngx-semantic-version/commit/25815dbfe94834fe9eb754905b8edf6e5fd8e88e)), closes [#20](https://github.com/d-koppenhagen/ngx-semantic-version/issues/20) 44 | 45 | ## [2.0.0-beta.2](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v2.0.0-beta.1...v2.0.0-beta.2) (2019-12-09) 46 | 47 | 48 | ### Bug Fixes 49 | 50 | * handle `standardVersionConfig` flag correctly ([6bb17ee](https://github.com/d-koppenhagen/ngx-semantic-version/commit/6bb17eef02313d922f3ad0201bf9c63d0141a2cd)) 51 | 52 | ## [2.0.0-beta.1](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v2.0.0-beta.0...v2.0.0-beta.1) (2019-12-06) 53 | 54 | 55 | ### Features 56 | 57 | * add package to devDependencies ([f129bb2](https://github.com/d-koppenhagen/ngx-semantic-version/commit/f129bb2712d7a6a41138b32c3440a81c13a6e15b)), closes [#18](https://github.com/d-koppenhagen/ngx-semantic-version/issues/18) 58 | 59 | ## [2.0.0-beta.0](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v2.0.0-alpha.1...v2.0.0-beta.0) (2019-11-21) 60 | 61 | ## [2.0.0-alpha.1](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v2.0.0-alpha.0...v2.0.0-alpha.1) (2019-11-18) 62 | 63 | 64 | ### ⚠ BREAKING CHANGES 65 | 66 | * `--force` will override existing files if there is a conflict. `--overrideConfigurations` can be used now to override conflicts within existing configuration parameters 67 | 68 | ### Features 69 | 70 | * introduce `--standardVersionConfig` param ([94e84c5](https://github.com/d-koppenhagen/ngx-semantic-version/commit/94e84c5b44cac887af6021508fb9ea2f8b4cb75e)) 71 | * introduce `overrideConfigurations` param ([f91f92e](https://github.com/d-koppenhagen/ngx-semantic-version/commit/f91f92eebffdfe2683c5ac6378f93810261b6d53)) 72 | 73 | ## [2.0.0-alpha.0](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v1.2.1...v2.0.0-alpha.0) (2019-11-15) 74 | 75 | 76 | ### ⚠ BREAKING CHANGES 77 | 78 | * `--husky=`, `--commitizen=`, `--standardVersion=` are not supported anymore| use `--packages=commitizen,husky,commitlint,standard-version` instead. 79 | By default all packaged will be added. 80 | 81 | ### Features 82 | 83 | * provide packages from x-promt ([3390ff0](https://github.com/d-koppenhagen/ngx-semantic-version/commit/3390ff04d803fd8829c530c0a86c2cb0f528dcb3)), closes [#11](https://github.com/d-koppenhagen/ngx-semantic-version/issues/11) 84 | 85 | ### [1.2.1](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v1.2.0...v1.2.1) (2019-11-06) 86 | 87 | 88 | ### Bug Fixes 89 | 90 | * add missing schema validation ([6554157](https://github.com/d-koppenhagen/ngx-semantic-version/commit/65541576ff55e1c857a074811fe2cefd84bd5de9)) 91 | 92 | ## [1.2.0](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v1.1.1...v1.2.0) (2019-11-02) 93 | 94 | 95 | ### Features 96 | 97 | * adds `--force` param ([60f4910](https://github.com/d-koppenhagen/ngx-semantic-version/commit/60f4910d3579453c3cb581fe6362f3f57184e8d3)), closes [#12](https://github.com/d-koppenhagen/ngx-semantic-version/issues/12) 98 | 99 | ### [1.1.1](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v1.1.0...v1.1.1) (2019-10-28) 100 | 101 | ## [1.1.0](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v1.0.0...v1.1.0) (2019-10-28) 102 | 103 | 104 | ### Features 105 | 106 | * **noisafno:** sfdafda ([093347a](https://github.com/d-koppenhagen/ngx-semantic-version/commit/093347a96141f03c8638a42d62e2fa42bd34c273)) 107 | * allow to specify an issue prefix ([fa1625f](https://github.com/d-koppenhagen/ngx-semantic-version/commit/fa1625fb8245edec79bf1c4eb7ffe861cf19a7b1)), closes [#10](https://github.com/d-koppenhagen/ngx-semantic-version/issues/10) 108 | 109 | 110 | ### Bug Fixes 111 | 112 | * **saf:** asf ([1ae998d](https://github.com/d-koppenhagen/ngx-semantic-version/commit/1ae998daffba0a20c8503bfc3fb4c3056db45d41)) 113 | 114 | ## [1.0.0](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v0.1.4...v1.0.0) (2019-10-21) 115 | 116 | ### [0.1.4](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v0.1.3...v0.1.4) (2019-10-21) 117 | 118 | ### [0.1.3](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v0.1.2...v0.1.3) (2019-10-21) 119 | 120 | 121 | ### Features 122 | 123 | * adds options to skip adding packages ([fc01543](https://github.com/d-koppenhagen/ngx-semantic-version/commit/fc01543f38548c79b2e99c8395f52446d9379004)), closes [#9](https://github.com/d-koppenhagen/ngx-semantic-version/issues/9) 124 | 125 | ### [0.1.2](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v0.1.1...v0.1.2) (2019-10-15) 126 | 127 | 128 | ### Bug Fixes 129 | 130 | * fixes migration ([9c18b44](https://github.com/d-koppenhagen/ngx-semantic-version/commit/9c18b441c653bd31593fbce5af7e39806e825698)) 131 | 132 | ### [0.1.1](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v0.1.0...v0.1.1) (2019-10-15) 133 | 134 | 135 | ### Bug Fixes 136 | 137 | * **ng-update:** use migration-02 within correct version ([4f971b7](https://github.com/d-koppenhagen/ngx-semantic-version/commit/4f971b78da89b67ef37fdc76aef604891b19c248)) 138 | 139 | ## [0.1.0](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v0.0.4...v0.1.0) (2019-10-15) 140 | 141 | 142 | ### ⚠ BREAKING CHANGES 143 | 144 | * **commitlint:** The default commitlint configuration was changed to `@commitlint/config-conventional` (before: `@commitlint/config-angular` 145 | 146 | ### Features 147 | 148 | * **commitlint:** use @commitlint/config-conventional ([6de7705](https://github.com/d-koppenhagen/ngx-semantic-version/commit/6de7705c4709cc80ed7e469aded1600af432ba58)), closes [#8](https://github.com/d-koppenhagen/ngx-semantic-version/issues/8) 149 | 150 | ### [0.0.4](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v0.0.3...v0.0.4) (2019-10-15) 151 | 152 | 153 | ### Bug Fixes 154 | 155 | * **ng-update:** proceed update within correct version ([5b72d45](https://github.com/d-koppenhagen/ngx-semantic-version/commit/5b72d456109ff898ae09387d48b207ea305ca017)) 156 | 157 | ### [0.0.3](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v0.0.1...v0.0.3) (2019-10-15) 158 | 159 | 160 | ### Features 161 | 162 | * **commitizen:** adds commitizen as dependncy and husky hook ([87f316e](https://github.com/d-koppenhagen/ngx-semantic-version/commit/87f316e68358ba101adfd7b22b4ebd12f456e5fa)) 163 | * adds ng-update support ([04ea589](https://github.com/d-koppenhagen/ngx-semantic-version/commit/04ea589cea711759ce5b90f4f461871c7f5f513c)), closes [#1](https://github.com/d-koppenhagen/ngx-semantic-version/issues/1) 164 | * removes `prepare-commit-msg` husky hook ([38d4a58](https://github.com/d-koppenhagen/ngx-semantic-version/commit/38d4a58eb32ce6e29b7c3ce27be192973fd19c38)) 165 | 166 | ### [0.0.2](https://github.com/d-koppenhagen/ngx-semantic-version/compare/v0.0.1...v0.0.2) (2019-10-13) 167 | 168 | 169 | ### Features 170 | 171 | * **commitizen:** adds commitizen as dependncy and husky hook ([87f316e](https://github.com/d-koppenhagen/ngx-semantic-version/commit/87f316e68358ba101adfd7b22b4ebd12f456e5fa)) 172 | 173 | ### 0.0.1 (2019-10-12) 174 | 175 | 176 | ### Features 177 | 178 | * adds initial version for ng add af00610 179 | -------------------------------------------------------------------------------- /DEVELOPMENT.md: -------------------------------------------------------------------------------- 1 | # ngx-semantic-version 2 | 3 | ## Development 4 | 5 | ### Testing 6 | 7 | To test locally, install `@angular-devkit/schematics-cli` globally and use the `schematics` command line tool. That tool acts the same as the `generate` command of the Angular CLI, but also has a debug mode. 8 | 9 | Check the documentation with 10 | 11 | ```bash 12 | schematics --help 13 | ``` 14 | 15 | ### Unit Testing 16 | 17 | `npm run test` will run the unit tests, using Jasmine as a runner and test framework. 18 | 19 | ### Publishing 20 | 21 | To publish, simply do: 22 | 23 | ```bash 24 | npm publish 25 | ``` 26 | 27 | That's it! 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Danny Koppenhagen 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ngx-semantic-version 2 | 3 | [![npm](https://img.shields.io/npm/v/ngx-semantic-version.svg)](https://www.npmjs.com/package/ngx-semantic-version) 4 | [![Dependency Status](https://david-dm.org/d-koppenhagen/ngx-semantic-version.svg)](https://david-dm.org/d-koppenhagen/ngx-semantic-version) 5 | [![devDependency Status](https://david-dm.org/d-koppenhagen/ngx-semantic-version/dev-status.svg)](https://david-dm.org/d-koppenhagen/ngx-semantic-version?type=dev) 6 | [![npm](https://img.shields.io/npm/l/ngx-semantic-version.svg)](https://www.npmjs.com/package/ngx-semantic-version) 7 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com) 8 | [![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.svg?v=102)](https://github.com/ellerbrock/open-source-badge/) 9 | 10 | [![ngx-semantic-version](https://img.shields.io/badge/%F0%9F%92%8E-ngx--semantic--version-blueviolet)](https://www.npmjs.com/package/ngx-semantic-version) 11 | [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)](https://github.com/semantic-release/semantic-release) 12 | [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) 13 | [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg)](https://conventionalcommits.org) 14 | 15 | [![npm](https://img.shields.io/npm/dw/ngx-semantic-version.svg)](https://www.npmjs.com/package/ngx-semantic-version) 16 | [![npm](https://img.shields.io/npm/dm/ngx-semantic-version.svg)](https://www.npmjs.com/package/ngx-semantic-version) 17 | [![npm](https://img.shields.io/npm/dy/ngx-semantic-version.svg)](https://www.npmjs.com/package/ngx-semantic-version) 18 | [![npm](https://img.shields.io/npm/dt/ngx-semantic-version.svg)](https://www.npmjs.com/package/ngx-semantic-version) 19 | 20 | [![GitHub forks](https://img.shields.io/github/forks/d-koppenhagen/ngx-semantic-version.svg?style=social&label=Fork)](https://github.com/d-koppenhagen/ngx-semantic-version/fork) [![GitHub stars](https://img.shields.io/github/stars/d-koppenhagen/ngx-semantic-version.svg?style=social&label=Star)](https://github.com/d-koppenhagen/ngx-semantic-version) 21 | 22 | Buy Me A Coffee 23 | 24 | _ngx-semantic-version_ is an Angular Schematic that will add and configure _commitlint_, _commitizen_, _husky_ and _standard-version_ for creating commit messages in the _conventional commit_ format and automate your release and Changelog generation respecting _semver_. 25 | 26 | The schematic will configure the following packages / services: 27 | 28 | - [commitlint](https://commitlint.js.org) 29 | - [husky](https://www.npmjs.com/package/husky) 30 | - [commitizen](https://www.npmjs.com/package/commitizen) 31 | - [standard-version](https://www.npmjs.com/package/standard-version) 32 | 33 | ## How to use 34 | 35 | ### Add the schematics to your project 36 | 37 | - Angular CLI >= 9.x.x 38 | ```bash 39 | ng add ngx-semantic-version 40 | ``` 41 | 42 | - Angular CLI 8.x.x | [docs](https://github.com/d-koppenhagen/ngx-semantic-version/tree/v1.2.1) 43 | 44 | ```bash 45 | ng add ngx-semantic-version@1 46 | ``` 47 | 48 | > if you have already configured one of the modules and you want to use the configuration provided 49 | by ngx-semantic-version, you can use `--overrideConfigurations` to override an existing configuration. 50 | Please check the changes carefully using git after running with `--overrideConfigurations`. 51 | 52 | #### available options 53 | 54 | | Flag | Description | 55 | | ------------------------- | ------------------------------------------------------------------ | 56 | | `--skipInstall` | Skips installing new `node_modules` after modifying `package.json` | 57 | | `--packages="commitlint, husky, commitizen, standard-version"` | Define the packages to add. | 58 | | `--issuePrefix=""`| Configure an issue prefix that should be checked by each commit | 59 | | `--overrideConfigurations`| Do override existing configuration parameters if necesary | 60 | | `--force` | Ignore errors and override already existing files | 61 | | `--standardVersionConfig` | Add the base configuration for _standard-version_ to `package.json` for adjusting it later| 62 | 63 | #### force including references by configuring an issue prefix 64 | 65 | When adding the schematic using e.g. `--issuePrefix="PREFIX-"`, commitlint will be configured to use 66 | the defined issue prefix in commit messages. Therefore the following configuration will be added 67 | to the `commitlint.config.js` configuration file: 68 | 69 | ```js 70 | module.exports = { 71 | // ... 72 | rules: { 73 | 'references-empty': [2, 'never'], 74 | }, 75 | parserPreset: { 76 | parserOpts: { 77 | issuePrefixes: ['PREFIX-'], 78 | }, 79 | }, 80 | }; 81 | ``` 82 | 83 | This is very helpful if you want to force the users to include always an reference to your issue 84 | tracking system (in the example above the issue racking system will use this style: `PREFIX-1242`). 85 | 86 | > The line `'references-empty': [2, 'never'],` will tell commitlint that an issue reference has 87 | to be included always. You can change the value of `2` to `1` to just warn the user instead of 88 | rejecting the commit messages. All configuration option are described in the official 89 | [docs of commitlint](https://commitlint.js.org/#/reference-rules). 90 | 91 | The prefix will be also configured for usage within _standard-version_ in your `package.json`: 92 | 93 | ```json 94 | // ... 95 | "standard-version": { 96 | "issuePrefixes": ["PREFIX-"], 97 | } 98 | ``` 99 | 100 | > [You can specify further options for _standard-version_](https://github.com/conventional-changelog/conventional-changelog-config-spec/blob/master/versions/2.1.0/README.md 101 | ) that will be uses for the generated links 102 | in `CHANGELOG.md` generation. You can adjust the configuration block `standard-version` in your 103 | `package.json` and adjusts the options to satisfy your needs. 104 | 105 | ### Update the schematics 106 | 107 | Run `ng update` to see if an update is available. 108 | To proceed running an update of _ngx-semantic-version_, run the following command: 109 | 110 | ```bash 111 | ng update ngx-semantic-version 112 | ``` 113 | 114 | > Updates will may touch your existing configuration. Please check the changes using git to verify the changes. 115 | 116 | ## What's included 117 | 118 | ### [commitlint](https://commitlint.js.org) 119 | 120 | Commitlint will lint your commit message and check it against some common rules. 121 | It will throw an error if the messages doesn't match with the rules. 122 | This schematic will install the ruleset [`@commitlint/config-conventional`](https://npmjs.com/package/@commitlint/config-conventional) by default. 123 | 124 | After adding the schematics you will be able to adjust the rules for your 125 | personal needs by adjusting the added file `commitlint.config.js`. 126 | 127 | You can find a description of supported adjustments in the 128 | [official documentation](https://commitlint.js.org/#/reference-rules). 129 | 130 | ![commitizen cli](https://raw.githubusercontent.com/d-koppenhagen/ngx-semantic-version/master/assets/commitlint.svg?sanitize=true) 131 | 132 | ### [husky](https://www.npmjs.com/package/husky) 133 | 134 | Husky allows us to hook into the git lifecycle using nodejs. It is used by _ngx-semantic-version_ to check a commit message right before storing it by using _commitlint_. 135 | Therefore it will add this part to your `package.json`: 136 | 137 | ```json 138 | ... 139 | "husky": { 140 | "hooks": { 141 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 142 | } 143 | }, 144 | ``` 145 | 146 | Husky uses the environment variable `HUSKY_GIT_PARAMS` containing the current git message you entered and it will pass this through _commitlint_ so it can be evaluated. 147 | 148 | ### [commitizen](https://www.npmjs.com/package/commitizen) 149 | 150 | When having restrictions within the commit message text it can be difficult 151 | to always satisfy the appropriate format. Commitizen will help you to build a 152 | commit message always in the appropriate format by letting you configure the 153 | final message via an interactive cli. 154 | 155 | When _commitizen_ is installed globally (`npm i -g commitizen`) you can run it by 156 | executing `git cz`. 157 | 158 | ![commitizen cli](https://raw.githubusercontent.com/d-koppenhagen/ngx-semantic-version/master/assets/commitizen.svg?sanitize=true) 159 | 160 | Alternatively, if you are using NPM 5.2+ you can use npx instead of installing globally: `npx git-cz`. 161 | 162 | _ngx-semantic-version_ will configure _commitizen_ in your `package.json`, so that is will use the _conventional changelog_ as well: 163 | 164 | ```json 165 | ... 166 | "config": { 167 | "commitizen": { 168 | "path": "./node_modules/cz-conventional-changelog" 169 | } 170 | } 171 | ``` 172 | 173 | > Tip: if you are using vscode, you can add the plugin [Visual Studio Code Commitizen Support](https://marketplace.visualstudio.com/items?itemName=KnisterPeter.vscode-commitizen) which will let you build the commit message directly via vscode. 174 | > ![commitizen vscode plugin](https://raw.githubusercontent.com/d-koppenhagen/ngx-semantic-version/master/assets/commitizen-vscode.png) 175 | 176 | ### [standard-version](https://www.npmjs.com/package/standard-version) 177 | 178 | Standard-version will create and update your app/package version and automatically 179 | generate a `CHANGELOG.md` file and keep it up-to-date by using the git history. 180 | It will check the messages for keywords (thanks to commitlint) and determine which part 181 | of the semantic version will be increased. Furthermore it will add a tag for the version. 182 | 183 | After adding this schematic, you can simply release a new version by running `npm run release`. 184 | This will keep your `CHNAGELOG.md` up to date and releases a new version of your project. 185 | 186 | _ngx-semantic-version_ will configure a new script in your `package.json` that can be used for releasing a new version: 187 | 188 | ```json 189 | ... 190 | "scripts": { 191 | "release": "standard-version", 192 | }, 193 | ``` 194 | 195 | If you typically use `npm version` to cut a new release, do this instead: 196 | 197 | ```bash 198 | npm run release 199 | ``` 200 | 201 | You should also consider use one of the following commands: 202 | 203 | ```bash 204 | npm run release -- --first-release # create the initial release and create the `CHANGELOG.md` 205 | npm run release -- --prerelease # create a pre-release instead of a regular one 206 | npm run release -- --prerelease alpha # cut a new alpha release version 207 | ``` 208 | 209 | To adjust the temnplate of the generated `CHANGELOG.md` or the types of commits included in it you need to modify the _standard-version_ configuration. 210 | You can use `--standardVersionConfig` within _ngx-semantic-version_ to add the default configuration to your `package.json`. 211 | After that you can simply adjust the configuration to your needs: 212 | 213 | ```bash 214 | ng add ngx-semantic-version --standardVersionConfig 215 | ``` 216 | 217 | > Please note that your projects [`repository` field](https://docs.npmjs.com/files/package.json#repository) should be filled in your `package.json`, as _standard-version_ will use this information for creating the links in the `CHANGELOG.md` to your issues and releases. Check out also the [official documentation](https://www.npmjs.com/package/standard-version#release-as-a-pre-release) for further information. 218 | 219 | ## Default configurations 220 | 221 | Check out the file [src/ng-add/defaults.ts](./src/ng-add/defaults.ts) if you want to see what part will be added to your `package.json` and see the default values. 222 | 223 | ## Development 224 | 225 | For development hints, have a look at [DEVELOPMENT.md](./DEVELOPMENT.md) 226 | -------------------------------------------------------------------------------- /assets/commitizen-vscode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/d-koppenhagen/ngx-semantic-version/ea70c29ceeb5eb330d103cb7a83fe70f47653eec/assets/commitizen-vscode.png -------------------------------------------------------------------------------- /assets/commitizen.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 138 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | ~/dev/ngx-semantic-version (master ) ~/dev/ngx-semantic-version (master ) git add . ~/dev/ngx-semantic-version (master ) git add . ~/dev/ngx-semantic-version (master ) git add . ~/dev/ngx-semantic-version (master ) git add . ~/dev/ngx-semantic-version (master ) git add . ~/dev/ngx-semantic-version (master ) git add . ~/dev/ngx-semantic-version (master ) git add . ~/dev/ngx-semantic-version (master ) git add . ~/dev/ngx-semantic-version (master ) git add . ~/dev/ngx-semantic-version (master ) git add . ~/dev/ngx-semantic-version (master ) ~/dev/ngx-semantic-version (master ) git add . ~/dev/ngx-semantic-version (master ) git add . ~/dev/ngx-semantic-version (master ) git add . ~/dev/ngx-semantic-version (master ) git add . ~/dev/ngx-semantic-version (master ) git cz ~/dev/ngx-semantic-version (master ) git cz ~/dev/ngx-semantic-version (master ) git cz cz-cli@4.0.3, cz-conventional-changelog@3.0.2? Select the type of change that you're committing: (Use arrow keys)❯ feat: A new feature fix: A bug fix improvement: An improvement to a current feature docs: Documentation only changes style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) refactor: A code change that neither fixes a bug nor adds a feature (Move up and down to reveal more choices) ? Select the type of change that you're committing: feat: A new feature ❯ fix: A bug fix improvement: An improvement to a current feature docs: Documentation only changes missing semi-colons, etc) refactor: A code change that neither fixes a bug nor adds a feature (Move up and down to reveal more choices) fix: A bug fix ❯ improvement: An improvement to a current feature ❯ docs: Documentation only changes ? Select the type of change that you're committing: docs: Documentation only changes ? What is the scope of this change (e.g. component or file name): (press enter to skip) ? What is the scope of this change (e.g. component or file name): (press enter to skip) ? Write a short, imperative tense description of the change (max 66 chars): (0) (1) u (2) up (3) upd (4) upda (5) updat (6) update (7) updates (7) updates (9) updates a (10) updates an (11) updates ani (12) updates anim (13) updates anima (14) updates animat (15) updates animate (16) updates animated (16) updates animated (18) updates animated i (19) updates animated im (20) updates animated ima (21) updates animated imag (22) updates animated image (23) updates animated images (23) updates animated images ? Provide a longer description of the change: (press enter to skip) ? Are there any breaking changes? (y/N) ? Are there any breaking changes? No ? Does this change affect any open issues? (y/N) ? Does this change affect any open issues? No Can't find Husky, skipping pre-commit hook You can reinstall it using 'npm install husky --save-dev' or delete this hookCan't find Husky, skipping prepare-commit-msg hookCan't find Husky, skipping commit-msg hookCan't find Husky, skipping post-commit hook[master 02f7e1c] docs: updates animated images 1 file changed, 91 insertions(+), 160 deletions(-) rewrite assets/commitizen.svg (93%)~/dev/ngx-semantic-version (master ) ~/dev/ngx-semantic-version (master ) 166 | -------------------------------------------------------------------------------- /assets/commitlint.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 56 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | ~/dev/ngx-semantic-version (master ) ~/dev/ngx-semantic-version (master ) e ~/dev/ngx-semantic-version (master ) ech ~/dev/ngx-semantic-version (master ) echo ~/dev/ngx-semantic-version (master ) echo 'foo ~/dev/ngx-semantic-version (master ) echo 'foo' ~/dev/ngx-semantic-version (master ) echo 'foo' | ~/dev/ngx-semantic-version (master ) echo 'foo' | npx ~/dev/ngx-semantic-version (master ) echo 'foo' | npx commi ~/dev/ngx-semantic-version (master ) echo 'foo' | npx commitli ~/dev/ngx-semantic-version (master ) echo 'foo' | npx commitlint ~/dev/ngx-semantic-version (master ) echo 'foo' | npx commitlint ~/dev/ngx-semantic-version (master ) echo 'foo' | npx commitlint input: foo subject may not be empty [subject-empty] type may not be empty [type-empty] found 2 problems, 0 warningsⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint~/dev/ngx-semantic-version (master ) 84 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * To check all configuration options, please visit 3 | * https://commitlint.js.org/#/reference-rules 4 | */ 5 | module.exports = { 6 | extends: ['@commitlint/config-conventional'], 7 | }; 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-semantic-version", 3 | "version": "2.3.0", 4 | "description": "This schematic will add commitlint, husky, commitizen and standard-version configurations", 5 | "scripts": { 6 | "release": "standard-version", 7 | "build": "tsc -p tsconfig.json", 8 | "build:watch": "tsc -p tsconfig.json --watch", 9 | "test": "npm run build && jasmine **/*_spec.js", 10 | "prepublish": "npm run build" 11 | }, 12 | "keywords": [ 13 | "schematics", 14 | "commitlint", 15 | "commitizen", 16 | "husky", 17 | "standard-version", 18 | "changelog", 19 | "semver", 20 | "angular", 21 | "angular-cli" 22 | ], 23 | "author": "Danny Koppenhagen (https://d-koppenhagen.de)", 24 | "homepage": "https://github.com/d-koppenhagen/ngx-semantic-version", 25 | "repository": { 26 | "type": "git", 27 | "url": "git+https://github.com/d-koppenhagen/ngx-semantic-version.git" 28 | }, 29 | "bugs": { 30 | "url": "https://github.com/d-koppenhagen/ngx-semantic-version/issues", 31 | "email": "mail@d-koppenhagen.de" 32 | }, 33 | "license": "MIT", 34 | "schematics": "./src/collection.json", 35 | "ng-add": { 36 | "save": "devDependencies" 37 | }, 38 | "ng-update": { 39 | "migrations": "./src/migration.json" 40 | }, 41 | "dependencies": { 42 | "@angular-devkit/core": "^11.0.0", 43 | "@angular-devkit/schematics": "^11.0.0", 44 | "typescript": "~4.0.5" 45 | }, 46 | "peerDependencies": { 47 | "@angular/cli": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0-0" 48 | }, 49 | "devDependencies": { 50 | "@commitlint/cli": "^11.0.0", 51 | "@commitlint/config-conventional": "^11.0.0", 52 | "@schematics/angular": "^11.0.0", 53 | "@types/jasmine": "~3.6.1", 54 | "@types/node": "^14.0.14", 55 | "commitizen": "^4.2.2", 56 | "cz-conventional-changelog": "^3.3.0", 57 | "husky": "^4.3.0", 58 | "jasmine": "^3.6.1", 59 | "standard-version": "^9.0.0" 60 | }, 61 | "husky": { 62 | "hooks": { 63 | "pre-push": "npm test", 64 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 65 | } 66 | }, 67 | "config": { 68 | "commitizen": { 69 | "path": "./node_modules/cz-conventional-changelog" 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/collection.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json", 3 | "schematics": { 4 | "ng-add": { 5 | "description": "This scematic will add and configure commitlint, husky, commitizen and standard-version configuration", 6 | "factory": "./ng-add/index", 7 | "schema": "./ng-add/schema.json" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/migration.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../node_modules/@angular-devkit/schematics/collection-schema.json", 3 | "schematics": { 4 | "migration-01": { 5 | "description": "Updates to Version 0.0.4", 6 | "version": "0.0.4", 7 | "factory": "./ng-update/migration-01/index" 8 | }, 9 | "migration-02": { 10 | "description": "Updates to Version 0.1.0", 11 | "version": "0.1.0", 12 | "factory": "./ng-update/migration-02/index" 13 | }, 14 | "migration-03": { 15 | "description": "Updates to Version 2", 16 | "version": "2", 17 | "factory": "./ng-update/migration-03/index" 18 | }, 19 | "migration-04": { 20 | "description": "Updates to latest tooling versions", 21 | "version": "2.2", 22 | "factory": "./ng-update/migration-04/index" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/ng-add/defaults.ts: -------------------------------------------------------------------------------- 1 | export const DEV_DEPS_TO_ADD = { 2 | commitlint: { 3 | '@commitlint/cli': '^11.0.0', 4 | '@commitlint/config-conventional': '^11.0.0', 5 | }, 6 | commitizen: { 7 | commitizen: '^4.2.2', 8 | 'cz-conventional-changelog': '^3.3.0', 9 | }, 10 | husky: { 11 | husky: '^4.3.0', 12 | }, 13 | 'standard-version': { 14 | 'standard-version': '^9.0.0', 15 | }, 16 | }; 17 | 18 | export const HUSKY_DEFAULTS = { 19 | hooks: { 20 | 'commit-msg': 'commitlint -E HUSKY_GIT_PARAMS', 21 | }, 22 | }; 23 | 24 | export const COMMITIZEN_DEFAULTS = { 25 | commitizen: { 26 | path: './node_modules/cz-conventional-changelog', 27 | }, 28 | }; 29 | 30 | export const STANDARD_VERSION_DEFAULTS = { 31 | types: [ 32 | { 33 | type: 'feat', 34 | section: 'Features', 35 | }, 36 | { 37 | type: 'fix', 38 | section: 'Bug Fixes', 39 | }, 40 | { 41 | type: 'chore', 42 | hidden: true, 43 | }, 44 | { 45 | type: 'ci', 46 | hidden: true, 47 | }, 48 | { 49 | type: 'build', 50 | hidden: true, 51 | }, 52 | { 53 | type: 'docs', 54 | hidden: true, 55 | }, 56 | { 57 | type: 'style', 58 | hidden: true, 59 | }, 60 | { 61 | type: 'refactor', 62 | hidden: true, 63 | }, 64 | { 65 | type: 'perf', 66 | hidden: true, 67 | }, 68 | { 69 | type: 'test', 70 | hidden: true, 71 | }, 72 | ], 73 | header: 'Changelog', 74 | commitUrlFormat: '{{host}}/{{owner}}/{{repository}}/commit/{{hash}}', 75 | compareUrlFormat: '{{host}}/{{owner}}/{{repository}}/compare/{{previousTag}}...{{currentTag}}', 76 | issueUrlFormat: '{{host}}/{{owner}}/{{repository}}/issues/{{id}}', 77 | userUrlFormat: '{{host}}/{{user}}', 78 | releaseCommitMessageFormat: 'chore(release): {{currentTag}}', 79 | issuePrefixes: ['#'], 80 | }; 81 | -------------------------------------------------------------------------------- /src/ng-add/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Rule, 3 | SchematicContext, 4 | Tree, 5 | apply, 6 | chain, 7 | mergeWith, 8 | template, 9 | url, 10 | noop, 11 | FileEntry, 12 | forEach, 13 | } from '@angular-devkit/schematics'; 14 | import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks'; 15 | 16 | import { NgxSemanticVersion as Schema, PackageName } from './schema'; 17 | import { 18 | getPackageJson, 19 | overwritePackageJson, 20 | getMergedPackageJsonConfig, 21 | PackageJsonConfigPart, 22 | } from '../utils'; 23 | import { 24 | DEV_DEPS_TO_ADD, 25 | HUSKY_DEFAULTS, 26 | COMMITIZEN_DEFAULTS, 27 | STANDARD_VERSION_DEFAULTS, 28 | } from './defaults'; 29 | 30 | export default (options: Schema): Rule => { 31 | const addStandardVersionConfigToPackageJson = 32 | (options.issuePrefix && options.issuePrefix !== '') || options.standardVersionConfig; 33 | return chain([ 34 | addDependencies(options), 35 | options.packages.includes('commitlint') ? addCommitlintConfigFile(options) : noop(), 36 | options.packages.includes('husky') ? addHuskyConfig(options) : noop(), 37 | options.packages.includes('commitizen') ? addCommitizenConfig(options) : noop(), 38 | options.packages.includes('standard-version') ? addNpmRunScript(options) : noop(), 39 | options.packages.includes('standard-version') && addStandardVersionConfigToPackageJson 40 | ? standardVersionConfig(options) 41 | : noop(), 42 | options.skipInstall ? noop() : installDependencies, 43 | ]); 44 | }; 45 | 46 | const addDependencies = (options: Schema) => (tree: Tree, context: SchematicContext) => { 47 | context.logger.info('Added npm packages as dev dependencies'); 48 | const packageJson = getPackageJson(tree); 49 | 50 | let devDepsToAdd: PackageJsonConfigPart = {}; 51 | 52 | const map = new Map([ 53 | ['commitlint', DEV_DEPS_TO_ADD], 54 | ['commitizen', DEV_DEPS_TO_ADD], 55 | ['husky', DEV_DEPS_TO_ADD], 56 | ['standard-version', DEV_DEPS_TO_ADD], 57 | ]); 58 | 59 | for (const [key, value] of map.entries()) { 60 | const searchKey = key as PackageName; 61 | if (options.packages.includes(searchKey)) { 62 | devDepsToAdd = { 63 | ...devDepsToAdd, 64 | ...value[searchKey], 65 | }; 66 | } else { 67 | context.logger.info(`- Skips adding ${searchKey}`); 68 | } 69 | } 70 | 71 | packageJson.devDependencies = { 72 | ...packageJson.devDependencies, 73 | ...devDepsToAdd, 74 | }; 75 | 76 | overwritePackageJson(tree, packageJson); 77 | }; 78 | 79 | const addNpmRunScript = (options: Schema) => (tree: Tree, context: SchematicContext) => { 80 | context.logger.info('Added npm script for release'); 81 | const packageJson = getPackageJson(tree); 82 | 83 | if (!packageJson.repository && !packageJson.bugs) { 84 | context.logger.warn( 85 | `Neither 'repository' or 'bugs' field found in your 'package.json'. To referencs your releases and issues correctly, you should add the fiels. 86 | Check out: https://github.com/d-koppenhagen/ngx-semantic-version/wiki/FAQ for further information`, 87 | ); 88 | } 89 | 90 | const configBefore = { ...packageJson.scripts }; 91 | const configNew = { release: 'standard-version' }; 92 | 93 | packageJson.scripts = getMergedPackageJsonConfig( 94 | configBefore, 95 | configNew, 96 | options.overrideConfigurations, 97 | ); 98 | overwritePackageJson(tree, packageJson); 99 | }; 100 | 101 | const addHuskyConfig = (options: Schema) => (tree: Tree, context: SchematicContext) => { 102 | addConfig(tree, context, options, 'husky', 'husky', HUSKY_DEFAULTS); 103 | }; 104 | 105 | const addCommitizenConfig = (options: Schema) => (tree: Tree, context: SchematicContext) => { 106 | addConfig(tree, context, options, 'commitizen', 'config', COMMITIZEN_DEFAULTS); 107 | }; 108 | 109 | const standardVersionConfig = (options: Schema) => (tree: Tree, context: SchematicContext) => { 110 | let defaults = {}; 111 | if (options.standardVersionConfig) defaults = { ...STANDARD_VERSION_DEFAULTS }; 112 | defaults = { ...defaults, issuePrefixes: [options.issuePrefix || '#'] }; 113 | addConfig(tree, context, options, 'standard-version', 'standard-version', defaults); 114 | }; 115 | 116 | function addConfig( 117 | tree: Tree, 118 | context: SchematicContext, 119 | options: Schema, 120 | what: string, 121 | getPackageJsonPart: 'husky' | 'config' | 'standard-version', 122 | defaults: object, 123 | ) { 124 | context.logger.info('Added ' + what + ' configuration'); 125 | const packageJson = getPackageJson(tree); 126 | const configBefore = { ...packageJson[getPackageJsonPart] }; 127 | packageJson[getPackageJsonPart] = getMergedPackageJsonConfig( 128 | configBefore, 129 | defaults, 130 | options.overrideConfigurations, 131 | ); 132 | overwritePackageJson(tree, packageJson); 133 | } 134 | 135 | const addCommitlintConfigFile = (options: Schema) => (tree: Tree, context: SchematicContext) => { 136 | context.logger.info('Added commitlint configuration file'); 137 | const sourceTemplates = url('./files'); 138 | const sourceParameterizedTemplates = apply(sourceTemplates, [ 139 | template({ 140 | issuePrefix: options.issuePrefix || '', 141 | }), 142 | forEach((fileEntry: FileEntry) => { 143 | // override existing files if force flag has been set 144 | if (options.overrideConfigurations && tree.exists(fileEntry.path)) { 145 | tree.overwrite(fileEntry.path, fileEntry.content); 146 | return null; 147 | } 148 | return fileEntry; 149 | }), 150 | ]); 151 | return mergeWith(sourceParameterizedTemplates)(tree, context); 152 | }; 153 | 154 | const installDependencies = () => (_tree: Tree, context: SchematicContext) => { 155 | context.logger.info('Installs npm dependencies'); 156 | context.addTask(new NodePackageInstallTask()); 157 | }; 158 | -------------------------------------------------------------------------------- /src/ng-add/index_spec.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'path'; 2 | import { HostTree } from '@angular-devkit/schematics'; 3 | import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; 4 | import { getFileContent } from '@schematics/angular/utility/test'; 5 | import { NgxSemanticVersion as Schema } from './schema'; 6 | import { setupProject } from '../test-utils'; 7 | import { STANDARD_VERSION_DEFAULTS } from './defaults'; 8 | 9 | const PACKAGE_JSON_PATH = '/package.json'; 10 | const COMMITLINT_PATH = '/commitlint.config.js'; 11 | 12 | describe('ngx-semantic-version schematic', () => { 13 | const schematicRunner = new SchematicTestRunner( 14 | 'ngx-semantic-version', 15 | resolve(__dirname, '../collection.json'), 16 | ); 17 | const project = 'foo'; 18 | const defaultOptions: Schema = { 19 | skipInstall: false, 20 | packages: ['commitlint', 'commitizen', 'husky', 'standard-version'], 21 | }; 22 | 23 | let appTree: UnitTestTree; 24 | 25 | beforeEach(async () => { 26 | appTree = new UnitTestTree(new HostTree()); 27 | appTree = await setupProject(appTree, schematicRunner, project); 28 | }); 29 | 30 | describe('when using the default options', () => { 31 | beforeEach(async () => { 32 | appTree = await schematicRunner 33 | .runSchematicAsync('ng-add', defaultOptions, appTree) 34 | .toPromise(); 35 | }); 36 | 37 | it(`should add the 'commitlint' configuration file`, () => { 38 | expect(appTree.files).toContain(COMMITLINT_PATH); 39 | const fileContent = getFileContent(appTree, COMMITLINT_PATH); 40 | expect(fileContent).not.toMatch(/rules: {\s+\'references-empty\': \[2, \'never\'\].\s+\},/g); 41 | expect(fileContent).not.toMatch( 42 | /parserPreset: {\s+parserOpts: \{\s+issuePrefixes: \[\'\PREFIX-\'\],\s+},\s+},/g, 43 | ); 44 | }); 45 | 46 | it(`should add all required dependencies to the 'package.json'`, () => { 47 | const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); 48 | const { devDependencies } = packageJson; 49 | expect(appTree.files).toContain(PACKAGE_JSON_PATH); 50 | expect(devDependencies['@commitlint/cli']).toBeDefined(); 51 | expect(devDependencies['@commitlint/config-conventional']).toBeDefined(); 52 | expect(devDependencies.commitizen).toBeDefined(); 53 | expect(devDependencies['cz-conventional-changelog']).toBeDefined(); 54 | expect(devDependencies.husky).toBeDefined(); 55 | expect(devDependencies['standard-version']).toBeDefined(); 56 | }); 57 | 58 | it('should add a npm run script', () => { 59 | const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); 60 | const { scripts } = packageJson; 61 | expect(appTree.files).toContain(PACKAGE_JSON_PATH); 62 | expect(scripts.release).toEqual('standard-version'); 63 | }); 64 | 65 | it(`should add the 'husky' configuration`, () => { 66 | const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); 67 | const { husky } = packageJson; 68 | expect(appTree.files).toContain(PACKAGE_JSON_PATH); 69 | expect(husky.hooks['commit-msg']).toEqual('commitlint -E HUSKY_GIT_PARAMS'); 70 | }); 71 | 72 | it(`should add the 'commitizen' configuration`, () => { 73 | const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); 74 | const { config } = packageJson; 75 | expect(appTree.files).toContain(PACKAGE_JSON_PATH); 76 | expect(config.commitizen.path).toEqual('./node_modules/cz-conventional-changelog'); 77 | }); 78 | }); 79 | 80 | describe(`when not using 'husky'`, () => { 81 | beforeEach(async () => { 82 | appTree = await schematicRunner 83 | .runSchematicAsync( 84 | 'ng-add', 85 | { 86 | ...defaultOptions, 87 | packages: ['commitlint', 'commitizen', 'standard-version'], 88 | }, 89 | appTree, 90 | ) 91 | .toPromise(); 92 | }); 93 | 94 | it(`should not add 'husky' to the project`, () => { 95 | const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); 96 | const { devDependencies } = packageJson; 97 | expect(appTree.files).toContain(PACKAGE_JSON_PATH); 98 | expect(devDependencies.husky).not.toBeDefined(); 99 | }); 100 | 101 | it(`should skip adding the 'husky' configuration`, () => { 102 | const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); 103 | const { husky } = packageJson; 104 | expect(appTree.files).toContain(PACKAGE_JSON_PATH); 105 | expect(husky).not.toBeDefined(); 106 | }); 107 | }); 108 | 109 | describe(`when disabling 'commitlint'`, () => { 110 | beforeEach(async () => { 111 | appTree = await schematicRunner 112 | .runSchematicAsync( 113 | 'ng-add', 114 | { 115 | ...defaultOptions, 116 | packages: ['commitizen', 'husky', 'standard-version'], 117 | }, 118 | appTree, 119 | ) 120 | .toPromise(); 121 | }); 122 | 123 | it(`should not add 'commitlint' to the project`, () => { 124 | const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); 125 | const { devDependencies } = packageJson; 126 | expect(appTree.files).toContain(PACKAGE_JSON_PATH); 127 | expect(devDependencies['@commitlint/cli']).not.toBeDefined(); 128 | expect(devDependencies['@commitlint/config-conventional']).not.toBeDefined(); 129 | }); 130 | }); 131 | 132 | describe(`when disabling 'commitizen'`, () => { 133 | beforeEach(async () => { 134 | appTree = await schematicRunner 135 | .runSchematicAsync( 136 | 'ng-add', 137 | { 138 | ...defaultOptions, 139 | packages: ['commitlint', 'husky', 'standard-version'], 140 | }, 141 | appTree, 142 | ) 143 | .toPromise(); 144 | }); 145 | 146 | it(`should not add 'commitizen' to the project`, () => { 147 | const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); 148 | const { devDependencies } = packageJson; 149 | expect(appTree.files).toContain(PACKAGE_JSON_PATH); 150 | expect(devDependencies.commitizen).not.toBeDefined(); 151 | }); 152 | 153 | it(`should skip adding the 'commitizen' configuration`, () => { 154 | const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); 155 | const { config } = packageJson; 156 | expect(appTree.files).toContain(PACKAGE_JSON_PATH); 157 | expect(config).not.toBeDefined(); 158 | }); 159 | }); 160 | 161 | describe(`when disabling 'standard-version'`, () => { 162 | beforeEach(async () => { 163 | appTree = await schematicRunner 164 | .runSchematicAsync( 165 | 'ng-add', 166 | { 167 | ...defaultOptions, 168 | packages: ['commitlint', 'commitizen', 'husky'], 169 | }, 170 | appTree, 171 | ) 172 | .toPromise(); 173 | }); 174 | 175 | it(`should not add 'standard-version' to the project`, () => { 176 | const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); 177 | const { devDependencies } = packageJson; 178 | expect(appTree.files).toContain(PACKAGE_JSON_PATH); 179 | expect(devDependencies['standard-version']).not.toBeDefined(); 180 | }); 181 | 182 | it('should skip adding a npm run script', () => { 183 | const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); 184 | const { scripts } = packageJson; 185 | expect(appTree.files).toContain(PACKAGE_JSON_PATH); 186 | expect(scripts.release).not.toBeDefined(); 187 | }); 188 | }); 189 | 190 | describe(`when using an issue prefix`, () => { 191 | beforeEach(async () => { 192 | appTree = await schematicRunner 193 | .runSchematicAsync('ng-add', { ...defaultOptions, issuePrefix: 'PREFIX-' }, appTree) 194 | .toPromise(); 195 | }); 196 | 197 | it(`should configure 'issuePrefixes' in '/commitlint.config.js'`, () => { 198 | expect(appTree.files).toContain(COMMITLINT_PATH); 199 | const fileContent = getFileContent(appTree, COMMITLINT_PATH); 200 | expect(fileContent).toMatch(/rules: {\s+\'references-empty\': \[2, \'never\'\].\s+\},/g); 201 | expect(fileContent).toMatch( 202 | /parserPreset: {\s+parserOpts: \{\s+issuePrefixes: \[\'\PREFIX-\'\],\s+},\s+},/g, 203 | ); 204 | }); 205 | 206 | it(`should add 'standard-version' config`, () => { 207 | const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); 208 | expect(packageJson['standard-version'].issuePrefixes).toContain('PREFIX-'); 209 | }); 210 | }); 211 | 212 | describe(`when using '--standardVersionConfig'`, () => { 213 | it(`should add the basic configuration to '/package.json'`, async () => { 214 | appTree = await schematicRunner 215 | .runSchematicAsync('ng-add', { ...defaultOptions, standardVersionConfig: true }, appTree) 216 | .toPromise(); 217 | const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); 218 | expect(packageJson['standard-version']).toEqual(STANDARD_VERSION_DEFAULTS); 219 | }); 220 | 221 | it(`should add the basic configuration with 'issuePrefix' to '/package.json'`, async () => { 222 | appTree = await schematicRunner 223 | .runSchematicAsync( 224 | 'ng-add', 225 | { ...defaultOptions, standardVersionConfig: true, issuePrefix: 'PREFIX-' }, 226 | appTree, 227 | ) 228 | .toPromise(); 229 | const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); 230 | const expectedConfig = { 231 | ...STANDARD_VERSION_DEFAULTS, 232 | issuePrefixes: ['PREFIX-'], 233 | }; 234 | expect(packageJson['standard-version']).toEqual(expectedConfig); 235 | }); 236 | }); 237 | 238 | describe(`when running in an existing project`, () => { 239 | let appTreeOnExistingProject: UnitTestTree; 240 | let packageJson: { [key: string]: any }; 241 | let packageJsonModified: { [key: string]: any }; 242 | 243 | beforeEach(async () => { 244 | appTree = await schematicRunner 245 | .runSchematicAsync('ng-add', defaultOptions, appTree) 246 | .toPromise(); 247 | const packageJson = JSON.parse(getFileContent(appTree, PACKAGE_JSON_PATH)); 248 | packageJsonModified = { 249 | ...packageJson, 250 | scripts: { 251 | release: 'foo ./bar', 252 | foo: 'bar', 253 | }, 254 | husky: { 255 | hooks: { 256 | 'commit-msg': 'foo-bar', 257 | }, 258 | }, 259 | config: { 260 | commitizen: { 261 | path: '~/foo-bar', 262 | }, 263 | other: { 264 | foo: 'bar', 265 | }, 266 | }, 267 | 'standard-version': { 268 | issuePrefixes: 'foo', 269 | skip: { 270 | changelog: true, 271 | }, 272 | }, 273 | }; 274 | }); 275 | 276 | describe(`and not using '--overrideConfigurations'`, () => { 277 | beforeEach(async () => { 278 | appTree.overwrite(PACKAGE_JSON_PATH, JSON.stringify(packageJsonModified)); 279 | appTree.delete(COMMITLINT_PATH); 280 | appTreeOnExistingProject = new UnitTestTree(appTree); 281 | appTreeOnExistingProject = await schematicRunner 282 | .runSchematicAsync( 283 | 'ng-add', 284 | { ...defaultOptions, issuePrefix: 'bar' }, 285 | appTreeOnExistingProject, 286 | ) 287 | .toPromise(); 288 | packageJson = JSON.parse(getFileContent(appTreeOnExistingProject, PACKAGE_JSON_PATH)); 289 | }); 290 | 291 | it(`should not override 'standard-version' config`, () => { 292 | expect(packageJson['standard-version'].issuePrefixes).toContain('foo'); 293 | }); 294 | 295 | it(`should not override 'scripts' config`, () => { 296 | expect(packageJson.scripts.release).toContain('foo ./bar'); 297 | }); 298 | 299 | it(`should not override 'commitizen' config`, () => { 300 | expect(packageJson.config.commitizen.path).toContain('~/foo-bar'); 301 | }); 302 | 303 | it(`should not override 'husky' config`, () => { 304 | expect(packageJson.husky.hooks['commit-msg']).toContain('foo-bar'); 305 | }); 306 | }); 307 | 308 | describe(`and using '--overrideConfigurations'`, () => { 309 | beforeEach(async () => { 310 | appTree.overwrite(PACKAGE_JSON_PATH, JSON.stringify(packageJsonModified)); 311 | appTree.overwrite(COMMITLINT_PATH, '// fooBar'); 312 | appTreeOnExistingProject = new UnitTestTree(appTree); 313 | appTreeOnExistingProject = await schematicRunner 314 | .runSchematicAsync( 315 | 'ng-add', 316 | { ...defaultOptions, overrideConfigurations: true, issuePrefix: 'bar' }, 317 | appTreeOnExistingProject, 318 | ) 319 | .toPromise(); 320 | packageJson = JSON.parse(getFileContent(appTreeOnExistingProject, PACKAGE_JSON_PATH)); 321 | }); 322 | 323 | it(`should override 'standard-version' config`, () => { 324 | expect(packageJson['standard-version'].issuePrefixes).toContain('bar'); 325 | expect(packageJson['standard-version'].skip.changelog).toBeTruthy; 326 | }); 327 | 328 | it(`should override 'scripts' config`, () => { 329 | expect(packageJson.scripts.release).toContain('standard-version'); 330 | expect(packageJson.scripts.foo).toContain('bar'); 331 | }); 332 | 333 | it(`should override 'commitizen' config`, () => { 334 | expect(packageJson.config.commitizen.path).toContain( 335 | './node_modules/cz-conventional-changelog', 336 | ); 337 | expect(packageJson.config.other.foo).toContain('bar'); 338 | }); 339 | 340 | it(`should override 'husky' config`, () => { 341 | expect(packageJson.husky.hooks['commit-msg']).toContain('commitlint -E HUSKY_GIT_PARAMS'); 342 | }); 343 | 344 | it(`should override an existing 'commitlint' configuration file`, () => { 345 | expect(appTree.files).toContain(COMMITLINT_PATH); 346 | const fileContent = getFileContent(appTree, COMMITLINT_PATH); 347 | expect(fileContent).toMatch(/module.exports = \{(.*)\};/gs); 348 | }); 349 | }); 350 | }); 351 | }); 352 | -------------------------------------------------------------------------------- /src/ng-add/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/schema", 3 | "id": "ngx-semantic-version", 4 | "title": "ngx-semantic-version Schema", 5 | "description": "configure commitlint, husky, commitizen and standard-version configuration", 6 | "type": "object", 7 | "properties": { 8 | "packages": { 9 | "type": "array", 10 | "description": "select the packages that should to be installed and configured", 11 | "uniqueItems": true, 12 | "minItems": 1, 13 | "items": { 14 | "enum": ["commitlint", "commitizen", "husky", "standard-version"], 15 | "type": "string" 16 | }, 17 | "default": ["commitlint", "commitizen", "husky", "standard-version"], 18 | "x-prompt": "What packages do you want to be installed and configured?" 19 | }, 20 | "skipInstall": { 21 | "type": "boolean", 22 | "description": "Skip installing the npm packages", 23 | "default": false 24 | }, 25 | "standardVersionConfig": { 26 | "type": "boolean", 27 | "description": "add the standard-version default configuration to the `packages.json` file", 28 | "default": false 29 | }, 30 | "issuePrefix": { 31 | "type": "string", 32 | "description": "configure an issue prefix that should be checked by each commit", 33 | "default": "" 34 | }, 35 | "overrideConfigurations": { 36 | "type": "boolean", 37 | "description": "Override existing configuration parameters", 38 | "default": false 39 | } 40 | }, 41 | "required": ["packages"] 42 | } 43 | -------------------------------------------------------------------------------- /src/ng-add/schema.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * ngx-semantic-version Schema 3 | * configure commitlint, husky, commitizen and standard-version configuration 4 | */ 5 | export interface NgxSemanticVersion { 6 | /** 7 | * select the packages that should to be installed and configured 8 | */ 9 | packages: PackageName[]; 10 | /** 11 | * Skip installing the npm packages 12 | */ 13 | skipInstall?: boolean; 14 | /** 15 | * add the standard-version default configuration to the `packages.json` file 16 | */ 17 | standardVersionConfig?: boolean; 18 | /** 19 | * configure an issue prefix that should be checked by each commit 20 | */ 21 | issuePrefix?: string; 22 | /** 23 | * Override existing configuration parameters 24 | */ 25 | overrideConfigurations?: boolean; 26 | } 27 | 28 | export type PackageName = 'commitlint' | 'commitizen' | 'husky' | 'standard-version'; 29 | -------------------------------------------------------------------------------- /src/ng-update/migration-01/index.ts: -------------------------------------------------------------------------------- 1 | import { Rule, SchematicContext, Tree, chain } from '@angular-devkit/schematics'; 2 | import { getPackageJson, overwritePackageJson } from '../../utils'; 3 | 4 | export default (_options: any): Rule => { 5 | return chain([addHuskyConfig, updateDependencies]); 6 | }; 7 | 8 | const addHuskyConfig = () => (tree: Tree, context: SchematicContext) => { 9 | context.logger.info('Removes old husky prepare-commit-msg configuration'); 10 | 11 | const packageJson = getPackageJson(tree); 12 | if ( 13 | packageJson.husky && 14 | packageJson.husky.hooks && 15 | packageJson.husky.hooks['prepare-commit-msg'] === 'exec < /dev/tty && git cz --hook' 16 | ) { 17 | delete packageJson.husky.hooks['prepare-commit-msg']; 18 | } 19 | 20 | overwritePackageJson(tree, packageJson); 21 | }; 22 | 23 | const updateDependencies = () => (tree: Tree, context: SchematicContext) => { 24 | context.logger.info('Updates npm packages as dev dependencies'); 25 | const packageJson = getPackageJson(tree); 26 | 27 | const devDepsToAdd = { 28 | husky: '^3.0.9', 29 | }; 30 | packageJson.devDependencies = { 31 | ...packageJson.devDependencies, 32 | ...devDepsToAdd, 33 | }; 34 | 35 | overwritePackageJson(tree, packageJson); 36 | }; 37 | -------------------------------------------------------------------------------- /src/ng-update/migration-01/index_spec.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; 3 | import { map } from 'rxjs/operators'; 4 | import { Observable } from 'rxjs'; 5 | import * as path from 'path'; 6 | 7 | const packagePath = '/package.json'; 8 | const collectionPath = path.join(__dirname, '../../migration.json'); 9 | 10 | const huskykHookForTest = (hook: string, command: string) => { 11 | return `{ 12 | "husky": { 13 | "hooks": { 14 | "${hook}": "${command}" 15 | } 16 | } 17 | }`; 18 | }; 19 | const packageJsonAfterMigration = (packgeJsonRawContent: string): Observable => { 20 | const emptyTree = Tree.empty() as UnitTestTree; 21 | const runner = new SchematicTestRunner('schematics', collectionPath); 22 | emptyTree.create(packagePath, packgeJsonRawContent); 23 | return runner.runSchematicAsync('migration-01', {}, emptyTree) 24 | .pipe( 25 | map(updatedTree => JSON.parse(updatedTree.readContent(packagePath))) 26 | ); 27 | }; 28 | 29 | describe('update from version 0.0.4', () => { 30 | const prepareCommitMsgHookToBeRemoved = 'exec < /dev/tty && git cz --hook'; 31 | 32 | it(`should remove a previous configuration`, () => { 33 | const beforeMigration = huskykHookForTest( 34 | 'prepare-commit-msg', 35 | prepareCommitMsgHookToBeRemoved, 36 | ); 37 | packageJsonAfterMigration(beforeMigration).subscribe((pkg) => { 38 | expect(pkg.husky.hooks['prepare-commit-msg']).not.toBeDefined(); 39 | }); 40 | }); 41 | it(`should not touch if the husky hook has been modified`, () => { 42 | const beforeMigration = huskykHookForTest('prepare-commit-msg', 'some other user defined hook'); 43 | packageJsonAfterMigration(beforeMigration).subscribe((pkg) => { 44 | expect(pkg.husky.hooks['prepare-commit-msg']).toBeDefined(); 45 | expect(pkg.husky.hooks['prepare-commit-msg']).not.toEqual(prepareCommitMsgHookToBeRemoved); 46 | }); 47 | }); 48 | it('should update dependencies in package.json', () => { 49 | const beforeMigration = `{ 50 | "devDependencies": { 51 | "husky": "^3.0.8" 52 | } 53 | }`; 54 | packageJsonAfterMigration(beforeMigration).subscribe((pkg) => { 55 | const { devDependencies } = pkg; 56 | expect(devDependencies.husky).toEqual('^3.0.9'); 57 | }); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /src/ng-update/migration-02/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Rule, 3 | SchematicContext, 4 | Tree, 5 | chain, 6 | apply, 7 | url, 8 | mergeWith, 9 | template, 10 | MergeStrategy, 11 | } from '@angular-devkit/schematics'; 12 | import { getPackageJson, overwritePackageJson } from '../../utils'; 13 | 14 | export default (_options: any): Rule => { 15 | return chain([removeCommitlintAngularConfig, overrideCommitlintConfigFile]); 16 | }; 17 | 18 | const removeCommitlintAngularConfig = () => (tree: Tree, context: SchematicContext) => { 19 | context.logger.info('Updates npm packages as dev dependencies'); 20 | const packageJson = getPackageJson(tree); 21 | 22 | if (packageJson.devDependencies['@commitlint/config-angular'] === '^8.2.0') { 23 | delete packageJson.devDependencies['@commitlint/config-angular']; 24 | } 25 | packageJson.devDependencies['@commitlint/config-conventional'] = '^8.2.0'; 26 | 27 | overwritePackageJson(tree, packageJson); 28 | }; 29 | 30 | const overrideCommitlintConfigFile = () => (tree: Tree, context: SchematicContext) => { 31 | context.logger.info('Added commitlint configuration file'); 32 | const sourceTemplates = url('./files/commitlint.config.js'); 33 | const sourceParameterizedTemplates = apply(sourceTemplates, [template({})]); 34 | return mergeWith(sourceParameterizedTemplates, MergeStrategy.Overwrite)(tree, context); 35 | }; 36 | -------------------------------------------------------------------------------- /src/ng-update/migration-02/index_spec.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; 3 | import { map } from 'rxjs/operators'; 4 | import { Observable } from 'rxjs'; 5 | import * as path from 'path'; 6 | 7 | const packagePath = '/package.json'; 8 | const collectionPath = path.join(__dirname, '../../migration.json'); 9 | 10 | const packageJsonAfterMigration = (packgeJsonRawContent: string): Observable => { 11 | const emptyTree = Tree.empty() as UnitTestTree; 12 | const runner = new SchematicTestRunner('schematics', collectionPath); 13 | emptyTree.create(packagePath, packgeJsonRawContent); 14 | return runner.runSchematicAsync('migration-02', {}, emptyTree) 15 | .pipe( 16 | map(updatedTree => JSON.parse(updatedTree.readContent(packagePath))) 17 | ); 18 | }; 19 | 20 | describe('update to version 0.0.5', () => { 21 | it('should remove @commitlint/config-angular@^8.2.0 from package.json', () => { 22 | const beforeMigration = `{ 23 | "devDependencies": { 24 | "@commitlint/config-angular": "^8.2.0" 25 | } 26 | }`; 27 | packageJsonAfterMigration(beforeMigration).subscribe((pkg) => { 28 | const { devDependencies } = pkg; 29 | expect(devDependencies['@commitlint/config-angular']).not.toBeDefined(); 30 | expect(devDependencies['@commitlint/config-conventional']).toEqual('^8.2.0'); 31 | }); 32 | }); 33 | 34 | it('should not remove modified @commitlint/config-angular version from package.json', () => { 35 | const beforeMigration = `{ 36 | "devDependencies": { 37 | "@commitlint/config-angular": "^8.0.0" 38 | } 39 | }`; 40 | packageJsonAfterMigration(beforeMigration).subscribe((pkg) => {; 41 | const { devDependencies } = pkg; 42 | expect(devDependencies['@commitlint/config-angular']).toEqual('^8.0.0'); 43 | }); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /src/ng-update/migration-03/index.ts: -------------------------------------------------------------------------------- 1 | import { Rule, SchematicContext, Tree, chain } from '@angular-devkit/schematics'; 2 | import { getPackageJson, overwritePackageJson } from '../../utils'; 3 | 4 | export default (_options: any): Rule => { 5 | return chain([updateDependencies]); 6 | }; 7 | 8 | const updateDependencies = () => (tree: Tree, context: SchematicContext) => { 9 | context.logger.info('Updates npm packages as dev dependencies'); 10 | const packageJson = getPackageJson(tree); 11 | 12 | // be sure that ngx-semantic-version will be removed from the `dependencies` section 13 | delete packageJson.dependencies['ngx-semantic-version']; 14 | 15 | overwritePackageJson(tree, packageJson); 16 | }; 17 | -------------------------------------------------------------------------------- /src/ng-update/migration-03/index_spec.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; 3 | import { map } from 'rxjs/operators'; 4 | import { Observable } from 'rxjs'; 5 | import * as path from 'path'; 6 | 7 | const packagePath = '/package.json'; 8 | const collectionPath = path.join(__dirname, '../../migration.json'); 9 | 10 | const packageJsonAfterMigration = (packgeJsonRawContent: string): Observable => { 11 | const emptyTree = Tree.empty() as UnitTestTree; 12 | const runner = new SchematicTestRunner('schematics', collectionPath); 13 | emptyTree.create(packagePath, packgeJsonRawContent); 14 | return runner.runSchematicAsync('migration-03', {}, emptyTree) 15 | .pipe( 16 | map(updatedTree => JSON.parse(updatedTree.readContent(packagePath))) 17 | ); 18 | }; 19 | 20 | describe('update to version >= 2', () => { 21 | it('should update dependencies in package.json', () => { 22 | const beforeMigration = `{ 23 | "dependencies": { 24 | "ngx-semantic-version": "1.2.1" 25 | } 26 | }`; 27 | packageJsonAfterMigration(beforeMigration).subscribe((pkg) => { 28 | const { dependencies } = pkg; 29 | expect(dependencies['ngx-semantic-version']).toBeUndefined; 30 | }); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /src/ng-update/migration-04/index.ts: -------------------------------------------------------------------------------- 1 | import { Rule, SchematicContext, Tree, chain } from '@angular-devkit/schematics'; 2 | import { getPackageJson, overwritePackageJson } from '../../utils'; 3 | import { NgxSemanticVersion as Schema, PackageName } from '../../ng-add/schema'; 4 | import { PackageJsonConfigPart } from '../../utils'; 5 | import { DEV_DEPS_TO_ADD } from '../../ng-add/defaults'; 6 | 7 | export default (_options: Schema): Rule => { 8 | return chain([updateDependencies]); 9 | }; 10 | 11 | const updateDependencies = () => (tree: Tree, context: SchematicContext) => { 12 | context.logger.info('Updating npm packages dev dependencies for tooling'); 13 | const packageJson = getPackageJson(tree); 14 | 15 | let devDepsToAdd: PackageJsonConfigPart = {}; 16 | 17 | const map = new Map([ 18 | ['commitlint', DEV_DEPS_TO_ADD], 19 | ['commitizen', DEV_DEPS_TO_ADD], 20 | ['husky', DEV_DEPS_TO_ADD], 21 | ['standard-version', DEV_DEPS_TO_ADD], 22 | ]); 23 | 24 | for (const [key, value] of map.entries()) { 25 | const searchKey = key as PackageName; 26 | devDepsToAdd = { 27 | ...devDepsToAdd, 28 | ...value[searchKey], 29 | }; 30 | } 31 | 32 | packageJson.devDependencies = { 33 | ...packageJson.devDependencies, 34 | ...devDepsToAdd, 35 | }; 36 | 37 | overwritePackageJson(tree, packageJson); 38 | }; 39 | -------------------------------------------------------------------------------- /src/ng-update/migration-04/index_spec.ts: -------------------------------------------------------------------------------- 1 | import { Tree } from '@angular-devkit/schematics'; 2 | import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; 3 | import { map } from 'rxjs/operators'; 4 | import { Observable } from 'rxjs'; 5 | import * as path from 'path'; 6 | 7 | const packagePath = '/package.json'; 8 | const collectionPath = path.join(__dirname, '../../migration.json'); 9 | 10 | const packageJsonAfterMigration = (packgeJsonRawContent: string): Observable => { 11 | const emptyTree = Tree.empty() as UnitTestTree; 12 | const runner = new SchematicTestRunner('schematics', collectionPath); 13 | emptyTree.create(packagePath, packgeJsonRawContent); 14 | return runner.runSchematicAsync('migration-04', {}, emptyTree) 15 | .pipe( 16 | map(updatedTree => JSON.parse(updatedTree.readContent(packagePath))) 17 | ); 18 | }; 19 | 20 | describe('update to version >= 2', () => { 21 | it('should not remove modified @commitlint/config-angular version from package.json', () => { 22 | const beforeMigration = `{ 23 | "devDependencies": { 24 | "@commitlint/cli": "0.0.0", 25 | "@commitlint/config-conventional": "0.0.0", 26 | "commitizen": "0.0.0", 27 | "cz-conventional-changelog": "0.0.0", 28 | "husky": "0.0.0", 29 | "standard-version": "0.0.0" 30 | } 31 | }`; 32 | packageJsonAfterMigration(beforeMigration).subscribe((pkg) => {; 33 | const { devDependencies } = pkg; 34 | expect(devDependencies['@commitlint/cli']).toEqual('^11.0.0'); 35 | expect(devDependencies['@commitlint/config-conventional']).toEqual('^11.0.0'); 36 | expect(devDependencies['commitizen']).toEqual('^4.2.2'); 37 | expect(devDependencies['cz-conventional-changelog']).toEqual('^3.3.0'); 38 | expect(devDependencies['husky']).toEqual('^4.3.0'); 39 | expect(devDependencies['standard-version']).toEqual('^9.0.0'); 40 | }); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /src/test-utils.ts: -------------------------------------------------------------------------------- 1 | import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; 2 | 3 | export async function setupProject( 4 | tree: UnitTestTree, 5 | schematicRunner: SchematicTestRunner, 6 | name: string, 7 | ) { 8 | tree = await schematicRunner 9 | .runExternalSchematicAsync('@schematics/angular', 'workspace', { 10 | name: 'workspace', 11 | version: '8.0.0', 12 | newProjectRoot: '', 13 | }) 14 | .toPromise(); 15 | 16 | tree = await schematicRunner 17 | .runExternalSchematicAsync( 18 | '@schematics/angular', 19 | 'application', 20 | { 21 | name, 22 | projectRoot: '', 23 | }, 24 | tree, 25 | ) 26 | .toPromise(); 27 | 28 | return tree; 29 | } 30 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | import { SchematicsException, Tree } from '@angular-devkit/schematics'; 3 | 4 | const PACKAGE_JSON = 'package.json'; 5 | 6 | export interface PackageJson { 7 | dependencies: PackageJsonConfigPart; 8 | devDependencies: PackageJsonConfigPart; 9 | name?: string; 10 | version?: string; 11 | license?: string; 12 | scripts?: PackageJsonConfigPart; 13 | repository?: PackageJsonConfigPart; 14 | bugs?: PackageJsonConfigPart; 15 | config?: { 16 | commitizen?: { 17 | path?: string; 18 | }; 19 | }; 20 | husky?: { 21 | hooks?: { 22 | 'prepare-commit-msg'?: string; 23 | 'commit-msg'?: string; 24 | }; 25 | }; 26 | 'standard-version': { 27 | issuePrefixes?: string[]; 28 | }; 29 | } 30 | 31 | export interface PackageJsonConfigPart { 32 | [key: string]: T; 33 | } 34 | 35 | class FileNotFoundException extends Error { 36 | constructor(fileName: string) { 37 | const message = `File ${fileName} not found!`; 38 | super(message); 39 | } 40 | } 41 | 42 | export const getJsonFile = (tree: Tree, path: string): T => { 43 | const file = tree.get(path); 44 | if (!file) { 45 | throw new FileNotFoundException(path); 46 | } 47 | 48 | try { 49 | const content = JSON.parse(file.content.toString()); 50 | 51 | return content as T; 52 | } catch (e) { 53 | throw new SchematicsException(`File ${path} could not be parsed!`); 54 | } 55 | }; 56 | 57 | export const getFileContents = (tree: Tree, filePath: string): string => { 58 | const buffer = tree.read(filePath) || ''; 59 | 60 | return buffer.toString(); 61 | }; 62 | 63 | export const getPackageJson = (tree: Tree, workingDirectory: string = ''): PackageJson => { 64 | const url = join(workingDirectory, PACKAGE_JSON); 65 | 66 | return getJsonFile(tree, url); 67 | }; 68 | 69 | export const overwritePackageJson = ( 70 | tree: Tree, 71 | content: PackageJson, 72 | workingDirectory: string = '', 73 | ) => { 74 | const url = join(workingDirectory, PACKAGE_JSON); 75 | 76 | tree.overwrite(url, JSON.stringify(content, null, 2)); 77 | }; 78 | 79 | export const getMergedPackageJsonConfig = ( 80 | existingConfig: PackageJsonConfigPart, 81 | newConfig: PackageJsonConfigPart, 82 | overrideExisting = true, 83 | ) => { 84 | let mergedConfig: PackageJsonConfigPart = {}; 85 | if (overrideExisting) { 86 | mergedConfig = { ...existingConfig, ...newConfig }; 87 | } else { 88 | mergedConfig = { ...newConfig, ...existingConfig }; 89 | } 90 | return mergedConfig; 91 | }; 92 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "tsconfig", 4 | "lib": ["es2018", "dom"], 5 | "declaration": true, 6 | "module": "commonjs", 7 | "moduleResolution": "node", 8 | "noEmitOnError": true, 9 | "noFallthroughCasesInSwitch": true, 10 | "noImplicitAny": true, 11 | "noImplicitThis": true, 12 | "noUnusedParameters": true, 13 | "noUnusedLocals": true, 14 | "rootDir": "src/", 15 | "skipDefaultLibCheck": true, 16 | "skipLibCheck": true, 17 | "sourceMap": true, 18 | "strictNullChecks": true, 19 | "target": "es6", 20 | "types": ["jasmine", "node"] 21 | }, 22 | "include": ["src/**/*"], 23 | "exclude": ["src/*/files/**/*"] 24 | } 25 | --------------------------------------------------------------------------------