├── .gitattributes
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── README.md
├── deploy.sh
├── generators
├── app
│ └── index.js
├── base.js
├── cli
│ ├── index.js
│ └── templates
│ │ └── cli.tpl
├── readme
│ ├── index.js
│ └── templates
│ │ └── README.tpl
├── src
│ ├── index.js
│ └── templates
│ │ ├── index.tpl
│ │ └── rollup.config.tpl
└── test
│ ├── index.js
│ └── templates
│ └── test.tpl
├── index.js
├── package.json
└── test
├── ci
└── index.js
├── generators
├── app.js
├── cli.js
├── readme.js
├── src.js
└── test.js
└── helpers
├── answers.json
└── set-up-mockery.js
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .tmp/
3 |
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: node_js
3 | env:
4 | global:
5 | - CI: true
6 | - GH_REF: github.com/maurizzzio/generator-mnm-example.git
7 | - secure: VqS4f6ybZSWQlJhKRZj6wVWhH6ywCaRo40gDQGd2xmcGUK0JRjDA6+tIQUgpGGFWlpCsm0EgtmTM18RzrfZceOr8o2NAMWMKENAo/8vu8JIojyxVD9th6dWW9JGojgoQaSVUpT7U91wena18qnGjU17vlWUyLEszln4o/RGYrGfEewG1wheYHNYoSwcQZJ8i7+wirRMFkLYB5GrYZaEWTXHg37GILdq+0oA5CH0XgYBPxLR4+u5w88Zno4kw1AdGaNvtywTJrHYAC5Wv6+lWuPTC8905FXqaEqUswYUYzYMy8+1NpttgDchGnpqKO8JdHhXhxKYdUPEg6PgIl16cYEx3BBAwdkZWt2412n2/4qZ6Oi03mR8zjpYt8T9T5t/H43UG3LO3+tDYqAoqyQkxwwrdz8duJp8lfkYWs5wo+U/mZMkNNXM1fmBoywNPyihjBDo8IUtMvNIkIzRRoG3DfKtmQKJHJCXueroOyPXGmiR1X49qd+04xAI9jIikB6SzAUARzK/4KqdsWeKSsbp2nr1iqj7Iltm9hEsJ2VMSfmeEn0RSlGE3m5XdXEhLXzK3D1J9bJyIyheDvuz42C9S1HCTuz1krGMGOaRIlsOrlHh38Zf/9x5lHKT4E6oqOPcQDo2rrox8zbvmWbYYFzmck7T1yLbP3BoU80afEptR4lg=
8 |
9 | node_js:
10 | - v5
11 | before_install: if [[ `npm -v` != 3* ]]; then npm i -g npm@3; fi
12 | script:
13 | - npm run lint
14 | - npm test
15 | - npm run test:ci
16 | after_success:
17 | - bash deploy.sh
18 |
19 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | # [0.6.0](https://github.com/maurizzzio/generator-mnm/compare/v0.5.1...v0.6.0) (2016-09-26)
3 |
4 |
5 | ### Build
6 |
7 | * generator-travis removed in favor of a custom one ([a51f39cb2e39597ae2c188c69689f4800f48752e](https://github.com/maurizzzio/generator-mnm/commit/a51f39cb2e39597ae2c188c69689f4800f48752e))
8 |
9 | ### Fix
10 |
11 | * added yamljs as a dependency ([4031ae436eda4d4db9cbcb15e3831d02347e4470](https://github.com/maurizzzio/generator-mnm/commit/4031ae436eda4d4db9cbcb15e3831d02347e4470))
12 | * task test run on CI ([5a50b079264ce5caa73e03ec044b0d9d425c37ad](https://github.com/maurizzzio/generator-mnm/commit/5a50b079264ce5caa73e03ec044b0d9d425c37ad))
13 | * travis now only tests against node v4 ([792ec4c0b0f2edf3ac57bc186b34606f81e8595c](https://github.com/maurizzzio/generator-mnm/commit/792ec4c0b0f2edf3ac57bc186b34606f81e8595c))
14 |
15 | ### New
16 |
17 | * added a task changelog to easily generate a CHANGELOG file ([fea3d04ba2f3376771bd1ffbe3a2d8439a017156](https://github.com/maurizzzio/generator-mnm/commit/fea3d04ba2f3376771bd1ffbe3a2d8439a017156))
18 | * common js bundle created with rollup ([e7b2148d3d9c6bda60b973374ff8701160902b93](https://github.com/maurizzzio/generator-mnm/commit/e7b2148d3d9c6bda60b973374ff8701160902b93)), closes [#2](https://github.com/maurizzzio/generator-mnm/issues/2)
19 |
20 |
21 |
22 |
23 | ## [0.5.1](https://github.com/maurizzzio/generator-mnm/compare/v0.5.0...v0.5.1) (2016-05-10)
24 |
25 |
26 |
27 |
28 |
29 | # [0.5.0](https://github.com/maurizzzio/generator-mnm/compare/v0.4.0...v0.5.0) (2016-05-09)
30 |
31 |
32 |
33 |
34 |
35 | # [0.4.0](https://github.com/maurizzzio/generator-mnm/compare/v0.3.0...v0.4.0) (2016-05-06)
36 |
37 |
38 |
39 |
40 |
41 | # [0.3.0](https://github.com/maurizzzio/generator-mnm/compare/v0.2.3...v0.3.0) (2015-12-08)
42 |
43 |
44 | ### Docs
45 |
46 | * docs related with ES6 bundlers ([9193d03d22dae63c2121b1ac09c891ae1d69e4e6](https://github.com/maurizzzio/generator-mnm/commit/9193d03d22dae63c2121b1ac09c891ae1d69e4e6))
47 |
48 | ### Fix
49 |
50 | * license field is not present in package.json ([8ccf13ae133c790f9fd6963073800e5af02b56dc](https://github.com/maurizzzio/generator-mnm/commit/8ccf13ae133c790f9fd6963073800e5af02b56dc)), closes [#3](https://github.com/maurizzzio/generator-mnm/issues/3)
51 |
52 |
53 |
54 |
55 | ## [0.2.3](https://github.com/maurizzzio/generator-mnm/compare/v0.2.2...v0.2.3) (2015-12-06)
56 |
57 |
58 |
59 |
60 |
61 | ## [0.2.2](https://github.com/maurizzzio/generator-mnm/compare/v0.2.1...v0.2.2) (2015-12-06)
62 |
63 |
64 |
65 |
66 |
67 | ## [0.2.1](https://github.com/maurizzzio/generator-mnm/compare/v0.2.0...v0.2.1) (2015-12-06)
68 |
69 |
70 |
71 |
72 |
73 | # [0.2.0](https://github.com/maurizzzio/generator-mnm/compare/v0.1.1...v0.2.0) (2015-11-27)
74 |
75 |
76 |
77 |
78 |
79 | ## [0.1.1](https://github.com/maurizzzio/generator-mnm/compare/v0.1.0...v0.1.1) (2015-11-26)
80 |
81 |
82 |
83 |
84 |
85 | # 0.1.0 (2015-11-25)
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |

3 |
4 |
5 | Create node modules writing ES6/ES7 today compiled with Babel, tested with ava, bundled with rollup and linted with standard on top of npm scripts
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | ## Install
24 |
25 | ```sh
26 | $ npm install -g yo generator-mnm
27 | ```
28 |
29 | ## Usage
30 |
31 | ```sh
32 | Usage:
33 | yo mnm:app [options] []
34 |
35 | Options:
36 | -h, --help # Print the generator's options and usage
37 | --skip-cache # Do not remember prompt answers Default: false
38 | --skip-install # Do not automatically install dependencies Default: false
39 | -a, --all # Ask all questions Default: false
40 | -y, --yes # Skip some questions, like $ npm init -y Default: false
41 |
42 | Arguments:
43 | name # module name
44 | If provided the module will be created inside .//
45 | otherwise it will be created in the current directory
46 |
47 | Examples:
48 |
49 | $ yo mnm
50 | $ yo mnm myAwesomeModule
51 |
52 | Type: String Required: false
53 | ```
54 |
55 | Example
56 |
57 | ```sh
58 | $ yo mnm -y
59 | create package.json
60 | create README.md
61 | create .gitignore
62 | create src/index.js
63 | create test/index.js
64 | create .travis.yml
65 | create .babelrc
66 | create rollup.config.js
67 | ```
68 |
69 | ## Features
70 |
71 | - Made out of many other generators, the main generator only creates a [`package.json` file](https://github.com/maurizzzio/generator-mnm/blob/master/generators/app/index.js#L225-L240) and a [minimal `.gitignore` file](https://github.com/maurizzzio/generator-mnm/blob/master/generators/app/index.js#L246-L248)
72 | - Composable, since the logic to create the README, cli and other files is on their own subgenerator
73 | - [Babel](https://babeljs.io) transpiles the code/tests
74 | - [standard](http://standardjs.com/) to lint the code
75 | - [ava](https://github.com/sindresorhus/ava) for testing
76 | - [yargs](https://github.com/bcoe/yargs) to parse cli arguments (optional)
77 | - [rollup](https://github.com/rollup/rollup) to create a common js compatible bundle
78 | - npm scripts as the build system
79 |
80 | ## Example
81 |
82 | Check [https://github.com/maurizzzio/generator-mnm-example](https://github.com/maurizzzio/generator-mnm-example)
83 |
84 | ## List of npm scripts included
85 |
86 | Common tasks
87 |
88 | | task | description |
89 | | ----- | --- |
90 | | `npm test` | `ava` |
91 | | `npm run build` | `rollup --config`|
92 | | `npm run lint` | `standard` |
93 | | `npm run clean` | Removes all the files inside `dist/`|
94 |
95 | Watching files
96 |
97 | | task | description |
98 | | --- | --- |
99 | | `npm run test:watch` | Same as `npm test` but with ` --watch` |
100 | | `npm run build:watch` | Same as `npm run build` but with ` --watch` |
101 |
102 | Pre/Post hooks
103 |
104 | | Task | description |
105 | | --- | --- |
106 | | `npm run prebuild` | Run before `build`, `npm clean -s && npm lint -s` |
107 | | `npm run preversion` | Run before `version`, `npm run build` |
108 |
109 | ### Useful npm commands that you should know
110 |
111 | - `npm version major|minor|patch` bumps the package version
112 | - `npm run` lists all available scripts
113 |
114 | ## Why?
115 |
116 | This project is heavily inspired by [this article by Keith Cirkel][stop-using-grunt-gulp] where he describes that the existing build system tools attempt to solve the problems that exist among them "covering up the inadequacies of the other tools while also surfacing their own".
117 |
118 | [James Halliday](https://www.npmjs.com/~substack) who is the creator of many awesome packages like `browserify` and `tape` also wrote an article where he points out that the command `npm run` is "perfectly adequate for everything while maintaining a very tiny configuration footprint."
119 |
120 | ### Articles to read:
121 |
122 | - [Why we should stop using grunt][stop]
123 | - [How to use npm as a build tool][how-to]
124 | - [Task automation with run][task-automation]
125 | - [Choose grunt, gulp or npm][choose]
126 |
127 | ### Inspiration projects
128 |
129 | - https://github.com/yeoman/generator-node
130 | - https://github.com/vinniegarcia/ES6-module-starter
131 | - https://github.com/sindresorhus/generator-nm
132 | - https://github.com/bucaran/generator-rise
133 | - https://github.com/iamstarkov/generator-zen
134 | - https://github.com/keithamus/npm-scripts-example 's awesome `package.json` file
135 |
136 | I'd like to thank [iamstarkov](https://github.com/iamstarkov) for his awesome work on generators that are actually composable
137 |
138 | ## Composability
139 |
140 | Just plug in any of the subgenerators or the `app` generator itself on your generator
141 |
142 |
143 |

144 |
145 |
146 | Generators used in this project
147 |
148 | - [generator-babel](https://github.com/iamstarkov/generator-babel)
149 | - [generator-git-init](https://github.com/iamstarkov/generator-git-init)
150 | - [generator-license](https://github.com/jozefizso/generator-license)
151 | - [generator-mnm/generators/src](./generators/src)
152 | - [generator-mnm/generators/test](./generators/test)
153 | - [generator-mnm/generators/cli](./generators/cli)
154 | - [generator-mnm/generators/readme](./generators/readme)
155 |
156 | ## Workflow
157 |
158 | ```sh
159 | # equivalent to npm init -y
160 | yo mnm -y
161 | # see https://www.npmjs.com/package/ghrepo
162 | ghrepo -m "initial commit"
163 | # see https://www.npmjs.com/package/travisjs
164 | travisjs hook # or travis enable with the travis gem
165 |
166 | # if a cli is needed
167 | yo mnm:cli
168 | ```
169 |
170 | ## Development
171 |
172 | - `npm test`
173 | - `npm test:ci` run the tests (open `./test/ci/.tmp` to see a generated)
174 |
175 | ## License
176 |
177 | 2015-2016 MIT © [Mauricio Poppe](http://maurizzzio.com)
178 |
179 | [stop-using-grunt-gulp]: http://blog.keithcirkel.co.uk/why-we-should-stop-using-grunt/
180 | [stop]: http://blog.keithcirkel.co.uk/why-we-should-stop-using-grunt/
181 | [how-to]: http://blog.keithcirkel.co.uk/how-to-use-npm-as-a-build-tool/
182 | [task-automation]: http://substack.net/task_automation_with_npm_run
183 | [choose]: http://ponyfoo.com/articles/choose-grunt-gulp-or-npm
184 |
185 |
--------------------------------------------------------------------------------
/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # exit with non-zero exit code on failure
4 | set -e
5 |
6 | # Taken from https://medium.com/philosophy-logic/publishing-gh-pages-with-travis-ci-53a8270e87db
7 |
8 | cd test/ci/.tmp
9 | git config user.name "Travis CI"
10 | git add .
11 | git commit -m "[travis build #$TRAVIS_JOB_NUMBER] Automatic deploy from https://travis-ci.org/maurizzzio/generator-mnm"
12 | git push --force "https://${GH_TOKEN}@${GH_REF}" master > /dev/null 2>&1
13 |
14 |
--------------------------------------------------------------------------------
/generators/app/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | var defined = require('defined')
3 | var extend = require('extend')
4 | var toCase = require('to-case')
5 | var githubUsername = require('github-username')
6 | var normalizeUrl = require('normalize-url')
7 | var isUrl = require('is-url')
8 | var mkdirp = require('mkdirp')
9 |
10 | var Base = require('../base')
11 |
12 | module.exports = Base.extend({
13 | constructor: function () {
14 | Base.apply(this, arguments)
15 |
16 | this.argument('name', {
17 | type: String,
18 | required: false,
19 | desc: [
20 | 'module name',
21 | 'If provided the module will be created inside ./myAwesomeModule/',
22 | 'otherwise it will be created in the current directory',
23 | '',
24 | 'Examples:',
25 | '',
26 | ' $ yo mnm',
27 | ' $ yo mnm myAwesomeModule',
28 | '',
29 | ''
30 | ].join('\n ')
31 | })
32 |
33 | this.option('all', {
34 | type: Boolean,
35 | required: false,
36 | alias: 'a',
37 | default: false,
38 | desc: 'Ask all questions'
39 | })
40 |
41 | this.option('yes', {
42 | type: Boolean,
43 | required: false,
44 | alias: 'y',
45 | default: false,
46 | desc: 'Skip some questions, like $ npm init -y'
47 | })
48 |
49 | // TODO: performant npm
50 | // this.option('performant', {
51 | // type: Boolean,
52 | // required: false,
53 | // alias: 'p',
54 | // default: false,
55 | // desc: 'Install with pnpm instead of npm, make sure you have pnpm installed'
56 | // })
57 | },
58 |
59 | initializing: function () {
60 | this.savedAnswers = this._globalConfig.getAll().promptValues || {}
61 | this.shouldSkipAll = this.options.yes
62 | this.shouldAskAll = this.options.all
63 | var defaults = extend({}, this.savedAnswers, {
64 | moduleName: toCase.slug(this.name || this.appname),
65 | moduleDescription: '',
66 | moduleKeywords: '',
67 | moduleLicense: 'MIT',
68 | coverage: true,
69 | // additional not configurable props
70 | src: 'src/',
71 | dist: 'dist/',
72 | test: 'test/'
73 | })
74 | this.props = extend({}, defaults)
75 | if (this.shouldSkipAll && this.shouldAskAll) {
76 | this.log('You have chosen to ask both "all" and "minimum" questions!\n')
77 | return
78 | }
79 | },
80 |
81 | _checkEmpty: function (message) {
82 | return function (v) {
83 | if (!v.length) { return message }
84 | return true
85 | }
86 | },
87 |
88 | _checkUrl: function (urlMessage) {
89 | return function (v) {
90 | if (v.length && !isUrl(normalizeUrl(v))) return urlMessage
91 | return true
92 | }
93 | },
94 |
95 | _shouldAskUserInfo: function (prop) {
96 | return this.shouldAskAll || !defined(this.savedAnswers[prop])
97 | },
98 |
99 | prompting: {
100 | userInfo: function () {
101 | var prompts = [{
102 | name: 'name',
103 | message: 'Your name:',
104 | when: this._shouldAskUserInfo('name'),
105 | validate: this._checkEmpty('Your name is required'),
106 | store: true
107 | }, {
108 | name: 'email',
109 | message: 'Your email:',
110 | when: this._shouldAskUserInfo('email'),
111 | validate: this._checkEmpty('Your email is required'),
112 | store: true
113 | }, {
114 | name: 'website',
115 | message: 'Your website:',
116 | when: this._shouldAskUserInfo('website'),
117 | validate: this._checkUrl('The input is not a valid url'),
118 | filter: function (v) {
119 | if (v.indexOf('.') === -1) return v
120 | return normalizeUrl(v)
121 | },
122 | required: false,
123 | store: true
124 | }]
125 |
126 | var done = this.async()
127 | this.prompt(prompts, function (props) {
128 | extend(this.props, props)
129 | if (this.props.website) {
130 | this.props.website = normalizeUrl(this.props.website)
131 | }
132 | done()
133 | }.bind(this))
134 | },
135 |
136 | askForGithubAccount: function () {
137 | var self = this
138 | var done = this.async()
139 | githubUsername(this.props.email, function (err, username) {
140 | if (err) throw (err)
141 | self.prompt({
142 | name: 'githubUsername',
143 | message: 'Your github username:',
144 | when: self._shouldAskUserInfo('githubUsername'),
145 | store: true
146 | }, function (answers) {
147 | extend(self.props, answers)
148 | done()
149 | })
150 | })
151 | },
152 |
153 | moduleInfo: function () {
154 | var self = this
155 | var done = this.async()
156 | this.prompt([{
157 | name: 'moduleName',
158 | message: 'Module name:',
159 | default: this.props.moduleName,
160 | validate: this._checkEmpty('Module name required'),
161 | when: !this.shouldSkipAll,
162 | filter: function (v) {
163 | return toCase.slug(v || '')
164 | }
165 | }, {
166 | name: 'moduleDescription',
167 | message: 'Module description:',
168 | validate: this._checkEmpty('Module description required'),
169 | when: !this.shouldSkipAll
170 | }, {
171 | name: 'moduleKeywords',
172 | message: 'Module keywords (comma to split):',
173 | when: !this.shouldSkipAll,
174 | filter: function (value) {
175 | return (value || '').split(',')
176 | .map(function (el) { return el.trim() })
177 | .filter(Boolean)
178 | }
179 | }, {
180 | name: 'moduleLicense',
181 | message: 'License:',
182 | default: this.props.moduleLicense,
183 | when: !this.shouldSkipAll
184 | }], function (answers) {
185 | extend(self.props, answers)
186 | done()
187 | })
188 | },
189 |
190 | addOns: function () {
191 | // additional stuff
192 | // - cli
193 | // - code coverage
194 | var prompts = [{
195 | // type: 'confirm',
196 | // name: 'cli',
197 | // message: '❯ do you need a cli?',
198 | // when: this.options.cli === undefined,
199 | // default: false
200 | // }, {
201 | type: 'confirm',
202 | name: 'coverage',
203 | message: 'Do you need code coverage?',
204 | when: !this.shouldSkipAll,
205 | default: this.props.coverage
206 | }]
207 | var done = this.async()
208 | this.prompt(prompts, function (answers) {
209 | extend(this.props, answers)
210 | done()
211 | }.bind(this))
212 | }
213 | },
214 |
215 | writing: {
216 | pkg: function () {
217 | if (this.name) {
218 | // if the argument `name` is given create the project inside it
219 | mkdirp(this.props.moduleName)
220 | this.destinationRoot(this.destinationPath(this.props.moduleName))
221 | }
222 |
223 | // check if there's an existing package.json
224 | var currentPkg = this.fs.readJSON(this.destinationPath('package.json'), {})
225 | var pkg = {
226 | name: this.props.moduleName,
227 | version: '0.0.0',
228 | description: this.props.moduleDescription,
229 | license: this.props.moduleLicense,
230 | author: {
231 | name: this.props.name,
232 | email: this.props.email,
233 | url: this.props.website
234 | },
235 | main: this.props.dist + this.props.moduleName + '.js',
236 | module: this.props.dist + this.props.moduleName + '.mjs',
237 | 'jsnext:main': this.props.dist + this.props.moduleName + '.mjs',
238 | keywords: this.props.moduleKeywords,
239 | repository: this.props.githubUsername + '/' + this.props.moduleName,
240 | scripts: {},
241 | dependencies: {}
242 | }
243 |
244 | // Let's extend package.json so we're not overwriting user previous fields
245 | this.fs.writeJSON('package.json', extend(true, pkg, currentPkg))
246 | },
247 |
248 | gitignore: function () {
249 | this._gitignore(['.DS_Store', 'node_modules'])
250 | }
251 | },
252 |
253 | default: function () {
254 | // git init
255 | this.composeWith('git-init', {}, {
256 | local: require.resolve('generator-git-init/generators/app')
257 | })
258 |
259 | // src/index.js and test/index.js
260 | this.composeWith('mnm:src', {
261 | options: {
262 | src: this.props.src,
263 | dist: this.props.dist,
264 | 'skip-install': this.options['skip-install']
265 | }
266 | }, { local: require.resolve('../src') })
267 |
268 | this.composeWith('mnm:test', {
269 | options: {
270 | src: this.props.src,
271 | test: this.props.test,
272 | coverage: this.props.coverage,
273 | 'skip-install': this.options['skip-install']
274 | }
275 | }, { local: require.resolve('../test') })
276 |
277 | // TODO: make the generator receive a license field
278 | // if (!this.shouldSkipAll) {
279 | // this.composeWith('license', {
280 | // options: {
281 | // name: this.props.name,
282 | // email: this.props.email,
283 | // website: this.props.website
284 | // },
285 | // prompts: {license: 'MIT'}
286 | // }, { local: require.resolve('generator-license/app') })
287 | // }
288 |
289 | if (!this.fs.exists(this.destinationPath('README.md'))) {
290 | this.composeWith('mnm:readme', {
291 | options: {
292 | githubUsername: this.props.githubUsername,
293 | codecov: this.props.coverage,
294 | yes: this.shouldSkipAll
295 | }
296 | }, { local: require.resolve('../readme') })
297 | }
298 | }
299 |
300 | })
301 |
--------------------------------------------------------------------------------
/generators/base.js:
--------------------------------------------------------------------------------
1 | var yeoman = require('yeoman-generator')
2 | var extend = require('extend')
3 | var sortedObject = require('sorted-object')
4 | var depsObject = require('deps-object')
5 | var yaml = require('yamljs')
6 |
7 | module.exports = yeoman.Base.extend({
8 | _saveDepsToPkg: function (deps) {
9 | var pkg = this.fs.readJSON(this.destinationPath('package.json'), {})
10 | var currentDeps = pkg.devDependencies || {}
11 | var mergedDeps = extend({}, currentDeps, deps)
12 | var sortedDeps = sortedObject(mergedDeps)
13 | pkg.devDependencies = sortedDeps
14 | this.fs.writeJSON(this.destinationPath('package.json'), pkg)
15 | },
16 |
17 | _saveDeps: function (deps) {
18 | return depsObject(deps)
19 | .then(function (devDependencies) {
20 | this._saveDepsToPkg(devDependencies)
21 | }.bind(this))
22 | .catch(function (err) { throw err })
23 | },
24 |
25 | _travis: function (additional) {
26 | var travisPath = this.destinationPath('.travis.yml')
27 | var existing = this.fs.exists(travisPath)
28 | ? yaml.parse(this.fs.read(travisPath))
29 | : {}
30 | var result = Object.assign({
31 | language: 'node_js',
32 | node_js: ['stable']
33 | }, existing, additional)
34 |
35 | this.fs.write(
36 | this.destinationPath('.travis.yml'),
37 | yaml.stringify(result, 3, 2)
38 | )
39 | },
40 |
41 | _gitignore: function (ignores) {
42 | var giPath = this.destinationPath('.gitignore')
43 | var file = this.fs.read(giPath, { defaults: '' })
44 | ignores.forEach(function (v) {
45 | if (file.indexOf(v) === -1) {
46 | file += v + '\n'
47 | }
48 | })
49 | this.fs.write(giPath, file)
50 | }
51 | })
52 |
--------------------------------------------------------------------------------
/generators/cli/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | var toCase = require('to-case')
3 | var relative = require('relative')
4 | var defined = require('defined')
5 |
6 | var Base = require('../base')
7 |
8 | module.exports = Base.extend({
9 | constructor: function () {
10 | Base.apply(this, arguments)
11 |
12 | this.option('in', {
13 | type: String,
14 | required: false,
15 | defaults: 'bin/index.js',
16 | desc: 'The location of cli source code'
17 | })
18 |
19 | this.option('out', {
20 | type: String,
21 | required: false,
22 | defaults: 'bin/index.es5.js',
23 | desc: 'The path to your cli written in the bin property of package.json'
24 | })
25 |
26 | this.option('src', {
27 | type: String,
28 | required: false,
29 | defaults: 'dist/index.js',
30 | desc: "The location of the project's source file"
31 | })
32 | },
33 |
34 | writing: {
35 | pkg: function () {
36 | var pkg = this.fs.readJSON(this.destinationPath('package.json'), {})
37 | pkg.scripts = pkg.scripts || {}
38 | pkg.scripts['build:cli'] = pkg.scripts['build:cli'] || 'babel ' + this.options.in + ' -o ' + this.options.out
39 |
40 | // pkg.bin value
41 | // - pkg.bin if pkb.bin was already in package.json
42 | // - options.bin (an override to options.cli, useful when the cli file
43 | // is transpiled)
44 | pkg.bin = defined(pkg.bin, this.options.out, this.options.in)
45 | this.fs.writeJSON(this.destinationPath('package.json'), pkg)
46 | },
47 |
48 | pkgDeps: function () {
49 | return this._saveDeps(['yargs'])
50 | },
51 |
52 | cli: function () {
53 | var pkg = this.fs.readJSON(this.destinationPath('package.json'), {})
54 | var cliPath = this.options.in
55 | var srcPath = this.options.src
56 | var relativePath = relative(cliPath, srcPath)
57 | if (relativePath[0] !== '.') {
58 | relativePath = './' + relativePath
59 | }
60 |
61 | this.fs.copyTpl(
62 | this.templatePath('cli.tpl'),
63 | this.destinationPath(cliPath), {
64 | camelName: toCase.camel(pkg.name || this.appname),
65 | indexPath: relativePath
66 | }
67 | )
68 | }
69 | },
70 |
71 | install: function () {
72 | if (!this.options['skip-install']) {
73 | this.npmInstall()
74 | }
75 | }
76 | })
77 |
--------------------------------------------------------------------------------
/generators/cli/templates/cli.tpl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | 'use strict'
3 |
4 | import yargs from 'yargs'
5 |
6 | import <%= camelName %> from '<%= indexPath %>'
7 |
8 | yargs
9 | .usage('Usage: $0 [an argument]')
10 | .demand(1)
11 |
12 | <%= camelName %>(yargs.argv)
13 |
14 |
--------------------------------------------------------------------------------
/generators/readme/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | var toCase = require('to-case')
3 | var extend = require('extend')
4 | var parseAuthor = require('parse-author')
5 |
6 | var Base = require('../base')
7 |
8 | module.exports = Base.extend({
9 | constructor: function () {
10 | Base.apply(this, arguments)
11 |
12 | this.option('codecov', {
13 | type: Boolean,
14 | required: false,
15 | default: false,
16 | desc: 'Include the codecov badge'
17 | })
18 | },
19 |
20 | initializing: function () {
21 | this.shouldSkipAll = this.options.yes
22 | this.props = {
23 | badges: ['npm', 'travis', this.options.codecov && 'codecov'].filter(Boolean)
24 | }
25 | },
26 |
27 | prompting: {
28 | badges: function () {
29 | var done = this.async()
30 | this.prompt({
31 | type: 'checkbox',
32 | name: 'badges',
33 | message: 'Select the badges that you want in your README',
34 | choices: [
35 | { name: 'npm' },
36 | { name: 'travis' },
37 | { name: 'codecov' },
38 | { name: 'david' },
39 | { name: 'downloads' }
40 | ],
41 | default: this.props.badges,
42 | when: !this.shouldSkipAll
43 | }, function (answers) {
44 | extend(this.props, answers)
45 | done()
46 | }.bind(this))
47 | }
48 | },
49 |
50 | writing: function () {
51 | var pkg = this.fs.readJSON(this.destinationPath('package.json'), {})
52 | var authorInfo
53 | if (pkg.author && typeof pkg.author === 'object') {
54 | authorInfo = pkg.author
55 | } else if (typeof pkg.author === 'string') {
56 | authorInfo = parseAuthor(pkg.author)
57 | } else {
58 | authorInfo = {}
59 | }
60 |
61 | // get githubUsername from repository field
62 | // assume for simplicity that the field has the form
63 | //
64 | // githubUsername/moduleName
65 | //
66 | var githubUsername = (pkg.repository || '').split('/')[0]
67 |
68 | extend(this.props, {
69 | name: authorInfo.name || '',
70 | email: authorInfo.email || '',
71 | website: authorInfo.url || '',
72 | githubUsername: githubUsername,
73 | moduleName: (pkg.name || this.appname),
74 | moduleDescription: pkg.description || '',
75 | moduleLicense: pkg.license || ''
76 | })
77 | this.props.camelModuleName = toCase.camel(this.props.moduleName)
78 | this.fs.copyTpl(
79 | this.templatePath('README.tpl'),
80 | this.destinationPath('README.md'),
81 | this.props
82 | )
83 | }
84 | })
85 |
86 |
--------------------------------------------------------------------------------
/generators/readme/templates/README.tpl:
--------------------------------------------------------------------------------
1 | <%
2 | var b = []
3 | if (~badges.indexOf('npm')) b.push('[![NPM version][npm-image]][npm-url]')
4 | if (~badges.indexOf('travis')) b.push('[![Build Status][travis-image]][travis-url]')
5 | if (~badges.indexOf('codecov')) b.push('[![Codecov Status][codecov-image]][codecov-url]')
6 | if (~badges.indexOf('david')) b.push('[![Dependency Status][depstat-image]][depstat-url]')
7 | if (~badges.indexOf('downloads')) b.push('[![Downloads][download-image]][npm-url]')
8 | b.push('[![Standard][standard-image]][standard-url]')
9 | %>
10 |
11 | # <%= moduleName %>
12 | <%= b.join('\n') %>
13 |
14 | > <%= moduleDescription %>
15 |
16 | ## Install
17 |
18 | ```sh
19 | npm install --save <%= moduleName %>
20 | ```
21 |
22 | ## Usage
23 |
24 | ```js
25 | import <%= camelModuleName %> from '<%= moduleName %>'
26 |
27 | <%= camelModuleName %>()
28 | ```
29 |
30 | ## License
31 |
32 | <% if (moduleLicense) { %> <%= moduleLicense + " © " %> <% } %><%= "[" + name + "](" + website + ")" %>
33 |
34 | [npm-url]: https://npmjs.org/package/<%= moduleName %>
35 | [npm-image]: https://img.shields.io/npm/v/<%= moduleName %>.svg?style=flat
36 |
37 | [travis-url]: https://travis-ci.org/<%= githubUsername %>/<%= moduleName %>
38 | [travis-image]: https://img.shields.io/travis/<%= githubUsername %>/<%= moduleName %>.svg?style=flat
39 |
40 | [codecov-url]: https://codecov.io/github/<%= githubUsername %>/<%= moduleName %>
41 | [codecov-image]: https://img.shields.io/codecov/c/github/<%= githubUsername %>/<%= moduleName %>.svg?style=flat
42 |
43 | [depstat-url]: https://david-dm.org/<%= githubUsername %>/<%= moduleName %>
44 | [depstat-image]: https://david-dm.org/<%= githubUsername %>/<%= moduleName %>.svg?style=flat
45 |
46 | [download-image]: http://img.shields.io/npm/dm/<%= moduleName %>.svg?style=flat
47 |
48 | [standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat
49 | [standard-url]: http://standardjs.com/
50 |
51 |
--------------------------------------------------------------------------------
/generators/src/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | var path = require('path')
3 | var toCase = require('to-case')
4 |
5 | var Base = require('../base')
6 |
7 | module.exports = Base.extend({
8 | constructor: function () {
9 | Base.apply(this, arguments)
10 |
11 | this.option('src', {
12 | type: String,
13 | required: false,
14 | defaults: 'src/',
15 | desc: 'Source folder'
16 | })
17 |
18 | this.option('dist', {
19 | type: String,
20 | required: false,
21 | defaults: 'dist/',
22 | desc: 'Dist folder (after compilation with Babel)'
23 | })
24 | },
25 |
26 | writing: {
27 | pkgScripts: function () {
28 | function setTask (name, task) {
29 | scripts[name] = scripts[name] || task
30 | }
31 |
32 | var pkg = this.fs.readJSON(this.destinationPath('package.json'), {})
33 |
34 | var scripts = pkg.scripts || {}
35 | setTask('clean', 'rimraf ' + this.options.dist + ' && mkdirp ' + this.options.dist)
36 | setTask('lint', 'standard')
37 | setTask('changelog', 'conventional-changelog -p eslint -i CHANGELOG.md -s -r 0')
38 | setTask('prebuild', 'npm run clean -s && npm run lint -s')
39 | setTask('build', 'rollup --config')
40 | setTask('build:watch', 'npm run build -- --watch')
41 | // instead of runnning this on prepublish which doesn't work as expecte on
42 | // npm@3 run it on preversion, this is because it's highly unlikely to do
43 | // something after `npm version`
44 | setTask('preversion', 'npm run build')
45 | pkg.scripts = scripts
46 |
47 | // standard ignores
48 | // no need to ignore this.options.dist since it honors .gitignore
49 |
50 | // `files` is like !.npmignore, i.e. the strategy is to ignore everything
51 | // but what's included on this field
52 | //
53 | // include dist/ (ignored in .gitignore but added through `files`)
54 | // include src/ (jsnext:main compatibility)
55 | pkg.files = pkg.files || []
56 |
57 | var files = [this.options.src, this.options.dist]
58 | files.forEach(function (path) {
59 | if (pkg.files.indexOf(path) === -1) {
60 | pkg.files.push(path)
61 | }
62 | })
63 | this.fs.writeJSON(this.destinationPath('package.json'), pkg)
64 | },
65 |
66 | pkgDeps: function () {
67 | return this._saveDeps([
68 | 'rimraf', 'mkdirp', 'standard', 'conventional-changelog',
69 | 'rollup', 'rollup-plugin-babel', 'rollup-watch', 'babelrc-rollup'
70 | ])
71 | },
72 |
73 | templates: function () {
74 | var pkg = this.fs.readJSON(this.destinationPath('package.json'), {})
75 | var srcPath = path.join(this.options.src, 'index.js')
76 |
77 | // copy index.tpl as srcPath
78 | // e.g. src/index.js
79 | this.fs.copyTpl(
80 | this.templatePath('index.tpl'),
81 | this.destinationPath(srcPath), {}
82 | )
83 |
84 | // copy rollup.config.tpl to rollup.config.js
85 | this.fs.copyTpl(
86 | this.templatePath('rollup.config.tpl'),
87 | this.destinationPath('rollup.config.js'), {
88 | srcPath: srcPath,
89 | moduleName: toCase.camel(pkg.name || this.appname)
90 | }
91 | )
92 | },
93 |
94 | gitignore: function () {
95 | this._gitignore([this.options.dist])
96 | }
97 | },
98 |
99 | default: function () {
100 | // using my own .travis generator because the other one force defaults
101 | this._travis({
102 | script: 'npm run build'
103 | })
104 |
105 | this.composeWith('babel', {
106 | options: {
107 | 'skip-install': this.options['skip-install'],
108 | config: {
109 | plugins: ['external-helpers']
110 | }
111 | }
112 | }, { local: require.resolve('generator-babel/generators/app') })
113 | },
114 |
115 | install: function () {
116 | if (!this.options['skip-install']) {
117 | this.npmInstall()
118 | }
119 | }
120 | })
121 |
--------------------------------------------------------------------------------
/generators/src/templates/index.tpl:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | export default awesome => {
4 | return `everything is <%= "${awesome}" %>`
5 | }
6 |
7 |
--------------------------------------------------------------------------------
/generators/src/templates/rollup.config.tpl:
--------------------------------------------------------------------------------
1 | import babel from 'rollup-plugin-babel'
2 | import babelrc from 'babelrc-rollup'
3 |
4 | let pkg = require('./package.json')
5 | let external = Object.keys(pkg.dependencies)
6 |
7 | export default {
8 | entry: '<%= srcPath %>',
9 | plugins: [ babel(babelrc()) ],
10 | external: external,
11 | targets: [{
12 | dest: pkg['main'],
13 | format: 'cjs'
14 | }, {
15 | dest: pkg['jsnext:main'],
16 | format: 'es'
17 | }]
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/generators/test/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | var path = require('path')
3 | var toCase = require('to-case')
4 | var relative = require('relative')
5 |
6 | var Base = require('../base')
7 |
8 | module.exports = Base.extend({
9 | constructor: function () {
10 | Base.apply(this, arguments)
11 |
12 | this.option('src', {
13 | type: String,
14 | required: false,
15 | defaults: 'src/',
16 | desc: 'Source code folder (relative to the project root)'
17 | })
18 |
19 | this.option('test', {
20 | type: String,
21 | required: false,
22 | defaults: 'test/',
23 | desc: 'Source code folder for the tests (relative to the project root)'
24 | })
25 |
26 | this.option('coverage', {
27 | type: Boolean,
28 | required: false,
29 | defaults: false,
30 | desc: 'Include code coverage script?'
31 | })
32 | },
33 |
34 | writing: {
35 | pkg: function () {
36 | var pkg = this.fs.readJSON(this.destinationPath('package.json'), {})
37 | pkg.scripts = pkg.scripts || {}
38 |
39 | // force the inclusion of these scripts
40 | // this is because initially "test": "echo no tests"
41 | pkg.scripts.test = 'ava'
42 | pkg.scripts['test:watch'] = 'npm test -- --watch'
43 | if (this.options.coverage) {
44 | // note that this will only be run on a CI server
45 | pkg.scripts.coverage = pkg.scripts.coverage || 'nyc npm test && nyc report --reporter=text-lcov > coverage.lcov && codecov'
46 | }
47 |
48 | // ava configuration
49 | pkg.ava = pkg.ava || {}
50 | pkg.ava.require = ['babel-register']
51 |
52 | this.fs.writeJSON('package.json', pkg)
53 | },
54 |
55 | pkgDeps: function () {
56 | return this._saveDeps(['ava'])
57 | },
58 |
59 | gitignore: function () {
60 | if (this.options.coverage) {
61 | return this._gitignore(['coverage', '.nyc_output'])
62 | }
63 | },
64 |
65 | templates: function () {
66 | var pkg = this.fs.readJSON(this.destinationPath('package.json'), {})
67 | var testPath = path.join(this.options.test, 'index.js')
68 | var srcPath = path.join(this.options.src, 'index.js')
69 | var relativePath = relative(testPath, srcPath)
70 | if (relativePath[0] !== '.') {
71 | relativePath = './' + relativePath
72 | }
73 |
74 | this.fs.copyTpl(
75 | this.templatePath('test.tpl'),
76 | this.destinationPath(testPath), {
77 | camelName: toCase.camel(pkg.name || this.appname),
78 | // computes the relative from `test` to `index`
79 | // e.g. from test/ to src/index.js = ../src/index.js
80 | indexPath: relativePath
81 | }
82 | )
83 | }
84 | },
85 |
86 | default: function () {
87 | if (this.options.coverage) {
88 | this._travis({
89 | before_install: 'npm install codecov && npm install nyc',
90 | after_success: 'npm run coverage'
91 | })
92 | }
93 | },
94 |
95 | install: function () {
96 | if (!this.options['skip-install']) {
97 | this.npmInstall()
98 | }
99 | }
100 | })
101 |
--------------------------------------------------------------------------------
/generators/test/templates/test.tpl:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import <%= camelName %> from '<%= indexPath %>'
4 | import test from 'ava'
5 |
6 | test('awesome:test', t => {
7 | const message = 'everything is awesome'
8 | t.is(<%= camelName %>('awesome'), message, message)
9 | })
10 |
11 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | app: require.resolve('./generators/app'),
3 | boilerplate: require.resolve('./generators/boilerplate'),
4 | readme: require.resolve('./generators/readme'),
5 | rollup: require.resolve('./generators/rollup'),
6 | git: require.resolve('./generators/git'),
7 | cli: require.resolve('./generators/cli')
8 | }
9 |
10 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "generator-mnm",
3 | "version": "0.6.0",
4 | "description": "Create node modules writing ES6 today compiled with Babel, tested with ava and linted with standard on top of npm scripts Create node modules with es6, test with tape on top of npm scripts",
5 | "license": "MIT",
6 | "main": "index.js",
7 | "repository": "maurizzzio/generator-mnm",
8 | "author": {
9 | "name": "Mauricio Poppe",
10 | "url": "https://github.com/maurizzzio"
11 | },
12 | "engines": {
13 | "node": ">=4"
14 | },
15 | "scripts": {
16 | "lint": "standard",
17 | "test": "mocha test/generators/*.js",
18 | "test:ci": "mocha test/ci/*.js"
19 | },
20 | "files": [
21 | "generators",
22 | "index.js"
23 | ],
24 | "keywords": [
25 | "mnm",
26 | "yeoman-generator",
27 | "boilerplate",
28 | "es6",
29 | "node",
30 | "module",
31 | "starter",
32 | "yeoman",
33 | "scaffold",
34 | "node-module",
35 | "npm scripts",
36 | "generator",
37 | "yo"
38 | ],
39 | "dependencies": {
40 | "defined": "^1.0.0",
41 | "deps-object": "^2.0.2",
42 | "extend": "^3.0.0",
43 | "generator-babel": "^2.0.2",
44 | "generator-git-init": "^1.0.4",
45 | "generator-license": "^3.1.1",
46 | "github-username": "^2.1.0",
47 | "is-url": "^1.2.1",
48 | "mkdirp": "^0.5.1",
49 | "normalize-url": "^1.5.2",
50 | "parse-author": "^1.0.0",
51 | "relative": "^3.0.2",
52 | "sorted-object": "^2.0.0",
53 | "to-case": "^2.0.0",
54 | "yamljs": "^0.2.8",
55 | "yeoman-generator": "^0.22.6"
56 | },
57 | "devDependencies": {
58 | "async-series": "0.0.1",
59 | "mocha": "^2.4.5",
60 | "mockery": "^1.4.0",
61 | "pinkie-promise": "^2.0.1",
62 | "standard": "^7.0.1",
63 | "yeoman-assert": "^2.2.1",
64 | "yeoman-test": "^1.4.0"
65 | },
66 | "standard": {
67 | "env": [
68 | "mocha"
69 | ]
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/test/ci/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | var path = require('path')
4 | var assert = require('yeoman-assert')
5 | var helpers = require('yeoman-test')
6 | var exec = require('child_process').exec
7 | var series = require('async-series')
8 |
9 | describe('generator-mnm on CI', function () {
10 | this.timeout(600000)
11 |
12 | function handleProcess (command, done) {
13 | exec(command, function (err) {
14 | if (err) { return done(err) }
15 | done(null)
16 | })
17 | }
18 |
19 | before(function (done) {
20 | helpers.run(path.join(__dirname, '../../generators/app'))
21 | .inDir(path.join(__dirname, '.tmp'))
22 | .withOptions({ skipInstall: false })
23 | .withPrompts({
24 | name: 'Mauricio Poppe',
25 | email: 'foo@bar.com',
26 | url: 'http://maurizzzio.com',
27 | githubUsername: 'maurizzzio',
28 | moduleName: 'generator-mnm-example',
29 | moduleDescription: 'An example of the generator https://github.com/maurizzzio/generator-mnm',
30 | moduleLicense: 'MIT',
31 | moduleKeywords: ['generator', 'example', 'mnm'],
32 | // addons
33 | coverage: true,
34 | // generator-license/app
35 | // license: 'MIT',
36 | // ./generators/readme
37 | badges: ['npm', 'travis', 'codecov', 'david', 'downloads']
38 | })
39 | .on('end', done)
40 | })
41 |
42 | describe('with default options', function () {
43 | it('should have the required files in package.json', function () {
44 | assert.file('package.json')
45 | assert.JSONFileContent('package.json', {
46 | name: 'generator-mnm-example',
47 | version: '0.0.0',
48 | main: 'dist/generator-mnm-example.js',
49 | module: 'dist/generator-mnm-example.mjs',
50 | 'jsnext:main': 'dist/generator-mnm-example.mjs',
51 | license: 'MIT'
52 | })
53 | })
54 |
55 | it('should have the required contents in .babelrc', function () {
56 | assert.file('.babelrc')
57 | assert.JSONFileContent('.babelrc', {
58 | presets: ['es2015']
59 | })
60 | })
61 |
62 | it('should have the required contents in .travis.yml', function () {
63 | assert.file('.travis.yml')
64 | assert.fileContent('.travis.yml', 'npm run build')
65 | assert.fileContent('.travis.yml', 'npm run coverage')
66 | })
67 |
68 | it('should execute package.json scripts', function (done) {
69 | series([
70 | function (cb) { handleProcess('npm run build', cb) },
71 | function (cb) { handleProcess('npm test', cb) }
72 | ], done)
73 | })
74 |
75 | it('should be compatible with commonjs\' require', function (done) {
76 | handleProcess('node -e "require(\'./dist/generator-mnm-example.js\')(\'awesome\')"', done)
77 | })
78 | })
79 | })
80 |
81 |
--------------------------------------------------------------------------------
/test/generators/app.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | var path = require('path')
4 | var extend = require('extend')
5 | var assert = require('yeoman-assert')
6 | var helpers = require('yeoman-test')
7 | var answers = require('../helpers/answers.json')
8 |
9 | describe('node-mnm:app', function () {
10 | this.timeout(20000)
11 |
12 | require('../helpers/set-up-mockery')(before, after)
13 |
14 | describe('running on new project', function () {
15 | before(function () {
16 | return helpers.run(path.join(__dirname, '../../generators/app'))
17 | .inDir(path.join(__dirname, '.tmp'))
18 | .withPrompts(extend(answers, {}))
19 | .toPromise()
20 | })
21 |
22 | it('creates files', function () {
23 | assert.file([
24 | '.travis.yml',
25 | '.gitignore',
26 | 'README.md',
27 | 'src/index.js',
28 | 'test/index.js'
29 | ])
30 | })
31 |
32 | it('creates package.json', function () {
33 | assert.file('package.json')
34 | assert.JSONFileContent('package.json', {
35 | name: answers.moduleName,
36 | version: '0.0.0',
37 | description: answers.moduleDescription,
38 | license: answers.moduleLicense,
39 | author: {
40 | name: answers.name,
41 | email: answers.email,
42 | url: 'http://' + answers.website
43 | },
44 | main: 'dist/' + answers.moduleName + '.js',
45 | module: 'dist/' + answers.moduleName + '.mjs',
46 | 'jsnext:main': 'dist/' + answers.moduleName + '.mjs',
47 | keywords: answers.moduleKeywords,
48 | repository: answers.githubUsername + '/' + answers.moduleName
49 | })
50 | })
51 |
52 | it('creates and fill contents in README.md', function () {
53 | assert.file('README.md')
54 | assert.fileContent('README.md', 'import generatorMnm from \'generator-mnm\'')
55 | assert.fileContent('README.md', '> A node module generator')
56 | assert.fileContent('README.md', 'npm install --save generator-mnm')
57 | assert.fileContent('README.md', 'MIT')
58 | assert.fileContent('README.md', '[Mauricio Poppe](http://maurizzzio.com)')
59 | assert.fileContent('README.md', '[travis-image]: https://img.shields.io/travis/maurizzzio/generator-mnm.svg')
60 | assert.fileContent('README.md', '[![Codecov Status][codecov-image]][codecov-url]')
61 | })
62 |
63 | it('creates a valid .npmignore file', function () {
64 | assert.file('.gitignore')
65 | assert.fileContent('.gitignore', '.DS_Store')
66 | assert.fileContent('.gitignore', 'node_modules')
67 | assert.fileContent('.gitignore', 'dist/')
68 | assert.fileContent('.gitignore', '.nyc_output')
69 | assert.fileContent('.gitignore', 'coverage')
70 | })
71 | })
72 | })
73 |
--------------------------------------------------------------------------------
/test/generators/cli.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var assert = require('yeoman-assert')
3 | var helpers = require('yeoman-test')
4 |
5 | require('../helpers/set-up-mockery')(before, after)
6 |
7 | describe('mnm::cli', function () {
8 | this.timeout(10000)
9 |
10 | describe('cli with default options', function () {
11 | before(function () {
12 | return helpers.run(path.join(__dirname, '../../generators/cli'))
13 | .inDir(path.join(__dirname, '.tmp'))
14 | .toPromise()
15 | })
16 |
17 | it('has a cli file', function () {
18 | assert.file('bin/index.js')
19 | })
20 |
21 | it('has a valid bin path in package.json', function () {
22 | assert.file('package.json')
23 | assert.JSONFileContent('package.json', {
24 | bin: 'bin/index.es5.js'
25 | })
26 | })
27 |
28 | it('has a script to build the cli', function () {
29 | assert.fileContent('package.json', 'build:cli')
30 | assert.fileContent('package.json', 'babel bin/index.js -o bin/index.es5.js')
31 | })
32 |
33 | it('has the correct file contents', function () {
34 | assert.file('bin/index.js')
35 | assert.fileContent('bin/index.js', '\'../dist/index.js\'')
36 | assert.fileContent('bin/index.js', '\'yargs\'')
37 | })
38 | })
39 | })
40 |
41 |
--------------------------------------------------------------------------------
/test/generators/readme.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var assert = require('yeoman-assert')
3 | var helpers = require('yeoman-test')
4 |
5 | require('../helpers/set-up-mockery')(before, after)
6 |
7 | describe('mnm::readme', function () {
8 | this.timeout(10000)
9 | describe('readme', function () {
10 | before(function () {
11 | return helpers.run(path.join(__dirname, '../../generators/readme'))
12 | .inDir(path.join(__dirname, '.tmp'))
13 | .toPromise()
14 | })
15 |
16 | it('creates a readme file', function () {
17 | assert.file('README.md')
18 | })
19 | })
20 | })
21 |
--------------------------------------------------------------------------------
/test/generators/src.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var assert = require('yeoman-assert')
3 | var helpers = require('yeoman-test')
4 |
5 | require('../helpers/set-up-mockery')(before, after)
6 |
7 | describe('mnm::src', function () {
8 | this.timeout(10000)
9 |
10 | describe('with default options', function () {
11 | before(function () {
12 | return helpers.run(path.join(__dirname, '../../generators/src'))
13 | .inDir(path.join(__dirname, '.tmp'))
14 | .toPromise()
15 | })
16 |
17 | it('creates a source file', function () {
18 | assert.file('src/index.js')
19 | assert.file('rollup.config.js')
20 | })
21 |
22 | it('modifies package.json scripts field', function () {
23 | assert.fileContent('package.json', '"lint": "standard"')
24 | assert.fileContent('package.json', '"clean": "rimraf dist/ && mkdirp dist/"')
25 | assert.fileContent('package.json', '"prebuild": "npm run clean -s && npm run lint -s"')
26 | assert.fileContent('package.json', '"build": "rollup --config"')
27 | assert.fileContent('package.json', '"build:watch": "npm run build -- --watch"')
28 | })
29 |
30 | it('modifies package.json files field', function () {
31 | assert.JSONFileContent('package.json', {
32 | files: ['src/', 'dist/']
33 | })
34 | })
35 |
36 | it('modifies package.json devDependencies field', function () {
37 | assert.JSONFileContent('package.json', {
38 | // NOTE: this should be updated when mnm dependencies are updated
39 | devDependencies: {
40 | 'babel-cli': '6.6.5',
41 | 'babel-register': '6.7.2',
42 | 'babel-preset-es2015': '*',
43 | rimraf: '*',
44 | mkdirp: '*',
45 | standard: '*'
46 | }
47 | })
48 | })
49 |
50 | it('creates/modifies .gitignore', function () {
51 | assert.file('.gitignore')
52 | assert.fileContent('.gitignore', 'dist/')
53 | })
54 |
55 | it('creates/modifies .travis.yml', function () {
56 | assert.file('.travis.yml')
57 | assert.fileContent('.travis.yml', 'script: \'npm run build\'')
58 | })
59 | })
60 |
61 | describe('with options', function () {
62 | before(function () {
63 | return helpers.run(path.join(__dirname, '../../generators/src'))
64 | .inDir(path.join(__dirname, '.tmp'))
65 | .withOptions({
66 | src: 'lib/',
67 | dist: 'build/'
68 | })
69 | .toPromise()
70 | })
71 |
72 | it('creates a source file', function () {
73 | assert.file('lib/index.js')
74 | })
75 |
76 | it('modifies package.json files field', function () {
77 | assert.JSONFileContent('package.json', {
78 | files: ['lib/', 'build/']
79 | })
80 | })
81 |
82 | it('creates/modifies .gitignore', function () {
83 | assert.file('.gitignore')
84 | assert.fileContent('.gitignore', 'build/')
85 | })
86 |
87 | it('modifies package.json scripts field', function () {
88 | assert.fileContent('package.json', '"build": "rollup --config"')
89 | })
90 | })
91 | })
92 |
--------------------------------------------------------------------------------
/test/generators/test.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 | var assert = require('yeoman-assert')
3 | var helpers = require('yeoman-test')
4 |
5 | describe('mnm::test', function () {
6 | this.timeout(10000)
7 |
8 | require('../helpers/set-up-mockery')(before, after)
9 |
10 | describe('test with default options', function () {
11 | before(function () {
12 | return helpers.run(path.join(__dirname, '../../generators/test'))
13 | .inDir(path.join(__dirname, '.tmp'))
14 | .toPromise()
15 | })
16 |
17 | it('creates test/index.js', function () {
18 | assert.file('test/index.js')
19 | assert.fileContent('test/index.js', 'import test from \'ava\'')
20 | })
21 |
22 | it('modifies package.json devDependencies field', function () {
23 | assert.JSONFileContent('package.json', {
24 | devDependencies: {
25 | ava: '*'
26 | }
27 | })
28 | })
29 |
30 | it('modifies package.json scripts field', function () {
31 | assert.fileContent('package.json', '"test": "ava"')
32 | assert.fileContent('package.json', '"test:watch": "npm test -- --watch"')
33 | assert.JSONFileContent('package.json', {
34 | ava: { require: ['babel-register'] }
35 | })
36 | })
37 | })
38 |
39 | describe('with coverage on', function () {
40 | before(function () {
41 | return helpers.run(path.join(__dirname, '../../generators/test'))
42 | .inDir(path.join(__dirname, '.tmp'))
43 | .withOptions({ coverage: true })
44 | .toPromise()
45 | })
46 |
47 | it('modifies package.json scripts field', function () {
48 | assert.fileContent('package.json', '"coverage": "nyc npm test && nyc report --reporter=text-lcov > coverage.lcov && codecov"')
49 | })
50 |
51 | it('creates/modifies .gitignore', function () {
52 | assert.file('.gitignore')
53 | assert.fileContent('.gitignore', '.nyc_output')
54 | assert.fileContent('.gitignore', 'coverage')
55 | })
56 |
57 | it('creates/modifies .travis.yml', function () {
58 | assert.file('.travis.yml')
59 | assert.fileContent('.travis.yml', 'before_install: \'npm install codecov && npm install nyc\'')
60 | assert.fileContent('.travis.yml', 'after_success: \'npm run coverage\'')
61 | })
62 | })
63 | })
64 |
--------------------------------------------------------------------------------
/test/helpers/answers.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Mauricio Poppe",
3 | "website": "maurizzzio.com",
4 | "githubUsername": "maurizzzio",
5 | "moduleName": "generator-mnm",
6 | "moduleDescription": "A node module generator",
7 | "moduleKeywords": ["foo", "bar"],
8 | "moduleLicense": "MIT"
9 | }
10 |
--------------------------------------------------------------------------------
/test/helpers/set-up-mockery.js:
--------------------------------------------------------------------------------
1 | var mockery = require('mockery')
2 | var helpers = require('yeoman-test')
3 | var Promise = require('pinkie-promise')
4 |
5 | module.exports = function (before, after) {
6 | before(function () {
7 | mockery.enable({
8 | warnOnUnregistered: false
9 | })
10 |
11 | mockery.registerMock('npm-name', function (name, cb) {
12 | cb(null, true)
13 | })
14 |
15 | mockery.registerMock('github-username', function (name, cb) {
16 | cb(null, 'unicornUser')
17 | })
18 |
19 | mockery.registerMock(
20 | require.resolve('generator-license/app'),
21 | helpers.createDummyGenerator()
22 | )
23 |
24 | mockery.registerMock('deps-object', function (deps) {
25 | var obj = deps.reduce(function (o, v) {
26 | var tok = v.split('@')
27 | if (tok.length === 1) tok.push('*')
28 | o[tok[0]] = tok[1]
29 | return o
30 | }, {})
31 | return Promise.resolve(obj)
32 | })
33 | })
34 |
35 | after(function () {
36 | mockery.disable()
37 | })
38 | }
39 |
40 |
--------------------------------------------------------------------------------