-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extract functions #22
Merged
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
3e997ed
chore: code@4.0.0
jackboberg 4ec3868
chore: read-pkg-up@2.0.0
jackboberg 5c71138
chore: tap@10.3.2
jackboberg 7512e17
chore: temporary-directory@1.0.2
jackboberg 3ee1d95
chore: mkdirp@0.5.1
jackboberg 03014a0
feat: Extract project data function
jackboberg 1b398e8
chore: testdouble@2.1.2
jackboberg 2a06623
feat: Extract command runner
jackboberg 6a647eb
refactor: Use new lib functions to clean up main
jackboberg File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ npm-debug.log | |
|
||
results | ||
coverage | ||
.nyc_output | ||
|
||
*.swp | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,35 @@ | ||
const Assert = require('assert') | ||
const Child = require('child_process') | ||
const FS = require('fs') | ||
const Parallel = require('run-parallel') | ||
const Path = require('path') | ||
const Parallel = require('run-parallel') | ||
const { command, project } = require('./lib') | ||
|
||
// get details about package and environment | ||
module.exports = (options, done) => { | ||
if (typeof options === 'function') { | ||
done = options | ||
options = {} | ||
} | ||
module.exports = (commands, done) => { | ||
if (isFunction(commands)) [ commands, done ] = [ {}, commands ] | ||
|
||
Assert.equal(typeof options, 'object', 'Options must be an object') | ||
Assert.equal(typeof done, 'function', 'Must pass in a callback function') | ||
Assert(isObject(commands), '`commands` must be an object') | ||
Assert(isFunction(done), 'Must pass in a callback function') | ||
|
||
Parallel([ | ||
packageDetails, | ||
(next) => process.nextTick(next, null, { env: process.env.NODE_ENV }), | ||
(next) => { | ||
const cmds = Object.assign({ node: 'node -v', npm: 'npm -v' }, options) | ||
|
||
commandDetails(cmds, next) | ||
} | ||
(next) => project(Path.dirname(require.main.filename), next), | ||
(next) => commandDetails(commands, next) | ||
], (err, results) => { | ||
if (err) done(err) | ||
else done(null, Object.assign({}, ...results)) | ||
done(err, Object.assign({}, ...results)) | ||
}) | ||
} | ||
|
||
// get name and version from package | ||
const packageDetails = (done) => { | ||
const packagePath = Path.join(process.cwd(), 'package.json') | ||
|
||
FS.readFile(packagePath, 'utf8', (err, data) => { | ||
if (err) return done(err) | ||
|
||
const { name, version } = JSON.parse(data) | ||
const isObject = (value) => typeof value === 'object' && !Array.isArray(value) | ||
|
||
done(null, { name, version }) | ||
}) | ||
} | ||
const isFunction = (value) => typeof value === 'function' | ||
|
||
// execute all passed commands and yield results | ||
const commandDetails = (cmds, done) => { | ||
const commandDetails = (commands, done) => { | ||
const cmds = Object.assign({ node: 'node -v', npm: 'npm -v' }, commands) | ||
const tasks = Object.keys(cmds) | ||
.reduce((acc, key) => Object.assign(acc, { [key]: proc(cmds[key]) }), {}) | ||
.reduce((acc, key) => Object.assign(acc, { | ||
[key]: (next) => command(cmds[key], next) | ||
}), {}) | ||
|
||
Parallel(tasks, done) | ||
} | ||
|
||
// curry command, return function that yields error string or result | ||
const proc = (cmd) => (done) => { | ||
Child.exec(cmd, (err, stdout) => { | ||
if (err) done(null, err.toString()) | ||
else done(null, stdout.replace(/\n/g, '')) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
const { exec } = require('child_process') | ||
const ReadPkgUp = require('read-pkg-up') | ||
|
||
// yield name and version from closest package.json, or empty object | ||
exports.project = (cwd, done) => { | ||
const resolved = ({ pkg }) => { | ||
if (!pkg) return done(null, {}) | ||
|
||
const { name, version } = pkg | ||
|
||
done(null, { name, version }) | ||
} | ||
const rejected = () => done(null, {}) | ||
|
||
ReadPkgUp({ cwd }).then(resolved, rejected) | ||
} | ||
|
||
// execute command and yield trimmed output | ||
exports.command = (cmd, done) => { | ||
exec(cmd, (err, stdout, stderr) => { | ||
if (err || stderr) done(null, err ? err.toString() : stderr.trim()) | ||
else done(null, stdout ? stdout.trim() : '') | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
const TD = require('testdouble') | ||
const { EOL } = require('os') | ||
const { exec } = TD.replace('child_process') | ||
const { expect } = require('code') | ||
const { test: describe } = require('tap') | ||
|
||
const { command } = require('../lib') | ||
|
||
describe('lib.command', ({ afterEach, beforeEach, plan, test }) => { | ||
const cmd = 'test' | ||
const output = `\toutput${EOL}` | ||
|
||
plan(5) | ||
|
||
beforeEach((done) => { | ||
TD.when(exec(cmd)).thenCallback(null, output) | ||
done() | ||
}) | ||
|
||
afterEach((done) => { | ||
TD.reset() | ||
done() | ||
}) | ||
|
||
test('executes the given command', (t) => { | ||
command(cmd, () => { | ||
const { callCount, calls } = TD.explain(exec) | ||
|
||
expect(callCount).to.equal(1) | ||
expect(calls[0].args).to.include(cmd) | ||
t.end() | ||
}) | ||
}) | ||
|
||
test('yields trimmed stdout', (t) => { | ||
command(cmd, (err, out) => { | ||
expect(err).to.not.exist() | ||
expect(out).to.equal('output') | ||
t.end() | ||
}) | ||
}) | ||
|
||
test('yields trimmed stderr', (t) => { | ||
TD.when(exec(cmd)).thenCallback(null, null, output) | ||
command(cmd, (err, out) => { | ||
expect(err).to.not.exist() | ||
expect(out).to.equal('output') | ||
t.end() | ||
}) | ||
}) | ||
|
||
test('when errors yields the error string', (t) => { | ||
const error = new Error('fail') | ||
|
||
TD.when(exec(cmd)).thenCallback(error) | ||
command(cmd, (err, out) => { | ||
expect(err).to.not.exist() | ||
expect(out).to.equal('Error: fail') | ||
t.end() | ||
}) | ||
}) | ||
|
||
test('whithout output yields an empty string', (t) => { | ||
TD.when(exec(cmd)).thenCallback() | ||
command(cmd, (err, out) => { | ||
expect(err).to.not.exist() | ||
expect(out).to.equal('') | ||
t.end() | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"name": "@test/module", | ||
"version": "1.2.3", | ||
"description": "an empty test module", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"keywords": [], | ||
"author": "Jack Boberg <hello@jackboberg.info> (http://jackboberg.info/)", | ||
"license": "MIT" | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is done to get all details regardless of errors right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually
err
never exists, all thetasks
yield an{}
when things go wrong. So, mostly this is just a simpler way to avoid adding// eslint-disable-line handle-callback-error
and still get 100% coverage.