├── .gitignore ├── LICENSE ├── README.md ├── assets └── preview.png ├── bin ├── steps │ ├── log-error.js │ ├── log-newline.js │ ├── log-success.js │ ├── log-welcome.js │ ├── prompt-author.js │ ├── prompt-description.js │ ├── prompt-git-origin.js │ ├── prompt-git.js │ ├── prompt-license.js │ ├── prompt-name.js │ ├── prompt-private.js │ ├── prompt-readme.js │ ├── prompt-version.js │ ├── update-changelog.js │ ├── update-git.js │ ├── update-license.js │ ├── update-packagejson.js │ └── update-readme.js ├── unboil.js └── utils │ ├── ensure-file.js │ └── sh-basic.js ├── package.json └── templates ├── licenses ├── agpl3.txt ├── apache.txt ├── bsd2.txt ├── bsd3.txt ├── gpl2.txt ├── gpl3.txt ├── isc.txt ├── lgpl.txt ├── mit.txt ├── mpl.txt └── wtfpl.txt └── readme.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | *.DS_Store 40 | .AppleDouble 41 | .LSOverride 42 | 43 | # Icon must end with two \r 44 | Icon 45 | 46 | 47 | # Thumbnails 48 | ._* 49 | 50 | # Files that might appear in the root of a volume 51 | .DocumentRevisions-V100 52 | .fseventsd 53 | .Spotlight-V100 54 | .TemporaryItems 55 | .Trashes 56 | .VolumeIcon.icns 57 | .com.apple.timemachine.donotpresent 58 | 59 | # Directories potentially created on remote AFP share 60 | .AppleDB 61 | .AppleDesktop 62 | Network Trash Folder 63 | Temporary Items 64 | .apdisk 65 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 brocessing 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 |

2 | logo 3 |

4 | 5 |

unboil

6 |

Boilerplate customiser for lazy people

7 |
8 | 9 | 10 | License 11 | 12 | 13 | 14 | Standard 15 | 16 | 17 | 18 | Standard 19 | 20 |
21 | 22 |
23 |
24 |
25 | 26 | ## Features 27 | - Fancy CLI interface to generate a new project from a boilerplate 28 | - Update & customize existing `package.json` 29 | - Update existing `LICENSE` accordingly to the updated package.json, create it if none 30 | - Update existing `README`, create it if none 31 | - Clear existing `.git` 32 | - Quickly re-init the git folder and add your git remote repository 33 | - Minimal module: only 4 dependencies 34 | 35 | ## Installation 36 | ```sh 37 | $ npm install -g unboil 38 | ``` 39 | 40 | ## Usage 41 | ```sh 42 | $ cd my-project 43 | $ unboil 44 | ``` 45 | 46 | ## License 47 | [MIT](https://tldrlegal.com/license/mit-license). 48 | -------------------------------------------------------------------------------- /assets/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brocessing/unboil/0022484c5f32ae72e43fe7cdb763719ecf4c2c8c/assets/preview.png -------------------------------------------------------------------------------- /bin/steps/log-error.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const sh = require('kool-shell')() 4 | .use(require('kool-shell/plugins/log')) 5 | 6 | module.exports = function (err, state) { 7 | process.stdout.write('\n') 8 | const msg = (err && err.message) ? err.message : err 9 | sh.error(msg + '\n') 10 | if (err.message && err.stack) sh.log(err.stack) 11 | } 12 | -------------------------------------------------------------------------------- /bin/steps/log-newline.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const sh = require('../utils/sh-basic') 4 | 5 | module.exports = function (state, next) { 6 | sh.log('') 7 | next(null, state) 8 | } -------------------------------------------------------------------------------- /bin/steps/log-success.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const sh = require('kool-shell')() 4 | .use(require('kool-shell/plugins/log')) 5 | 6 | module.exports = function (err, state) { 7 | process.stdout.write('\n') 8 | sh.success(sh.colors.yellow(state.package.name) + ' is unboiled !\n') 9 | } 10 | -------------------------------------------------------------------------------- /bin/steps/log-welcome.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const colors = require('kool-shell/utils/colors') 4 | const sh = require('kool-shell')() 5 | .use(require('kool-shell/plugins/log')) 6 | 7 | module.exports = function (next) { 8 | process.stdout.write('\n') 9 | sh.info(colors.gray('🍳 Unboiling ' + process.cwd())) 10 | 11 | // initialize the state flow 12 | next(null, { 13 | package: {}, 14 | tasks: {} 15 | }) 16 | } 17 | -------------------------------------------------------------------------------- /bin/steps/prompt-author.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const sh = require('kool-shell')() 4 | .use(require('kool-shell/plugins/input')) 5 | .use(require('kool-shell/plugins/exec')) 6 | 7 | function ask (author) { 8 | const def = author && author !== '' ? author : false 9 | const label = def ? 'Author: (' + def + ')' : 'Author:' 10 | return sh.input(label, { 11 | onSubmit: answer => def && (!answer || answer === '') ? def : answer 12 | }) 13 | } 14 | 15 | module.exports = function (state, next) { 16 | sh.silentExec('git', ['config', 'user.name']) 17 | .then(out => out.stdout) 18 | .catch(out => '') 19 | .then(ask) 20 | .then(author => { 21 | state.package.author = author 22 | next(null, state) 23 | }) 24 | .catch(err => next(err, state)) 25 | } 26 | -------------------------------------------------------------------------------- /bin/steps/prompt-description.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const sh = require('kool-shell')() 4 | .use(require('kool-shell/plugins/input')) 5 | 6 | module.exports = function (state, next) { 7 | sh.input('Description:', { onSubmit: answer => answer.trim() }) 8 | .then(description => { 9 | state.package.description = description 10 | next(null, state) 11 | }) 12 | .catch(err => next(err, state)) 13 | } 14 | -------------------------------------------------------------------------------- /bin/steps/prompt-git-origin.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const sh = require('../utils/sh-basic') 4 | 5 | const REGEX = /^(git@([a-z0-9._~/?#\[\]@!$&'()*+,;=`-]+):|https?:\/\/([a-z0-9._~?#\[\]@!$&'()*+,;=`-]+)\/)([a-z0-9._~:/?#\[\]@!$&'()*+,;=`-]+)\.git$/i 6 | 7 | const GIT_DOMAINS = [ 8 | 'www.bitbucket.org', 9 | 'bitbucket.org', 10 | 'www.github.com', 11 | 'github.com', 12 | 'www.gitlab.com', 13 | 'gitlab.com' 14 | ] 15 | 16 | 17 | function validate (answer = '') { 18 | let url = (answer + '').trim() 19 | if (url.substr(-1, 1) === '/') url = url.slice(0, -1) 20 | if (url.substr(-4, 4) !== '.git') url += '.git' 21 | 22 | const result = url.match(REGEX) 23 | if (!result) { 24 | sh.error('Invalid repository origin') 25 | return ask() 26 | } 27 | const host = result[2] || result[3] 28 | const path = result[4] 29 | return { host, path, url } 30 | } 31 | 32 | function ask () { 33 | return sh.input('Repository origin (ssh/https):', { onSubmit: validate }) 34 | } 35 | 36 | module.exports = function (state, next) { 37 | if (!state.hasGitRepo) return next(null, state) 38 | 39 | ask() 40 | .then(({ host, path, url }) => { 41 | 42 | state.gitOriginUrl = url 43 | 44 | state.package.repository = { 45 | type: 'git', 46 | url: 'git+' + url 47 | } 48 | 49 | if (~GIT_DOMAINS.indexOf(host)) { 50 | const projectUrl = `https://${host}/${path}` 51 | state.package.homepage = projectUrl + '#readme' 52 | state.package.bugs = { url: projectUrl + '/issues' } 53 | } 54 | 55 | next(null, state) 56 | }) 57 | .catch(err => next(err, state)) 58 | } 59 | -------------------------------------------------------------------------------- /bin/steps/prompt-git.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fs = require('fs-extra') 4 | const path = require('path') 5 | const sh = require('kool-shell')() 6 | .use(require('kool-shell/plugins/log')) 7 | .use(require('kool-shell/plugins/input')) 8 | 9 | const GIT_PATH = path.join(process.cwd(), '.git') 10 | 11 | function ask(name) { 12 | return sh.input( 13 | `Does ${sh.colors.yellow(name)} have a git repository? (yes)`, 14 | { onSubmit: answer => !answer.match(/^no?$/i) } 15 | ) 16 | } 17 | 18 | module.exports = function (state, next) { 19 | fs.pathExists(GIT_PATH) 20 | .then(exists => exists ? ask(state.package.name) : false) 21 | .then(answer => { 22 | state.hasGitRepo = !!answer 23 | state.package.homepage = null 24 | state.package.bugs = null 25 | state.package.repository = null 26 | next(null, state) 27 | }) 28 | .catch(err => next(err, state)) 29 | } 30 | -------------------------------------------------------------------------------- /bin/steps/prompt-license.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const { license } = require('../../package.json') 4 | const sh = require('kool-shell')() 5 | .use(require('kool-shell/plugins/input')) 6 | 7 | const DEFAULT_LICENSE = license || 'MIT' 8 | const def = val => val === undefined || val === '' ? DEFAULT_LICENSE : val 9 | 10 | function ask() { 11 | return sh.input(`License: (${DEFAULT_LICENSE})`, { 12 | onSubmit: answer => def(answer).trim() 13 | }) 14 | } 15 | 16 | module.exports = function (state, next) { 17 | ask() 18 | .then(license => { 19 | // @TODO : if (license !== DEFAULT_LICENSE) update LICENSE file 20 | state.package.license = license 21 | next(null, state) 22 | }) 23 | .catch(err => next(err, state)) 24 | } 25 | -------------------------------------------------------------------------------- /bin/steps/prompt-name.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const slug = require('slug') 4 | const path = require('path') 5 | const sh = require('../utils/sh-basic') 6 | 7 | const DEFAULT_NAME = slug(path.basename(process.cwd())) 8 | 9 | const def = val => val === undefined || val === '' ? DEFAULT_NAME : val 10 | 11 | const errors = { 12 | noName: 'You must provide a name to create a module', 13 | tooLong: 'Module name can\'t contain more than 214 characters', 14 | badStartChar: 'Module name can only start with a lowercase alphabetic character', 15 | badChar: 'Module name should contain only lowercase alphanumeric characters, dots, hyphens, and underscores', 16 | badTrimming: 'Module name cannot contain leading or trailing spaces' 17 | } 18 | 19 | function realName (slug) { 20 | return slug 21 | .split('-') 22 | .map(w => w.charAt(0).toUpperCase() + w.substring(1)) 23 | .join(' ') 24 | } 25 | 26 | function validateName (name, cb) { 27 | if (name === undefined || typeof name !== 'string' || name.length === 0) { return cb(errors.noName) } 28 | if (name.length > 214) return cb(errors.tooLong) 29 | if (name.trim() !== name) return cb(errors.badTrimming) 30 | if (!name.match(/^[a-z]/)) return cb(errors.badStartChar) 31 | if (!name.match(/^[a-z0-9_\-.]*$/)) return cb(errors.badChar) 32 | 33 | return cb(null, name) 34 | } 35 | 36 | function ask () { 37 | return sh.input(`Name: (${DEFAULT_NAME})`, { 38 | onSubmit: answer => { 39 | return validateName(def(answer.trim()), (err, name) => { 40 | if (err) { 41 | sh.error(err) 42 | return ask() 43 | } else return name 44 | }) 45 | } 46 | }) 47 | } 48 | 49 | module.exports = function (state, next) { 50 | ask() 51 | .then(name => { 52 | state.package.name = name 53 | state.name = realName(name) 54 | next(null, state) 55 | }) 56 | .catch(err => next(err, state)) 57 | } 58 | -------------------------------------------------------------------------------- /bin/steps/prompt-private.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fs = require('fs-extra') 4 | const path = require('path') 5 | const sh = require('kool-shell')() 6 | .use(require('kool-shell/plugins/log')) 7 | .use(require('kool-shell/plugins/input')) 8 | 9 | function ask(name) { 10 | return sh.input( 11 | `Is ${sh.colors.yellow(name)} a private package? (no)`, 12 | { onSubmit: answer => !!answer.match(/^y(es)?$/i) } 13 | ) 14 | } 15 | 16 | module.exports = function (state, next) { 17 | ask(state.package.name) 18 | .then(answer => { 19 | state.package.private = answer 20 | next(null, state) 21 | }) 22 | .catch(err => next(err, state)) 23 | } 24 | -------------------------------------------------------------------------------- /bin/steps/prompt-readme.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const sh = require('../utils/sh-basic') 4 | 5 | function ask () { 6 | return sh.input( 7 | `Do you want ${sh.colors.yellow('README')} to be unboiled ? (yes)`, 8 | { onSubmit: answer => answer === '' || !!answer.match(/^y(es)?$/i) } 9 | ) 10 | } 11 | 12 | module.exports = function (state, next) { 13 | ask() 14 | .then(answer => { 15 | state.clearReadme = answer 16 | next(null, state) 17 | }) 18 | .catch(err => next(err, state)) 19 | } 20 | -------------------------------------------------------------------------------- /bin/steps/prompt-version.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const sh = require('../utils/sh-basic') 4 | 5 | const DEFAULT_VERSION = '0.0.1' 6 | const REGEX = /^((\w{1}|[1-9]{1}\w+)\.){2}(\w{1}|[1-9]{1}\w+)$/g 7 | 8 | const isValid = val => REGEX.test(val) 9 | const def = val => val === undefined || val === '' ? DEFAULT_VERSION : val 10 | 11 | function ask () { 12 | return sh.input('Version: (' + DEFAULT_VERSION + ')', { 13 | onSubmit: answer => { 14 | answer = def(answer) 15 | if (isValid(answer)) return answer 16 | sh.error('Invalid version: "' + answer + '"') 17 | return ask() 18 | } 19 | }) 20 | } 21 | 22 | module.exports = function (state, next) { 23 | ask() 24 | .then(version => { 25 | state.package.version = version 26 | next(null, state) 27 | }) 28 | .catch(err => next(err, state)) 29 | } 30 | -------------------------------------------------------------------------------- /bin/steps/update-changelog.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fs = require('fs-extra') 4 | const path = require('path') 5 | const sh = require('../utils/sh-basic') 6 | 7 | const CHANGELOGMD_PATH = path.join(process.cwd(), 'CHANGELOG.md') 8 | const CHANGELOG_PATH = path.join(process.cwd(), 'CHANGELOG') 9 | 10 | function ensureChangelogFile() { 11 | return new Promise((resolve, reject) => { 12 | fs.pathExists(CHANGELOG_PATH) 13 | .then(exists => { 14 | if (exists) resolve(CHANGELOG_PATH) 15 | else fs.ensureFile(CHANGELOGMD_PATH) 16 | .then(() => resolve(CHANGELOGMD_PATH)) 17 | .catch(reject) 18 | }) 19 | .catch(reject) 20 | }) 21 | } 22 | 23 | module.exports = function (state, next) { 24 | let changelogPath = null 25 | return ensureChangelogFile() 26 | .then(file => { changelogPath = file }) 27 | .then(output => fs.writeFile(changelogPath, '')) 28 | .then(() => sh.debug(`CHANGELOG file updated`)) 29 | .then(() => next(null, state)) 30 | .catch(err => next(err, state)) 31 | } 32 | -------------------------------------------------------------------------------- /bin/steps/update-git.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fs = require('fs-extra') 4 | const path = require('path') 5 | const sh = require('../utils/sh-basic') 6 | 7 | const GIT_PATH = path.join(process.cwd(), '.git') 8 | 9 | module.exports = function (state, next) { 10 | fs.remove(GIT_PATH) 11 | .then(() => state.hasGitRepo ? sh.silentExec('git', ['init']) : { code: 0 }) 12 | .then(res => { 13 | if (!state.hasGitRepo) return sh.debug(`.git folder removed`) 14 | if (res.code !== 0) return Promise.reject(res.stderr) 15 | sh.debug(`.git folder (re)created`) 16 | }) 17 | .then(() => { 18 | const repoUrl = state.gitOriginUrl 19 | if (state.hasGitRepo && repoUrl) return new Promise((resolve, reject) => { 20 | sh.silentExec('git', ['remote', 'add', 'origin', repoUrl]) 21 | .then(res => res.code !== 0 ? Promise.reject(res.stderr) : '') 22 | .then(() => sh.debug(`${repoUrl} added as remote origin`)) 23 | .then(resolve) 24 | .catch(reject) 25 | }) 26 | }) 27 | .then(() => next(null, state)) 28 | .catch(err => next(err, state)) 29 | } 30 | -------------------------------------------------------------------------------- /bin/steps/update-license.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fs = require('fs-extra') 4 | const path = require('path') 5 | const sh = require('../utils/sh-basic') 6 | const ensureFile = require('../utils/ensure-file') 7 | 8 | const LICENSEMD_PATH = path.join(process.cwd(), 'LICENSE.md') 9 | const LICENSE_PATH = path.join(process.cwd(), 'LICENSE') 10 | const CURRENT_YEAR = (new Date()).getFullYear() 11 | 12 | module.exports = function (state, next) { 13 | const license = state.package.license.toLowerCase() 14 | const templatePath = path.join(__dirname, '..', '..', 'templates', 'licenses', license + '.txt') 15 | let licensePath = null 16 | return ensureFile(LICENSEMD_PATH, LICENSE_PATH) 17 | .then(file => { licensePath = file }) 18 | .then(() => fs.pathExists(templatePath)) 19 | .then(exists => exists ? fs.readFile(templatePath, 'utf8') : '') 20 | .then(template => template 21 | .replace(/\{\{ project \}\}/g, state.package.name) 22 | .replace(/\{\{ author \}\}/g, state.package.author) 23 | .replace(/\{\{ year \}\}/g, CURRENT_YEAR)) 24 | .then(output => fs.writeFile(licensePath, output)) 25 | .then(() => sh.debug(`LICENSE file updated`)) 26 | .then(() => next(null, state)) 27 | .catch(err => next(err, state)) 28 | } 29 | -------------------------------------------------------------------------------- /bin/steps/update-packagejson.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fs = require('fs-extra') 4 | const path = require('path') 5 | const sh = require('../utils/sh-basic') 6 | 7 | const PACKAGE_PATH = path.join(process.cwd(), 'package.json') 8 | 9 | function loadPackageJson () { 10 | return new Promise((resolve, reject) => { 11 | fs.pathExists(PACKAGE_PATH) 12 | .then(exists => { 13 | if (!exists) return resolve({}) 14 | else fs.readJson(PACKAGE_PATH) 15 | .then(resolve) 16 | .catch(reject) 17 | }) 18 | .catch(reject) 19 | }) 20 | } 21 | 22 | module.exports = function (state, next) { 23 | loadPackageJson() 24 | .then(oldPackage => { 25 | const newPackage = Object.assign({}, oldPackage, state.package) 26 | 27 | for (let k in state.package) { 28 | if (state.package[k] === null) delete newPackage[k] 29 | } 30 | 31 | if (!newPackage.dependencies) newPackage.dependencies = {} 32 | if (!newPackage.devDependencies) newPackage.devDependencies = {} 33 | 34 | fs.writeJson(PACKAGE_PATH, newPackage, {spaces: 2}) 35 | .then(() => sh.debug(`package.json updated`)) 36 | .then(() => next(null, state)) 37 | .catch(err => next(err, state)) 38 | }) 39 | .catch(err => next(err, state)) 40 | } 41 | -------------------------------------------------------------------------------- /bin/steps/update-readme.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fs = require('fs-extra') 4 | const path = require('path') 5 | const sh = require('../utils/sh-basic') 6 | const ensureFile = require('../utils/ensure-file') 7 | 8 | const READMEMD_PATH = path.join(process.cwd(), 'README.md') 9 | const README_PATH = path.join(process.cwd(), 'README') 10 | const TEMPLATE_PATH = path.join(__dirname, '..', '..', 'templates', 'readme.txt') 11 | 12 | module.exports = function (state, next) { 13 | let readmePath = null 14 | if (state.clearReadme) { 15 | ensureFile(README_PATH, READMEMD_PATH) 16 | .then(file => { readmePath = file }) 17 | .then(() => fs.readFile(TEMPLATE_PATH, 'utf8')) 18 | .then(template => template 19 | .replace(/\{\{ project \}\}/g, state.package.name) 20 | .replace(/\{\{ description \}\}/g, state.package.description)) 21 | .then(output => fs.writeFile(readmePath, output)) 22 | .then(() => sh.debug(`README file updated`)) 23 | .then(() => next(null, state)) 24 | .catch(err => next(err, state)) 25 | } else next(null, state) 26 | } 27 | -------------------------------------------------------------------------------- /bin/unboil.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | 'use strict' 4 | 5 | const waterfall = require('run-waterfall') 6 | 7 | waterfall( 8 | [ 9 | require('./steps/log-welcome'), 10 | 11 | require('./steps/log-newline'), 12 | 13 | require('./steps/prompt-name'), 14 | require('./steps/prompt-version'), 15 | require('./steps/prompt-description'), 16 | require('./steps/prompt-author'), 17 | require('./steps/prompt-license'), 18 | require('./steps/prompt-private'), 19 | require('./steps/prompt-readme'), 20 | require('./steps/prompt-git'), 21 | require('./steps/prompt-git-origin'), 22 | 23 | require('./steps/log-newline'), 24 | 25 | require('./steps/update-packagejson'), 26 | require('./steps/update-license'), 27 | require('./steps/update-readme'), 28 | require('./steps/update-changelog'), 29 | require('./steps/update-git'), 30 | ], 31 | (err, state) => err 32 | ? require('./steps/log-error')(err, state) 33 | : require('./steps/log-success')(err, state) 34 | ) 35 | -------------------------------------------------------------------------------- /bin/utils/ensure-file.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const fs = require('fs-extra') 4 | const path = require('path') 5 | 6 | function ensureFile (preferedPath, fallbackPath) { 7 | return new Promise((resolve, reject) => { 8 | fs.pathExists(preferedPath) 9 | .then(exists => { 10 | if (exists) resolve(preferedPath) 11 | else fs.ensureFile(fallbackPath) 12 | .then(() => resolve(fallbackPath)) 13 | .catch(reject) 14 | }) 15 | .catch(reject) 16 | }) 17 | } 18 | 19 | module.exports = ensureFile 20 | -------------------------------------------------------------------------------- /bin/utils/sh-basic.js: -------------------------------------------------------------------------------- 1 | const colors = require('kool-shell/utils/colors') 2 | 3 | module.exports = require('kool-shell')() 4 | .use(require('kool-shell/plugins/exec')) 5 | .use(require('kool-shell/plugins/input')) 6 | .use(require('kool-shell/plugins/log'), { 7 | level: 'debug', 8 | color: true, 9 | debugPrefix: colors.gray(' → '), 10 | errorPrefix: colors.red(' × '), 11 | warnPrefix: colors.red(' ! ') 12 | }) 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "unboil", 3 | "version": "0.1.3", 4 | "description": "Boilerplate customiser for lazy people", 5 | "main": "bin/unboil.js", 6 | "bin": { 7 | "unboil": "bin/unboil.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/brocessing/unboil.git" 12 | }, 13 | "author": "Brocessing", 14 | "license": "MIT", 15 | "bugs": { 16 | "url": "https://github.com/brocessing/unboil/issues" 17 | }, 18 | "homepage": "https://github.com/brocessing/unboil#readme", 19 | "dependencies": { 20 | "fs-extra": "^4.0.1", 21 | "kool-shell": "^1.5.0", 22 | "run-waterfall": "^1.1.3", 23 | "slug": "^0.9.1" 24 | }, 25 | "devDependencies": {}, 26 | "scripts": { 27 | "test": "echo \"Error: no test specified\" && exit 1" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /templates/licenses/agpl3.txt: -------------------------------------------------------------------------------- 1 | {{ project }} 2 | Copyright (C) {{ year }} {{ author }} 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU Affero General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU Affero General Public License for more details. 13 | 14 | You should have received a copy of the GNU Affero General Public License 15 | along with this program. If not, see . 16 | -------------------------------------------------------------------------------- /templates/licenses/apache.txt: -------------------------------------------------------------------------------- 1 | Copyright {{ year }} {{ author }} 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 12 | or implied. See the License for the specific language governing 13 | permissions and limitations under the License. 14 | -------------------------------------------------------------------------------- /templates/licenses/bsd2.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) {{ year }}, {{ author }} 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 18 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 22 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 23 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /templates/licenses/bsd3.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) {{ year }}, {{ author }} 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, 9 | this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | * Neither the name of {{ project }} nor the names of its contributors 14 | may be used to endorse or promote products derived from this software 15 | without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 21 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 25 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 26 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /templates/licenses/gpl2.txt: -------------------------------------------------------------------------------- 1 | {{ project }} 2 | Copyright (C) {{ year }} {{ author }} 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License along 15 | with this program; if not, write to the Free Software Foundation, Inc., 16 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -------------------------------------------------------------------------------- /templates/licenses/gpl3.txt: -------------------------------------------------------------------------------- 1 | {{ project }} 2 | Copyright (C) {{ year }} {{ author }} 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | -------------------------------------------------------------------------------- /templates/licenses/isc.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) {{ year }} {{ author }} 2 | 3 | Permission to use, copy, modify, and distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -------------------------------------------------------------------------------- /templates/licenses/lgpl.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | 6 | Everyone is permitted to copy and distribute verbatim copies of this license 7 | document, but changing it is not allowed. 8 | 9 | This version of the GNU Lesser General Public License incorporates the terms 10 | and conditions of version 3 of the GNU General Public License, supplemented 11 | by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, “this License” refers to version 3 of the GNU Lesser General 16 | Public License, and the “GNU GPL” refers to version 3 of the 17 | GNU General Public License. 18 | 19 | “The Library” refers to a covered work governed by this License, other than 20 | an Application or a Combined Work as defined below. 21 | 22 | An “Application” is any work that makes use of an interface provided by the 23 | Library, but which is not otherwise based on the Library. Defining a subclass 24 | of a class defined by the Library is deemed a mode of using an interface 25 | provided by the Library. 26 | 27 | A “Combined Work” is a work produced by combining or linking an Application 28 | with the Library. The particular version of the Library with which the 29 | Combined Work was made is also called the “Linked Version”. 30 | 31 | The “Minimal Corresponding Source” for a Combined Work means the Corresponding 32 | Source for the Combined Work, excluding any source code for portions of the 33 | Combined Work that, considered in isolation, are based on the Application, 34 | and not on the Linked Version. 35 | 36 | The “Corresponding Application Code” for a Combined Work means the object code 37 | and/or source code for the Application, including any data and utility programs 38 | needed for reproducing the Combined Work from the Application, but excluding 39 | the System Libraries of the Combined Work. 40 | 41 | 1. Exception to Section 3 of the GNU GPL. 42 | 43 | You may convey a covered work under sections 3 and 4 of this License without 44 | being bound by section 3 of the GNU GPL. 45 | 46 | 2. Conveying Modified Versions. 47 | 48 | If you modify a copy of the Library, and, in your modifications, a facility 49 | refers to a function or data to be supplied by an Application that uses the 50 | facility (other than as an argument passed when the facility is invoked), 51 | then you may convey a copy of the modified version: 52 | 53 | a) under this License, provided that you make a good faith effort to 54 | ensure that, in the event an Application does not supply the function or 55 | data, the facility still operates, and performs whatever part of its 56 | purpose remains meaningful, or 57 | 58 | b) under the GNU GPL, with none of the additional permissions of this 59 | License applicable to that copy. 60 | 61 | 3. Object Code Incorporating Material from Library Header Files. 62 | 63 | The object code form of an Application may incorporate material from a header 64 | file that is part of the Library. You may convey such object code under terms 65 | of your choice, provided that, if the incorporated material is not limited to 66 | numerical parameters, data structure layouts and accessors, or small macros, 67 | inline functions and templates (ten or fewer lines in length), 68 | you do both of the following: 69 | 70 | a) Give prominent notice with each copy of the object code that the Library 71 | is used in it and that the Library and its use are covered by this License. 72 | 73 | b) Accompany the object code with a copy of the GNU GPL 74 | and this license document. 75 | 76 | 4. Combined Works. 77 | 78 | You may convey a Combined Work under terms of your choice that, taken together, 79 | effectively do not restrict modification of the portions of the Library 80 | contained in the Combined Work and reverse engineering for debugging such 81 | modifications, if you also do each of the following: 82 | 83 | a) Give prominent notice with each copy of the Combined Work that the 84 | Library is used in it and that the Library and its use are covered 85 | by this License. 86 | 87 | b) Accompany the Combined Work with a copy of the GNU GPL and 88 | this license document. 89 | 90 | c) For a Combined Work that displays copyright notices during execution, 91 | include the copyright notice for the Library among these notices, as well 92 | as a reference directing the user to the copies of the GNU GPL 93 | and this license document. 94 | 95 | d) Do one of the following: 96 | 97 | 0) Convey the Minimal Corresponding Source under the terms of this 98 | License, and the Corresponding Application Code in a form suitable 99 | for, and under terms that permit, the user to recombine or relink 100 | the Application with a modified version of the Linked Version to 101 | produce a modified Combined Work, in the manner specified by section 6 102 | of the GNU GPL for conveying Corresponding Source. 103 | 104 | 1) Use a suitable shared library mechanism for linking with the 105 | Library. A suitable mechanism is one that (a) uses at run time a 106 | copy of the Library already present on the user's computer system, 107 | and (b) will operate properly with a modified version of the Library 108 | that is interface-compatible with the Linked Version. 109 | 110 | e) Provide Installation Information, but only if you would otherwise be 111 | required to provide such information under section 6 of the GNU GPL, and 112 | only to the extent that such information is necessary to install and 113 | execute a modified version of the Combined Work produced by recombining 114 | or relinking the Application with a modified version of the Linked Version. 115 | (If you use option 4d0, the Installation Information must accompany the 116 | Minimal Corresponding Source and Corresponding Application Code. If you 117 | use option 4d1, you must provide the Installation Information in the 118 | manner specified by section 6 of the GNU GPL for 119 | conveying Corresponding Source.) 120 | 121 | 5. Combined Libraries. 122 | 123 | You may place library facilities that are a work based on the Library side by 124 | side in a single library together with other library facilities that are not 125 | Applications and are not covered by this License, and convey such a combined 126 | library under terms of your choice, if you do both of the following: 127 | 128 | a) Accompany the combined library with a copy of the same work based on 129 | the Library, uncombined with any other library facilities, conveyed under 130 | the terms of this License. 131 | 132 | b) Give prominent notice with the combined library that part of it is a 133 | work based on the Library, and explaining where to find the accompanying 134 | uncombined form of the same work. 135 | 136 | 6. Revised Versions of the GNU Lesser General Public License. 137 | 138 | The Free Software Foundation may publish revised and/or new versions of the 139 | GNU Lesser General Public License from time to time. Such new versions will 140 | be similar in spirit to the present version, but may differ in detail to 141 | address new problems or concerns. 142 | 143 | Each version is given a distinguishing version number. If the Library as you 144 | received it specifies that a certain numbered version of the GNU Lesser 145 | General Public License “or any later version” applies to it, you have the 146 | option of following the terms and conditions either of that published version 147 | or of any later version published by the Free Software Foundation. If the 148 | Library as you received it does not specify a version number of the GNU Lesser 149 | General Public License, you may choose any version of the GNU Lesser General 150 | Public License ever published by the Free Software Foundation. 151 | 152 | If the Library as you received it specifies that a proxy can decide whether 153 | future versions of the GNU Lesser General Public License shall apply, that 154 | proxy's public statement of acceptance of any version is permanent 155 | authorization for you to choose that version for the Library. 156 | -------------------------------------------------------------------------------- /templates/licenses/mit.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) {{ year }} {{ author }} 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 20 | OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /templates/licenses/mpl.txt: -------------------------------------------------------------------------------- 1 | This Source Code Form is subject to the terms of the 2 | Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed 3 | with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | -------------------------------------------------------------------------------- /templates/licenses/wtfpl.txt: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) {{ year }} {{ author }} 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | 15 | -------------------------------------------------------------------------------- /templates/readme.txt: -------------------------------------------------------------------------------- 1 | # {{ project }} 2 | > {{ description }} 3 | --------------------------------------------------------------------------------