Compare commits

...

21 Commits

Author SHA1 Message Date
calebboyd 90ae7de7ac chore: bump fuse-box 2017-10-16 13:02:08 -05:00
Alexis Tyler 96f67ecba4 chore(docs): fix typo & add missing period 2017-10-15 19:32:12 -05:00
calebboyd 6526a611a8 chore: bump deps 2017-10-10 09:56:22 -04:00
calebboyd f9bf4ca464 chore: add chat badge 2017-10-07 09:27:30 -05:00
calebboyd 4ec8a43d60 fix: consistent cwd usage 2017-10-05 20:54:37 -05:00
calebboyd 77109235c4 chore: separate bindings and .node embedding 2017-10-05 18:58:41 -05:00
Bryce Gibson c1531cbf23 Pause logger before and resume after spawn. 2017-10-04 22:22:53 -05:00
Bryce Gibson c5f3116c18 Show process output when loglevel is verbose. 2017-10-04 22:22:53 -05:00
calebboyd 03e2985c7a feat: stat and statSync 2017-10-03 01:54:06 -05:00
calebboyd a4b48611d9 feat: readdir and readdirSync 2017-10-03 00:39:33 -05:00
calebboyd 83d3ccf1c5 feat: support the cluster module 2017-10-02 22:28:04 -05:00
calebboyd 356d4c1886 fix(nix): only make output executable 2017-10-02 21:49:05 -05:00
calebboyd b74bdfc53b chore: fusebox beta 2017-10-02 18:04:32 -05:00
calebboyd 927820a5ec chore: service progress 2017-10-02 18:02:32 -05:00
calebboyd 4ef98bdc8a chore: re-order docs 2017-09-30 15:44:57 -05:00
calebboyd 90d7beb4f3 docs: add native module note 2017-09-30 15:28:03 -05:00
calebboyd 55c95b4663 docs: elaborate on target 2017-09-30 15:06:34 -05:00
calebboyd fe5aa0be09 fix: dequote 2017-09-29 23:16:09 -05:00
calebboyd 2a2526d3bc fix: disable stdin for programatic usage 2017-09-29 17:49:17 -05:00
calebboyd c8310ce3bc docs: update readme 2017-09-28 22:02:27 -05:00
calebboyd bb356a967b chore: multi-arch builds on travis 2017-09-28 16:06:55 -05:00
28 changed files with 616 additions and 330 deletions
+3
View File
@@ -1,4 +1,7 @@
language: node_js
before_install:
- sudo apt-get -qq update
- sudo apt-get install -y g++-multilib
node_js:
- '6'
script: npm run asset-compile
+26 -13
View File
@@ -5,13 +5,14 @@
<a href="https://www.npmjs.com/package/nexe"><img src="https://img.shields.io/npm/dt/nexe.svg" alt="Downloads"></a>
<a href="https://www.npmjs.com/package/nexe"><img src="https://img.shields.io/npm/v/nexe.svg" alt="Version"></a>
<a href="https://www.npmjs.com/package/nexe"><img src="https://img.shields.io/npm/l/nexe.svg" alt="License"></a>
<a href="https://gitter.im/nexe/nexe?utm_source=badge&utm_medium=badge"><img src="https://badges.gitter.im/nexe/nexe.svg"></a>
</p>
<p align="center"><code>npm i nexe -g</code></p>
<p align="center">Nexe is a command-line utility that compiles your Node.js application into a single executable file.</p>
<p align="center">
<img src="https://cloud.githubusercontent.com/assets/5818726/26533446/ce19ee5a-43de-11e7-9540-caf7ebd93370.gif"/>
<img src="https://user-images.githubusercontent.com/5818726/30999006-df7e0ae0-a497-11e7-96db-9ce87ae67b34.gif"/>
</p>
## Motivation and Features
@@ -51,7 +52,7 @@ Additional files or resources can be added to the binary by passing `-r "glob/pa
## Compiling Node
By default `nexe` will attempt to download a pre-built executable. However, It may be unavailable ([github releases](https://github.com/nexe/nexe/releases))
or you may want to customize what is built. See `nexe --help` for a list of options available when passing the [`--build`](#build-boolean) option. You will also need to ensure your environment is setup to [build node](https://github.com/nodejs/node/blob/master/BUILDING.md). Note: the `python` binary in your path should be an acceptbale version of python 2. eg. Systems that have python2 will need to create a [symlink](https://github.com/nexe/nexe/issues/354#issuecomment-319874486)
or you may want to customize what is built. See `nexe --help` for a list of options available when passing the [`--build`](#build-boolean) option. You will also need to ensure your environment is setup to [build node](https://github.com/nodejs/node/blob/master/BUILDING.md). Note: the `python` binary in your path should be an acceptable version of python 2. eg. Systems that have python2 will need to create a [symlink](https://github.com/nexe/nexe/issues/354#issuecomment-319874486).
## Node.js API
@@ -87,8 +88,17 @@ compile({
- Output executable file path
- default: same as `name` with an OS specific extension.
- #### `target: string | object`
- Combination of platform-arch-version. e.g. `'win32-ia32-6.10.3'`
- An object or string describing platform-arch-version. e.g. `'windows-ia32-6.10.3'`
- each segment is optional, and will be merged with the current environment
- Examples: ([full list](https://github.com/nexe/nexe/releases))
- `'win32-x86-8.6.0`
- `{ platform: 'alpine' }`
- `darwin-8.6.0`
- `linux-x64`
- `macos-8.4.0`
See [test/target.spec.ts](test/target.spec.ts)
- If the [`build`](#build-boolean) flag is set, the platform portion of the target is ignored.
- default: `process`
- #### `bundle: string | boolean`
- If a string is provided it must be a valid relative module path
@@ -120,7 +130,7 @@ compile({
- #### `make: string[]`
- Array of arguments for the node build make step, on windows this step recieves options for vcBuild.bat
- default: `[]` or `['nosign', 'release']` for non windows systems
- #### `make: string[]`
- #### `vcBuild: string[]`
- Alias for `make` option
- #### `snapshot: string`
- path to a file to be used as the warmup snapshot for the build
@@ -171,8 +181,7 @@ compile({
Patches and Plugins are just a middleware functions that take two arguments, the `compiler`, and `next`. The compiler is described below, and `next` ensures that the pipeline continues. Its invocation should always be awaited or returned to ensure correct behavior. Patches also require that [`--build`](#build-boolean) be set, while plugins do not.
For examples, see the built in patches: [src/patches](src/patches)
A plugin
For examples, see the built in patches: [src/patches](src/patches).
### `NexeCompiler`
@@ -196,16 +205,15 @@ Any modifications made to `NexeFile#contents` will be maintained in the cache _w
## Native Modules
Nexe has a plugin built for use with [fuse-box](http://fuse-box.org) > 2.2.1. This plugin currently supports modules that require `.node` files and those that use the `bindings` module.
Take a look at the (windows) [example](examples/native-build/build.js)
Any `.node` binding can be used with nexe. These library files will be bundled and written alongside the resulting binary at runtime. Currently, nexe supports modules loaded directly (`.node` files) and those loaded with the `'bindings'` module. It does not yet support modules using `node-pre-gyp#find`.
- [ ] Implement support `node-pre-gyp#find`.
Its important to note: unless your native module conditionally loads each platform binary. Nexe builds with native modules will be platform specific. Eg. You will no longer be able to use cross platform builds.
## Maintainers
Nexe builds with native modules will need to target the same version, platform and architecture as the platform hosting the module. At least until [N-API](https://github.com/nodejs/abi-stable-node) is fully propegated
[![Jared Allard](https://avatars.githubusercontent.com/u/2391349?s=130)](https://jaredallard.me/) | [![Caleb Boyd](https://avatars.githubusercontent.com/u/5818726?s=130)](https://github.com/calebboyd) | [![Christopher Karper](https://avatars.githubusercontent.com/u/653156?s=130)](https://github.com/ckarper) | [![Dustin Greif](https://avatars.githubusercontent.com/u/3026298?s=130)](https://github.com/dgreif) |
---|---|---|---
[Jared Allard](https://github.com/jaredallard) | [Caleb Boyd](http://github.com/calebboyd) | [Christopher Karper](https://github.com/ckarper) | [Dustin Greif](https://github.com/dgreif) |
TODO
- [ ] Implement support for `node-pre-gyp#find`.
## Contributing
@@ -221,6 +229,11 @@ Testing
$ npm test
```
## Maintainers
[![Jared Allard](https://avatars.githubusercontent.com/u/2391349?s=130)](https://jaredallard.me/) | [![Caleb Boyd](https://avatars.githubusercontent.com/u/5818726?s=130)](https://github.com/calebboyd) | [![Christopher Karper](https://avatars.githubusercontent.com/u/653156?s=130)](https://github.com/ckarper) | [![Dustin Greif](https://avatars.githubusercontent.com/u/3026298?s=130)](https://github.com/dgreif) |
---|---|---|---
[Jared Allard](https://github.com/jaredallard) | [Caleb Boyd](http://github.com/calebboyd) | [Christopher Karper](https://github.com/ckarper) | [Dustin Greif](https://github.com/dgreif) |
### Former
+7 -6
View File
@@ -2,7 +2,7 @@
"name": "nexe",
"description": "Create a single executable out of your Node.js application",
"license": "MIT",
"version": "2.0.0-rc.9",
"version": "2.0.0-rc.16",
"contributors": [
"Craig Condon <craig.j.condon@gmail.com> (http://crcn.io)",
"Jared Allard <jaredallard@outlook.com>",
@@ -10,10 +10,11 @@
],
"scripts": {
"asset-compile": "ts-node tasks/asset-compile",
"prebuild": "rimraf lib && npm run lint",
"prepublish": "npm test && npm run build",
"test": "mocha test/**/*.spec.ts",
"lint": "prettier --parser typescript --no-semi --print-width 100 --single-quote --write \"src/**/*.ts\"",
"test": "mocha",
"fmt": "prettier --parser typescript --no-semi --print-width 100 --single-quote --write \"{src,plugins,tasks}/**/*.ts\"",
"prepare": "npm run build",
"prepublishOnly": "npm test",
"prebuild": "rimraf lib && npm run fmt",
"build": "tsc --declaration",
"postbuild": "ts-node tasks/post-build"
},
@@ -37,7 +38,7 @@
"app-builder": "^5.1.0",
"chalk": "^1.1.3",
"download": "^6.2.0",
"fuse-box": "2.2.31",
"fuse-box": "^2.3.4-beta.5",
"globby": "^6.1.0",
"minimist": "^1.2.0",
"mkdirp": "^0.5.1",
+5 -3
View File
@@ -2,21 +2,23 @@
"name": "nexe-daemon",
"version": "1.0.0",
"description": "Plugin for nexe to create installable services",
"main": "index.js",
"main": "lib/index.js",
"scripts": {
"clean": "rimraf *.js",
"build": "tsc",
"postpublish": "npm run clean"
},
"files": [
"*.js",
"lib",
"winsw.exe"
],
"author": "Caleb Boyd",
"license": "MIT",
"devDependencies": {
"nexe": "^2.0.0-rc.6",
"rimraf": "^2.6.2",
"typescript": "^2.5.2"
},
"dependencies": {
"nexe": "^2.0.0-rc.11"
}
}
+11 -13
View File
@@ -12,38 +12,36 @@ interface NexeDaemonOptions {
type DaemonOptions = NexeOptions & { daemon: { windows: NexeDaemonOptions } }
function renderWinswConfig(options: any) {
return '<configuration>\r\n' +
return (
'<configuration>\r\n' +
`${Object.keys(options).reduce((config: string, element: string) => {
return config += `<${element}>${options[element]}</${element}>\r\n`
return (config += `<${element}>${options[element]}</${element}>\r\n`)
}, '')}</configuration>\r\n`
)
}
export default function daemon (compiler: NexeCompiler<DaemonOptions>, next: () => Promise<void>) {
export default function daemon(compiler: NexeCompiler<DaemonOptions>, next: () => Promise<void>) {
if (compiler.target.platform !== 'windows') {
return next()
}
compiler.addResource(
'./nexe/plugin/daemon/winsw.exe',
readFileSync(require.resolve('./winsw.exe'))
)
readFileSync(require.resolve('../winsw.exe'))
)
const name = compiler.options.name,
options = compiler.options.daemon.windows,
options = (compiler.options.daemon && compiler.options.daemon.windows) || {},
defaults: NexeDaemonOptions = {
id: name,
name,
description: name,
executable: '%BASE%\\' + compiler.output
}
}
compiler.addResource(
'./nexe/plugin/daemon/winsw-config.xml',
'./nexe/plugin/daemon/winsw.xml',
Buffer.from(renderWinswConfig(Object.assign(defaults, options)))
)
compiler.addResource(
'./nexe/plugin/daemon/app.js',
Buffer.from(compiler.input)
)
compiler.addResource('./nexe/plugin/daemon/app.js', Buffer.from(compiler.input))
compiler.input = '{{replace:plugins/nexe-daemon/lib/nexe-daemon.js}}'
return next()
+65 -3
View File
@@ -1,4 +1,66 @@
console.log('hello world')
if (true) {
console.log('wat')
const installCommands = ['-i', '--install']
const installIndex = process.argv.findIndex(x => installCommands.includes(x))
import * as path from 'path'
import * as fs from 'fs'
import * as cp from 'child_process'
function mkdirp(r: string, t?: any): any {
;(t = t || null), (r = path.resolve(r))
try {
fs.mkdirSync(r), (t = t || r)
} catch (c) {
if ('ENOENT' === c.code) (t = mkdirp(path.dirname(r), t)), mkdirp(r, t)
else {
var i
try {
i = fs.statSync(r)
} catch (r) {
throw c
}
if (!i.isDirectory()) throw c
}
}
return t
}
if (~installIndex) {
console.log('DIRECTORY FOUND')
const directory = process.argv[installIndex + 1]
if (directory) {
mkdirp(path.dirname(directory))
const filename = path.join(directory, path.basename(process.execPath))
const readStream = fs.createReadStream(process.execPath)
const writeStream = fs.createWriteStream(filename)
const onError = function() {
readStream.removeAllListeners()
writeStream.removeAllListeners()
//TODO
}
readStream
.on('error', onError)
.pipe(writeStream)
.on('error', onError)
.on('close', () => {
const winsw = filename.replace('.exe', '-service.exe')
fs.writeFileSync(winsw, fs.readFileSync('./nexe/plugin/daemon/winsw.exe'))
fs.writeFileSync(
filename.replace('.exe', '-service.xml'),
fs.readFileSync('./nexe/plugin/daemon/winsw.xml')
)
installService(winsw)
})
}
} else {
console.log('DIRECTORY NOT FOUND')
require('./nexe/plugin/daemon/app.js')
}
function installService(filename: string) {
cp.exec(filename + ' install', error => {
if (error && !error.message.includes('already exists')) {
throw error
}
})
}
+3 -3
View File
@@ -1458,9 +1458,9 @@ negotiator@0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9"
nexe@^2.0.0-rc.6:
version "2.0.0-rc.6"
resolved "https://registry.yarnpkg.com/nexe/-/nexe-2.0.0-rc.6.tgz#b3990bb67098a93bc488b21ad88aee67b62cf0d5"
nexe@^2.0.0-rc.11:
version "2.0.0-rc.11"
resolved "https://registry.yarnpkg.com/nexe/-/nexe-2.0.0-rc.11.tgz#cd06fc91da8db008fffa6dde1a9a8dd6decf2c35"
dependencies:
app-builder "^5.1.0"
chalk "^1.1.3"
-68
View File
@@ -3,74 +3,6 @@ import * as path from 'path'
import * as child from 'child_process'
import { createHash } from 'crypto'
export interface ExtractNodeModuleOptions {
[key: string]: { additionalFiles: string[] } | true
}
function hashName(name: string | Buffer) {
return createHash('md5')
.update(name)
.digest('hex')
.toString()
.slice(0, 8)
}
export function embedDotNode(
options: ExtractNodeModuleOptions,
file: { contents: string; absPath: string }
) {
const contents = fs.readFileSync(file.absPath)
const modulePathParts = file.absPath.split(path.sep).reverse()
const module = modulePathParts[modulePathParts.findIndex(x => x === 'node_modules') - 1]
const bindingName = path.basename(file.absPath)
const settings = options[module]
const moduleDir = hashName(contents)
file.contents = `
var fs=require('fs');var path=require('path');var binding='${contents.toString(
'base64'
)}';function mkdirp(r,t){t=t||null,r=path.resolve(r);try{fs.mkdirSync(r),t=t||r}catch(c){if("ENOENT"===c.code)t=mkdirp(path.dirname(r),t),mkdirp(r,t);else{var i;try{i=fs.statSync(r)}catch(r){throw c}if(!i.isDirectory())throw c}}return t};`
if (!settings || settings === true) {
file.contents += `
mkdirp('${moduleDir}');
var bindingPath = path.join(process.cwd(), '${moduleDir}', '${bindingName}')
require('fs').writeFileSync(bindingPath, Buffer.from(binding, 'base64'))
process.dlopen(module, bindingPath)
`.trim()
return
}
let depth = 0
settings.additionalFiles.forEach(file => {
let ownDepth = 0
file.split('/').forEach(x => x === '..' && ownDepth++)
depth = ownDepth > depth ? ownDepth : depth
})
let segments = [moduleDir]
while (depth--) {
segments.push(hashName(moduleDir + depth))
}
segments.push(bindingName)
file.contents += `
var cwd = process.cwd()
var bindingFileParts = ${JSON.stringify(segments)};
var bindingFile = path.join.apply(path, [cwd].concat(bindingFileParts));
mkdirp(path.dirname(bindingFile));
fs.writeFileSync(bindingFile, Buffer.from(binding, 'base64'));
${settings.additionalFiles.reduce((code, filename, i) => {
const contents = fs.readFileSync(path.join(path.dirname(file.absPath), filename))
return (code += `
var file${i} = '${contents.toString('base64')}';
var filePath${i} = path.join(cwd, bindingFileParts[0], '${filename.split('../').join('')}');
mkdirp(path.dirname(filePath${i}));
fs.writeFileSync(filePath${i}, Buffer.from(file${i}, 'base64'));
`)
}, '')};
process.dlopen(module, bindingFile)
`
}
function findNativeModulePath(filePath: string, bindingsArg: string) {
const dirname = path.dirname(filePath)
const tempFile = Math.random() * 100 + '.js'
+71
View File
@@ -0,0 +1,71 @@
import { createHash } from 'crypto'
import * as path from 'path'
export interface EmbedNodeModuleOptions {
[key: string]: { additionalFiles: string[] } | true
}
function hashName(name: string | Buffer) {
return createHash('md5')
.update(name)
.digest('hex')
.toString()
.slice(0, 8)
}
export function embedDotNode(
options: EmbedNodeModuleOptions,
file: { contents: string; absPath: string }
) {
const contents = fs.readFileSync(file.absPath)
const modulePathParts = file.absPath.split(path.sep).reverse()
const module = modulePathParts[modulePathParts.findIndex(x => x === 'node_modules') - 1]
const bindingName = path.basename(file.absPath)
const settings = options[module]
const moduleDir = hashName(contents)
file.contents = `
var fs=require('fs');var path=require('path');var binding='${contents.toString(
'base64'
)}';function mkdirp(r,t){t=t||null,r=path.resolve(r);try{fs.mkdirSync(r),t=t||r}catch(c){if("ENOENT"===c.code)t=mkdirp(path.dirname(r),t),mkdirp(r,t);else{var i;try{i=fs.statSync(r)}catch(r){throw c}if(!i.isDirectory())throw c}}return t};`
if (!settings || settings === true) {
file.contents += `
mkdirp('${moduleDir}');
var bindingPath = path.join(process.cwd(), '${moduleDir}', '${bindingName}')
require('fs').writeFileSync(bindingPath, Buffer.from(binding, 'base64'))
process.dlopen(module, bindingPath)
`.trim()
return {}
}
let depth = 0
settings.additionalFiles.forEach(file => {
let ownDepth = 0
file.split('/').forEach(x => x === '..' && ownDepth++)
depth = ownDepth > depth ? ownDepth : depth
})
let segments = [moduleDir]
while (depth--) {
segments.push(hashName(moduleDir + depth))
}
segments.push(bindingName)
file.contents += `
var cwd = process.cwd()
var bindingFileParts = ${JSON.stringify(segments)};
var bindingFile = path.join.apply(path, [cwd].concat(bindingFileParts));
mkdirp(path.dirname(bindingFile));
fs.writeFileSync(bindingFile, Buffer.from(binding, 'base64'));
${settings.additionalFiles.reduce((code, filename, i) => {
const contents = fs.readFileSync(path.join(path.dirname(file.absPath), filename))
return (code += `
var file${i} = '${contents.toString('base64')}';
var filePath${i} = path.join(cwd, bindingFileParts[0], '${filename.split('../').join('')}');
mkdirp(path.dirname(filePath${i}));
fs.writeFileSync(filePath${i}, Buffer.from(file${i}, 'base64'));
`)
}, '')};
process.dlopen(module, bindingFile)
`
}
+4 -3
View File
@@ -1,4 +1,5 @@
import { BindingsRewrite, embedDotNode, ExtractNodeModuleOptions } from './bindings-rewrite'
import { BindingsRewrite } from './bindings-rewrite'
import { embedDotNode, EmbedNodeModuleOptions } from './embed-node'
export interface FuseBoxFile {
info: { absPath: string }
@@ -21,14 +22,14 @@ export interface FuseBoxFile {
): void
}
export default function(options: ExtractNodeModuleOptions = {}) {
export default function(options: EmbedNodeModuleOptions = {}) {
return new NativeModulePlugin(options)
}
export class NativeModulePlugin {
public test = /node_modules.*(\.js|\.node)$|\.node$/
public limit2Project = false
private modules: (keyof ExtractNodeModuleOptions)[]
private modules: (keyof EmbedNodeModuleOptions)[]
constructor(public options = {}) {}
+27 -20
View File
@@ -4,7 +4,7 @@ import { createHash } from 'crypto'
import { createReadStream } from 'fs'
import { Readable } from 'stream'
import { spawn } from 'child_process'
import { Logger } from './logger'
import { Logger, LogStep } from './logger'
import { readFileAsync, writeFileAsync, pathExistsAsync, dequote, isWindows, bound } from './util'
import { NexeOptions, version } from './options'
import { NexeTarget } from './target'
@@ -32,7 +32,7 @@ interface NexeHeader {
export class NexeCompiler<T extends NexeOptions = NexeOptions> {
private start = Date.now()
private env = { ...process.env }
private compileStep: { modify: Function; log: Function }
private compileStep: LogStep
public log = new Logger(this.options.loglevel)
public src: string
public files: NexeFile[] = []
@@ -45,10 +45,7 @@ export class NexeCompiler<T extends NexeOptions = NexeOptions> {
index: {},
bundle: Buffer.from('')
}
public output = isWindows
? `${(this.options.output || this.options.name).replace(/\.exe$/, '')}.exe`
: `${this.options.output || this.options.name}`
public output = this.options.output
private nodeSrcBinPath: string
constructor(public options: T) {
const { python } = (this.options = options)
@@ -132,14 +129,25 @@ export class NexeCompiler<T extends NexeOptions = NexeOptions> {
}
private _runBuildCommandAsync(command: string, args: string[]) {
if (this.log.verbose) {
this.compileStep.pause()
}
return new Promise((resolve, reject) => {
spawn(command, args, {
cwd: this.src,
env: this.env,
stdio: 'ignore'
stdio: this.log.verbose ? 'inherit' : 'ignore'
})
.once('error', reject)
.once('error', (e: Error) => {
if (this.log.verbose) {
this.compileStep.resume()
}
reject(e)
})
.once('close', (code: number) => {
if (this.log.verbose) {
this.compileStep.resume()
}
if (code != 0) {
const error = `${command} ${args.join(' ')} exited with code: ${code}`
reject(new Error(error))
@@ -185,18 +193,17 @@ export class NexeCompiler<T extends NexeOptions = NexeOptions> {
throw new Error(`${assetName} not available, create it using the --build flag`)
}
const filename = this.getNodeExecutableLocation(target)
await download(
asset.browser_download_url,
dirname(filename),
downloadOptions
).on('response', (res: IncomingMessage) => {
const total = +res.headers['content-length']!
let current = 0
res.on('data', data => {
current += data.length
this.compileStep.modify(`Downloading...${(current / total * 100).toFixed()}%`)
})
})
await download(asset.browser_download_url, dirname(filename), downloadOptions).on(
'response',
(res: IncomingMessage) => {
const total = +res.headers['content-length']!
let current = 0
res.on('data', data => {
current += data.length
this.compileStep.modify(`Downloading...${(current / total * 100).toFixed()}%`)
})
}
)
return createReadStream(filename)
}
+7 -3
View File
@@ -6,10 +6,12 @@ const frameLength = 120
export interface LogStep {
modify(text: string, color?: string): void
log(text: string, color?: string): void
pause(): void
resume(): void
}
export class Logger {
private verbose: boolean
public verbose: boolean
private silent: boolean
private ora: any
private modify: Function
@@ -48,7 +50,7 @@ export class Logger {
step(text: string, method: string = 'succeed'): LogStep {
if (this.silent) {
return { modify() {}, log() {} }
return { modify() {}, log() {}, pause() {}, resume() {} }
}
if (!this.ora.id) {
this.ora.start().text = text
@@ -62,7 +64,9 @@ export class Logger {
return {
modify: this.modify,
log: this.verbose ? this.write : this.modify
log: this.verbose ? this.write : this.modify,
pause: () => this.ora.stopAndPersist(),
resume: () => this.ora.start()
} as LogStep
}
}
+2 -2
View File
@@ -1,7 +1,7 @@
import { compose, Middleware } from 'app-builder'
import resource from './steps/resource'
import { NexeCompiler } from './compiler'
import { argv, version, help, normalizeOptionsAsync, NexeOptions, NexePatch } from './options'
import { argv, version, help, normalizeOptions, NexeOptions, NexePatch } from './options'
import cli from './steps/cli'
import bundle from './steps/bundle'
import download from './steps/download'
@@ -15,7 +15,7 @@ async function compile(
compilerOptions?: Partial<NexeOptions>,
callback?: (err: Error | null) => void
) {
const options = await normalizeOptionsAsync(compilerOptions)
const options = normalizeOptions(compilerOptions)
const compiler = new NexeCompiler(options)
const build = compiler.options.build
+30 -23
View File
@@ -1,9 +1,9 @@
import * as parseArgv from 'minimist'
import { NexeCompiler } from './compiler'
import { isWindows, padRight } from './util'
import { basename, extname, join, isAbsolute, relative, dirname } from 'path'
import { basename, extname, join, isAbsolute, relative, dirname, resolve } from 'path'
import { getTarget, NexeTarget } from './target'
import { EOL } from 'os'
import { EOL, homedir } from 'os'
import * as c from 'chalk'
export const version = '{{replace:0}}'
@@ -34,6 +34,7 @@ export interface NexeOptions {
native: any
empty: boolean
sourceUrl?: string
enableStdIn?: boolean
python?: string
loglevel: 'info' | 'silent' | 'verbose'
silent?: boolean
@@ -82,7 +83,7 @@ const alias = {
l: 'loglevel',
'fake-argv': 'fakeArgv'
}
const argv = parseArgv(process.argv, { alias, default: defaults })
const argv = parseArgv(process.argv, { alias, default: { ...defaults, enableStdIn: true } })
const g = c.gray
let help = `
${c.bold('nexe <entry-file> [options]')}
@@ -112,7 +113,7 @@ ${c.bold('nexe <entry-file> [options]')}
${c.underline.bold('Other options:')}
--bundle -- custom bundling module with 'createBundle' export
--temp -- temp file storage default './nexe'
--temp -- temp file storage default '~/.nexe'
--cwd -- set the current working directory for the command
--fake-argv -- fake argv[1] with entry file
--clean -- force download of sources
@@ -181,36 +182,38 @@ function extractName(options: NexeOptions) {
return name.replace(/\.exe$/, '')
}
function isEntryFile(filename: string) {
return filename && !isAbsolute(filename) && filename !== 'node' && /\.(tsx?|jsx?)$/.test(filename)
function isEntryFile(filename?: string): filename is string {
return Boolean(
filename && !isAbsolute(filename) && filename !== 'node' && /\.(tsx?|jsx?)$/.test(filename)
)
}
function findInput(input: string, cwd: string) {
const maybeInput = argv._.slice().pop() || ''
export function resolveEntry(input: string, cwd: string, maybeEntry?: string) {
if (input) {
return input
return resolve(cwd, input)
}
if (isEntryFile(maybeInput)) {
return maybeInput
if (isEntryFile(maybeEntry)) {
return resolve(cwd, maybeEntry)
}
if (!process.stdin.isTTY) {
return ''
}
try {
const main = require.resolve(cwd)
return './' + relative(cwd, main)
return require.resolve(cwd)
} catch (e) {
void e
throw new Error('No entry file found')
}
return ''
}
function normalizeOptionsAsync(input?: Partial<NexeOptions>): Promise<NexeOptions> {
function normalizeOptions(input?: Partial<NexeOptions>): NexeOptions {
const options = Object.assign({}, defaults, input) as NexeOptions
const opts = options as any
options.temp = options.temp || process.env.NEXE_TEMP || join(options.cwd, '.nexe')
options.input = findInput(options.input, options.cwd)
const cwd = (options.cwd = resolve(options.cwd))
options.temp = options.temp
? resolve(cwd, options.temp)
: process.env.NEXE_TEMP || join(homedir(), '.nexe')
const maybeEntry = input === argv ? argv._[argv._.length - 1] : undefined
options.input = resolveEntry(options.input, cwd, maybeEntry)
options.name = extractName(options)
options.loglevel = extractLogLevel(options)
options.flags = flatten(opts.flag, options.flags)
@@ -219,6 +222,10 @@ function normalizeOptionsAsync(input?: Partial<NexeOptions>): Promise<NexeOption
options.configure = flatten(options.configure)
options.resources = flatten(opts.resource, options.resources)
options.rc = options.rc || extractCliMap(/^rc-.*/, options)
options.output = isWindows
? `${(options.output || options.name).replace(/\.exe$/, '')}.exe`
: `${options.output || options.name}`
options.output = resolve(cwd, options.output)
if (!options.targets.length) {
options.targets.push(getTarget())
@@ -240,14 +247,14 @@ function normalizeOptionsAsync(input?: Partial<NexeOptions>): Promise<NexeOption
return x
}
options.plugins = options.plugins.map(requireDefault)
options.patches = options.patches.map(requireDefault)
options.plugins = flatten(opts.plugin, options.plugins).map(requireDefault)
options.patches = flatten(opts.patch, options.patches).map(requireDefault)
Object.keys(alias)
.filter(k => k !== 'rc')
.forEach(x => delete opts[x])
return Promise.resolve(options)
return options
}
export { argv, normalizeOptionsAsync, help }
export { argv, normalizeOptions, help }
+8 -6
View File
@@ -16,17 +16,18 @@ function createBundle(options: NexeOptions) {
})
)
}
const cwd = options.cwd
const fuse = FuseBox.init({
cache: false,
log: Boolean(process.env.NEXE_BUNDLE_LOG) || false,
homeDir: options.cwd,
homeDir: cwd,
sourceMaps: false,
writeBundles: false,
output: '$name.js',
target: 'server',
plugins
})
const input = relative(options.cwd, options.input).replace(/\\/g, '/')
const input = relative(cwd, resolve(cwd, options.input)).replace(/\\/g, '/')
fuse.bundle(options.name).instructions(`> ${input}`)
return fuse.run().then((x: any) => {
let output = ''
@@ -36,8 +37,9 @@ function createBundle(options: NexeOptions) {
}
export default async function bundle(compiler: NexeCompiler, next: any) {
if (!compiler.options.bundle) {
compiler.input = await readFileAsync(compiler.options.input, 'utf-8')
const { bundle, cwd, empty, input } = compiler.options
if (!bundle) {
compiler.input = await readFileAsync(resolve(cwd, input), 'utf-8')
return next()
}
@@ -48,13 +50,13 @@ export default async function bundle(compiler: NexeCompiler, next: any) {
let producer = createBundle
if (typeof compiler.options.bundle === 'string') {
producer = require(resolve(compiler.options.cwd, compiler.options.bundle)).createBundle
producer = require(resolve(cwd, bundle)).createBundle
}
compiler.input = await producer(compiler.options)
if ('string' === typeof compiler.options.debugBundle) {
await writeFileAsync(compiler.options.debugBundle, compiler.input)
await writeFileAsync(resolve(cwd, compiler.options.debugBundle), compiler.input)
}
return next()
+22 -15
View File
@@ -1,19 +1,22 @@
import { normalize } from 'path'
import { normalize, relative } from 'path'
import { Readable } from 'stream'
import { createWriteStream, chmodSync } from 'fs'
import { createWriteStream, chmodSync, statSync } from 'fs'
import { readFileAsync, dequote, isWindows } from '../util'
import { NexeCompiler } from '../compiler'
import { NexeTarget } from '../target'
function readStreamAsync(stream: NodeJS.ReadableStream): PromiseLike<string> {
function getStdIn(stdin: NodeJS.ReadStream): Promise<string> {
return new Promise(resolve => {
let input = ''
stream.setEncoding('utf-8')
stream.on('data', (x: string) => {
input += x
})
stream.once('end', () => resolve(dequote(input)))
stream.resume && stream.resume()
let out = ''
stdin
.setEncoding('utf8')
.on('readable', () => {
let current
while ((current = stdin.read())) {
out += current
}
})
.on('end', () => resolve(out))
})
}
@@ -34,9 +37,9 @@ function readStreamAsync(stream: NodeJS.ReadableStream): PromiseLike<string> {
export default async function cli(compiler: NexeCompiler, next: () => Promise<void>) {
const { log } = compiler
let stdInUsed = false
if (!process.stdin.isTTY) {
if (!process.stdin.isTTY && compiler.options.enableStdIn) {
stdInUsed = true
compiler.input = await readStreamAsync(process.stdin)
compiler.input = dequote(await getStdIn(process.stdin))
}
await next()
@@ -53,11 +56,15 @@ export default async function cli(compiler: NexeCompiler, next: () => Promise<vo
if (e) {
reject(e)
} else if (compiler.output) {
chmodSync(compiler.output, '755')
const output = compiler.output
const mode = statSync(output).mode | 0o111
chmodSync(output, mode.toString(8).slice(-3))
const inputFile = relative(process.cwd(), compiler.options.input)
const outputFile = relative(process.cwd(), output)
step.log(
`Entry: '${stdInUsed
? '[stdin]'
: compiler.options.input}' written to: ${compiler.output}`
? compiler.options.empty ? '[empty]' : '[stdin]'
: inputFile}' written to: ${outputFile}`
)
resolve(compiler.quit())
}
+98 -3
View File
@@ -1,22 +1,73 @@
import { Stats } from 'fs'
import { ok } from 'assert'
import { resolve, normalize } from 'path'
import { dirname, resolve, normalize, basename } from 'path'
const binary = (process as any).__nexe as NexeBinary
ok(binary)
const manifest = binary.resources
const directories: { [key: string]: { [key: string]: boolean } } = {}
const isString = (x: any): x is string => typeof x === 'string' || x instanceof String
const isNotFile = () => false
const isNotDirectory = isNotFile
const isFile = () => true
const isDirectory = isFile
if (Object.keys(manifest).length) {
const fs = require('fs')
const originalReadFile = fs.readFile
const originalReadFileSync = fs.readFileSync
const originalReaddir = fs.readdir
const originalReaddirSync = fs.readdirSync
const originalStatSync = fs.statSync
const originalStat = fs.stat
const resourceStart = binary.layout.resourceStart
const statTime = function() {
const stat = binary.layout.stat
return {
dev: 0,
ino: 0,
nlink: 0,
rdev: 0,
uid: 123,
gid: 500,
blksize: 4096,
blocks: 0,
atime: new Date(stat.atime),
atimeMs: stat.atime.getTime(),
mtime: new Date(stat.mtime),
mtimeMs: stat.mtime.getTime(),
ctime: new Date(stat.ctime),
ctimMs: stat.ctime.getTime(),
birthtime: new Date(stat.birthtime),
birthtimeMs: stat.birthtime.getTime()
}
}
const createStat = function(directoryExtensions: any, fileExtensions?: any) {
if (!fileExtensions) {
return Object.assign({}, binary.layout.stat, directoryExtensions, { size: 0 }, statTime())
}
const size = directoryExtensions[1]
return Object.assign({}, binary.layout.stat, fileExtensions, { size }, statTime())
}
const ownStat = function(path: string | Buffer) {
const key = resolve(path)
if (directories[key]) {
return createStat({ isDirectory, isFile: isNotFile })
}
if (manifest[key]) {
return createStat(manifest[key], { isFile, isDirectory: isNotDirectory })
}
}
let setupManifest = () => {
const manifest = binary.resources
Object.keys(manifest).forEach(key => {
const absolutePath = resolve(key)
const dirPath = dirname(absolutePath)
directories[dirPath] = directories[dirPath] || {}
directories[dirPath][basename(absolutePath)] = true
if (!manifest[absolutePath]) {
manifest[absolutePath] = manifest[key]
}
@@ -27,8 +78,35 @@ if (Object.keys(manifest).length) {
})
setupManifest = () => {}
}
//TODO track inflight fs reqs??
//naive patches intended to work for most use cases
var nfs = {
readdir: function readdir(path: string | Buffer, options: any, callback: any) {
setupManifest()
path = path.toString()
if ('function' === typeof options) {
callback = options
options = { encoding: 'utf8' }
}
const dir = directories[resolve(path)]
if (dir) {
process.nextTick(() => {
callback(null, Object.keys(dir))
})
} else {
return originalReaddir.apply(fs, arguments)
}
},
readdirSync: function readdirSync(path: string | Buffer, options: any) {
setupManifest()
path = path.toString()
const dir = directories[resolve(path)]
if (dir) {
return Object.keys(dir)
}
return originalReaddirSync.apply(fs, arguments)
},
readFile: function readFile(file: any, options: any, callback: any) {
setupManifest()
const entry = manifest[file]
@@ -75,6 +153,23 @@ if (Object.keys(manifest).length) {
fs.readSync(fd, result, 0, length, resourceOffset)
fs.closeSync(fd)
return encoding ? result.toString(encoding) : result
},
statSync: function statSync(path: string | Buffer) {
const stat = ownStat(path)
if (stat) {
return stat
}
return originalStatSync.apply(fs, arguments)
},
stat: function stat(path: string | Buffer, callback: any) {
const stat = ownStat(path)
if (stat) {
process.nextTick(() => {
callback(null, stat)
})
} else {
return originalStat.apply(fs, arguments)
}
}
}
Object.assign(fs, nfs)
+12
View File
@@ -7,10 +7,22 @@ function wrap(code: string) {
export default function(compiler: NexeCompiler, next: () => Promise<void>) {
compiler.shims.push(wrap(compiler.getHeader()))
compiler.shims.push(
wrap(`
if (process.argv[1] && process.env.NODE_UNIQUE_ID) {
const cluster = require('cluster')
cluster._setupWorker()
delete process.env.NODE_UNIQUE_ID
}
`)
)
if (compiler.options.resources.length) {
compiler.shims.push(wrap('{{replace:lib/steps/shim-fs.js}}'))
}
//compiler.shims.push(wrap('{/{replace:lib/steps/shim-require.js}}'))
if (compiler.options.fakeArgv) {
const nty = !process.stdin.isTTY
const input = nty ? '[stdin]' : compiler.options.input
+1
View File
@@ -28,6 +28,7 @@ const prettyPlatform: { [key: string]: NodePlatform } = {
//TODO arm
const prettyArch: { [key: string]: NodeArch } = {
x86: 'x86',
amd64: 'x64',
ia32: 'x86',
x32: 'x86',
x64: 'x64'
+16 -20
View File
@@ -1,8 +1,5 @@
import * as nexe from '../lib/nexe'
import {
getUnBuiltReleases,
getLatestGitRelease
} from '../lib/releases'
import { getUnBuiltReleases, getLatestGitRelease } from '../lib/releases'
import * as ci from './ci'
import { runAlpineBuild } from './docker'
import { getTarget } from '../lib/target'
@@ -15,11 +12,12 @@ const env = process.env,
isLinux = Boolean(env.TRAVIS),
isWindows = Boolean(env.APPVEYOR),
isMac = Boolean(env.CIRCLECI),
isPullRequest = Boolean(env.CIRCLE_PR_NUMBER)
|| Boolean(env.APPVEYOR_PULL_REQUEST_NUMBER)
|| Boolean(env.TRAVIS_PULL_REQUEST_BRANCH),
headers = {
'Authorization': 'token ' + env.GITHUB_TOKEN,
isPullRequest =
Boolean(env.CIRCLE_PR_NUMBER) ||
Boolean(env.APPVEYOR_PULL_REQUEST_NUMBER) ||
Boolean(env.TRAVIS_PULL_REQUEST_BRANCH),
headers = {
Authorization: 'token ' + env.GITHUB_TOKEN,
'User-Agent': 'nexe (https://www.npmjs.com/package/nexe)'
}
@@ -32,7 +30,7 @@ if (require.main === module) {
}
}
async function build () {
async function build() {
if (isScheduled) {
const releases = await getUnBuiltReleases({ headers })
if (!releases.length) {
@@ -54,8 +52,7 @@ async function build () {
}
if (env.NEXE_VERSION) {
const
target = getTarget(env.NEXE_VERSION),
const target = getTarget(env.NEXE_VERSION),
output = isWindows ? './out.exe' : './out',
options = {
empty: true,
@@ -63,16 +60,15 @@ async function build () {
target,
output
}
const stop = keepalive()
if (target.platform === 'alpine') {
await runAlpineBuild(target, nexe.version.split('.')[0])
await runAlpineBuild(target)
} else {
await nexe.compile(options)
await nexe.compile(options)
}
stop()
if (await pathExistsAsync(output)) {
await assertNexeBinary(output)
const gitRelease = await getLatestGitRelease({ headers })
@@ -80,7 +76,7 @@ async function build () {
query: { name: target.toString() },
body: await readFileAsync(output),
headers: {
'Authorization': 'token ' + env.GITHUB_TOKEN,
Authorization: 'token ' + env.GITHUB_TOKEN,
'Content-Type': 'application/octet-stream',
'User-Agent': 'nexe (https://www.npmjs.com/package/nexe)'
}
@@ -90,12 +86,12 @@ async function build () {
}
}
function keepalive () {
function keepalive() {
const keepalive = setInterval(() => console.log('Building...'), 300 * 1000)
return () => clearInterval(keepalive)
}
function assertNexeBinary (file: string) {
function assertNexeBinary(file: string) {
return execFileAsync(file).catch(e => {
if (e && e.stack && e.stack.includes('Invalid Nexe binary')) {
return
+5 -8
View File
@@ -5,8 +5,7 @@ const { env } = process
export function triggerMacBuild(release: NexeTarget, branch: string) {
assert.ok(env.CIRCLE_TOKEN)
const circle = `https://circleci.com/api/v1.1/project/github/nexe/nexe/tree/${
branch}?circle-token=${env.CIRCLE_TOKEN}`
const circle = `https://circleci.com/api/v1.1/project/github/nexe/nexe/tree/${branch}?circle-token=${env.CIRCLE_TOKEN}`
return got(circle, {
json: true,
body: {
@@ -17,7 +16,7 @@ export function triggerMacBuild(release: NexeTarget, branch: string) {
})
}
export function triggerDockerBuild (release: NexeTarget, branch: string) {
export function triggerDockerBuild(release: NexeTarget, branch: string) {
assert.ok(env.TRAVIS_TOKEN)
const travis = `https://api.travis-ci.org/repo/nexe%2Fnexe/requests`
return got(travis, {
@@ -38,15 +37,13 @@ export function triggerDockerBuild (release: NexeTarget, branch: string) {
},
headers: {
'Travis-API-Version': '3',
'Authorization': `token ${env.TRAVIS_TOKEN}`
Authorization: `token ${env.TRAVIS_TOKEN}`
}
})
}
export function triggerWindowsBuild (release: NexeTarget) {
export function triggerWindowsBuild(release: NexeTarget) {
const hasVersion = 'NEXE_VERSION' in env
env.NEXE_VERSION = hasVersion
? env.NEXE_VERSION!.trim()
: release.toString()
env.NEXE_VERSION = hasVersion ? env.NEXE_VERSION!.trim() : release.toString()
return Promise.resolve()
}
+18 -13
View File
@@ -5,7 +5,7 @@ import got = require('got')
import execa = require('execa')
import { appendFileSync } from 'fs'
function alpine (target: NexeTarget, nexeVersion: string) {
function alpine(target: NexeTarget) {
return `
FROM ${target.arch === 'x64' ? '' : 'i386/'}alpine:3.4
RUN apk add --no-cache curl make gcc g++ binutils-gold python linux-headers paxctl libgcc libstdc++ git vim tar gzip wget
@@ -26,29 +26,34 @@ RUN rm /nexe_temp/\${NODE_VERSION}/out/Release/node && \
`.trim()
}
export async function runAlpineBuild (target: NexeTarget, nexeVersion: string) {
await writeFileAsync('Dockerfile', alpine(target, nexeVersion))
export async function runAlpineBuild(target: NexeTarget) {
await writeFileAsync('Dockerfile', alpine(target))
const outFilename = 'nexe-alpine-build-log.txt'
await writeFileAsync(outFilename, '')
let output: any = []
try {
output.push(await execa.shell(`docker build -t nexe-alpine .`))
output.push(await execa.shell(`docker run -d --name nexe nexe-alpine sh`))
output.push(await execa.shell(`docker cp nexe:/out out`))
output.push(await execa.shell(`docker build -t nexe-alpine .`))
output.push(await execa.shell(`docker run -d --name nexe nexe-alpine sh`))
output.push(await execa.shell(`docker cp nexe:/out out`))
output.push(await execa.shell(`docker rm nexe`))
} catch(e) {
} catch (e) {
console.log('Error running docker', e)
} finally {
output.forEach((x: any) => {
appendFileSync(outFilename, x.stderr)
appendFileSync(outFilename, x.stdout)
})
await got(`https://transfer.sh/${Math.random().toString(36).substring(2)}.txt`, {
body: await readFileAsync(outFilename),
method: 'PUT'
})
.then(x => console.log('Posted docker log: ', x.body))
.catch(e => console.log('Error posting log', e))
await got(
`https://transfer.sh/${Math.random()
.toString(36)
.substring(2)}.txt`,
{
body: await readFileAsync(outFilename),
method: 'PUT'
}
)
.then(x => console.log('Posted docker log: ', x.body))
.catch(e => console.log('Error posting log', e))
}
}
+4 -6
View File
@@ -10,21 +10,19 @@ inject('lib/patches/third-party-main.js')
inject('lib/steps/shim.js')
inject('lib/options.js', JSON.stringify(require('../package.json').version))
function inject (filename: string, ...replacements: string[]) {
function inject(filename: string, ...replacements: string[]) {
let contents = readFileSync(filename, 'utf8')
contents = contents.replace(/('{{(.*)}}')/g, (substring: string, ...matches: string[]) => {
if (!matches || !matches[1]) {
return substring
}
}
const [replace, file] = matches[1].split(':')
if (replace !== 'replace') {
return substring
}
console.log('Replacing: ', substring)
return replacements[+file]
? replacements[+file]
: JSON.stringify(readFileSync(file, 'utf8'))
})
return replacements[+file] ? replacements[+file] : JSON.stringify(readFileSync(file, 'utf8'))
})
writeFileSync(filename, contents)
console.log(`Wrote: ${filename}`)
}
+3
View File
@@ -0,0 +1,3 @@
{
"main": "entry-file.js"
}
+1
View File
@@ -1,3 +1,4 @@
./test/**/*.spec.ts
--check-leaks
--require ts-node/register
--recursive
+48
View File
@@ -0,0 +1,48 @@
import { normalizeOptions } from '../src/options'
import { expect } from 'chai'
import * as path from 'path'
const ext = process.platform === 'win32' ? '.exe' : ''
describe('options', () => {
describe('cwd', () => {
it('should use process.cwd() if nothing is provided', () => {
const options = normalizeOptions()
expect(options.cwd).to.equal(process.cwd())
})
it('should use the main module in a package directory', () => {
const options = normalizeOptions()
expect(options.input).to.equal(path.resolve('./index.js'))
})
it('should resolve pathed options against cwd', () => {
const cwd = '/a/b/c'
const options = normalizeOptions({
cwd,
input: '123.js',
output: 'abc',
temp: './d'
})
expect(options.temp).to.equal(path.resolve(cwd, './d'))
expect(options.input).to.equal(path.resolve(cwd, '123.js'))
expect(options.output).to.equal(path.resolve(cwd, `abc${ext}`))
})
})
describe('output', () => {
it('should work', () => {
const options = normalizeOptions({
output: './some-output'
})
expect(options.output).to.equal(path.resolve(`./some-output${ext}`))
})
it('should default to the input file name if not index', () => {
const options = normalizeOptions({
input: 'src/folder/app.js'
})
expect(options.output).to.equal(path.resolve(`./app${ext}`))
})
it('should default to the folder/project name if filename is index', () => {
const options = normalizeOptions()
expect(options.output).to.equal(path.resolve(`./nexe${ext}`))
})
})
})
+2
View File
@@ -10,7 +10,9 @@ describe('Targets', () => {
['win-ia32-6.11.2', 'windows-x86-6.11.2'],
[{ version: '6.11.2', platform: 'win', arch: 'ia32' }, 'windows-x86-6.11.2'],
['win32-x64-6.11.2', 'windows-x64-6.11.2'],
['win-amd64-6.11.2', 'windows-x64-6.11.2'],
['darwin-x64-v8.4.0', 'mac-x64-8.4.0'],
['macos-x64-v8.4.0', 'mac-x64-8.4.0'],
['static-x86-6.10.3', 'alpine-x86-6.10.3'],
['linux-x32', `linux-x86-${process.version.slice(1)}`],
['alpine-notsupported-6.10.3', `alpine-${arch}-6.10.3`],
+117 -99
View File
@@ -11,8 +11,8 @@
resolved "https://registry.yarnpkg.com/@types/chalk/-/chalk-0.4.31.tgz#a31d74241a6b1edbb973cf36d97a2896834a51f9"
"@types/execa@^0.7.0":
version "0.7.0"
resolved "https://registry.yarnpkg.com/@types/execa/-/execa-0.7.0.tgz#ba499e099ab6141159975d60fadb5a5b78b979f7"
version "0.7.1"
resolved "https://registry.yarnpkg.com/@types/execa/-/execa-0.7.1.tgz#1817d3f36b0b8b55a92219f71121538fd6e238a5"
dependencies:
"@types/node" "*"
@@ -46,8 +46,8 @@
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.43.tgz#03c54589c43ad048cbcbfd63999b55d0424eec27"
"@types/node@*":
version "8.0.30"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.30.tgz#aa3c42946fc6357737eb215349fe728b38679d05"
version "8.0.37"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.37.tgz#d5b1bbc942915f20f4d83ea04a2aba1df7ac9d5f"
"@types/ora@^0.3.31":
version "0.3.32"
@@ -64,37 +64,23 @@
resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-0.0.28.tgz#5562519bc7963caca8abf7f128cae3b594d41d06"
abbrev@1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f"
version "1.1.1"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
accepts@~1.3.3:
accepts@~1.3.4:
version "1.3.4"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f"
dependencies:
mime-types "~2.1.16"
negotiator "0.6.1"
acorn-es7-plugin@^1.1.7:
version "1.1.7"
resolved "https://registry.yarnpkg.com/acorn-es7-plugin/-/acorn-es7-plugin-1.1.7.tgz#f2ee1f3228a90eead1245f9ab1922eb2e71d336b"
acorn-es7@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/acorn-es7/-/acorn-es7-0.1.0.tgz#4a6de4522faacb4c31209e1b73b5f301ed2bb30a"
dependencies:
acorn "^2.6.4"
acorn-jsx@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-4.0.1.tgz#ada5a01573727a237774ce625564d079ec9de12a"
dependencies:
acorn "^5.0.3"
acorn@^2.6.4:
version "2.7.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-2.7.0.tgz#ab6e7d9d886aaca8b085bc3312b79a198433f0e7"
acorn@^5.0.3:
acorn@^5.0.3, acorn@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.2.tgz#911cb53e036807cf0fa778dc5d370fbd864246d7"
@@ -113,8 +99,8 @@ ajv@^4.9.1:
json-stable-stringify "^1.0.1"
ajv@^5.1.0:
version "5.2.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.2.tgz#47c68d69e86f5d953103b0074a9430dc63da5e39"
version "5.2.3"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.3.tgz#c06f598778c44c6b161abafe3466b81ad1814ed2"
dependencies:
co "^4.6.0"
fast-deep-equal "^1.0.0"
@@ -305,6 +291,21 @@ block-stream@*:
dependencies:
inherits "~2.0.0"
body-parser@1.18.2:
version "1.18.2"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454"
dependencies:
bytes "3.0.0"
content-type "~1.0.4"
debug "2.6.9"
depd "~1.1.1"
http-errors "~1.6.2"
iconv-lite "0.4.19"
on-finished "~2.3.0"
qs "6.5.1"
raw-body "2.3.2"
type-is "~1.6.15"
boom@2.x.x:
version "2.10.1"
resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f"
@@ -354,6 +355,10 @@ buffer@^3.0.1:
ieee754 "^1.1.4"
isarray "^1.0.0"
bytes@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
@@ -502,7 +507,7 @@ content-disposition@0.5.2, content-disposition@^0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
content-type@~1.0.2:
content-type@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
@@ -729,7 +734,7 @@ esutils@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b"
etag@~1.8.0, etag@~1.8.1:
etag@~1.8.1:
version "1.8.1"
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
@@ -764,37 +769,39 @@ expand-range@^1.8.1:
fill-range "^2.1.0"
express@^4.14.0:
version "4.15.5"
resolved "https://registry.yarnpkg.com/express/-/express-4.15.5.tgz#670235ca9598890a5ae8170b83db722b842ed927"
version "4.16.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.16.2.tgz#e35c6dfe2d64b7dca0a5cd4f21781be3299e076c"
dependencies:
accepts "~1.3.3"
accepts "~1.3.4"
array-flatten "1.1.1"
body-parser "1.18.2"
content-disposition "0.5.2"
content-type "~1.0.2"
content-type "~1.0.4"
cookie "0.3.1"
cookie-signature "1.0.6"
debug "2.6.9"
depd "~1.1.1"
encodeurl "~1.0.1"
escape-html "~1.0.3"
etag "~1.8.0"
finalhandler "~1.0.6"
etag "~1.8.1"
finalhandler "1.1.0"
fresh "0.5.2"
merge-descriptors "1.0.1"
methods "~1.1.2"
on-finished "~2.3.0"
parseurl "~1.3.1"
parseurl "~1.3.2"
path-to-regexp "0.1.7"
proxy-addr "~1.1.5"
qs "6.5.0"
proxy-addr "~2.0.2"
qs "6.5.1"
range-parser "~1.2.0"
send "0.15.6"
serve-static "1.12.6"
setprototypeof "1.0.3"
safe-buffer "5.1.1"
send "0.16.1"
serve-static "1.13.1"
setprototypeof "1.1.0"
statuses "~1.3.1"
type-is "~1.6.15"
utils-merge "1.0.0"
vary "~1.1.1"
utils-merge "1.0.1"
vary "~1.1.2"
ext-list@^2.0.0:
version "2.2.2"
@@ -902,9 +909,9 @@ fill-range@^2.1.0:
repeat-element "^1.1.2"
repeat-string "^1.5.2"
finalhandler@~1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.6.tgz#007aea33d1a4d3e42017f624848ad58d212f814f"
finalhandler@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5"
dependencies:
debug "2.6.9"
encodeurl "~1.0.1"
@@ -950,7 +957,7 @@ form-data@~2.3.1:
combined-stream "^1.0.5"
mime-types "^2.1.12"
forwarded@~0.1.0:
forwarded@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
@@ -993,13 +1000,11 @@ fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2:
mkdirp ">=0.5 0"
rimraf "2"
fuse-box@2.2.31:
version "2.2.31"
resolved "https://registry.yarnpkg.com/fuse-box/-/fuse-box-2.2.31.tgz#36d267a6c6a79952a9c1fb7d1643c1949a6d42f5"
fuse-box@^2.3.4-beta.5:
version "2.3.4-beta.9"
resolved "https://registry.yarnpkg.com/fuse-box/-/fuse-box-2.3.4-beta.9.tgz#e52054eac8d4fbe8bcc6130bb418ae645fb2adea"
dependencies:
acorn "^5.0.3"
acorn-es7 "^0.1.0"
acorn-es7-plugin "^1.1.7"
acorn "^5.1.2"
acorn-jsx "^4.0.1"
ansi "^0.3.1"
app-root-path "^2.0.1"
@@ -1233,7 +1238,7 @@ homedir-polyfill@^1.0.1:
dependencies:
parse-passwd "^1.0.0"
http-errors@~1.6.2:
http-errors@1.6.2, http-errors@~1.6.2:
version "1.6.2"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
dependencies:
@@ -1258,7 +1263,7 @@ http-signature@~1.2.0:
jsprim "^1.2.2"
sshpk "^1.7.0"
iconv-lite@^0.4.17, iconv-lite@~0.4.13:
iconv-lite@0.4.19, iconv-lite@^0.4.17, iconv-lite@~0.4.13:
version "0.4.19"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
@@ -1318,9 +1323,9 @@ inquirer@^3.0.6:
strip-ansi "^4.0.0"
through "^2.3.6"
ipaddr.js@1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.4.0.tgz#296aca878a821816e5b85d0a285a99bcff4582f0"
ipaddr.js@1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.5.2.tgz#d4b505bde9946987ccf0fc58d9010ff9607e3fa0"
is-binary-path@^1.0.0:
version "1.0.1"
@@ -1635,9 +1640,9 @@ mime-types@^2.1.12, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17,
dependencies:
mime-db "~1.30.0"
mime@1.3.4:
version "1.3.4"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53"
mime@1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
mimic-fn@^1.0.0:
version "1.1.0"
@@ -1892,7 +1897,7 @@ parse-passwd@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
parseurl@~1.3.1, parseurl@~1.3.2:
parseurl@~1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3"
@@ -1947,11 +1952,11 @@ pinkie@^2.0.0:
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
postcss@^6.0.1:
version "6.0.12"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.12.tgz#6b0155089d2d212f7bd6a0cecd4c58c007403535"
version "6.0.13"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.13.tgz#b9ecab4ee00c89db3ec931145bd9590bbf3f125f"
dependencies:
chalk "^2.1.0"
source-map "^0.5.7"
source-map "^0.6.1"
supports-color "^4.4.0"
prelude-ls@~1.1.2:
@@ -1967,8 +1972,8 @@ preserve@^0.2.0:
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
prettier@^1.6.1:
version "1.7.0"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.7.0.tgz#47481588f41f7c90f63938feb202ac82554e7150"
version "1.7.4"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.7.4.tgz#5e8624ae9363c80f95ec644584ecdf55d74f93fa"
pretty-time@^0.2.0:
version "0.2.0"
@@ -1989,12 +1994,12 @@ proto-list@~1.2.1:
version "1.2.4"
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
proxy-addr@~1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.5.tgz#71c0ee3b102de3f202f3b64f608d173fcba1a918"
proxy-addr@~2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec"
dependencies:
forwarded "~0.1.0"
ipaddr.js "1.4.0"
forwarded "~0.1.2"
ipaddr.js "1.5.2"
pseudomap@^1.0.2:
version "1.0.2"
@@ -2004,18 +2009,14 @@ punycode@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
qs@6.5.0:
version "6.5.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49"
qs@6.5.1, qs@~6.5.1:
version "6.5.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
qs@~6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
qs@~6.5.1:
version "6.5.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
randomatic@^1.1.3:
version "1.1.7"
resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c"
@@ -2027,9 +2028,18 @@ range-parser@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
raw-body@2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89"
dependencies:
bytes "3.0.0"
http-errors "1.6.2"
iconv-lite "0.4.19"
unpipe "1.0.0"
rc@^1.1.7:
version "1.2.1"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95"
version "1.2.2"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.2.tgz#d8ce9cb57e8d64d9c7badd9876c7c34cbe3c7077"
dependencies:
deep-extend "~0.4.0"
ini "~1.3.0"
@@ -2118,8 +2128,8 @@ request@2.81.0:
uuid "^3.0.0"
request@^2.79.0:
version "2.82.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.82.0.tgz#2ba8a92cd7ac45660ea2b10a53ae67cd247516ea"
version "2.83.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356"
dependencies:
aws-sign2 "~0.7.0"
aws4 "^1.6.0"
@@ -2140,7 +2150,7 @@ request@^2.79.0:
qs "~6.5.1"
safe-buffer "^5.1.1"
stringstream "~0.0.5"
tough-cookie "~2.3.2"
tough-cookie "~2.3.3"
tunnel-agent "^0.6.0"
uuid "^3.1.0"
@@ -2177,7 +2187,7 @@ rx@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782"
safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
@@ -2191,9 +2201,9 @@ semver@^5.3.0:
version "5.4.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
send@0.15.6:
version "0.15.6"
resolved "https://registry.yarnpkg.com/send/-/send-0.15.6.tgz#20f23a9c925b762ab82705fe2f9db252ace47e34"
send@0.16.1:
version "0.16.1"
resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3"
dependencies:
debug "2.6.9"
depd "~1.1.1"
@@ -2203,20 +2213,20 @@ send@0.15.6:
etag "~1.8.1"
fresh "0.5.2"
http-errors "~1.6.2"
mime "1.3.4"
mime "1.4.1"
ms "2.0.0"
on-finished "~2.3.0"
range-parser "~1.2.0"
statuses "~1.3.1"
serve-static@1.12.6:
version "1.12.6"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.6.tgz#b973773f63449934da54e5beba5e31d9f4211577"
serve-static@1.13.1:
version "1.13.1"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.1.tgz#4c57d53404a761d8f2e7c1e8a18a47dbf278a719"
dependencies:
encodeurl "~1.0.1"
escape-html "~1.0.3"
parseurl "~1.3.2"
send "0.15.6"
send "0.16.1"
set-blocking@~2.0.0:
version "2.0.0"
@@ -2230,6 +2240,10 @@ setprototypeof@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04"
setprototypeof@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -2278,10 +2292,14 @@ source-map-support@^0.4.0:
dependencies:
source-map "^0.5.6"
source-map@^0.5.1, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.6:
source-map@^0.5.1, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.6:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
source-map@^0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
sshpk@^1.7.0:
version "1.13.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3"
@@ -2421,7 +2439,7 @@ tmp@^0.0.33:
dependencies:
os-tmpdir "~1.0.2"
tough-cookie@~2.3.0, tough-cookie@~2.3.2:
tough-cookie@~2.3.0, tough-cookie@~2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561"
dependencies:
@@ -2483,8 +2501,8 @@ type-is@~1.6.15:
mime-types "~2.1.15"
typescript@^2.4.1:
version "2.5.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.2.tgz#038a95f7d9bbb420b1bf35ba31d4c5c1dd3ffe34"
version "2.5.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.5.3.tgz#df3dcdc38f3beb800d4bc322646b04a3f6ca7f0d"
uglify-js@3.0.28:
version "3.0.28"
@@ -2508,7 +2526,7 @@ unbzip2-stream@^1.0.9:
buffer "^3.0.1"
through "^2.3.6"
unpipe@~1.0.0:
unpipe@1.0.0, unpipe@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
@@ -2530,9 +2548,9 @@ utils-extend@^1.0.4, utils-extend@^1.0.6, utils-extend@^1.0.7:
version "1.0.8"
resolved "https://registry.yarnpkg.com/utils-extend/-/utils-extend-1.0.8.tgz#ccfd7b64540f8e90ee21eec57769d0651cab8a5f"
utils-merge@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8"
utils-merge@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
uuid@^3.0.0, uuid@^3.1.0:
version "3.1.0"
@@ -2544,7 +2562,7 @@ v8flags@^3.0.0:
dependencies:
homedir-polyfill "^1.0.1"
vary@~1.1.1:
vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"