Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 931af404ae | |||
| f83298a0af | |||
| 717e825b17 | |||
| 5ac0afb0dd | |||
| 23f550818b | |||
| 3d18eae18a | |||
| 6f553d0fba | |||
| aba3047191 | |||
| 52b58a107d | |||
| ec734e4fb1 | |||
| 7c755e666f | |||
| 90ae7de7ac | |||
| 96f67ecba4 | |||
| 6526a611a8 | |||
| f9bf4ca464 | |||
| 4ec8a43d60 | |||
| 77109235c4 | |||
| c1531cbf23 | |||
| c5f3116c18 | |||
| 03e2985c7a | |||
| a4b48611d9 | |||
| 83d3ccf1c5 | |||
| 356d4c1886 | |||
| b74bdfc53b | |||
| 927820a5ec | |||
| 4ef98bdc8a | |||
| 90d7beb4f3 | |||
| 55c95b4663 |
@@ -5,6 +5,7 @@
|
||||
<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>
|
||||
@@ -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
|
||||
@@ -154,6 +164,10 @@ compile({
|
||||
- default: `false`
|
||||
- #### `fakeArgv: boolean`
|
||||
- fake the entry point file name (`process.argv[1]`). If nexe was used with stdin this will be `'[stdin]'`.
|
||||
- #### `ghToken: string`
|
||||
- Provide a Github Token for accessing nexe releases
|
||||
- This is usually needed in CI environments
|
||||
- default: `process.env.GITHUB_TOKEN`
|
||||
- #### `sourceUrl: string`
|
||||
- Provide an alternate url for the node source code
|
||||
- Note: temporary files will still be created for this under the specified version
|
||||
@@ -171,8 +185,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 +209,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
|
||||
|
||||
[](https://jaredallard.me/) | [](https://github.com/calebboyd) | [](https://github.com/ckarper) | [](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 +233,11 @@ Testing
|
||||
$ npm test
|
||||
```
|
||||
|
||||
## Maintainers
|
||||
|
||||
[](https://jaredallard.me/) | [](https://github.com/calebboyd) | [](https://github.com/ckarper) | [](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
-1
@@ -1,3 +1,9 @@
|
||||
dependencies:
|
||||
override:
|
||||
- export NVS_HOME="$HOME/.nvs" && git clone https://github.com/jasongin/nvs "$NVS_HOME" && . "$NVS_HOME/nvs.sh" install
|
||||
- nvs add lts && nvs link lts && nvs use default
|
||||
- npm i yarn -g
|
||||
- yarn
|
||||
test:
|
||||
override:
|
||||
- npm run asset-compile
|
||||
- yarn run asset-compile
|
||||
|
||||
+7
-6
@@ -2,7 +2,7 @@
|
||||
"name": "nexe",
|
||||
"description": "Create a single executable out of your Node.js application",
|
||||
"license": "MIT",
|
||||
"version": "2.0.0-rc.11",
|
||||
"version": "2.0.0-rc.22",
|
||||
"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.11",
|
||||
"globby": "^6.1.0",
|
||||
"minimist": "^1.2.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import { createHash } from 'crypto'
|
||||
import * as path from 'path'
|
||||
import * as fs from 'fs'
|
||||
|
||||
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)
|
||||
`
|
||||
}
|
||||
@@ -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 = {}) {}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
//TODO
|
||||
+32
-20
@@ -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))
|
||||
@@ -177,6 +185,9 @@ export class NexeCompiler<T extends NexeOptions = NexeOptions> {
|
||||
'User-Agent': 'nexe (https://www.npmjs.com/package/nexe)'
|
||||
}
|
||||
}
|
||||
if (this.options.ghToken) {
|
||||
downloadOptions.headers.Authorization = 'token ' + this.options.ghToken
|
||||
}
|
||||
const githubRelease = await getLatestGitRelease(downloadOptions)
|
||||
const assetName = target.toString()
|
||||
const asset = githubRelease.assets.find(x => x.name === assetName)
|
||||
@@ -185,18 +196,19 @@ 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()}%`)
|
||||
})
|
||||
})
|
||||
// Remove the authorization, as the download is done via amazon S3 and does not need the token
|
||||
delete downloadOptions.headers.Authorization
|
||||
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
@@ -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
@@ -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
|
||||
|
||||
|
||||
+36
-27
@@ -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}}'
|
||||
@@ -33,6 +33,7 @@ export interface NexeOptions {
|
||||
plugins: (string | NexePatch)[]
|
||||
native: any
|
||||
empty: boolean
|
||||
ghToken: string
|
||||
sourceUrl?: string
|
||||
enableStdIn?: boolean
|
||||
python?: string
|
||||
@@ -81,7 +82,8 @@ const alias = {
|
||||
m: 'make',
|
||||
h: 'help',
|
||||
l: 'loglevel',
|
||||
'fake-argv': 'fakeArgv'
|
||||
'fake-argv': 'fakeArgv',
|
||||
'gh-token': 'ghToken'
|
||||
}
|
||||
const argv = parseArgv(process.argv, { alias, default: { ...defaults, enableStdIn: true } })
|
||||
const g = c.gray
|
||||
@@ -113,7 +115,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
|
||||
@@ -182,48 +184,55 @@ 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)
|
||||
options.targets = flatten(opts.target, options.targets).map(getTarget)
|
||||
if (!options.targets.length) {
|
||||
options.targets.push(getTarget())
|
||||
}
|
||||
options.ghToken = options.ghToken || process.env.GITHUB_TOKEN || ''
|
||||
options.make = flatten(options.vcBuild, options.make)
|
||||
options.configure = flatten(options.configure)
|
||||
options.resources = flatten(opts.resource, options.resources)
|
||||
options.rc = options.rc || extractCliMap(/^rc-.*/, options)
|
||||
|
||||
if (!options.targets.length) {
|
||||
options.targets.push(getTarget())
|
||||
}
|
||||
options.output =
|
||||
(options.targets[0] as NexeTarget).platform === 'windows'
|
||||
? `${(options.output || options.name).replace(/\.exe$/, '')}.exe`
|
||||
: `${options.output || options.name}`
|
||||
options.output = resolve(cwd, options.output)
|
||||
|
||||
if (options.build) {
|
||||
const { arch } = options.targets[0] as NexeTarget
|
||||
@@ -241,14 +250,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 }
|
||||
|
||||
@@ -32,7 +32,6 @@ async function getJson<T>(url: string, options?: any) {
|
||||
return JSON.parse((await got(url, options)).body) as T
|
||||
}
|
||||
|
||||
//TODO only build the latest of each major...?
|
||||
function isBuildableVersion(version: string) {
|
||||
const major = +version.split('.')[0]
|
||||
return !~[0, 1, 2, 3, 4, 5, 7].indexOf(major) || version === '4.8.4'
|
||||
|
||||
+8
-6
@@ -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()
|
||||
|
||||
+8
-4
@@ -1,6 +1,6 @@
|
||||
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'
|
||||
@@ -56,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') //todo fix erroneous rw mode change
|
||||
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
|
||||
? compiler.options.empty ? '[empty]' : '[stdin]'
|
||||
: compiler.options.input}' written to: ${compiler.output}`
|
||||
: inputFile}' written to: ${outputFile}`
|
||||
)
|
||||
resolve(compiler.quit())
|
||||
}
|
||||
|
||||
+98
-3
@@ -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)
|
||||
|
||||
+15
-3
@@ -7,17 +7,29 @@ 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}}'))
|
||||
}
|
||||
|
||||
if (compiler.options.fakeArgv) {
|
||||
//compiler.shims.push(wrap('{/{replace:lib/steps/shim-require.js}}'))
|
||||
|
||||
if (compiler.options.fakeArgv !== false) {
|
||||
const nty = !process.stdin.isTTY
|
||||
const input = nty ? '[stdin]' : compiler.options.input
|
||||
const input = nty ? '[stdin]' : JSON.stringify(compiler.options.input)
|
||||
compiler.shims.push(
|
||||
wrap(`
|
||||
var r = require('path').resolve;
|
||||
process.argv.splice(1,0, ${nty ? `'${input}'` : `r("${input}")`});`)
|
||||
process.argv.splice(1,0, ${nty ? `'${input}'` : `r(${input})`});`)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
+15
-18
@@ -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,15 +60,15 @@ async function build () {
|
||||
target,
|
||||
output
|
||||
}
|
||||
|
||||
|
||||
const stop = keepalive()
|
||||
if (target.platform === 'alpine') {
|
||||
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 })
|
||||
@@ -79,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)'
|
||||
}
|
||||
@@ -89,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
@@ -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()
|
||||
}
|
||||
|
||||
+17
-12
@@ -5,7 +5,7 @@ import got = require('got')
|
||||
import execa = require('execa')
|
||||
import { appendFileSync } from 'fs'
|
||||
|
||||
function alpine (target: NexeTarget) {
|
||||
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) {
|
||||
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
@@ -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}`)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"main": "entry-file.js"
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
./test/**/*.spec.ts
|
||||
--check-leaks
|
||||
--require ts-node/register
|
||||
--recursive
|
||||
|
||||
@@ -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}`))
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -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`],
|
||||
|
||||
@@ -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.11:
|
||||
version "2.3.4-beta.11"
|
||||
resolved "https://registry.yarnpkg.com/fuse-box/-/fuse-box-2.3.4-beta.11.tgz#76c0e6938e0e73ea00676f46d8691c6efa226d40"
|
||||
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"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user