Eli Perelman
8 years ago
8 changed files with 299 additions and 0 deletions
@ -0,0 +1,41 @@ |
|||||
|
# Logs |
||||
|
logs |
||||
|
*.log |
||||
|
npm-debug.log* |
||||
|
|
||||
|
# Runtime data |
||||
|
pids |
||||
|
*.pid |
||||
|
*.seed |
||||
|
*.pid.lock |
||||
|
|
||||
|
# Directory for instrumented libs generated by jscoverage/JSCover |
||||
|
lib-cov |
||||
|
|
||||
|
# Coverage directory used by tools like istanbul |
||||
|
coverage |
||||
|
|
||||
|
# nyc test coverage |
||||
|
.nyc_output |
||||
|
|
||||
|
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) |
||||
|
.grunt |
||||
|
|
||||
|
# node-waf configuration |
||||
|
.lock-wscript |
||||
|
|
||||
|
# Compiled binary addons (http://nodejs.org/api/addons.html) |
||||
|
build/Release |
||||
|
|
||||
|
# Dependency directories |
||||
|
node_modules |
||||
|
jspm_packages |
||||
|
|
||||
|
# Optional npm cache directory |
||||
|
.npm |
||||
|
|
||||
|
# Optional eslint cache |
||||
|
.eslintcache |
||||
|
|
||||
|
# Optional REPL history |
||||
|
.node_repl_history |
@ -0,0 +1,55 @@ |
|||||
|
#!/usr/bin/env node |
||||
|
'use strict'; |
||||
|
|
||||
|
const path = require('path'); |
||||
|
const Vorpal = require('vorpal'); |
||||
|
const commands = require('../package.json').commands; |
||||
|
|
||||
|
const cli = new Vorpal(); |
||||
|
const register = (command) => { |
||||
|
const cmd = command.command; |
||||
|
const name = cmd.split(' ')[0]; |
||||
|
const options = command.options || []; |
||||
|
const dir = path.resolve(__dirname, `../commands/${name}`); |
||||
|
const cliCommand = cli.command(cmd, command.description); |
||||
|
|
||||
|
Object |
||||
|
.keys(options) |
||||
|
.map(option => { |
||||
|
if (Array.isArray(options[option])) { |
||||
|
cliCommand.option.apply(cliCommand, [option].concat(options[option])); |
||||
|
} else { |
||||
|
cliCommand.option(option, options[option]); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
cliCommand |
||||
|
.action(function(args) { |
||||
|
const done = (code) => process.exit(code || 0); |
||||
|
|
||||
|
if (this.commandObject._events) { |
||||
|
const options = Object |
||||
|
.keys(this.commandObject._events) |
||||
|
.reduce((options, key) => { |
||||
|
options[key] = this.commandObject[key]; |
||||
|
|
||||
|
return options; |
||||
|
}, {}); |
||||
|
|
||||
|
args.options = Object.assign(options, args.options); |
||||
|
} |
||||
|
|
||||
|
process.env.NODE_ENV = command.environment || 'development'; |
||||
|
|
||||
|
// Kick off the command |
||||
|
require(dir)(args, done); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
commands.map(register); |
||||
|
|
||||
|
cli |
||||
|
.find('exit') |
||||
|
.hidden(); |
||||
|
|
||||
|
cli.parse.apply(cli, process.argv[2] ? [process.argv] : process.argv.concat(['help'])); |
@ -0,0 +1,51 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const getPreset = require('../../src/get-preset'); |
||||
|
const DevServer = require('webpack-dev-server'); |
||||
|
const webpack = require('webpack'); |
||||
|
|
||||
|
const build = (config, done) => { |
||||
|
webpack(config, (err, stats) => { |
||||
|
if (!err) { |
||||
|
console.log(stats.toString({ colors: true })); |
||||
|
} else { |
||||
|
console.error(err.stack || err); |
||||
|
|
||||
|
if (err.details) { |
||||
|
console.error(err.details); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
done(); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
const watch = (config, done) => { |
||||
|
const protocol = config.devServer.https ? 'https' : 'http'; |
||||
|
const host = config.devServer.host || 'localhost'; |
||||
|
const port = config.devServer.port || 5000; |
||||
|
const compiler = webpack(config); |
||||
|
const server = new DevServer(compiler, config.devServer); |
||||
|
|
||||
|
process.on('SIGINT', done); |
||||
|
server.listen(port, host, () => console.log(`Listening on ${protocol}://${host}:${port}`)); |
||||
|
}; |
||||
|
|
||||
|
module.exports = (args, done) => { |
||||
|
const config = getPreset(args.options.preset); |
||||
|
|
||||
|
if (process.env.NODE_ENV === 'production') { |
||||
|
return build(config, done); |
||||
|
} |
||||
|
|
||||
|
// If we can't start a development server, just do a build,
|
||||
|
// which is currently the case for Node.js packages since we
|
||||
|
// don't have HMR implemented
|
||||
|
if (!config.devServer || config.target === 'node') { |
||||
|
console.log('Warning: This preset does not support watch compilation. Falling back to a one-time build.'); |
||||
|
return build(config, done); |
||||
|
} |
||||
|
|
||||
|
watch(config, done); |
||||
|
}; |
||||
|
|
@ -0,0 +1,37 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const yeoman = require('yeoman-environment'); |
||||
|
const crypto = require('crypto'); |
||||
|
const npm = require('npm'); |
||||
|
const os = require('os'); |
||||
|
const path = require('path'); |
||||
|
|
||||
|
const env = yeoman.createEnv(); |
||||
|
|
||||
|
module.exports = (args, done) => { |
||||
|
// For initializing a project, the preset is not installed in the project.
|
||||
|
// Rather, we install it ourselves into a temp directory and invoke from there.
|
||||
|
const tempDir = path.join(os.tmpdir(), crypto.randomBytes(8).toString('hex')); |
||||
|
const packageName = args.packageName; |
||||
|
|
||||
|
npm.load({ loglevel: 'silent' }, (err, npm) => { |
||||
|
if (err) { |
||||
|
console.error(err); |
||||
|
return done(1); |
||||
|
} |
||||
|
|
||||
|
const pkg = path.join(tempDir, 'node_modules', packageName.startsWith('@') || !packageName.includes(path.sep) ? |
||||
|
packageName : |
||||
|
path.basename(packageName)); |
||||
|
|
||||
|
npm.commands.install(tempDir, [packageName], (err) => { |
||||
|
if (err) { |
||||
|
console.error(err); |
||||
|
return done(1); |
||||
|
} |
||||
|
|
||||
|
env.register(pkg, 'neutrino:init'); |
||||
|
env.run('neutrino:init', done); |
||||
|
}); |
||||
|
}); |
||||
|
}; |
@ -0,0 +1,11 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const webpack = require('webpack'); |
||||
|
const build = require('../build'); |
||||
|
|
||||
|
module.exports = (args, done) => { |
||||
|
// Right now the main point of having this `start` entry point is to ensure that
|
||||
|
// NODE_ENV is development.
|
||||
|
// TODO: consolidate build command to accept a --watch flag which correctly handles NODE_ENV
|
||||
|
return build(args, done); |
||||
|
}; |
@ -0,0 +1,17 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const getPreset = require('../../src/get-preset'); |
||||
|
const Server = require('karma').Server; |
||||
|
|
||||
|
module.exports = (args, done) => { |
||||
|
const config = getPreset(args.options.preset); |
||||
|
const karma = config.karma; |
||||
|
|
||||
|
delete config.karma; |
||||
|
delete config.plugins; |
||||
|
karma.webpack = config; |
||||
|
karma.singleRun = !args.options.watch; |
||||
|
karma.autoWatch = args.options.watch; |
||||
|
|
||||
|
new Server(karma, done).start(); |
||||
|
}; |
@ -0,0 +1,57 @@ |
|||||
|
{ |
||||
|
"name": "neutrino", |
||||
|
"version": "2.0.0", |
||||
|
"description": "Create and build JS applications with managed configurations", |
||||
|
"main": "bin/neutrino", |
||||
|
"bin": { |
||||
|
"neutrino": "./bin/neutrino" |
||||
|
}, |
||||
|
"commands": [ |
||||
|
{ |
||||
|
"command": "init <packageName>", |
||||
|
"description": "Scaffold and initialize a project based on a scaffolding package" |
||||
|
}, |
||||
|
{ |
||||
|
"command": "start", |
||||
|
"description": "Start a development server on a given port", |
||||
|
"options": { |
||||
|
"-p, --preset [nameOrFile]": "Specify a configuration preset for running the development server", |
||||
|
"--port [port]": [ |
||||
|
"Specify a port on which to start the development server", |
||||
|
4000 |
||||
|
] |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"command": "build", |
||||
|
"description": "Compile the source directory to a built project", |
||||
|
"environment": "production", |
||||
|
"options": { |
||||
|
"-p, --preset [nameOrFile]": "Specify a configuration preset for building the source" |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"command": "test", |
||||
|
"description": "Run a set of test suites", |
||||
|
"environment": "test", |
||||
|
"options": { |
||||
|
"-p, --preset [nameOrFile]": "Specify a configuration preset for running tests", |
||||
|
"--watch": "Watch source directory for changes and re-run tests" |
||||
|
} |
||||
|
} |
||||
|
], |
||||
|
"keywords": [], |
||||
|
"author": "Eli Perelman <eli@eliperelman.com>", |
||||
|
"license": "MPL-2.0", |
||||
|
"dependencies": { |
||||
|
"karma": "1.2.0", |
||||
|
"npm": "3.10.6", |
||||
|
"resolve": "1.1.7", |
||||
|
"vorpal": "1.4.1", |
||||
|
"webpack": "1.13.2", |
||||
|
"webpack-dev-server": "1.15.0", |
||||
|
"webpack-hot-middleware": "2.12.2", |
||||
|
"webpack-merge": "0.14.1", |
||||
|
"yeoman-environment": "1.6.3" |
||||
|
} |
||||
|
} |
@ -0,0 +1,30 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const path = require('path'); |
||||
|
|
||||
|
module.exports = (preset) => { |
||||
|
const cwd = process.cwd(); |
||||
|
|
||||
|
if (!preset) { |
||||
|
const pkg = require(path.join(cwd, 'package.json')); |
||||
|
|
||||
|
if (!pkg.config || !pkg.config.preset) { |
||||
|
throw new Error(`This command requires a preset.
|
||||
|
Specify one using -p, --preset, or in your package.json as \`config.preset\`.`); |
||||
|
} |
||||
|
|
||||
|
preset = pkg.config.preset; |
||||
|
} |
||||
|
|
||||
|
// Try requiring the preset as an absolute dependency, and if that fails
|
||||
|
// try requiring it as relative to the project
|
||||
|
try { |
||||
|
return require(preset); |
||||
|
} catch (err) { |
||||
|
try { |
||||
|
return require(path.join(process.cwd(), preset)); |
||||
|
} catch (err) { |
||||
|
return require(path.join(process.cwd(), 'node_modules', preset)); |
||||
|
} |
||||
|
} |
||||
|
}; |
Loading…
Reference in new issue