Leo Lamprecht
8 years ago
4 changed files with 220 additions and 3 deletions
@ -1,3 +1,104 @@ |
|||
#!/usr/bin/env node |
|||
|
|||
import chalk from 'chalk'; |
|||
// Native |
|||
import path from 'path' |
|||
|
|||
// Packages |
|||
import fs from 'fs-extra' |
|||
import tmp from 'tmp' |
|||
import args from 'args' |
|||
import chalk from 'chalk' |
|||
import md5 from 'md5' |
|||
|
|||
// Ours |
|||
import {copyContents, injectPackage} from '../lib/static' |
|||
|
|||
args |
|||
.option('cmd', 'The command to run when starting') |
|||
.option('packages', 'Custom packages to add to dependencies (comma-separated)') |
|||
.option('name', 'Custom name for deployment') |
|||
.option('arguments', 'Flags that you want to pass to now') |
|||
.option('single', 'Serve single page apps with just one index.html') |
|||
|
|||
const flags = args.parse(process.argv) |
|||
|
|||
if (flags.cmd && flags.single) { |
|||
console.log(chalk.red('The "single" flag only works if you\'re not using a custom command')) |
|||
} |
|||
|
|||
const file = args.sub[0] |
|||
let current = process.cwd() |
|||
|
|||
if (file) { |
|||
current = path.resolve(process.cwd(), file) |
|||
} |
|||
|
|||
if (!fs.existsSync(current)) { |
|||
console.error(chalk.red('Specified path doesn\'t exist!')) |
|||
process.exit(1) |
|||
} |
|||
|
|||
const uniqueIdentifier = md5(current) |
|||
const listCommand = 'list ./content' + (flags.single ? ' -s' : '') |
|||
|
|||
const pkgDefaults = { |
|||
name: 'ns', |
|||
version: '1.0.0', |
|||
scripts: { |
|||
start: flags.cmd || listCommand |
|||
}, |
|||
dependencies: { |
|||
list: 'latest' |
|||
} |
|||
} |
|||
|
|||
if (flags.packages) { |
|||
const list = flags.packages.split(',') |
|||
|
|||
for (const item of list) { |
|||
pkgDefaults.dependencies[item] = 'latest' |
|||
} |
|||
|
|||
if (flags.cmd) { |
|||
delete pkgDefaults.dependencies.list |
|||
} |
|||
} |
|||
|
|||
if (flags.name) { |
|||
pkgDefaults.name = flags.name |
|||
} |
|||
|
|||
let tmpDir = false |
|||
|
|||
try { |
|||
tmpDir = tmp.dirSync({ |
|||
// We need to use the hased directory identifier |
|||
// Because if we don't use the same id every time, |
|||
// now won't update the existing deployment and create a new one instead |
|||
name: `now-serve-${uniqueIdentifier}`, |
|||
|
|||
// Keep it, because we'll remove it manually later |
|||
keep: true |
|||
}) |
|||
} catch (err) { |
|||
throw err |
|||
} |
|||
|
|||
const details = fs.lstatSync(current) |
|||
|
|||
if (details.isDirectory()) { |
|||
copyContents(current, tmpDir.name, pkgDefaults, flags.arguments) |
|||
} else if (details.isFile()) { |
|||
const fileName = path.parse(current).base |
|||
const target = path.join(tmpDir.name, '/content', fileName) |
|||
|
|||
fs.copy(current, target, err => { |
|||
if (err) { |
|||
throw err |
|||
} |
|||
|
|||
injectPackage(tmpDir.name, pkgDefaults, flags.arguments) |
|||
}) |
|||
} else { |
|||
console.error(chalk.red('Path is neither a file nor a directory!')) |
|||
} |
|||
|
@ -0,0 +1,111 @@ |
|||
// Native
|
|||
import path from 'path' |
|||
import {spawn} from 'child_process' |
|||
|
|||
// Packages
|
|||
import fs from 'fs-extra' |
|||
import {walk} from 'walk' |
|||
|
|||
export function injectPackage(tmpDir, defaults, flags) { |
|||
const pkgPath = path.join(tmpDir, 'package.json') |
|||
|
|||
fs.writeJSON(pkgPath, defaults, err => { |
|||
if (err) { |
|||
throw err |
|||
} |
|||
|
|||
exports.deploy(tmpDir, flags) |
|||
}) |
|||
} |
|||
|
|||
export function deploy(dir, flags) { |
|||
const oldCwd = process.cwd() |
|||
const cmd = process.platform === 'win32' ? 'now.cmd' : 'now' |
|||
|
|||
process.chdir(dir) |
|||
const flagsAllowed = typeof flags === 'string' |
|||
const flagList = [] |
|||
|
|||
if (flagsAllowed) { |
|||
let splitted = flags.split(', ') |
|||
|
|||
for (const item of splitted) { |
|||
if (item.indexOf(',') > -1) { |
|||
splitted = flags.split(',') |
|||
break |
|||
} |
|||
} |
|||
|
|||
for (const item of splitted) { |
|||
flagList.push(item) |
|||
} |
|||
} |
|||
|
|||
for (const flag of flagList) { |
|||
const index = flagList.indexOf(flag) |
|||
const prefix = flag.length > 1 ? '--' : '-' |
|||
|
|||
if (flag === '') { |
|||
flagList.splice(index, 1) |
|||
} else { |
|||
flagList[index] = prefix + flag |
|||
} |
|||
} |
|||
|
|||
// Run now and deploy
|
|||
const now = spawn(cmd, flagList, { |
|||
stdio: 'inherit' |
|||
}) |
|||
|
|||
now.on('error', err => console.error(err)) |
|||
|
|||
now.on('exit', () => { |
|||
process.chdir(oldCwd) |
|||
exports.cleanup(dir) |
|||
}) |
|||
|
|||
process.on('SIGINT', () => { |
|||
now.kill('SIGINT') |
|||
exports.cleanup(dir) |
|||
}) |
|||
} |
|||
|
|||
export function cleanup(dir) { |
|||
fs.remove(dir, err => { |
|||
if (err) { |
|||
throw err |
|||
} |
|||
|
|||
process.exit() |
|||
}) |
|||
} |
|||
|
|||
export function copyContents(content, tmp, defaults, flags) { |
|||
// Ignore packages
|
|||
const walker = walk(content, { |
|||
filters: [ |
|||
'node_modules' |
|||
] |
|||
}) |
|||
|
|||
walker.on('file', (root, fileStats, next) => { |
|||
const file = path.join(root, fileStats.name) |
|||
const target = path.join(tmp + '/content', path.relative(content, file)) |
|||
|
|||
// Once a file is found, copy it to the temp directory
|
|||
fs.copy(file, target, err => { |
|||
if (err) { |
|||
throw err |
|||
} |
|||
|
|||
next() |
|||
}) |
|||
}) |
|||
|
|||
walker.on('errors', (root, nodeStatsArray, next) => { |
|||
console.error(`Not able to copy file: ${nodeStatsArray}`) |
|||
next() |
|||
}) |
|||
|
|||
walker.on('end', () => exports.injectPackage(tmp, defaults, flags)) |
|||
} |
Loading…
Reference in new issue