Leo Lamprecht
8 years ago
4 changed files with 220 additions and 3 deletions
@ -1,3 +1,104 @@ |
|||||
#!/usr/bin/env node |
#!/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