chore(bundling): start alternate bundling strategy
This commit is contained in:
Vendored
+1
-3
@@ -1,5 +1,3 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"esbenp.prettier-vscode"
|
||||
]
|
||||
"recommendations": [ "eg2.tslint" ]
|
||||
}
|
||||
|
||||
Vendored
+3
-5
@@ -1,9 +1,7 @@
|
||||
{
|
||||
"typescript.tsdk": "./node_modules/typescript/lib",
|
||||
"prettier.semi": false,
|
||||
"prettier.singleQuote": true,
|
||||
"prettier.typescriptEnable": ["typescript"],
|
||||
"editor.trimAutoWhitespace": true,
|
||||
"tslint.enable": true,
|
||||
"tslint.run": "onType",
|
||||
"tslint.autoFixOnSave": true,
|
||||
"files.exclude": {
|
||||
"**/.git": true,
|
||||
"**/.svn": true,
|
||||
|
||||
@@ -237,9 +237,9 @@ $ npm test
|
||||
|
||||
## Maintainers
|
||||
|
||||
[](https://jaredallard.me/) | [](https://github.com/calebboyd) | [](https://github.com/ckarper) | [](https://github.com/dgreif) |
|
||||
[](https://jaredallard.me/) | [](https://github.com/calebboyd) | [](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) |
|
||||
[Jared Allard](https://github.com/jaredallard) | [Caleb Boyd](http://github.com/calebboyd) | [Dustin Greif](https://github.com/dgreif) |
|
||||
|
||||
### Former
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
const { echo } = require('shelljs')
|
||||
echo('hello world')
|
||||
@@ -0,0 +1,37 @@
|
||||
const { resolve } = require('resolve-dependencies')
|
||||
const path = require('path')
|
||||
|
||||
module.exports.createBundle = async function createBundle (options) {
|
||||
console.log(path.isAbsolute(options.input))
|
||||
const { entries, files } = await resolve(options.input)
|
||||
const lcp = findLcp(Object.keys(files))
|
||||
const relFiles = relativize(files, lcp)
|
||||
console.log('LCP', relFiles)
|
||||
return Promise.resolve(`console.log('hello world')`)
|
||||
}
|
||||
|
||||
function relativize (files, lcp) {
|
||||
const result = {}
|
||||
for(const absPath in files) {
|
||||
const relPath = '.' + path.sep + path.relative(lcp, absPath)
|
||||
const file = files[absPath]
|
||||
file.relPath = relPath
|
||||
result[relPath] = file
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
function findLcp(paths, sep = path.sep) {
|
||||
let position, first = paths[0] || ''
|
||||
findPosition: {
|
||||
for (position = 0;; position++) {
|
||||
for (let i = 0; i < paths.length; i++) {
|
||||
if (paths[i][position] && paths[i][position] === first[position])
|
||||
continue
|
||||
while (position > 0 && first[--position] !== sep) {}
|
||||
break findPosition
|
||||
}
|
||||
}
|
||||
}
|
||||
return first.slice(0, position)
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
{
|
||||
"name": "dynamic-modules",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
|
||||
"integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
|
||||
"requires": {
|
||||
"balanced-match": "1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"circular-json": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.1.tgz",
|
||||
"integrity": "sha512-UjgcRlTAhAkLeXmDe2wK7ktwy/tgAqxiSndTIPiFZuIPLZmzHzWMwUIe9h9m/OokypG7snxCDEuwJshGBdPvaw=="
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
||||
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
||||
"requires": {
|
||||
"fs.realpath": "1.0.0",
|
||||
"inflight": "1.0.6",
|
||||
"inherits": "2.0.3",
|
||||
"minimatch": "3.0.4",
|
||||
"once": "1.4.0",
|
||||
"path-is-absolute": "1.0.1"
|
||||
}
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"requires": {
|
||||
"once": "1.4.0",
|
||||
"wrappy": "1.0.2"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"interpret": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz",
|
||||
"integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ="
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"requires": {
|
||||
"brace-expansion": "1.1.8"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"requires": {
|
||||
"wrappy": "1.0.2"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||
},
|
||||
"path-parse": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
|
||||
"integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME="
|
||||
},
|
||||
"rechoir": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
|
||||
"integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
|
||||
"requires": {
|
||||
"resolve": "1.5.0"
|
||||
}
|
||||
},
|
||||
"resolve": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz",
|
||||
"integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==",
|
||||
"requires": {
|
||||
"path-parse": "1.0.5"
|
||||
}
|
||||
},
|
||||
"shelljs": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.1.tgz",
|
||||
"integrity": "sha512-YA/iYtZpzFe5HyWVGrb02FjPxc4EMCfpoU/Phg9fQoyMC72u9598OUBrsU8IrtwAKG0tO8IYaqbaLIw+k3IRGA==",
|
||||
"requires": {
|
||||
"glob": "7.1.2",
|
||||
"interpret": "1.1.0",
|
||||
"rechoir": "0.6.2"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "dynamic-modules",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"circular-json": "^0.5.1",
|
||||
"shelljs": "^0.8.1"
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,9 @@ if (require.main === module) {
|
||||
process.stderr.write(showHelp ? options.help : options.version + eol)
|
||||
} else {
|
||||
const nexe = require('./lib/nexe')
|
||||
nexe.compile(argv)
|
||||
nexe.compile(argv).catch(() => {
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
module.exports = require('./lib/nexe')
|
||||
|
||||
Generated
+2112
File diff suppressed because it is too large
Load Diff
+29
-31
@@ -2,7 +2,7 @@
|
||||
"name": "nexe",
|
||||
"description": "Create a single executable out of your Node.js application",
|
||||
"license": "MIT",
|
||||
"version": "2.0.0-rc.34",
|
||||
"version": "2.0.0-next.10",
|
||||
"contributors": [
|
||||
"Craig Condon <craig.j.condon@gmail.com> (http://crcn.io)",
|
||||
"Jared Allard <jaredallard@outlook.com>",
|
||||
@@ -11,10 +11,9 @@
|
||||
"scripts": {
|
||||
"asset-compile": "ts-node tasks/asset-compile",
|
||||
"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",
|
||||
"lint": "tslint \"{src,plugins,tasks}/**/*.ts\" --fix",
|
||||
"prepublishOnly": "npm run lint && npm run build && npm test",
|
||||
"prebuild": "rimraf lib",
|
||||
"build": "tsc --declaration",
|
||||
"postbuild": "ts-node tasks/post-build"
|
||||
},
|
||||
@@ -23,8 +22,7 @@
|
||||
"url": "git://github.com/nexe/nexe.git"
|
||||
},
|
||||
"files": [
|
||||
"lib",
|
||||
"source-map-support.js"
|
||||
"lib"
|
||||
],
|
||||
"typings": "lib/nexe.d.ts",
|
||||
"main": "index.js",
|
||||
@@ -35,37 +33,37 @@
|
||||
"node": ">=6"
|
||||
},
|
||||
"dependencies": {
|
||||
"app-builder": "^5.1.0",
|
||||
"typescript": "2.5.3",
|
||||
"app-builder": "^5.2.0",
|
||||
"caw": "^2.0.1",
|
||||
"chalk": "^1.1.3",
|
||||
"download": "^6.2.0",
|
||||
"fuse-box": "^3.1.0",
|
||||
"globby": "^6.1.0",
|
||||
"got": "^8.0.3",
|
||||
"chalk": "^2.3.2",
|
||||
"download": "^6.2.5",
|
||||
"globby": "^8.0.1",
|
||||
"got": "^8.3.0",
|
||||
"minimist": "^1.2.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"ora": "^1.2.0",
|
||||
"ora": "^2.0.0",
|
||||
"pify": "^3.0.0",
|
||||
"rimraf": "^2.6.1",
|
||||
"uglify-es": "^3.3.9",
|
||||
"uglify-js": "3.0.28"
|
||||
"resolve-dependencies": "^1.1.0",
|
||||
"rimraf": "^2.6.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.0.4",
|
||||
"@types/chalk": "^0.4.31",
|
||||
"@types/execa": "^0.7.0",
|
||||
"@types/globby": "^0.6.0",
|
||||
"@types/chai": "^4.1.2",
|
||||
"@types/execa": "^0.8.1",
|
||||
"@types/globby": "^6.1.0",
|
||||
"@types/minimist": "^1.2.0",
|
||||
"@types/mkdirp": "^0.3.29",
|
||||
"@types/mocha": "^2.2.42",
|
||||
"@types/ora": "^0.3.31",
|
||||
"@types/pify": "0.0.28",
|
||||
"@types/rimraf": "0.0.28",
|
||||
"@types/mkdirp": "^0.5.2",
|
||||
"@types/mocha": "^2.2.48",
|
||||
"@types/ora": "^1.3.1",
|
||||
"@types/pify": "3.0.0",
|
||||
"@types/rimraf": "2.0.2",
|
||||
"chai": "^4.1.2",
|
||||
"execa": "^0.8.0",
|
||||
"mocha": "^3.5.0",
|
||||
"prettier": "^1.6.1",
|
||||
"ts-node": "3.3.0"
|
||||
"execa": "^0.9.0",
|
||||
"mocha": "^5.0.0",
|
||||
"prettier": "^1.10.2",
|
||||
"ts-node": "4.1.0",
|
||||
"tslint": "^5.9.1",
|
||||
"tslint-config-prettier": "^1.7.0",
|
||||
"tslint-plugin-prettier": "^1.3.0",
|
||||
"typescript": "2.7.1"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,70 +0,0 @@
|
||||
import { BindingsRewrite } from './bindings-rewrite'
|
||||
import { embedDotNode, EmbedNodeModuleOptions } from './embed-node'
|
||||
|
||||
export interface FuseBoxFile {
|
||||
info: { absPath: string }
|
||||
absPath: string
|
||||
contents: string
|
||||
analysis: {
|
||||
dependencies: string[]
|
||||
requiresRegeneration: boolean
|
||||
}
|
||||
consume(): void
|
||||
loadContents(): void
|
||||
makeAnalysis(
|
||||
parsingOptions?: any,
|
||||
traversalPlugin?: {
|
||||
plugins: Array<{
|
||||
onNode(file: FuseBoxFile, node: any, parent: any): void
|
||||
onEnd(file: FuseBoxFile): void
|
||||
}>
|
||||
}
|
||||
): void
|
||||
}
|
||||
|
||||
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 EmbedNodeModuleOptions)[]
|
||||
|
||||
constructor(public options = {}) {}
|
||||
|
||||
init(context: any) {
|
||||
context.allowExtension('.node')
|
||||
}
|
||||
|
||||
transform(file: FuseBoxFile) {
|
||||
file.loadContents()
|
||||
|
||||
if (file.absPath.endsWith('.node')) {
|
||||
embedDotNode(this.options, file)
|
||||
return
|
||||
}
|
||||
|
||||
const bindingsRewrite = new BindingsRewrite()
|
||||
|
||||
file.makeAnalysis(null, {
|
||||
plugins: [
|
||||
{
|
||||
onNode(file, node, parent) {
|
||||
bindingsRewrite.onNode(file.absPath, node, parent)
|
||||
},
|
||||
onEnd(file) {
|
||||
if (bindingsRewrite.rewrite) {
|
||||
const index = file.analysis.dependencies.indexOf('bindings')
|
||||
if (~index) {
|
||||
file.analysis.dependencies.splice(index, 1)
|
||||
}
|
||||
file.analysis.dependencies.push(...bindingsRewrite.nativeModulePaths)
|
||||
file.analysis.requiresRegeneration = true
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export * from './fuse-native-module-plugin'
|
||||
@@ -1 +0,0 @@
|
||||
//TODO
|
||||
+11
-28
@@ -29,15 +29,15 @@ interface NexeHeader {
|
||||
version: string
|
||||
}
|
||||
|
||||
export class NexeCompiler<T extends NexeOptions = NexeOptions> {
|
||||
export class NexeCompiler {
|
||||
private start = Date.now()
|
||||
private env: any
|
||||
private compileStep: LogStep
|
||||
private env = { ...process.env }
|
||||
private compileStep: LogStep | undefined
|
||||
public log = new Logger(this.options.loglevel)
|
||||
public src: string
|
||||
public files: NexeFile[] = []
|
||||
public shims: string[] = []
|
||||
public input: string
|
||||
public input: string | undefined
|
||||
public bundledInput?: string
|
||||
public targets: NexeTarget[]
|
||||
public target: NexeTarget
|
||||
@@ -47,7 +47,7 @@ export class NexeCompiler<T extends NexeOptions = NexeOptions> {
|
||||
}
|
||||
public output = this.options.output
|
||||
private nodeSrcBinPath: string
|
||||
constructor(public options: T) {
|
||||
constructor(public options: NexeOptions) {
|
||||
const { python } = (this.options = options)
|
||||
this.targets = options.targets as NexeTarget[]
|
||||
this.target = this.targets[0]
|
||||
@@ -136,7 +136,7 @@ export class NexeCompiler<T extends NexeOptions = NexeOptions> {
|
||||
|
||||
private _runBuildCommandAsync(command: string, args: string[]) {
|
||||
if (this.log.verbose) {
|
||||
this.compileStep.pause()
|
||||
this.compileStep!.pause()
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
spawn(command, args, {
|
||||
@@ -146,13 +146,13 @@ export class NexeCompiler<T extends NexeOptions = NexeOptions> {
|
||||
})
|
||||
.once('error', (e: Error) => {
|
||||
if (this.log.verbose) {
|
||||
this.compileStep.resume()
|
||||
this.compileStep!.resume()
|
||||
}
|
||||
reject(e)
|
||||
})
|
||||
.once('close', (code: number) => {
|
||||
if (this.log.verbose) {
|
||||
this.compileStep.resume()
|
||||
this.compileStep!.resume()
|
||||
}
|
||||
if (code != 0) {
|
||||
const error = `${command} ${args.join(' ')} exited with code: ${code}`
|
||||
@@ -171,14 +171,14 @@ export class NexeCompiler<T extends NexeOptions = NexeOptions> {
|
||||
}
|
||||
|
||||
private async _buildAsync() {
|
||||
this.compileStep.log(
|
||||
this.compileStep!.log(
|
||||
`Configuring node build${
|
||||
this.options.configure.length ? ': ' + this.options.configure : '...'
|
||||
}`
|
||||
)
|
||||
await this._configureAsync()
|
||||
const buildOptions = this.options.make
|
||||
this.compileStep.log(
|
||||
this.compileStep!.log(
|
||||
`Compiling Node${buildOptions.length ? ' with arguments: ' + buildOptions : '...'}`
|
||||
)
|
||||
await this._runBuildCommandAsync(make, buildOptions)
|
||||
@@ -211,30 +211,13 @@ export class NexeCompiler<T extends NexeOptions = NexeOptions> {
|
||||
let current = 0
|
||||
res.on('data', data => {
|
||||
current += data.length
|
||||
this.compileStep.modify(`Downloading...${(current / total * 100).toFixed()}%`)
|
||||
this.compileStep!.modify(`Downloading...${(current / total * 100).toFixed()}%`)
|
||||
})
|
||||
}
|
||||
)
|
||||
return createReadStream(filename)
|
||||
}
|
||||
|
||||
getHeader() {
|
||||
const version =
|
||||
['configure', 'vcBuild', 'make'].reduce((a, c) => {
|
||||
return (a += (this.options as any)[c]
|
||||
.slice()
|
||||
.sort()
|
||||
.join())
|
||||
}, '') + this.options.enableNodeCli
|
||||
const header = {
|
||||
resources: this.resources.index,
|
||||
version: createHash('md5')
|
||||
.update(version)
|
||||
.digest('hex')
|
||||
}
|
||||
return `process.__nexe=${JSON.stringify(header)};`
|
||||
}
|
||||
|
||||
async compileAsync(target: NexeTarget) {
|
||||
const step = (this.compileStep = this.log.step('Compiling result'))
|
||||
const build = this.options.build
|
||||
|
||||
+14
-19
@@ -1,10 +1,10 @@
|
||||
import { EOL } from 'os'
|
||||
import { compose, Middleware } from 'app-builder'
|
||||
import { rimrafAsync } from './util'
|
||||
import { NexeTarget } from './target'
|
||||
import { NexeCompiler } from './compiler'
|
||||
import { normalizeOptions, NexeOptions, NexePatch } from './options'
|
||||
import resource from './steps/resource'
|
||||
import clean from './steps/clean'
|
||||
import cli from './steps/cli'
|
||||
import bundle from './steps/bundle'
|
||||
import download from './steps/download'
|
||||
@@ -18,26 +18,19 @@ async function compile(
|
||||
) {
|
||||
const options = normalizeOptions(compilerOptions)
|
||||
const compiler = new NexeCompiler(options)
|
||||
const build = compiler.options.build
|
||||
const build = options.build
|
||||
|
||||
if (options.clean) {
|
||||
let path = compiler.src
|
||||
if (!options.build) {
|
||||
path = compiler.getNodeExecutableLocation(compiler.options.targets[0] as NexeTarget)
|
||||
}
|
||||
const step = compiler.log.step('Cleaning up nexe build artifacts...')
|
||||
step.log(`Deleting contents at: ${path}`)
|
||||
await rimrafAsync(path)
|
||||
step.log(`Deleted contents at: ${path}`)
|
||||
return compiler.quit()
|
||||
}
|
||||
const nexe = compose(
|
||||
clean,
|
||||
resource,
|
||||
bundle,
|
||||
shim,
|
||||
cli,
|
||||
options.build ? [download, artifacts, ...patches, ...(options.patches as NexePatch[])] : [],
|
||||
options.plugins as NexePatch[]
|
||||
)
|
||||
|
||||
const buildSteps = build
|
||||
? [download, artifacts, ...patches, ...(options.patches as NexePatch[])]
|
||||
: []
|
||||
const nexe = compose(resource, bundle, shim, cli, buildSteps, options.plugins as NexePatch[])
|
||||
let error = null
|
||||
|
||||
try {
|
||||
await nexe(compiler)
|
||||
} catch (e) {
|
||||
@@ -46,12 +39,14 @@ async function compile(
|
||||
|
||||
if (error) {
|
||||
if (compiler.options.loglevel !== 'silent' && error) {
|
||||
process.stderr.write(EOL + error.stack + EOL)
|
||||
console.log(error)
|
||||
process.stderr.write(EOL + error.message + EOL)
|
||||
}
|
||||
compiler.quit()
|
||||
if (callback) return callback(error)
|
||||
return Promise.reject(error)
|
||||
}
|
||||
|
||||
if (callback) callback(null)
|
||||
}
|
||||
|
||||
|
||||
+10
-8
@@ -4,8 +4,7 @@ import { isWindows, padRight } from './util'
|
||||
import { basename, extname, join, isAbsolute, relative, dirname, resolve } from 'path'
|
||||
import { getTarget, NexeTarget } from './target'
|
||||
import { EOL, homedir } from 'os'
|
||||
import * as c from 'chalk'
|
||||
|
||||
import c from 'chalk'
|
||||
const caw = require('caw')
|
||||
|
||||
export const version = '{{replace:0}}'
|
||||
@@ -140,12 +139,15 @@ function flatten(...args: any[]): string[] {
|
||||
function extractCliMap(match: RegExp, options: any) {
|
||||
return Object.keys(options)
|
||||
.filter(x => match.test(x))
|
||||
.reduce((map: { [key: string]: string }, option: keyof NexeOptions) => {
|
||||
const key = option.split('-')[1]
|
||||
map[key] = options[option]
|
||||
delete options[option]
|
||||
return map
|
||||
}, {})
|
||||
.reduce(
|
||||
(map: any, option: any) => {
|
||||
const key = option.split('-')[1]
|
||||
map[key] = options[option]
|
||||
delete options[option]
|
||||
return map
|
||||
},
|
||||
{} as any
|
||||
)
|
||||
}
|
||||
|
||||
function tryResolveMainFileName(cwd: string) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const fs = require('fs')
|
||||
const fd = fs.openSync(process.execPath, 'r')
|
||||
const stat = fs.statSync(process.execPath)
|
||||
const footer = Buffer.from(Array(32))
|
||||
const footer = Buffer.alloc(32, 0)
|
||||
|
||||
fs.readSync(fd, footer, 0, 32, stat.size - 32)
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
//add placeholder patches so methods can be monkeypatched after being dereferenced
|
||||
const __nexe_patches = ((process as any).nexe = { patches: {} }).patches as any
|
||||
|
||||
function __nexe_noop_patch(this: any, original: any, ...args: any[]) {
|
||||
return original.call(this, ...args)
|
||||
}
|
||||
|
||||
function __nexe_patch(obj: any, method: string, patch: any) {
|
||||
__nexe_patches[method] = patch
|
||||
const original = obj[method]
|
||||
obj[method] = function(this: any, ...args: any[]) {
|
||||
return __nexe_patches[method].call(this, original, ...args)
|
||||
}
|
||||
}
|
||||
|
||||
__nexe_patch((process as any).binding('fs'), 'internalModuleReadFile', __nexe_noop_patch)
|
||||
__nexe_patch((process as any).binding('fs'), 'internalModuleStat', __nexe_noop_patch)
|
||||
@@ -1,8 +1,14 @@
|
||||
import { NexeCompiler } from '../compiler'
|
||||
import { readFileSync } from 'fs'
|
||||
import { join } from 'path'
|
||||
import { wrap } from '../util'
|
||||
|
||||
export default async function main(compiler: NexeCompiler, next: () => Promise<void>) {
|
||||
const file = await compiler.readFileAsync('lib/internal/bootstrap_node.js')
|
||||
const parts = file.contents.split('function(process) {')
|
||||
file.contents =
|
||||
parts[0] + `function(process) {` + '{{replace:lib/patches/bootstrap.js}}' + parts[1]
|
||||
|
||||
await compiler.setFileContentsAsync(
|
||||
'lib/_third_party_main.js',
|
||||
'{{replace:lib/patches/boot-nexe.js}}'
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ export async function getUnBuiltReleases(options?: any) {
|
||||
platforms.forEach(platform => {
|
||||
architectures.forEach(arch => {
|
||||
if (arch === 'x86' && platform === 'mac') return
|
||||
if (arch === 'arm71' && platform !== 'linux') return
|
||||
if (arch === 'arm7l' && platform !== 'linux') return
|
||||
versions.push(getTarget({ platform, arch, version }))
|
||||
})
|
||||
})
|
||||
|
||||
@@ -39,7 +39,6 @@ function maybeReadFileContentsAsync(file: string) {
|
||||
* - After the patch functions have run, the temporary directory is emptied
|
||||
* - Original versions of sources to be patched are written to the temporary directory
|
||||
* - Finally, The patched files are written into source.
|
||||
*
|
||||
*/
|
||||
export default async function artifacts(compiler: NexeCompiler, next: () => Promise<void>) {
|
||||
const { src } = compiler
|
||||
|
||||
+20
-35
@@ -1,39 +1,23 @@
|
||||
import { NexeCompiler } from '../compiler'
|
||||
import { readFileAsync, writeFileAsync } from '../util'
|
||||
import { resolve, relative } from 'path'
|
||||
import NativeModulePlugin from '../bundling/fuse-native-module-plugin'
|
||||
import { NexeOptions } from '../options'
|
||||
import resolveFiles from 'resolve-dependencies'
|
||||
|
||||
function createBundle(options: NexeOptions) {
|
||||
const { FuseBox, JSONPlugin, CSSPlugin, HTMLPlugin, QuantumPlugin } = require('fuse-box')
|
||||
const plugins: any = [JSONPlugin(), CSSPlugin(), HTMLPlugin(), NativeModulePlugin(options.native)]
|
||||
if (options.compress) {
|
||||
plugins.push(
|
||||
QuantumPlugin({
|
||||
target: 'server@esnext',
|
||||
uglify: true,
|
||||
bakeApiIntoBundle: options.name
|
||||
})
|
||||
)
|
||||
}
|
||||
const cwd = options.cwd
|
||||
const fuse = FuseBox.init({
|
||||
cache: false,
|
||||
log: Boolean(process.env.NEXE_BUNDLE_LOG) || false,
|
||||
homeDir: cwd,
|
||||
sourceMaps: false,
|
||||
writeBundles: false,
|
||||
output: '$name.js',
|
||||
target: 'server@esnext', //try not to transpile
|
||||
plugins
|
||||
})
|
||||
const input = relative(cwd, resolve(cwd, options.input)).replace(/\\/g, '/')
|
||||
fuse.bundle(options.name).instructions(`> ${input}`)
|
||||
return fuse.run().then((x: any) => {
|
||||
let output = ''
|
||||
x.bundles.forEach((y: any) => (output = y.context.output.lastPrimaryOutput.content.toString()))
|
||||
return output
|
||||
function makeRelative(cwd: string, path: string) {
|
||||
return './' + relative(cwd, path)
|
||||
}
|
||||
|
||||
let producer = async function(compiler: NexeCompiler) {
|
||||
const { cwd, input } = compiler.options
|
||||
const { files } = await resolveFiles({ entries: [compiler.options.input], cwd })
|
||||
Object.keys(files).forEach(x => {
|
||||
const file = files[x]!
|
||||
if (file) {
|
||||
compiler.addResource(makeRelative(cwd, x), Buffer.from(file.contents))
|
||||
}
|
||||
})
|
||||
return Promise.resolve('require(' + JSON.stringify(makeRelative(cwd, input)) + ')')
|
||||
}
|
||||
|
||||
export default async function bundle(compiler: NexeCompiler, next: any) {
|
||||
@@ -43,20 +27,21 @@ export default async function bundle(compiler: NexeCompiler, next: any) {
|
||||
return next()
|
||||
}
|
||||
|
||||
if (compiler.options.empty || !compiler.options.input) {
|
||||
if (!input) {
|
||||
compiler.input = ''
|
||||
return next()
|
||||
}
|
||||
|
||||
let producer = createBundle
|
||||
if (typeof bundle === 'string') {
|
||||
producer = require(resolve(cwd, bundle)).createBundle
|
||||
}
|
||||
|
||||
compiler.input = await producer(compiler.options)
|
||||
compiler.input = await producer(compiler)
|
||||
const debugBundle = compiler.options.debugBundle
|
||||
|
||||
if ('string' === typeof compiler.options.debugBundle) {
|
||||
await writeFileAsync(resolve(cwd, compiler.options.debugBundle), compiler.input)
|
||||
if (debugBundle) {
|
||||
let bundleDebugFile = typeof debugBundle === 'string' ? debugBundle : 'nexe-debug.bundle.js'
|
||||
await writeFileAsync(resolve(cwd, bundleDebugFile), compiler.input)
|
||||
}
|
||||
|
||||
return next()
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { NexeCompiler } from '../compiler'
|
||||
import { rimrafAsync } from '../util'
|
||||
import { NexeTarget } from '../target'
|
||||
|
||||
export default async function clean(compiler: NexeCompiler, next: () => Promise<any>) {
|
||||
const { options } = compiler
|
||||
if (options.clean) {
|
||||
let path = compiler.src
|
||||
if (!options.build) {
|
||||
path = compiler.getNodeExecutableLocation(compiler.options.targets[0] as NexeTarget)
|
||||
}
|
||||
const step = compiler.log.step('Cleaning up nexe build artifacts...')
|
||||
step.log(`Deleting contents at: ${path}`)
|
||||
await rimrafAsync(path)
|
||||
step.log(`Deleted contents at: ${path}`)
|
||||
return compiler.quit()
|
||||
}
|
||||
return next()
|
||||
}
|
||||
@@ -3,15 +3,16 @@ import { Buffer } from 'buffer'
|
||||
import * as globs from 'globby'
|
||||
import { NexeCompiler } from '../compiler'
|
||||
|
||||
export default async function resource(compiler: NexeCompiler, next: () => Promise<void>) {
|
||||
export default async function resource(compiler: NexeCompiler, next: () => Promise<any>) {
|
||||
const resources = compiler.resources
|
||||
const { cwd } = compiler.options
|
||||
|
||||
if (!compiler.options.resources.length) {
|
||||
return next()
|
||||
}
|
||||
const step = compiler.log.step('Bundling Resources...')
|
||||
let count = 0
|
||||
await each(globs(compiler.options.resources), async file => {
|
||||
await each(globs(compiler.options.resources, { cwd }), async file => {
|
||||
if (await isDirectoryAsync(file)) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -256,6 +256,29 @@ const nfs: any = {
|
||||
}
|
||||
}
|
||||
}
|
||||
const patches = (process as any).nexe.patches
|
||||
delete (process as any).nexe
|
||||
|
||||
patches.internalModuleReadFile = function(this: any, original: any, ...args: any[]) {
|
||||
const [filepath] = args
|
||||
setupManifest()
|
||||
if (manifest[filepath]) {
|
||||
return nfs.readFileSync(filepath, 'utf-8')
|
||||
}
|
||||
return original.call(this, ...args)
|
||||
}
|
||||
patches.internalModuleStat = function(this: any, original: any, ...args: any[]) {
|
||||
setupManifest()
|
||||
const [filepath] = args
|
||||
if (manifest[filepath]) {
|
||||
return 0
|
||||
}
|
||||
if (directories[filepath]) {
|
||||
return 1
|
||||
}
|
||||
return original.call(this, ...args)
|
||||
}
|
||||
Object.assign(fs, nfs)
|
||||
|
||||
if (typeof fs.exists === 'function') {
|
||||
nfs.exists = function(filepath: string, cb: Function) {
|
||||
|
||||
+12
-15
@@ -1,12 +1,12 @@
|
||||
import { NexeCompiler } from '../compiler'
|
||||
|
||||
function wrap(code: string) {
|
||||
return '!(function () {' + code + '})();'
|
||||
}
|
||||
import { relative } from 'path'
|
||||
import { wrap } from '../util'
|
||||
|
||||
export default function(compiler: NexeCompiler, next: () => Promise<void>) {
|
||||
compiler.shims.push(wrap(compiler.getHeader()))
|
||||
|
||||
compiler.shims.push(
|
||||
wrap(`process.__nexe=${JSON.stringify({ resources: compiler.resources.index })};`)
|
||||
)
|
||||
compiler.shims.push(wrap('{{replace:lib/steps/shim-fs.js}}'))
|
||||
compiler.shims.push(
|
||||
wrap(`
|
||||
if (process.argv[1] && process.env.NODE_UNIQUE_ID) {
|
||||
@@ -17,19 +17,16 @@ export default function(compiler: NexeCompiler, next: () => Promise<void>) {
|
||||
`)
|
||||
)
|
||||
|
||||
if (compiler.options.resources.length) {
|
||||
compiler.shims.push(wrap('{{replace:lib/steps/shim-fs.js}}'))
|
||||
}
|
||||
|
||||
//compiler.shims.push(wrap('{/{replace:lib/steps/shim-require.js}}'))
|
||||
|
||||
if (compiler.options.fakeArgv !== false) {
|
||||
const nty = !process.stdin.isTTY
|
||||
const input = nty ? '[stdin]' : JSON.stringify(compiler.options.input)
|
||||
const input = nty
|
||||
? '[stdin]'
|
||||
: JSON.stringify(relative(compiler.options.cwd, compiler.options.input))
|
||||
|
||||
compiler.shims.push(
|
||||
wrap(`
|
||||
var r = require('path').resolve;
|
||||
process.argv.splice(1,0, ${nty ? `'${input}'` : `r(${input})`});`)
|
||||
var r = require('path').resolve;
|
||||
process.argv.splice(1,0, ${nty ? `'${input}'` : `r(${input})`});`)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -1,8 +1,8 @@
|
||||
export type NodePlatform = 'windows' | 'mac' | 'alpine' | 'linux'
|
||||
export type NodeArch = 'x86' | 'x64' | 'arm71'
|
||||
export type NodeArch = 'x86' | 'x64' | 'arm7l' | 'arm6'
|
||||
|
||||
const platforms: NodePlatform[] = ['windows', 'mac', 'alpine', 'linux'],
|
||||
architectures: NodeArch[] = ['x86', 'x64', 'arm71']
|
||||
architectures: NodeArch[] = ['x86', 'x64', 'arm7l', 'arm6']
|
||||
|
||||
export { platforms, architectures }
|
||||
|
||||
@@ -25,12 +25,12 @@ const prettyPlatform: { [key: string]: NodePlatform } = {
|
||||
alpine: 'alpine'
|
||||
}
|
||||
|
||||
//TODO arm
|
||||
const prettyArch: { [key: string]: NodeArch } = {
|
||||
x86: 'x86',
|
||||
arm: 'arm71',
|
||||
arm7: 'arm71',
|
||||
arm71: 'arm71',
|
||||
arm6: 'arm6',
|
||||
arm: 'arm7l',
|
||||
arm7: 'arm7l',
|
||||
arm7l: 'arm7l',
|
||||
amd64: 'x64',
|
||||
ia32: 'x86',
|
||||
x32: 'x86',
|
||||
|
||||
Vendored
+2
-2
@@ -3,8 +3,8 @@ declare module 'got' {
|
||||
(url: string, options?: any): Promise<{ body: string }>
|
||||
stream(url: string, optoins?: any): any
|
||||
}
|
||||
function got(url: string, options?: any): Promise<{ body: string }>
|
||||
export = got as GotFn
|
||||
const got: GotFn
|
||||
export = got
|
||||
}
|
||||
declare module 'download' {
|
||||
import { Duplex } from 'stream'
|
||||
|
||||
+11
-5
@@ -10,9 +10,11 @@ export async function each<T>(
|
||||
action: (item: T, index: number, list: T[]) => Promise<any>
|
||||
) {
|
||||
const l = await list
|
||||
for (let i = 0; i < l.length; i++) {
|
||||
await action(l[i], i, l)
|
||||
}
|
||||
return Promise.all(l.map(action))
|
||||
}
|
||||
|
||||
export function wrap(code: string) {
|
||||
return '!(function () {' + code + '})();'
|
||||
}
|
||||
|
||||
function falseOnEnoent(e: any) {
|
||||
@@ -28,7 +30,7 @@ function padRight(str: string, l: number) {
|
||||
|
||||
const bound: MethodDecorator = function bound<T>(
|
||||
target: Object,
|
||||
propertyKey: string,
|
||||
propertyKey: string | Symbol,
|
||||
descriptor: TypedPropertyDescriptor<T>
|
||||
) {
|
||||
const configurable = true
|
||||
@@ -36,7 +38,11 @@ const bound: MethodDecorator = function bound<T>(
|
||||
configurable,
|
||||
get(this: T) {
|
||||
const value = (descriptor.value as any).bind(this)
|
||||
Object.defineProperty(this, propertyKey, { configurable, value, writable: true })
|
||||
Object.defineProperty(this, propertyKey as string, {
|
||||
configurable,
|
||||
value,
|
||||
writable: true
|
||||
})
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as nexe from '../lib/nexe'
|
||||
import { getUnBuiltReleases, getLatestGitRelease } from '../lib/releases'
|
||||
import * as ci from './ci'
|
||||
import { runAlpineBuild } from './docker'
|
||||
import { runDockerBuild } from './docker'
|
||||
import { getTarget } from '../lib/target'
|
||||
import { pathExistsAsync, statAsync, readFileAsync, execFileAsync } from '../lib/util'
|
||||
import got = require('got')
|
||||
@@ -62,8 +62,8 @@ async function build() {
|
||||
}
|
||||
console.log('Building: ', target)
|
||||
const stop = keepalive()
|
||||
if (target.platform === 'alpine') {
|
||||
await runAlpineBuild(target)
|
||||
if (['arm71', 'alpine'].indexOf(target.platform)) {
|
||||
await runDockerBuild(target)
|
||||
} else {
|
||||
await nexe.compile(options)
|
||||
}
|
||||
|
||||
+19
-6
@@ -1,4 +1,4 @@
|
||||
import { NexeTarget } from '../lib/target'
|
||||
import { NexeTarget, architectures } from '../lib/target'
|
||||
import { writeFileAsync, readFileAsync } from '../lib/util'
|
||||
import { spawn } from 'child_process'
|
||||
import got = require('got')
|
||||
@@ -26,15 +26,28 @@ RUN rm /nexe_temp/\${NODE_VERSION}/out/Release/node && \
|
||||
`.trim()
|
||||
}
|
||||
|
||||
export async function runAlpineBuild(target: NexeTarget) {
|
||||
await writeFileAsync('Dockerfile', alpine(target))
|
||||
const outFilename = 'nexe-alpine-build-log.txt'
|
||||
function arm(target: NexeTarget) {
|
||||
return `
|
||||
FROM hypriot/rpi-node
|
||||
ENV NEXE_VERSION=beta
|
||||
WORKDIR /
|
||||
|
||||
RUN yarn global add nexe@\${NEXE_VERSION} && \
|
||||
nexe --build --empty -o out -t ${target.version}
|
||||
`.trim()
|
||||
}
|
||||
|
||||
export async function runDockerBuild(target: NexeTarget) {
|
||||
//todo switch on alpine and arm
|
||||
const dockerfile = alpine(target)
|
||||
await writeFileAsync('Dockerfile', dockerfile)
|
||||
const outFilename = 'nexe-docker-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 build -t nexe-docker .`))
|
||||
output.push(await execa.shell(`docker run -d --name nexe nexe-docker sh`))
|
||||
output.push(await execa.shell(`docker cp nexe:/out out`))
|
||||
output.push(await execa.shell(`docker rm nexe`))
|
||||
} catch (e) {
|
||||
|
||||
@@ -8,7 +8,7 @@ describe('options', () => {
|
||||
describe('cwd', () => {
|
||||
it('should use process.cwd() if nothing is provided', () => {
|
||||
const options = normalizeOptions()
|
||||
expect(options.cwd).to.equal(process.cwd())
|
||||
expect(options.cwd).to.equal(process.cwd())
|
||||
})
|
||||
it('should use the main module in a package directory', () => {
|
||||
const options = normalizeOptions()
|
||||
@@ -16,11 +16,11 @@ describe('options', () => {
|
||||
})
|
||||
it('should resolve pathed options against cwd', () => {
|
||||
const cwd = '/a/b/c'
|
||||
const options = normalizeOptions({
|
||||
cwd,
|
||||
const options = normalizeOptions({
|
||||
cwd,
|
||||
input: '123.js',
|
||||
output: 'abc',
|
||||
temp: './d'
|
||||
temp: './d'
|
||||
})
|
||||
expect(options.temp).to.equal(path.resolve(cwd, './d'))
|
||||
expect(options.input).to.equal(path.resolve(cwd, '123.js'))
|
||||
@@ -39,7 +39,7 @@ describe('options', () => {
|
||||
input: 'src/folder/app.js'
|
||||
})
|
||||
expect(options.output).to.equal(path.resolve(`./app${ext}`))
|
||||
})
|
||||
})
|
||||
it('should default to the folder/project name if filename is index', () => {
|
||||
const options = normalizeOptions()
|
||||
expect(options.output).to.equal(path.resolve(`./nexe${ext}`))
|
||||
|
||||
+2
-3
@@ -6,7 +6,7 @@ import { getTarget, NexeTarget } from '../src/target'
|
||||
const arch = process.arch === 'ia32' ? 'x86' : process.arch
|
||||
|
||||
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'],
|
||||
@@ -23,8 +23,7 @@ describe('Targets', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it ('should stringify and toString', () => {
|
||||
it('should stringify and toString', () => {
|
||||
expect(JSON.stringify(getTarget(process))).to.equal(`"${getTarget(process)}"`)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"rulesDirectory": ["tslint-plugin-prettier", "tslint-config-prettier"],
|
||||
"linterOptions": {
|
||||
"exclude": ["**/node_modules/**/*"]
|
||||
},
|
||||
"rules": {
|
||||
"prettier": [true, { "semi": false, "printWidth": 100, "singleQuote": true }]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user