Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 32033b6d15 | |||
| bc1d579baa | |||
| 6ffd47f1f1 | |||
| c4e16fb6e0 | |||
| ea6f1f0808 | |||
| c1055149ab | |||
| 79fffc358a | |||
| c8cf13a9dd | |||
| 928b8134a7 | |||
| 0a2e8dba00 | |||
| 01c977bb3c | |||
| ac5bf1876a | |||
| d6ba5d193f | |||
| b785b72724 | |||
| de6bb58a10 | |||
| 56dfef1e45 | |||
| 8f3d29812a | |||
| c44877d6ad | |||
| a4db04dbee | |||
| ec7f7f318e | |||
| e49d72db88 | |||
| 1686c1f68c |
@@ -49,8 +49,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 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).
|
||||
By default `nexe` will attempt to download a pre-built executable. These are listed on the [Nexe V3 releases page](https://github.com/nexe/nexe/releases/tag/v3.3.3). The exact version you want may be unavailable 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
|
||||
|
||||
@@ -117,8 +116,8 @@ compile({
|
||||
- default: true
|
||||
- #### `build: boolean`
|
||||
- Build node from source, passing this flag tells nexe to download and build from source. Subsequently using this flag will cause nexe to use the previously built binary. To rebuild, first add [`--clean`](#clean-boolean)
|
||||
- #### `asset: string`
|
||||
- Provide a pre-built nexe binary asset, this can either be an http or https URL or a file path.
|
||||
- #### `remote: string`
|
||||
- Provide a custom remote location for fetching pre-built nexe binaries from. This can either be an HTTP or HTTPS URL or a file path.
|
||||
- default: `null`
|
||||
- #### `python: string`
|
||||
- On Linux this is the path pointing to your python2 executable
|
||||
|
||||
+4
-3
@@ -19,13 +19,13 @@ schedules:
|
||||
- master
|
||||
jobs:
|
||||
- job: BaseBuild
|
||||
timeoutInMinutes: 180
|
||||
timeoutInMinutes: 360
|
||||
strategy:
|
||||
matrix:
|
||||
linux:
|
||||
imageName: 'ubuntu-16.04'
|
||||
mac:
|
||||
imageName: 'macos-10.13'
|
||||
imageName: 'macos-10.15'
|
||||
windows_2017:
|
||||
imageName: 'vs2017-win2016'
|
||||
windows_2015:
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
- task: NodeTool@0
|
||||
displayName: Install Node
|
||||
inputs:
|
||||
versionSpec: '10.x'
|
||||
versionSpec: '12.x'
|
||||
- script: sudo apt-get update && sudo apt-get install -y libc6-dev-i386 gcc-multilib g++-multilib
|
||||
condition: contains(variables['Agent.JobName'], 'linux')
|
||||
displayName: Install Linux build dependencies
|
||||
@@ -55,6 +55,7 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: $(PersonalGithubToken)
|
||||
NEXE_VERBOSE: $(NEXE_VERBOSE)
|
||||
msbuild_args: /3G
|
||||
condition: not(contains(variables['Agent.JobName'], 'windows'))
|
||||
- powershell: |
|
||||
iex (new-object net.webclient).downloadstring('https://get.scoop.sh')
|
||||
|
||||
Generated
+489
-304
File diff suppressed because it is too large
Load Diff
+20
-20
@@ -2,7 +2,7 @@
|
||||
"name": "nexe",
|
||||
"description": "Create a single executable out of your Node.js application",
|
||||
"license": "MIT",
|
||||
"version": "4.0.0-beta.3",
|
||||
"version": "4.0.0-beta.11",
|
||||
"contributors": [
|
||||
"Craig Condon <craig.j.condon@gmail.com> (http://crcn.io)",
|
||||
"Jared Allard <jaredallard@outlook.com>",
|
||||
@@ -30,47 +30,47 @@
|
||||
"nexe": "index.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
"node": ">=10"
|
||||
},
|
||||
"dependencies": {
|
||||
"@calebboyd/semaphore": "^1.3.1",
|
||||
"app-builder": "^5.2.0",
|
||||
"app-builder": "^6.2.2",
|
||||
"caw": "^2.0.1",
|
||||
"chalk": "^2.4.2",
|
||||
"cherow": "1.6.9",
|
||||
"download": "^7.1.0",
|
||||
"globby": "^10.0.1",
|
||||
"globby": "^11.0.1",
|
||||
"got": "^9.6.0",
|
||||
"minimist": "^1.2.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"minimist": "^1.2.5",
|
||||
"mkdirp": "^1.0.4",
|
||||
"multistream": "^4.0.0",
|
||||
"ora": "^3.4.0",
|
||||
"pify": "^4.0.1",
|
||||
"resolve-dependencies": "^3.0.2",
|
||||
"resolve-dependencies": "^4.2.2",
|
||||
"rimraf": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.2.3",
|
||||
"@types/chai": "^4.2.11",
|
||||
"@types/download": "^6.2.4",
|
||||
"@types/execa": "^2.0.0",
|
||||
"@types/globby": "^9.1.0",
|
||||
"@types/got": "^9.6.7",
|
||||
"@types/got": "^9.6.10",
|
||||
"@types/minimist": "^1.2.0",
|
||||
"@types/mkdirp": "^0.5.2",
|
||||
"@types/mocha": "^5.2.7",
|
||||
"@types/mkdirp": "^1.0.0",
|
||||
"@types/mocha": "^7.0.2",
|
||||
"@types/multistream": "^2.1.1",
|
||||
"@types/ora": "^3.2.0",
|
||||
"@types/pify": "3.0.2",
|
||||
"@types/rimraf": "2.0.2",
|
||||
"@types/semver": "^6.0.2",
|
||||
"@types/rimraf": "3.0.0",
|
||||
"@types/semver": "^7.1.0",
|
||||
"chai": "^4.2.0",
|
||||
"execa": "^2.1.0",
|
||||
"mocha": "^6.2.1",
|
||||
"prettier": "^1.18.2",
|
||||
"ts-node": "^8.4.1",
|
||||
"tslint": "^5.20.0",
|
||||
"execa": "^4.0.0",
|
||||
"mocha": "^7.1.1",
|
||||
"prettier": "^2.0.5",
|
||||
"ts-node": "^8.9.0",
|
||||
"tslint": "^6.1.1",
|
||||
"tslint-config-prettier": "^1.18.0",
|
||||
"tslint-plugin-prettier": "^2.0.1",
|
||||
"typescript": "^3.6.3"
|
||||
"tslint-plugin-prettier": "^2.3.0",
|
||||
"typescript": "^3.8.3"
|
||||
}
|
||||
}
|
||||
|
||||
+29
-28
@@ -11,7 +11,8 @@ import {
|
||||
dequote,
|
||||
isWindows,
|
||||
bound,
|
||||
semverGt
|
||||
semverGt,
|
||||
wrap,
|
||||
} from './util'
|
||||
import { NexeOptions, version } from './options'
|
||||
import { NexeTarget } from './target'
|
||||
@@ -108,12 +109,18 @@ export class NexeCompiler {
|
||||
//SOMEDAY iterate over multiple targets with `--outDir`
|
||||
this.targets = options.targets as NexeTarget[]
|
||||
this.target = this.targets[0]
|
||||
if (options.asset && options.asset.startsWith('http')) {
|
||||
this.remoteAsset = options.asset
|
||||
} else {
|
||||
this.remoteAsset =
|
||||
'https://github.com/nexe/nexe/releases/download/v3.0.0/' + this.target.toString()
|
||||
if (
|
||||
!(
|
||||
options.remote.startsWith('http://') ||
|
||||
options.remote.startsWith('https://') ||
|
||||
options.remote.startsWith('file://')
|
||||
)
|
||||
) {
|
||||
throw new NexeError(
|
||||
`Invalid remote URI scheme (must be http, https, or file): ${options.remote}`
|
||||
)
|
||||
}
|
||||
this.remoteAsset = options.remote + this.target.toString()
|
||||
this.src = join(this.options.temp, this.target.version)
|
||||
this.configureScript = configure + (semverGt(this.target.version, '10.10.0') ? '.py' : '')
|
||||
this.nodeSrcBinPath = isWindows
|
||||
@@ -140,27 +147,19 @@ export class NexeCompiler {
|
||||
return this.bundle.addResource(absoluteFileName, content)
|
||||
}
|
||||
|
||||
get binaryConfiguration() {
|
||||
return { resources: this.bundle.index }
|
||||
}
|
||||
|
||||
get resourceSize() {
|
||||
return this.bundle.blobSize
|
||||
}
|
||||
|
||||
@bound
|
||||
async readFileAsync(file: string) {
|
||||
this.assertBuild()
|
||||
let cachedFile = this.files.find(x => normalize(x.filename) === normalize(file))
|
||||
let cachedFile = this.files.find((x) => normalize(x.filename) === normalize(file))
|
||||
if (!cachedFile) {
|
||||
const absPath = join(this.src, file)
|
||||
cachedFile = {
|
||||
absPath,
|
||||
filename: file,
|
||||
contents: await readFileAsync(absPath, 'utf-8').catch(x => {
|
||||
contents: await readFileAsync(absPath, 'utf-8').catch((x) => {
|
||||
if (x.code === 'ENOENT') return ''
|
||||
throw x
|
||||
})
|
||||
}),
|
||||
}
|
||||
this.files.push(cachedFile)
|
||||
}
|
||||
@@ -198,9 +197,6 @@ export class NexeCompiler {
|
||||
}
|
||||
|
||||
public getNodeExecutableLocation(target?: NexeTarget) {
|
||||
if (this.options.asset && !this.options.asset.startsWith('http')) {
|
||||
return resolve(this.options.cwd, this.options.asset)
|
||||
}
|
||||
if (target) {
|
||||
return join(this.options.temp, target.toString())
|
||||
}
|
||||
@@ -215,7 +211,7 @@ export class NexeCompiler {
|
||||
spawn(command, args, {
|
||||
cwd: this.src,
|
||||
env: this.env,
|
||||
stdio: this.log.verbose ? 'inherit' : 'ignore'
|
||||
stdio: this.log.verbose ? 'inherit' : 'ignore',
|
||||
})
|
||||
.once('error', (e: Error) => {
|
||||
if (this.log.verbose) {
|
||||
@@ -242,7 +238,7 @@ export class NexeCompiler {
|
||||
}
|
||||
return this._runBuildCommandAsync(this.env.PYTHON || 'python', [
|
||||
this.configureScript,
|
||||
...this.options.configure
|
||||
...this.options.configure,
|
||||
])
|
||||
}
|
||||
|
||||
@@ -298,22 +294,27 @@ export class NexeCompiler {
|
||||
return [this.shims.join(''), this.startup].join(';')
|
||||
}
|
||||
|
||||
private _assembleDeliverable(binary: NodeJS.ReadableStream) {
|
||||
private async _assembleDeliverable(binary: NodeJS.ReadableStream) {
|
||||
if (!this.options.mangle) {
|
||||
return binary
|
||||
}
|
||||
const bundle = await this.bundle.toStream()
|
||||
|
||||
this.shims.unshift(
|
||||
wrap(`process.__nexe = ${JSON.stringify({ resources: this.bundle.fileIndex() })};\n`)
|
||||
)
|
||||
|
||||
const startup = this.code(),
|
||||
codeSize = Buffer.byteLength(startup)
|
||||
codeSize = Buffer.byteLength(startup),
|
||||
lengths = Buffer.from(Array(16))
|
||||
|
||||
const lengths = Buffer.from(Array(16))
|
||||
lengths.writeDoubleLE(codeSize, 0)
|
||||
lengths.writeDoubleLE(this.bundle.blobSize, 8)
|
||||
lengths.writeDoubleLE(this.bundle.size, 8)
|
||||
return new (MultiStream as any)([
|
||||
binary,
|
||||
toStream(startup),
|
||||
this.bundle.toStream(),
|
||||
toStream(Buffer.concat([Buffer.from('<nexe~~sentinel>'), lengths]))
|
||||
bundle,
|
||||
toStream(Buffer.concat([Buffer.from('<nexe~~sentinel>'), lengths])),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
+68
-27
@@ -1,12 +1,23 @@
|
||||
import { stat as getStat, Stats, createReadStream } from 'fs'
|
||||
import * as fs from 'fs'
|
||||
import { promisify } from 'util'
|
||||
import { relative } from 'path'
|
||||
import { Readable } from 'stream'
|
||||
import { each } from '@calebboyd/semaphore'
|
||||
import MultiStream = require('multistream')
|
||||
|
||||
const stat = (file: string): Promise<Stats> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
getStat(file, (err, stats) => (err ? reject(err) : resolve(stats)))
|
||||
})
|
||||
const { createReadStream } = fs,
|
||||
lstat = promisify(fs.lstat),
|
||||
realpath = promisify(fs.realpath),
|
||||
stat = promisify(fs.stat)
|
||||
|
||||
export type MultiStreams = (Readable | (() => Readable))[]
|
||||
|
||||
function renderSortedObject(entries: [string, [number, number]][], streams: MultiStreams) {
|
||||
return entries.sort().reduce((obj, [key, value]) => {
|
||||
streams.push((value as any).stream)
|
||||
;(value as any).stream = void 0
|
||||
return Object.assign(obj, { [key]: value })
|
||||
}, {})
|
||||
}
|
||||
|
||||
function makeRelative(cwd: string, path: string) {
|
||||
@@ -18,7 +29,7 @@ export function toStream(content: Buffer | string) {
|
||||
read() {
|
||||
this.push(content)
|
||||
this.push(null)
|
||||
}
|
||||
},
|
||||
})
|
||||
return readable
|
||||
}
|
||||
@@ -35,39 +46,69 @@ export interface BundleOptions {
|
||||
}
|
||||
|
||||
export class Bundle {
|
||||
size = 0
|
||||
cwd: string
|
||||
rendered = false
|
||||
files: { [key: string]: string | Buffer | undefined } = {}
|
||||
streams: MultiStreams = []
|
||||
private index: { [relativeFilePath: string]: [number, number] } = {}
|
||||
constructor({ cwd }: { cwd: string } = { cwd: process.cwd() }) {
|
||||
this.cwd = cwd
|
||||
}
|
||||
cwd: string
|
||||
blobSize: number = 0
|
||||
index: { [relativeFilePath: string]: [number, number] } = {}
|
||||
streams: (Readable | (() => Readable))[] = []
|
||||
|
||||
async addResource(absoluteFileName: string, content?: Buffer | string) {
|
||||
addResource(absoluteFileName: string, content?: Buffer | string) {
|
||||
this.files[absoluteFileName] = content
|
||||
}
|
||||
|
||||
async addEntry(absoluteFileName: string, content?: Buffer | string) {
|
||||
let length = 0
|
||||
let linkpath = ''
|
||||
if (content !== undefined) {
|
||||
length = Buffer.byteLength(content)
|
||||
} else {
|
||||
const stats = await stat(absoluteFileName)
|
||||
let stats = await lstat(absoluteFileName)
|
||||
if (stats.isSymbolicLink()) {
|
||||
linkpath = absoluteFileName
|
||||
absoluteFileName = await realpath(linkpath)
|
||||
stats = await stat(linkpath)
|
||||
}
|
||||
length = stats.size
|
||||
}
|
||||
|
||||
const start = this.blobSize
|
||||
|
||||
this.blobSize += length
|
||||
this.index[makeRelative(this.cwd, absoluteFileName)] = [start, length]
|
||||
this.streams.push(() => (content ? toStream(content) : createReadStream(absoluteFileName)))
|
||||
const name = makeRelative(this.cwd, absoluteFileName),
|
||||
existing = this.index[name]
|
||||
if (!existing) {
|
||||
const start = this.size
|
||||
this.size += length
|
||||
this.index[name] = [start, length]
|
||||
}
|
||||
if (linkpath) {
|
||||
const linkName = makeRelative(this.cwd, absoluteFileName)
|
||||
this.index[linkName] = this.index[name]
|
||||
}
|
||||
if (!existing) {
|
||||
;(this.index[name] as any).stream = () =>
|
||||
content ? toStream(content) : createReadStream(absoluteFileName)
|
||||
}
|
||||
}
|
||||
|
||||
concat() {
|
||||
throw new Error('Not Implemented')
|
||||
}
|
||||
|
||||
toStream() {
|
||||
return new (MultiStream as any)(this.streams)
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
fileIndex() {
|
||||
if (!this.rendered) {
|
||||
throw new Error('Index not rendered must call toStream() first')
|
||||
}
|
||||
return this.index
|
||||
}
|
||||
|
||||
async toStream() {
|
||||
this.files
|
||||
await each(
|
||||
Object.keys(this.files),
|
||||
(key: string) => {
|
||||
return this.addEntry(key, this.files[key])
|
||||
},
|
||||
{ concurrency: 10 }
|
||||
)
|
||||
this.index = renderSortedObject(Object.entries(this.index), this.streams)
|
||||
this.rendered = true
|
||||
return new (MultiStream as any)(this.streams)
|
||||
}
|
||||
}
|
||||
|
||||
+37
-28
@@ -15,6 +15,12 @@ export interface NexeBinary {
|
||||
let originalFsMethods: any = null
|
||||
let lazyRestoreFs = () => {}
|
||||
|
||||
// optional Win32 file namespace prefix followed by drive letter and colon
|
||||
const windowsFullPathRegex = /^(\\{2}\?\\)?([a-zA-Z]):/
|
||||
|
||||
const upcaseDriveLetter = (s: string): string =>
|
||||
s.replace(windowsFullPathRegex, (_match, ns, drive) => `${ns || ''}${drive.toUpperCase()}:`)
|
||||
|
||||
function shimFs(binary: NexeBinary, fs: any = require('fs')) {
|
||||
if (originalFsMethods !== null) {
|
||||
return
|
||||
@@ -28,18 +34,21 @@ function shimFs(binary: NexeBinary, fs: any = require('fs')) {
|
||||
isString = (x: any): x is string => typeof x === 'string' || x instanceof String,
|
||||
noop = () => {},
|
||||
path = require('path'),
|
||||
baseDir = path.dirname(process.execPath)
|
||||
winPath: (key: string) => string = isWin ? upcaseDriveLetter : (s) => s,
|
||||
baseDir = winPath(path.dirname(process.execPath))
|
||||
|
||||
let log = (_: string) => true
|
||||
let loggedManifest = false
|
||||
if ((process.env.DEBUG || '').toLowerCase().includes('nexe:require')) {
|
||||
log = (text: string) => process.stderr.write('[nexe] - ' + text + '\n')
|
||||
}
|
||||
|
||||
const winPath = (key: string) => {
|
||||
if (isWin && key.substr(1, 2) === ':\\') {
|
||||
key = key[0].toUpperCase() + key.substr(1)
|
||||
log = (text: string) => {
|
||||
setupManifest()
|
||||
if (!loggedManifest) {
|
||||
process.stderr.write('[nexe] - MANIFEST' + JSON.stringify(manifest, null, 4) + '\n')
|
||||
process.stderr.write('[nexe] - DIRECTORIES' + JSON.stringify(directories, null, 4) + '\n')
|
||||
loggedManifest = true
|
||||
}
|
||||
return process.stderr.write('[nexe] - ' + text + '\n')
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
const getKey = function getKey(filepath: string | Buffer | null): string {
|
||||
@@ -54,7 +63,7 @@ function shimFs(binary: NexeBinary, fs: any = require('fs')) {
|
||||
return winPath(key)
|
||||
}
|
||||
|
||||
const statTime = function() {
|
||||
const statTime = function () {
|
||||
return {
|
||||
dev: 0,
|
||||
ino: 0,
|
||||
@@ -71,7 +80,7 @@ function shimFs(binary: NexeBinary, fs: any = require('fs')) {
|
||||
ctime: new Date(stat.ctime),
|
||||
ctimMs: stat.ctime.getTime(),
|
||||
birthtime: new Date(stat.birthtime),
|
||||
birthtimeMs: stat.birthtime.getTime()
|
||||
birthtimeMs: stat.birthtime.getTime(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +89,7 @@ function shimFs(binary: NexeBinary, fs: any = require('fs')) {
|
||||
BigInt = eval('BigInt')
|
||||
} catch (ignored) {}
|
||||
|
||||
const createStat = function(extensions: any, options: any) {
|
||||
const createStat = function (extensions: any, options: any) {
|
||||
const stat = Object.assign(new fs.Stats(), binary.layout.stat, statTime(), extensions)
|
||||
if (options && options.bigint && BigInt) {
|
||||
for (const k in stat) {
|
||||
@@ -92,7 +101,7 @@ function shimFs(binary: NexeBinary, fs: any = require('fs')) {
|
||||
return stat
|
||||
}
|
||||
|
||||
const ownStat = function(filepath: any, options: any) {
|
||||
const ownStat = function (filepath: any, options: any) {
|
||||
setupManifest()
|
||||
const key = getKey(filepath)
|
||||
if (directories[key]) {
|
||||
@@ -115,7 +124,7 @@ function shimFs(binary: NexeBinary, fs: any = require('fs')) {
|
||||
}
|
||||
|
||||
let setupManifest = () => {
|
||||
Object.keys(manifest).forEach(filepath => {
|
||||
Object.keys(manifest).forEach((filepath) => {
|
||||
const entry = manifest[filepath]
|
||||
const absolutePath = getKey(filepath)
|
||||
const longPath = makeLong(absolutePath)
|
||||
@@ -209,19 +218,19 @@ function shimFs(binary: NexeBinary, fs: any = require('fs')) {
|
||||
const encoding = fileOpts(options).encoding
|
||||
callback = typeof options === 'function' ? options : callback
|
||||
|
||||
originalFsMethods.open(blobPath, 'r', function(err: Error, fd: number) {
|
||||
originalFsMethods.open(blobPath, 'r', function (err: Error, fd: number) {
|
||||
if (err) return callback(err, null)
|
||||
originalFsMethods.read(fd, Buffer.alloc(length), 0, length, resourceOffset, function(
|
||||
originalFsMethods.read(fd, Buffer.alloc(length), 0, length, resourceOffset, function (
|
||||
error: Error,
|
||||
bytesRead: number,
|
||||
result: Buffer
|
||||
) {
|
||||
if (error) {
|
||||
return originalFsMethods.close(fd, function() {
|
||||
return originalFsMethods.close(fd, function () {
|
||||
callback(error, null)
|
||||
})
|
||||
}
|
||||
originalFsMethods.close(fd, function(err: Error) {
|
||||
originalFsMethods.close(fd, function (err: Error) {
|
||||
if (err) {
|
||||
return callback(err, result)
|
||||
}
|
||||
@@ -244,7 +253,7 @@ function shimFs(binary: NexeBinary, fs: any = require('fs')) {
|
||||
blobPath,
|
||||
Object.assign({}, opts, {
|
||||
start: resourceOffset,
|
||||
end: resourceOffset + length - 1
|
||||
end: resourceOffset + length - 1,
|
||||
})
|
||||
)
|
||||
},
|
||||
@@ -285,11 +294,11 @@ function shimFs(binary: NexeBinary, fs: any = require('fs')) {
|
||||
} else {
|
||||
return originalFsMethods.stat.apply(fs, arguments)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
if (typeof fs.exists === 'function') {
|
||||
nfs.exists = function(filepath: string, cb: Function) {
|
||||
nfs.exists = function (filepath: string, cb: Function) {
|
||||
cb = cb || noop
|
||||
const exists = nfs.existsSync(filepath)
|
||||
process.nextTick(() => cb(exists))
|
||||
@@ -298,9 +307,9 @@ function shimFs(binary: NexeBinary, fs: any = require('fs')) {
|
||||
|
||||
const patches = (process as any).nexe.patches || {}
|
||||
delete (process as any).nexe
|
||||
patches.internalModuleReadFile = function(this: any, original: any, ...args: any[]) {
|
||||
const [filepath] = args
|
||||
patches.internalModuleReadFile = function (this: any, original: any, ...args: any[]) {
|
||||
setupManifest()
|
||||
const filepath = getKey(args[0])
|
||||
if (manifest[filepath]) {
|
||||
log('read (hit) ' + filepath)
|
||||
return nfs.readFileSync(filepath, 'utf-8')
|
||||
@@ -309,9 +318,9 @@ function shimFs(binary: NexeBinary, fs: any = require('fs')) {
|
||||
return original.call(this, ...args)
|
||||
}
|
||||
patches.internalModuleReadJSON = patches.internalModuleReadFile
|
||||
patches.internalModuleStat = function(this: any, original: any, ...args: any[]) {
|
||||
patches.internalModuleStat = function (this: any, original: any, ...args: any[]) {
|
||||
setupManifest()
|
||||
const [filepath] = args
|
||||
const filepath = getKey(args[0])
|
||||
if (manifest[filepath]) {
|
||||
log('stat (hit) ' + filepath + ' ' + 0)
|
||||
return 0
|
||||
@@ -332,7 +341,7 @@ function shimFs(binary: NexeBinary, fs: any = require('fs')) {
|
||||
}
|
||||
|
||||
if (typeof fs.exists === 'function') {
|
||||
nfs.exists = function(filepath: string, cb: Function) {
|
||||
nfs.exists = function (filepath: string, cb: Function) {
|
||||
cb = cb || noop
|
||||
const exists = nfs.existsSync(filepath)
|
||||
if (!exists) {
|
||||
@@ -343,7 +352,7 @@ function shimFs(binary: NexeBinary, fs: any = require('fs')) {
|
||||
}
|
||||
|
||||
if (typeof fs.copyFile === 'function') {
|
||||
nfs.copyFile = function(filepath: string, dest: string, flags: number, callback: Function) {
|
||||
nfs.copyFile = function (filepath: string, dest: string, flags: number, callback: Function) {
|
||||
setupManifest()
|
||||
const entry = manifest[getKey(filepath)]
|
||||
if (!entry) {
|
||||
@@ -365,7 +374,7 @@ function shimFs(binary: NexeBinary, fs: any = require('fs')) {
|
||||
})
|
||||
})
|
||||
}
|
||||
nfs.copyFileSync = function(filepath: string, dest: string) {
|
||||
nfs.copyFileSync = function (filepath: string, dest: string) {
|
||||
setupManifest()
|
||||
const entry = manifest[getKey(filepath)]
|
||||
if (!entry) {
|
||||
@@ -378,7 +387,7 @@ function shimFs(binary: NexeBinary, fs: any = require('fs')) {
|
||||
Object.assign(fs, nfs)
|
||||
|
||||
lazyRestoreFs = () => {
|
||||
Object.keys(nfs).forEach(key => {
|
||||
Object.keys(nfs).forEach((key) => {
|
||||
fs[key] = originalFsMethods[key]
|
||||
})
|
||||
lazyRestoreFs = () => {}
|
||||
|
||||
+3
-3
@@ -24,7 +24,7 @@ export class Logger {
|
||||
this.ora = ora({
|
||||
text: 'Starting...',
|
||||
color: 'blue',
|
||||
spinner: 'dots'
|
||||
spinner: 'dots',
|
||||
})
|
||||
this.ora.stop()
|
||||
}
|
||||
@@ -35,7 +35,7 @@ export class Logger {
|
||||
|
||||
flush() {
|
||||
!this.silent && this.ora.succeed()
|
||||
return new Promise(resolve => setTimeout(resolve, frameLength))
|
||||
return new Promise((resolve) => setTimeout(resolve, frameLength))
|
||||
}
|
||||
|
||||
_write(update: string, color = 'green') {
|
||||
@@ -66,7 +66,7 @@ export class Logger {
|
||||
modify: this.modify,
|
||||
log: this.verbose ? this.write : this.modify,
|
||||
pause: () => this.ora.stopAndPersist(),
|
||||
resume: () => this.ora.start()
|
||||
resume: () => this.ora.start(),
|
||||
} as LogStep
|
||||
}
|
||||
}
|
||||
|
||||
+20
-19
@@ -21,7 +21,7 @@ export interface NexeOptions {
|
||||
output: string
|
||||
targets: (string | NexeTarget)[]
|
||||
name: string
|
||||
asset: string
|
||||
remote: string
|
||||
cwd: string
|
||||
fs: boolean | string[]
|
||||
flags: string[]
|
||||
@@ -70,7 +70,8 @@ const defaults = {
|
||||
build: false,
|
||||
bundle: true,
|
||||
patches: [],
|
||||
plugins: []
|
||||
plugins: [],
|
||||
remote: 'https://github.com/nexe/nexe/releases/download/v3.3.3/',
|
||||
}
|
||||
const alias = {
|
||||
i: 'input',
|
||||
@@ -80,7 +81,6 @@ const alias = {
|
||||
b: 'build',
|
||||
n: 'name',
|
||||
r: 'resource',
|
||||
a: 'asset',
|
||||
p: 'python',
|
||||
f: 'flag',
|
||||
c: 'configure',
|
||||
@@ -88,7 +88,7 @@ const alias = {
|
||||
h: 'help',
|
||||
l: 'loglevel',
|
||||
'fake-argv': 'fakeArgv',
|
||||
'gh-token': 'ghToken'
|
||||
'gh-token': 'ghToken',
|
||||
}
|
||||
const argv = parseArgv(process.argv, { alias, default: { ...defaults } })
|
||||
let help = `
|
||||
@@ -101,7 +101,7 @@ ${c.bold('nexe <entry-file> [options]')}
|
||||
-t --target -- node version description
|
||||
-n --name -- main app module name
|
||||
-r --resource -- *embed files (glob) within the binary
|
||||
-a --asset -- alternate asset path, file or url pointing to a base (nexe) binary
|
||||
--remote -- alternate location (URL) to download pre-built base (nexe) binaries from
|
||||
--plugin -- extend nexe runtime behavior
|
||||
|
||||
${c.underline.bold('Building from source:')}
|
||||
@@ -112,7 +112,7 @@ ${c.bold('nexe <entry-file> [options]')}
|
||||
-c --configure -- *arguments to the configure step
|
||||
-m --make -- *arguments to the make/build step
|
||||
--patch -- module with middleware default export for adding a build patch
|
||||
--no-mangle -- used when generating base binaries, or when patching _third_party_main manually.
|
||||
--no-mangle -- used when generating base binaries, or when patching _third_party_main manually
|
||||
--snapshot -- path to a warmup snapshot
|
||||
--ico -- file name for alternate icon file (windows)
|
||||
--rc-* -- populate rc file options (windows)
|
||||
@@ -133,7 +133,7 @@ ${c.bold('nexe <entry-file> [options]')}
|
||||
help = EOL + help + EOL
|
||||
|
||||
function flatten(...args: any[]): string[] {
|
||||
return ([] as string[]).concat(...args).filter(x => x)
|
||||
return ([] as string[]).concat(...args).filter((x) => x)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,16 +144,13 @@ function flatten(...args: any[]): string[] {
|
||||
*/
|
||||
function extractCliMap(match: RegExp, options: any) {
|
||||
return Object.keys(options)
|
||||
.filter(x => match.test(x))
|
||||
.reduce(
|
||||
(map: any, option: any) => {
|
||||
const key = option.split('-')[1]
|
||||
map[key] = options[option]
|
||||
delete options[option]
|
||||
return map
|
||||
},
|
||||
{} as any
|
||||
)
|
||||
.filter((x) => match.test(x))
|
||||
.reduce((map: any, option: any) => {
|
||||
const key = option.split('-')[1]
|
||||
map[key] = options[option]
|
||||
delete options[option]
|
||||
return map
|
||||
}, {} as any)
|
||||
}
|
||||
|
||||
function extractLogLevel(options: NexeOptions) {
|
||||
@@ -252,6 +249,10 @@ function normalizeOptions(input?: Partial<NexeOptions>): NexeOptions {
|
||||
options.configure = flatten(options.configure)
|
||||
options.resources = flatten(opts.resource, options.resources)
|
||||
|
||||
if (!options.remote.endsWith('/')) {
|
||||
options.remote += '/'
|
||||
}
|
||||
|
||||
options.downloadOptions = options.downloadOptions || {}
|
||||
options.downloadOptions.headers = options.downloadOptions.headers || {}
|
||||
options.downloadOptions.headers['User-Agent'] = 'nexe (https://www.npmjs.com/package/nexe)'
|
||||
@@ -292,8 +293,8 @@ function normalizeOptions(input?: Partial<NexeOptions>): NexeOptions {
|
||||
}
|
||||
|
||||
Object.keys(alias)
|
||||
.filter(k => k !== 'rc')
|
||||
.forEach(x => delete opts[x])
|
||||
.filter((k) => k !== 'rc')
|
||||
.forEach((x) => delete opts[x])
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
@@ -20,13 +20,13 @@ const footer = tailWindow.slice(footerPosition, footerPosition + 32),
|
||||
Object.defineProperty(
|
||||
process,
|
||||
'__nexe',
|
||||
(function() {
|
||||
(function () {
|
||||
let nexeHeader: any = null
|
||||
return {
|
||||
get: function() {
|
||||
get: function () {
|
||||
return nexeHeader
|
||||
},
|
||||
set: function(value: any) {
|
||||
set: function (value: any) {
|
||||
if (nexeHeader) {
|
||||
throw new Error('This property is readonly')
|
||||
}
|
||||
@@ -37,13 +37,13 @@ Object.defineProperty(
|
||||
contentSize,
|
||||
contentStart,
|
||||
resourceSize,
|
||||
resourceStart
|
||||
}
|
||||
resourceStart,
|
||||
},
|
||||
})
|
||||
Object.freeze(nexeHeader)
|
||||
},
|
||||
enumerable: false,
|
||||
configurable: false
|
||||
configurable: false,
|
||||
}
|
||||
})()
|
||||
)
|
||||
|
||||
@@ -7,7 +7,11 @@ export default async function disableNodeCli(compiler: NexeCompiler, next: () =>
|
||||
}
|
||||
|
||||
if (semverGt(compiler.target.version, '11.6.0')) {
|
||||
await compiler.replaceInFileAsync('src/node.cc', /(?<!int )ProcessGlobalArgs\(argv/g, '0;//$&')
|
||||
await compiler.replaceInFileAsync(
|
||||
'src/node.cc',
|
||||
/(?<!int )ProcessGlobalArgs\(argv[^;]*;/gm,
|
||||
'0;/*$&*/'
|
||||
)
|
||||
} else if (semverGt(compiler.target.version, '10.9')) {
|
||||
await compiler.replaceInFileAsync('src/node.cc', /(?<!void )ProcessArgv\(argv/g, '//$&')
|
||||
} else if (semverGt(compiler.target.version, '9.999')) {
|
||||
@@ -17,7 +21,7 @@ export default async function disableNodeCli(compiler: NexeCompiler, next: () =>
|
||||
'int i = v8_argc; i < v8_argc; i++'
|
||||
)
|
||||
let matches = 0
|
||||
await compiler.replaceInFileAsync('src/node.cc', /v8_argc > 1/g, match => {
|
||||
await compiler.replaceInFileAsync('src/node.cc', /v8_argc > 1/g, (match) => {
|
||||
if (matches++) {
|
||||
return 'false'
|
||||
}
|
||||
|
||||
+2
-2
@@ -13,8 +13,8 @@ export default async function nodeGyp(
|
||||
`
|
||||
${nodeGypMarker}
|
||||
${files
|
||||
.filter(x => x.filename.startsWith('lib'))
|
||||
.map(x => `'${x.filename}'`)
|
||||
.filter((x) => x.filename.startsWith('lib'))
|
||||
.map((x) => `'${x.filename}'`)
|
||||
.toString()},
|
||||
`.trim()
|
||||
)
|
||||
|
||||
@@ -8,7 +8,7 @@ export default async function nodeRc(compiler: NexeCompiler, next: () => Promise
|
||||
|
||||
const file = await compiler.readFileAsync('src/res/node.rc')
|
||||
|
||||
Object.keys(options).forEach(key => {
|
||||
Object.keys(options).forEach((key) => {
|
||||
let value = options[key]
|
||||
const isVar = /^[A-Z_]+$/.test(value)
|
||||
value = isVar ? value : `"${value}"`
|
||||
@@ -17,7 +17,7 @@ export default async function nodeRc(compiler: NexeCompiler, next: () => Promise
|
||||
`VALUE "${key}", ${value}`
|
||||
)
|
||||
})
|
||||
;['PRODUCTVERSION', 'FILEVERSION'].forEach(x => {
|
||||
;['PRODUCTVERSION', 'FILEVERSION'].forEach((x) => {
|
||||
if (options[x]) {
|
||||
file.contents = file.contents.replace(new RegExp(x + ' .*$', 'm'), `${x} ${options[x]}`)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { resolve } from 'path'
|
||||
import { NexeCompiler } from '../compiler'
|
||||
import { semverGt } from '../util'
|
||||
|
||||
export default async function(compiler: NexeCompiler, next: () => Promise<void>) {
|
||||
export default async function (compiler: NexeCompiler, next: () => Promise<void>) {
|
||||
const { snapshot, warmup, cwd } = compiler.options
|
||||
|
||||
if (!snapshot) {
|
||||
|
||||
@@ -42,7 +42,7 @@ export default async function main(compiler: NexeCompiler, next: () => Promise<v
|
||||
next: true,
|
||||
globalReturn: true,
|
||||
node: true,
|
||||
skipShebang: true
|
||||
skipShebang: true,
|
||||
}),
|
||||
location = { start: { line: 0 } }
|
||||
|
||||
@@ -65,10 +65,23 @@ export default async function main(compiler: NexeCompiler, next: () => Promise<v
|
||||
file.contents = fileLines.join('\n')
|
||||
|
||||
if (semverGt(version, '11.99')) {
|
||||
if (semverGt(version, '12.17.99')) {
|
||||
await compiler.replaceInFileAsync(
|
||||
bootFile,
|
||||
'initializeFrozenIntrinsics();',
|
||||
'initializeFrozenIntrinsics();\n' + wrap('{{replace:lib/patches/boot-nexe.js}}')
|
||||
)
|
||||
} else {
|
||||
await compiler.replaceInFileAsync(
|
||||
bootFile,
|
||||
'initializePolicy();',
|
||||
'initializePolicy();\n' + wrap('{{replace:lib/patches/boot-nexe.js}}')
|
||||
)
|
||||
}
|
||||
await compiler.replaceInFileAsync(
|
||||
bootFile,
|
||||
'initializePolicy();',
|
||||
'initializePolicy();\n' + wrap('{{replace:lib/patches/boot-nexe.js}}')
|
||||
'assert(!CJSLoader.hasLoadedAnyUserCJSModule)',
|
||||
'/*assert(!CJSLoader.hasLoadedAnyUserCJSModule)*/'
|
||||
)
|
||||
await compiler.replaceInFileAsync(
|
||||
'src/node.cc',
|
||||
|
||||
+5
-8
@@ -2,7 +2,7 @@ import got = require('got')
|
||||
import { platforms, architectures, NexeTarget, getTarget, targetsEqual } from './target'
|
||||
export { NexeTarget }
|
||||
|
||||
const versionsToSkip = [0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 15, 17, 19, 21, 22]
|
||||
const versionsToSkip = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 17, 19, 21, 22]
|
||||
export interface GitAsset {
|
||||
name: string
|
||||
url: string
|
||||
@@ -28,9 +28,6 @@ function isBuildableVersion(version: string) {
|
||||
if (version === '12.11.0') {
|
||||
return false
|
||||
}
|
||||
if (version === '4.9.1') {
|
||||
return true
|
||||
}
|
||||
return !versionsToSkip.includes(Number(version.split('.')[0]))
|
||||
}
|
||||
|
||||
@@ -42,7 +39,7 @@ export async function getUnBuiltReleases(options?: any) {
|
||||
const nodeReleases = await getJson<NodeRelease[]>(
|
||||
'https://nodejs.org/download/release/index.json'
|
||||
)
|
||||
const existingVersions = (await getLatestGitRelease(options)).assets.map(x => getTarget(x.name))
|
||||
const existingVersions = (await getLatestGitRelease(options)).assets.map((x) => getTarget(x.name))
|
||||
|
||||
const versionMap: { [key: string]: true } = {}
|
||||
return nodeReleases
|
||||
@@ -52,8 +49,8 @@ export async function getUnBuiltReleases(options?: any) {
|
||||
return versions
|
||||
}
|
||||
versionMap[version] = true
|
||||
platforms.forEach(platform => {
|
||||
architectures.forEach(arch => {
|
||||
platforms.forEach((platform) => {
|
||||
architectures.forEach((arch) => {
|
||||
if (arch === 'x86' && platform === 'mac') return
|
||||
if (arch.includes('arm')) return
|
||||
versions.push(getTarget({ platform, arch, version }))
|
||||
@@ -61,5 +58,5 @@ export async function getUnBuiltReleases(options?: any) {
|
||||
})
|
||||
return versions
|
||||
}, [])
|
||||
.filter(x => !existingVersions.some(t => targetsEqual(t, x)))
|
||||
.filter((x) => !existingVersions.some((t) => targetsEqual(t, x)))
|
||||
}
|
||||
|
||||
+12
-13
@@ -1,29 +1,28 @@
|
||||
import { join, dirname } from 'path'
|
||||
import { readdir, unlink } from 'fs'
|
||||
import * as fs from 'fs'
|
||||
import { promisify } from 'util'
|
||||
import { readFileAsync, writeFileAsync, isDirectoryAsync } from '../util'
|
||||
import * as mkdirp from 'mkdirp'
|
||||
import mkdirpAsync = require('mkdirp')
|
||||
import { NexeCompiler } from '../compiler'
|
||||
import pify = require('pify')
|
||||
|
||||
const mkdirpAsync = pify(mkdirp)
|
||||
const unlinkAsync = pify(unlink)
|
||||
const readdirAsync = pify(readdir)
|
||||
const unlinkAsync = promisify(fs.unlink),
|
||||
readdirAsync = promisify(fs.readdir)
|
||||
|
||||
function readDirAsync(dir: string): Promise<string[]> {
|
||||
return readdirAsync(dir).then(paths => {
|
||||
return readdirAsync(dir).then((paths) => {
|
||||
return Promise.all(
|
||||
paths.map((file: string) => {
|
||||
const path = join(dir, file)
|
||||
return isDirectoryAsync(path).then(x => (x ? readDirAsync(path) : (path as any)))
|
||||
return isDirectoryAsync(path).then((x) => (x ? readDirAsync(path) : (path as any)))
|
||||
})
|
||||
).then(result => {
|
||||
).then((result) => {
|
||||
return [].concat(...(result as any))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function maybeReadFileContentsAsync(file: string) {
|
||||
return readFileAsync(file, 'utf-8').catch(e => {
|
||||
return readFileAsync(file, 'utf-8').catch((e) => {
|
||||
if (e.code === 'ENOENT') {
|
||||
return ''
|
||||
}
|
||||
@@ -47,16 +46,16 @@ export default async function artifacts(compiler: NexeCompiler, next: () => Prom
|
||||
const tmpFiles = await readDirAsync(temp)
|
||||
|
||||
await Promise.all(
|
||||
tmpFiles.map(async path => {
|
||||
tmpFiles.map(async (path) => {
|
||||
return compiler.writeFileAsync(path.replace(temp, ''), await readFileAsync(path, 'utf-8'))
|
||||
})
|
||||
)
|
||||
|
||||
await next()
|
||||
|
||||
await Promise.all(tmpFiles.map(x => unlinkAsync(x)))
|
||||
await Promise.all(tmpFiles.map((x) => unlinkAsync(x)))
|
||||
return Promise.all(
|
||||
compiler.files.map(async file => {
|
||||
compiler.files.map(async (file) => {
|
||||
const sourceFile = join(src, file.filename)
|
||||
const tempFile = join(temp, file.filename)
|
||||
const fileContents = await maybeReadFileContentsAsync(sourceFile)
|
||||
|
||||
+4
-6
@@ -7,7 +7,7 @@ import { Readable } from 'stream'
|
||||
|
||||
function getStdIn(stdin: Readable): Promise<string> {
|
||||
let out = ''
|
||||
return new Promise(resolve => {
|
||||
return new Promise((resolve) => {
|
||||
stdin
|
||||
.setEncoding('utf8')
|
||||
.on('readable', () => {
|
||||
@@ -64,18 +64,16 @@ export default async function bundle(compiler: NexeCompiler, next: any) {
|
||||
|
||||
const { files, warnings } = await resolveFiles(
|
||||
input,
|
||||
...Object.keys(compiler.bundle.index).filter(x => x.endsWith('.js')),
|
||||
...Object.keys(compiler.bundle.files).filter((x) => x.endsWith('.js')),
|
||||
{ cwd, expand: 'variable', loadContent: false }
|
||||
)
|
||||
|
||||
if (
|
||||
warnings.filter(x => x.startsWith('Error parsing file') && !x.includes('node_modules')).length
|
||||
warnings.filter((x) => x.startsWith('Error parsing file') && !x.includes('node_modules')).length
|
||||
) {
|
||||
throw new NexeError('Parsing Error:\n' + warnings.join('\n'))
|
||||
}
|
||||
|
||||
await each(Object.keys(files), (filename: string) => compiler.addResource(filename), {
|
||||
concurrency: 10
|
||||
})
|
||||
Object.keys(files).forEach((x) => compiler.addResource(x))
|
||||
return next()
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ function fetchNodeSourceAsync(dest: string, url: string, step: LogStep, options
|
||||
.on('response', (res: IncomingMessage) => {
|
||||
const total = +res.headers['content-length']!
|
||||
let current = 0
|
||||
res.on('data', data => {
|
||||
res.on('data', (data) => {
|
||||
current += data.length
|
||||
setText((current / total) * 100)
|
||||
if (current === total) {
|
||||
@@ -32,7 +32,7 @@ async function fetchPrebuiltBinary(compiler: NexeCompiler, step: any) {
|
||||
(res: IncomingMessage) => {
|
||||
const total = +res.headers['content-length']!
|
||||
let current = 0
|
||||
res.on('data', data => {
|
||||
res.on('data', (data) => {
|
||||
current += data.length
|
||||
step!.modify(`Downloading...${((current / total) * 100).toFixed()}%`)
|
||||
})
|
||||
|
||||
@@ -3,13 +3,18 @@ import * as globs from 'globby'
|
||||
import { NexeCompiler } from '../compiler'
|
||||
|
||||
export default async function resource(compiler: NexeCompiler, next: () => Promise<any>) {
|
||||
const { cwd } = compiler.options
|
||||
if (!compiler.options.resources.length) {
|
||||
const { cwd, resources } = compiler.options
|
||||
if (!resources.length) {
|
||||
return next()
|
||||
}
|
||||
const step = compiler.log.step('Bundling Resources...')
|
||||
let count = 0
|
||||
await each(globs(compiler.options.resources, { cwd }), async file => {
|
||||
|
||||
// workaround for https://github.com/sindresorhus/globby/issues/127
|
||||
// and https://github.com/mrmlnc/fast-glob#pattern-syntax
|
||||
const resourcesWithForwardSlashes = resources.map((r) => r.replace(/\\/g, '/'))
|
||||
|
||||
await each(globs(resourcesWithForwardSlashes, { cwd }), async (file) => {
|
||||
if (await isDirectoryAsync(file)) {
|
||||
return
|
||||
}
|
||||
@@ -17,6 +22,6 @@ export default async function resource(compiler: NexeCompiler, next: () => Promi
|
||||
step.log(`Including file: ${file}`)
|
||||
await compiler.addResource(file)
|
||||
})
|
||||
step.log(`Included ${count} file(s). ${(compiler.resourceSize / 1e6).toFixed(3)} MB`)
|
||||
step.log(`Included ${count} file(s)`)
|
||||
return next()
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,12 +1,11 @@
|
||||
import { NexeCompiler } from '../compiler'
|
||||
import { wrap } from '../util'
|
||||
|
||||
export default async function(compiler: NexeCompiler, next: () => Promise<void>) {
|
||||
export default async function (compiler: NexeCompiler, next: () => Promise<void>) {
|
||||
await next()
|
||||
|
||||
compiler.shims.push(
|
||||
wrap(
|
||||
`process.__nexe = ${JSON.stringify(compiler.binaryConfiguration)};\n` +
|
||||
'' +
|
||||
'{{replace:lib/fs/patch.js}}' +
|
||||
'\nshimFs(process.__nexe)' +
|
||||
`\n${compiler.options.fs ? '' : 'restoreFs()'}`
|
||||
|
||||
+3
-3
@@ -21,7 +21,7 @@ const prettyPlatform: { [key: string]: NodePlatform } = {
|
||||
mac: 'mac',
|
||||
linux: 'linux',
|
||||
static: 'alpine',
|
||||
alpine: 'alpine'
|
||||
alpine: 'alpine',
|
||||
}
|
||||
|
||||
const prettyArch: { [key: string]: NodeArch } = {
|
||||
@@ -35,7 +35,7 @@ const prettyArch: { [key: string]: NodeArch } = {
|
||||
amd64: 'x64',
|
||||
ia32: 'x86',
|
||||
x32: 'x86',
|
||||
x64: 'x64'
|
||||
x64: 'x64',
|
||||
}
|
||||
|
||||
function isVersion(x: string) {
|
||||
@@ -80,7 +80,7 @@ export function getTarget(target: string | Partial<NexeTarget> = ''): NexeTarget
|
||||
target
|
||||
.toLowerCase()
|
||||
.split('-')
|
||||
.forEach(x => {
|
||||
.forEach((x) => {
|
||||
if (isVersion(x)) {
|
||||
version = x.replace(/v/g, '')
|
||||
}
|
||||
|
||||
+5
-5
@@ -42,10 +42,10 @@ const bound: MethodDecorator = function bound<T>(
|
||||
Object.defineProperty(this, propertyKey as string, {
|
||||
configurable,
|
||||
value,
|
||||
writable: true
|
||||
writable: true,
|
||||
})
|
||||
return value
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,13 +72,13 @@ const isWindows = process.platform === 'win32'
|
||||
|
||||
function pathExistsAsync(path: string) {
|
||||
return statAsync(path)
|
||||
.then(x => true)
|
||||
.then((x) => true)
|
||||
.catch(falseOnEnoent)
|
||||
}
|
||||
|
||||
function isDirectoryAsync(path: string) {
|
||||
return statAsync(path)
|
||||
.then(x => x.isDirectory())
|
||||
.then((x) => x.isDirectory())
|
||||
.catch(falseOnEnoent)
|
||||
}
|
||||
/**
|
||||
@@ -109,5 +109,5 @@ export {
|
||||
readFileAsync,
|
||||
pathExistsAsync,
|
||||
isDirectoryAsync,
|
||||
writeFileAsync
|
||||
writeFileAsync,
|
||||
}
|
||||
|
||||
+12
-12
@@ -14,12 +14,12 @@ const env = process.env,
|
||||
isMac = process.platform === 'darwin',
|
||||
headers = {
|
||||
Authorization: 'token ' + env.GITHUB_TOKEN,
|
||||
'User-Agent': 'nexe (https://www.npmjs.com/package/nexe)'
|
||||
'User-Agent': 'nexe (https://www.npmjs.com/package/nexe)',
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
if (!isPullRequest) {
|
||||
build().catch(x => {
|
||||
build().catch((x) => {
|
||||
console.error(x)
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -31,10 +31,10 @@ async function build() {
|
||||
if (!releases.length) {
|
||||
return
|
||||
}
|
||||
const windowsBuild = releases.find(x => x.platform === 'windows'),
|
||||
macBuild = releases.find(x => x.platform === 'mac'),
|
||||
linux = releases.find(x => x.platform === 'linux'),
|
||||
alpine = releases.find(x => x.platform === 'alpine')
|
||||
const windowsBuild = releases.find((x) => x.platform === 'windows'),
|
||||
macBuild = releases.find((x) => x.platform === 'mac'),
|
||||
linux = releases.find((x) => x.platform === 'linux'),
|
||||
alpine = releases.find((x) => x.platform === 'alpine')
|
||||
|
||||
let target: NexeTarget | undefined
|
||||
|
||||
@@ -62,7 +62,7 @@ async function build() {
|
||||
verbose: Boolean(env.NEXE_VERBOSE!),
|
||||
target,
|
||||
make: ['-j' + cpus().length],
|
||||
output
|
||||
output,
|
||||
}
|
||||
console.log('Building: ' + target + ' on ' + buildHost)
|
||||
const stop = keepalive()
|
||||
@@ -80,7 +80,7 @@ async function build() {
|
||||
await assertNexeBinary(output)
|
||||
const gitRelease = await getLatestGitRelease({ headers }),
|
||||
unbuiltReleases = await getUnBuiltReleases({ headers })
|
||||
if (!unbuiltReleases.some(x => targetsEqual(x, target!))) {
|
||||
if (!unbuiltReleases.some((x) => targetsEqual(x, target!))) {
|
||||
console.log(`${target} already uploaded.`)
|
||||
process.exit(0)
|
||||
return
|
||||
@@ -90,9 +90,9 @@ async function build() {
|
||||
body: await readFileAsync(output),
|
||||
headers: {
|
||||
...headers,
|
||||
'Content-Type': 'application/octet-stream'
|
||||
}
|
||||
}).catch(reason => {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
},
|
||||
}).catch((reason) => {
|
||||
console.log(reason && reason.response && reason.response.body)
|
||||
throw reason
|
||||
})
|
||||
@@ -107,7 +107,7 @@ function keepalive() {
|
||||
}
|
||||
|
||||
function assertNexeBinary(file: string) {
|
||||
return execFileAsync(file).catch(e => {
|
||||
return execFileAsync(file).catch((e) => {
|
||||
if (e && e.stack && e.stack.includes('Invalid Nexe binary')) {
|
||||
return
|
||||
}
|
||||
|
||||
+7
-12
@@ -6,7 +6,7 @@ import { appendFileSync } from 'fs'
|
||||
|
||||
function alpine(target: NexeTarget) {
|
||||
return `
|
||||
FROM ${target.arch === 'x64' ? '' : 'i386/'}alpine:3.4
|
||||
FROM ${target.arch === 'x64' ? '' : 'i386/'}alpine:3.12
|
||||
RUN apk add --no-cache curl make gcc g++ binutils-gold python linux-headers paxctl libgcc libstdc++ git vim tar gzip wget
|
||||
ENV NODE_VERSION=${target.version}
|
||||
ENV NEXE_VERSION=latest
|
||||
@@ -58,16 +58,11 @@ export async function runDockerBuild(target: NexeTarget) {
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,26 @@ describe('options', () => {
|
||||
expect(options.output).to.equal(path.resolve(cwd, `abc${ext}`))
|
||||
})
|
||||
})
|
||||
|
||||
describe('remote', () => {
|
||||
it('should use default remote', () => {
|
||||
const options = normalizeOptions({})
|
||||
expect(options.remote).to.equal('https://github.com/nexe/nexe/releases/download/v3.3.3/')
|
||||
})
|
||||
it('should append trailing slash to third-party remote if necessary', () => {
|
||||
const options = normalizeOptions({
|
||||
remote: 'https://sitejs.org/nexe'
|
||||
})
|
||||
expect(options.remote).to.equal('https://sitejs.org/nexe/')
|
||||
})
|
||||
it('should not append trailing slash to third-party remote that already has one', () => {
|
||||
const options = normalizeOptions({
|
||||
remote: 'https://sitejs.org/nexe/'
|
||||
})
|
||||
expect(options.remote).to.equal('https://sitejs.org/nexe/')
|
||||
})
|
||||
})
|
||||
|
||||
describe('output', () => {
|
||||
it('should work', () => {
|
||||
const options = normalizeOptions({
|
||||
|
||||
Reference in New Issue
Block a user