diff --git a/lib/api/init.js b/lib/api/init.js index 6cce194..aaffbe1 100644 --- a/lib/api/init.js +++ b/lib/api/init.js @@ -1,4 +1,4 @@ -import Promise from 'bluebird' +import W from 'when' /* * Initialize an existing template at a @@ -11,5 +11,5 @@ import Promise from 'bluebird' export default function (sprout, name, target, options) { const template = sprout.templates[name] if (template) { return template.init(target, options) } - return Promise.reject(new Error(`template ${name} does not exist`)) + return W.reject(new Error(`template ${name} does not exist`)) } diff --git a/lib/api/remove.js b/lib/api/remove.js index d50133d..726f71b 100644 --- a/lib/api/remove.js +++ b/lib/api/remove.js @@ -1,4 +1,4 @@ -import Promise from 'bluebird' +import W from 'when' /* * Remove a template. @@ -13,5 +13,5 @@ export default function (sprout, name) { delete sprout.templates[name] }) } - return Promise.reject(new Error(`template ${name} does not exist`)) + return W.reject(new Error(`template ${name} does not exist`)) } diff --git a/lib/api/run.js b/lib/api/run.js index fbaff3e..4bd34b5 100644 --- a/lib/api/run.js +++ b/lib/api/run.js @@ -1,4 +1,4 @@ -import Promise from 'bluebird' +import W from 'when' /* * Run a generator in an existing template @@ -13,5 +13,5 @@ import Promise from 'bluebird' export default function (sprout, name, target, generator, args) { const template = sprout.templates[name] if (template) { return template.run(target, generator, args) } - return Promise.reject(new Error(`template ${name} does not exist`)) + return W.reject(new Error(`template ${name} does not exist`)) } diff --git a/lib/index.js b/lib/index.js index a981a96..d98475b 100644 --- a/lib/index.js +++ b/lib/index.js @@ -44,7 +44,7 @@ class Sprout { * @return {Promise} - Promise for Sprout instance. */ add (name, src) { - return api.add(this, name, src).return(this) + return api.add(this, name, src).yield(this) } /* @@ -53,7 +53,7 @@ class Sprout { * @return {Promise} - Promise for Sprout instance. */ remove (name) { - return api.remove(this, name).return(this) + return api.remove(this, name).yield(this) } /* @@ -65,7 +65,7 @@ class Sprout { * @return {Promise} - Promise for Sprout instance. */ init (name, target, options) { - return api.init(this, name, target, options).return(this) + return api.init(this, name, target, options).yield(this) } /* @@ -78,8 +78,7 @@ class Sprout { * @return {Promise} - Promise for Sprout instance. */ run (name, target, generator, args) { - return api.run(this, name, target, generator, args) - .return(this) + return api.run(this, name, target, generator, args).yield(this) } } diff --git a/lib/template.js b/lib/template.js index d49d082..5b9e714 100644 --- a/lib/template.js +++ b/lib/template.js @@ -1,6 +1,7 @@ import Utils from './utils' import {isGitUrl, isBinaryFile} from './helpers' -import Promise from 'bluebird' +import W from 'when' +import node from 'when/node' import which from 'which' import path from 'path' import yaml from 'js-yaml' @@ -13,12 +14,15 @@ import _dns from 'dns' import {exec as _exec} from 'child_process' import {ncp as _ncp} from 'ncp' -const rimraf = Promise.promisify(_rimraf) -const exec = Promise.promisify(_exec) -const readdirp = Promise.promisify(_readdirp) -const ncp = Promise.promisify(_ncp) -const fs = Promise.promisifyAll(_fs) -const dns = Promise.promisifyAll(_dns) +const rimraf = node.lift(_rimraf) +const exec = node.lift(_exec) +const readdirp = node.lift(_readdirp) +const ncp = node.lift(_ncp) +const fs = node.liftAll(_fs, (pfs, lifted, name) => { + pfs[`${name}Async`] = lifted + return pfs +}) +const dns = node.liftAll(_dns) /* * Register CoffeeScript `init` file in template @@ -61,7 +65,7 @@ class Template { * @return {Promise} - promise for Template instance. */ save () { - return new Promise((resolve, reject) => { + return W.promise((resolve, reject) => { // Check if `src` (path or URL) is provided. if (!this.src) { return reject(new Error('no source provided')) } @@ -75,7 +79,7 @@ class Template { // If source is remote, try to resolve google.com to make sure internet // connection exists. if (this.isRemote) { - return dns.resolveAsync('google.com').catch(function () { + return dns.resolve('google.com').catch(function () { throw new Error('make sure that you are connected to the internet!') }) } @@ -104,7 +108,7 @@ class Template { }).then(() => { // Anything occuring beyond this point which throws an error should // trigger the removal of the template directory! - return new Promise((resolve, reject) => { + return W.promise((resolve, reject) => { // Check for init.js or init.coffee. if (!fs.existsSync(path.join(this.path, 'init.js')) && !fs.existsSync(path.join(this.path, 'init.coffee'))) { return reject(new Error('neither init.coffee nor init.js exist in this template')) @@ -121,7 +125,7 @@ class Template { // thrown. return rimraf(this.path).then(() => { throw error }) }) - }).return(this) + }).yield(this) } /* @@ -185,7 +189,7 @@ class Template { }).then(() => { // Create the target directory. this.emitter.emit('msg', `creating target directory: ${target}`) - return fs.mkdirAsync(target) + return fs.mkdir(target) }).then(() => { // Install npm dependencies, if present. Eventually, this should work with // package managers other than npm. @@ -197,7 +201,7 @@ class Template { }).then(() => { // Anything occuring beyond this point which throws an error should // trigger the removal of target directory! - return new Promise((resolve, reject) => { + return W.promise((resolve, reject) => { // Check for init.js. If init.js doesn't exist, confirm that // init.coffee exists. Require init once this is determined. var initCoffee = path.join(this.path, 'init.coffee') @@ -224,7 +228,7 @@ class Template { // Run before hook if present. if (init.before) { this.emitter.emit('msg', 'running before hook') - return Promise.method(init.before)(utils, config) + return W(init.before(utils, config)) } }).then(() => { // Merge in all known values for config. @@ -257,7 +261,7 @@ class Template { // Run beforeRender hook if present. if (init.beforeRender) { this.emitter.emit('msg', 'running beforeRender hook') - return Promise.method(init.beforeRender)(utils, config) + return W(init.beforeRender(utils, config)) } }).then(() => { // Read target directory. @@ -282,7 +286,7 @@ class Template { }) // Write all files with our Utils class. - return Promise.map(files, (file) => { + return W.map(files, (file) => { this.emitter.emit('msg', `reading ${file.fullPath}`) // If the file is not a binary, render it. @@ -298,7 +302,7 @@ class Template { // Run after hook if present. if (init.after) { this.emitter.emit('msg', 'running after hook') - return Promise.method(init.after)(utils, config) + return W(init.after(utils, config)) } }).then(() => { // If original branch is stored, checkout to said branch. @@ -311,7 +315,7 @@ class Template { // thrown. return rimraf(target).then(() => { throw error }) }) - }).return(this) + }).yield(this) } /* @@ -319,7 +323,7 @@ class Template { * @return {Promise} - Promise for Template instance. */ update () { - return new Promise((resolve, reject) => { + return W.promise((resolve, reject) => { // Confirm template is a git repository. If not, throw an error. if (!fs.existsSync(path.join(this.path, '.git'))) { return reject(new Error(`${this.name} is not a git repository`)) @@ -340,7 +344,7 @@ class Template { return exec('git pull ' + origin + ' HEAD', { cwd: this.path }) } }) - }).return(this) + }).yield(this) } /* @@ -351,7 +355,7 @@ class Template { * @return {Promise} - Promise for Template instance. */ run (target, generator, args) { - return new Promise((resolve, reject) => { + return W.promise((resolve, reject) => { // If target not passed, throw an error. if (!target) { return reject(new Error('target path required')) @@ -400,7 +404,7 @@ class Template { // Call the generator pass the Utils instance and the arguments. this.emitter.emit('msg', `running ${generator} generator`) return generator.apply(null, args) - }).return(this) + }).yield(this) } /* @@ -408,19 +412,16 @@ class Template { * @return {Promise} - Promise for Template instance. */ remove () { - return new Promise((resolve, reject) => { - // Resolve if path does not exist. - if (!fs.existsSync(this.path)) { return resolve() } + // Resolve if path does not exist. + if (!fs.existsSync(this.path)) { return W.resolve() } - // rm -rf the path. - this.emitter.emit('msg', 'removing template') + // rm -rf the path. + this.emitter.emit('msg', 'removing template') - var lstat = fs.lstatSync(this.path) - if (lstat.isSymbolicLink()) { - return resolve(fs.unlinkAsync(this.path)) - } - return resolve(rimraf(this.path)) - }).return(this) + return fs.lstatAsync(this.path).then((stat) => { + if (stat.isSymbolicLink()) { return fs.unlink(this.path) } + return rimraf(this.path) + }).yield(this) } } diff --git a/lib/utils.js b/lib/utils.js index 03c24b8..2aa8817 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,4 +1,5 @@ -import Promise from 'bluebird' +import W from 'when' +import node from 'when/node' import ejs from 'ejs' import path from 'path' import _ from 'lodash' @@ -8,10 +9,13 @@ import _mkdirp from 'mkdirp' import {exec as _exec} from 'child_process' import {ncp as _ncp} from 'ncp' -const fs = Promise.promisifyAll(_fs) -const exec = Promise.promisify(_exec) -const ncp = Promise.promisify(_ncp) -const mkdirp = Promise.promisify(_mkdirp) +const fs = node.liftAll(_fs, (pfs, lifted, name) => { + pfs[`${name}Async`] = lifted + return pfs +}) +const exec = node.lift(_exec) +const ncp = node.lift(_ncp) +const mkdirp = node.lift(_mkdirp) /* * Given a source path and a target path, returns a Utils instance. @@ -172,7 +176,7 @@ function rename (from, to) { */ function remove (from, what) { if (!_.isArray(what)) what = [what] - return Promise.map(what, (p) => { + return W.map(what, (p) => { return fs.unlinkSync(path.resolve(from, p)) } ) diff --git a/package.json b/package.json index 046f28a..3a52a91 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,6 @@ ], "dependencies": { "argparse": "^1.0.2", - "bluebird": "^2.9.27", "coffee-script": "^1.9.3", "ejs": "^2.3.1", "isbinaryfile": "^3.0.0", @@ -23,6 +22,7 @@ "readdirp": "^2.0.0", "rimraf": "^2.5.2", "underscore.string": "^3.1.1", + "when": "^3.7.7", "which": "^1.1.1" }, "devDependencies": { diff --git a/readme.md b/readme.md index 054742d..26bdab0 100644 --- a/readme.md +++ b/readme.md @@ -15,7 +15,7 @@ We are aware that the [yeoman project](https://github.com/yeoman/yo) serves a si ### Usage -Sprout is most commonly manipulated through its [command-line interface](http://github.com/carrot/sprout-cli). However, Sprout was made specifically to be easy to integrate into javascript applications and libraries that create project structures for you. It can be installed locally via npm and used directly in a node project. The API is similar to the CLI interface described above. Each method returns a [A+ compliant](http://promises-aplus.github.io/promises-spec/) promise (with extra sugar from [bluebird](https://github.com/petkaantonov/bluebird)). +Sprout is most commonly manipulated through its [command-line interface](http://github.com/carrot/sprout-cli). However, Sprout was made specifically to be easy to integrate into javascript applications and libraries that create project structures for you. It can be installed locally via npm and used directly in a node project. The API is similar to the CLI interface described above. Each method returns a [A+ compliant](http://promises-aplus.github.io/promises-spec/) promise (with extra sugar from [when.js](https://github.com/cujojs/when)). ### Installation diff --git a/test/test.js b/test/test.js index a16fea4..d974454 100644 --- a/test/test.js +++ b/test/test.js @@ -3,12 +3,13 @@ import chai from 'chai' import path from 'path' import fs from 'fs' -import rimraf from 'rimraf' +import W from 'when' +import node from 'when/node' +import _rimraf from 'rimraf' import mockery from 'mockery' import errno from 'errno' -import { exec } from 'child_process' +import { exec as _exec } from 'child_process' import os from 'os' -import Promise from 'bluebird' import Sprout from '..' import apiAdd from '../lib/api/add' import apiInit from '../lib/api/init' @@ -18,7 +19,9 @@ import Template from '../lib/template' import Utils from '../lib/utils' import * as helpers from '../lib/helpers' -var fixturesPath = path.join(__dirname, 'fixtures') +const exec = node.lift(_exec) +const rimraf = node.lift(_rimraf) +const fixturesPath = path.join(__dirname, 'fixtures') chai.should() @@ -670,7 +673,7 @@ describe('template', ).then( function (template) { fs.existsSync(template.path).should.be.true - return Promise.promisify(rimraf)(template.root) + return rimraf(template.root) } ).then( function () { @@ -724,7 +727,7 @@ describe('template', return template.save().then( function () { fs.existsSync(template.path).should.be.true - return Promise.promisify(rimraf)(path.join(template.path, '.git')) + return rimraf(path.join(template.path, '.git')) } ).then( function () { @@ -891,10 +894,10 @@ describe('template', var srcInit = path.join(src, 'init.js') var target = path.join(fixture, 'target') var template - return Promise.promisify(rimraf)(sproutPath).then( + return rimraf(sproutPath).then( function () { fs.mkdirSync(sproutPath) - return Promise.promisify(rimraf)(src) + return rimraf(src) } ).then( function () { @@ -962,10 +965,10 @@ describe('template', var srcInit = path.join(src, 'init.js') var target = path.join(fixture, 'target') var template - return Promise.promisify(rimraf)(sproutPath).then( + return rimraf(sproutPath).then( function () { fs.mkdirSync(sproutPath) - return Promise.promisify(rimraf)(src) + return rimraf(src) } ).then( function () { @@ -1177,11 +1180,7 @@ describe('template', var target = path.join(fixture, 'target') var template = new Template(sprout, name, src) var q = function () { - return new Promise( - function (resolve, reject) { - return resolve({foo: 'bar'}) - } - ) + return W.resolve({ foo: 'bar' }) } return gitInit(src).then( function () { @@ -1578,7 +1577,7 @@ describe('template', ).then( function (template) { fs.existsSync(template.path).should.be.true - return Promise.promisify(rimraf)(path.join(template.path, '.git')) + return rimraf(path.join(template.path, '.git')) } ).then( function () { @@ -2107,8 +2106,7 @@ describe('utils', return utils.target.write('nested/deep/foo', 'bar').then( function (output) { fs.readFileSync(path.join(fixture, 'nested', 'deep', 'foo'), 'utf8').should.eq('bar') - rimraf.sync(path.join(fixture, 'nested')) - done() + rimraf(path.join(fixture, 'nested')).then(_ => done()) } ) } @@ -2121,8 +2119,7 @@ describe('utils', return utils.target.write('nested/deep/foo', 'bar').then( function (output) { fs.readFileSync(path.join(fixture, 'nested', 'deep', 'foo'), 'utf8').should.eq('bar') - rimraf.sync(path.join(fixture, 'nested', 'deep')) - done() + rimraf(path.join(fixture, 'nested', 'deep')).then(_ => done()) } ) } @@ -2233,7 +2230,7 @@ describe('helpers', */ var gitInit = function (dir) { - return Promise.promisify(exec)('git init .', { cwd: dir }) + return exec('git init .', { cwd: dir }) } /* @@ -2244,7 +2241,7 @@ var gitInit = function (dir) { */ var gitTag = function (dir, tag) { - return Promise.promisify(exec)('git tag ' + tag, { cwd: dir }) + return exec('git tag ' + tag, { cwd: dir }) } /* @@ -2255,7 +2252,7 @@ var gitTag = function (dir, tag) { */ var gitCreateBranch = function (dir, branch) { - return Promise.promisify(exec)('git checkout -b ' + branch, { cwd: dir }) + return exec('git checkout -b ' + branch, { cwd: dir }) } /* @@ -2266,7 +2263,7 @@ var gitCreateBranch = function (dir, branch) { */ var gitCheckout = function (dir, branch) { - return Promise.promisify(exec)('git checkout ' + branch, { cwd: dir }) + return exec('git checkout ' + branch, { cwd: dir }) } /* @@ -2276,7 +2273,7 @@ var gitCheckout = function (dir, branch) { */ var gitCommitAdd = function (dir) { - return Promise.promisify(exec)('git add . && git commit -m "sprout test" .', { cwd: dir }) + return exec('git add . && git commit -m "sprout test" .', { cwd: dir }) } /* @@ -2286,7 +2283,7 @@ var gitCommitAdd = function (dir) { */ var gitCurrentBranch = function (dir) { - return Promise.promisify(exec)('git rev-parse --abbrev-ref HEAD', { cwd: dir }).spread( + return exec('git rev-parse --abbrev-ref HEAD', { cwd: dir }).spread( function (stdout) { return stdout }