fix: input detection and validity

closes #556, #548, #547, #533
This commit is contained in:
calebboyd
2018-11-28 20:20:33 -06:00
parent b3b6c6b936
commit dcea374922
7 changed files with 67 additions and 55 deletions
+6 -3
View File
@@ -1,7 +1,6 @@
import { delimiter, dirname, normalize, join } from 'path'
import { Buffer } from 'buffer'
import { createReadStream } from 'fs'
import { Readable, Stream } from 'stream'
import { spawn } from 'child_process'
import { Logger, LogStep } from './logger'
import {
@@ -84,6 +83,10 @@ export class NexeCompiler {
* Output filename (-o myapp.exe)
*/
public output = this.options.output
/**
* Flag to indicate whether or notstdin was used for input
*/
public stdinUsed = false
/**
* Path to the configure script
*/
@@ -168,9 +171,9 @@ export class NexeCompiler {
entry.contents = contents
}
quit() {
quit(error?: any) {
const time = Date.now() - this.start
this.log.write(`Finished in ${time / 1000}s`)
this.log.write(`Finished in ${time / 1000}s`, error ? 'red' : 'green')
return this.log.flush()
}
+1 -1
View File
@@ -36,10 +36,10 @@ async function compile(
}
if (error) {
compiler.quit(error)
if (compiler.options.loglevel !== 'silent' && error) {
process.stderr.write(EOL + error.message + EOL)
}
compiler.quit()
if (callback) return callback(error)
return Promise.reject(error)
}
+17 -12
View File
@@ -1,6 +1,6 @@
import * as parseArgv from 'minimist'
import { NexeCompiler } from './compiler'
import { isWindows } from './util'
import { isWindows, STDIN_FLAG } from './util'
import { basename, extname, join, isAbsolute, resolve } from 'path'
import { getTarget, NexeTarget } from './target'
import { EOL, homedir } from 'os'
@@ -194,11 +194,16 @@ function isEntryFile(filename?: string): filename is string {
return Boolean(filename && !isAbsolute(filename))
}
export function resolveEntry(input: string, cwd: string, maybeEntry?: string) {
if (input === '-' || maybeEntry === '-') {
return ''
}
export function resolveEntry(
input: string,
cwd: string,
maybeEntry: string | undefined,
bundle: boolean | string
) {
let result = null
if (input === '-' || maybeEntry === '-') {
return STDIN_FLAG
}
if (input && isAbsolute(input)) {
return input
}
@@ -206,19 +211,19 @@ export function resolveEntry(input: string, cwd: string, maybeEntry?: string) {
const inputPath = padRelative(input)
result = resolveFileNameSync(cwd, inputPath)
}
if (isEntryFile(maybeEntry) && (!result || !result.absPath)) {
const inputPath = padRelative(maybeEntry)
result = resolveFileNameSync(cwd, inputPath)
}
if (!process.stdin.isTTY) {
return ''
if (!process.stdin.isTTY && (!result || !result.absPath) && bundle === defaults.bundle) {
return STDIN_FLAG
}
if (!result || !result.absPath) {
result = resolveFileNameSync(cwd, '.')
}
if (!result.absPath) throw new Error(`Entry file "${input}" not found!`)
if (!result.absPath) {
throw new Error(`Entry file "${input}" not found!`)
}
return result.absPath
}
@@ -234,8 +239,8 @@ function normalizeOptions(input?: Partial<NexeOptions>): NexeOptions {
? resolve(cwd, options.temp)
: process.env.NEXE_TEMP || join(homedir(), '.nexe')
const maybeEntry = isCli(input) ? argv._[argv._.length - 1] : undefined
options.input = resolveEntry(options.input, cwd, maybeEntry)
options.enableStdIn = isCli(input) && options.input === ''
options.input = resolveEntry(options.input, cwd, maybeEntry, options.bundle)
options.enableStdIn = isCli(input) && options.input === STDIN_FLAG
options.name = extractName(options)
options.loglevel = extractLogLevel(options)
options.flags = flatten(opts.flag, options.flags)
+37 -3
View File
@@ -1,20 +1,54 @@
import { NexeCompiler } from '../compiler'
import { resolve } from 'path'
import { resolve, relative } from 'path'
import { each } from '@calebboyd/semaphore'
import resolveFiles from 'resolve-dependencies'
import { dequote, STDIN_FLAG } from '../util'
import { Readable } from 'stream'
function getStdIn(stdin: Readable): Promise<string> {
return new Promise(resolve => {
let out = ''
stdin
.setEncoding('utf8')
.on('readable', () => {
let current
while ((current = stdin.read())) {
out += current
}
})
.on('end', () => resolve(out))
})
}
export default async function bundle(compiler: NexeCompiler, next: any) {
const { bundle, cwd, input } = compiler.options
compiler.entrypoint = './' + relative(cwd, input)
compiler.startup = ';require("module").runMain();'
if (!bundle) {
await compiler.addResource(resolve(cwd, input))
return next()
}
if (!input) {
let code = ''
if (typeof bundle === 'string') {
code = await require(bundle).createBundle(compiler.options)
}
if (input === STDIN_FLAG) {
compiler.stdinUsed = true
compiler.entrypoint = './__nexe_stdin.js'
code = code || dequote(await getStdIn(process.stdin))
await compiler.addResource(resolve(cwd, compiler.entrypoint), code)
return next()
}
const { files } = await resolveFiles(input, { cwd, expand: true, loadContent: false })
const { files, warnings } = await resolveFiles(input, { cwd, expand: true, loadContent: false })
if (warnings.length) {
throw new Error('Parsing Error:\n' + warnings.join('\n'))
}
await each(Object.keys(files), (filename: string) => compiler.addResource(filename), {
concurrency: 10
})
+4 -35
View File
@@ -1,24 +1,8 @@
import { normalize, relative, resolve } from 'path'
import { normalize, relative } from 'path'
import { createWriteStream, chmodSync, statSync } from 'fs'
import { dequote } from '../util'
import { Readable } from 'stream'
import { NexeCompiler } from '../compiler'
import { NexeTarget } from '../target'
function getStdIn(stdin: Readable): Promise<string> {
return new Promise(resolve => {
let out = ''
stdin
.setEncoding('utf8')
.on('readable', () => {
let current
while ((current = stdin.read())) {
out += current
}
})
.on('end', () => resolve(out))
})
}
import { STDIN_FLAG } from '../util'
/**
* The "cli" step detects the appropriate input. If no input options are passed,
@@ -26,28 +10,13 @@ function getStdIn(stdin: Readable): Promise<string> {
* After all the build steps have run, the output (the executable) is written to a file or piped to stdout.
*
* Configuration:
* - compiler.options.input - file path to the input bundle.
* - fallbacks: stdin, package.json#main
* - compiler.options.output - file path to the output executable.
* - fallbacks: stdout, nexe_ + epoch + ext
*
* @param {*} compiler
* @param {*} next
*/
export default async function cli(compiler: NexeCompiler, next: () => Promise<void>) {
const { log } = compiler
let stdInUsed = false
if (!process.stdin.isTTY && compiler.options.enableStdIn) {
stdInUsed = true
compiler.entrypoint = './__nexe_stdin.js'
const code = dequote(await getStdIn(process.stdin))
await compiler.addResource(resolve(compiler.options.cwd, compiler.entrypoint), code)
} else {
compiler.entrypoint = './' + relative(compiler.options.cwd, compiler.options.input)
}
compiler.startup = ';require("module").runMain();'
await next()
const { log } = compiler
const target = compiler.options.targets.shift() as NexeTarget
const deliverable = await compiler.compileAsync(target)
@@ -67,7 +36,7 @@ export default async function cli(compiler: NexeCompiler, next: () => Promise<vo
const outputFile = relative(process.cwd(), output)
step.log(
`Entry: '${
stdInUsed ? (compiler.options.mangle ? '[stdin]' : '[none]') : inputFile
compiler.stdinUsed ? (compiler.options.mangle ? STDIN_FLAG : '[none]') : inputFile
}' written to: ${outputFile}`
)
resolve(compiler.quit())
+1
View File
@@ -4,6 +4,7 @@ import pify = require('pify')
import rimraf = require('rimraf')
const rimrafAsync = pify(rimraf)
export const STDIN_FLAG = '[stdin]'
export async function each<T>(
list: T[] | Promise<T[]>,