From e62cd19b42fb8ce5e4a4612b602ecf90a731ea64 Mon Sep 17 00:00:00 2001 From: calebboyd Date: Thu, 31 Aug 2017 08:46:50 -0500 Subject: [PATCH] feat: targets --- src/compiler.ts | 18 ++++++++--- src/options.ts | 2 +- src/releases.ts | 72 +++++++++++++++++++++++++++++++++++++++++++ src/steps/download.ts | 16 ++++++---- src/types.d.ts | 6 +++- tasks/build.ts | 2 +- tasks/ci.ts | 2 +- tasks/releases.ts | 62 ------------------------------------- 8 files changed, 104 insertions(+), 76 deletions(-) create mode 100644 src/releases.ts delete mode 100644 tasks/releases.ts diff --git a/src/compiler.ts b/src/compiler.ts index 14ee089..6abdbab 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -1,4 +1,4 @@ -import { normalize, join } from 'path' +import { dirname, normalize, join } from 'path' import { Buffer } from 'buffer' import { createHash } from 'crypto' import { createReadStream } from 'fs' @@ -8,6 +8,7 @@ import { Logger } from './logger' import { readFileAsync, writeFileAsync, pathExistsAsync, dequote, isWindows } from './util' import { NexeOptions, nexeVersion } from './options' import { NexeTarget } from './target' +import { getLatestGitRelease, storeAsset } from './releases' const isBsd = Boolean(~process.platform.indexOf('bsd')) const make = isWindows ? 'vcbuild.bat' : isBsd ? 'gmake' : 'make' @@ -133,8 +134,17 @@ export class NexeCompiler { return createReadStream(this._getNodeExecutableLocation()) } - private _fetchPrebuiltBinaryAsync() { - return this._buildAsync() + private async _fetchPrebuiltBinaryAsync(target: NexeTarget) { + const githubRelease = await getLatestGitRelease() + const assetName = target.toString() + const asset = githubRelease.assets.find(x => x.name === assetName) + + if (!asset) { + throw new Error(`${assetName} not available, create one using --build`) + } + const filename = this._getNodeExecutableLocation(target) + await storeAsset(asset, dirname(filename)) + return createReadStream(filename) } private _generateHeader() { @@ -161,7 +171,7 @@ export class NexeCompiler { const header = this._generateHeader() if (target && !binary) { - binary = await this._fetchPrebuiltBinaryAsync() + binary = await this._fetchPrebuiltBinaryAsync(target) } if (!binary) { diff --git a/src/options.ts b/src/options.ts index 5bf2cc7..f8ee5c0 100644 --- a/src/options.ts +++ b/src/options.ts @@ -61,7 +61,7 @@ const defaults = { vcBuild: isWindows ? ['nosign', 'release', process.arch] : [], enableNodeCli: false, compress: false, - build: true, + build: false, bundle: true, patches: [] } diff --git a/src/releases.ts b/src/releases.ts new file mode 100644 index 0000000..1aaf960 --- /dev/null +++ b/src/releases.ts @@ -0,0 +1,72 @@ +import got = require('got') +import download = require('download') +import { + NodePlatform, + NodeArch, + platforms, + architectures, + NexeTarget, + getTarget, + targetsEqual +} from './target' +export { NexeTarget } + +export interface GitAsset { + name: string + url: string + browser_download_url: string +} + +export interface GitRelease { + tag_name: string + assets_url: string + upload_url: string + assets: GitAsset[] +} + +interface NodeRelease { + version: string +} + +async function getJson(url: string) { + return JSON.parse((await got(url)).body) as T +} + +//TODO only build the latest of each major...? +function isBuildableVersion(version: string) { + const major = +version.split('.')[0] + return !~[0, 1, 2, 3, 4, 5, 7].indexOf(major) || version === '4.8.4' +} + +export function getLatestGitRelease() { + return getJson('https://api.github.com/repos/nexe/nexe/releases/latest') +} + +export async function storeAsset(asset: GitAsset, dest: string) { + await download(asset.browser_download_url, dest) +} + +export async function getUnBuiltReleases() { + const nodeReleases = await getJson( + 'https://nodejs.org/download/release/index.json' + ) + const existingVersions = (await getLatestGitRelease()).assets.map(x => getTarget(x.name)) + + const versionMap: { [key: string]: true } = {} + return nodeReleases + .reduce((versions: NexeTarget[], { version }) => { + version = version.replace('v', '').trim() + if (!isBuildableVersion(version) || versionMap[version]) { + return versions + } + versionMap[version] = true + platforms.forEach(platform => { + architectures.forEach(arch => { + if (arch === 'x86' && platform === 'mac') return + versions.push(getTarget({ platform, arch, version })) + }) + }) + return versions + }, []) + .filter(x => !existingVersions.some(t => targetsEqual(t, x))) +} diff --git a/src/steps/download.ts b/src/steps/download.ts index 3484e69..b117c17 100644 --- a/src/steps/download.ts +++ b/src/steps/download.ts @@ -1,12 +1,12 @@ import download = require('download') -import { isDirectoryAsync } from '../util' +import { pathExistsAsync } from '../util' import { LogStep } from '../logger' import { IncomingMessage } from 'http' import { NexeCompiler } from '../compiler' -function fetchNodeSourceAsync(cwd: string, url: string, step: LogStep, options = {}) { +function fetchNodeSourceAsync(dest: string, url: string, step: LogStep, options = {}) { const setText = (p: number) => step.modify(`Downloading Node: ${p.toFixed()}%...`) - return download(url, cwd, Object.assign(options, { extract: true, strip: 1 })) + return download(url, dest, Object.assign(options, { extract: true, strip: 1 })) .on('response', (res: IncomingMessage) => { const total = +res.headers['content-length']! let current = 0 @@ -18,7 +18,7 @@ function fetchNodeSourceAsync(cwd: string, url: string, step: LogStep, options = } }) }) - .then(() => step.log(`Node source extracted to: ${cwd}`)) + .then(() => step.log(`Node source extracted to: ${dest}`)) } /** @@ -31,10 +31,14 @@ export default async function downloadNode(compiler: NexeCompiler, next: () => P const { version, sourceUrl, downloadOptions } = compiler.options const url = sourceUrl || `https://nodejs.org/dist/v${version}/node-v${version}.tar.gz` const step = log.step(`Downloading Node.js source from: ${url}`) - if (await isDirectoryAsync(src)) { + if (await pathExistsAsync(src)) { step.log('Source already downloaded') return next() } - return fetchNodeSourceAsync(src, url, step, downloadOptions).then(next) + if (compiler.options.build) { + await fetchNodeSourceAsync(src, url, step, downloadOptions).then(next) + } + + return next() } diff --git a/src/types.d.ts b/src/types.d.ts index 43a6673..50e76ff 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -1,6 +1,10 @@ declare module 'got' { + interface GotFn { + (url: string, options?: any): Promise<{ body: string }> + stream(url: string, optoins?: any): any + } function got(url: string, options?: any): Promise<{ body: string }> - export = got + export = got as GotFn } declare module 'download' { import { Duplex } from 'stream' diff --git a/tasks/build.ts b/tasks/build.ts index fa5e651..f71c293 100644 --- a/tasks/build.ts +++ b/tasks/build.ts @@ -2,7 +2,7 @@ import { compile } from '../src/nexe' import { getUnBuiltReleases, getLatestGitRelease -} from './releases' +} from '../src/releases' import * as ci from './ci' import { getTarget } from '../src/target' import { pathExistsAsync, statAsync, readFileAsync, execFileAsync } from '../src/util' diff --git a/tasks/ci.ts b/tasks/ci.ts index 010212d..85ac877 100644 --- a/tasks/ci.ts +++ b/tasks/ci.ts @@ -1,4 +1,4 @@ -import { NexeTarget } from './releases' +import { NexeTarget } from '../src/releases' import got = require('got') import * as assert from 'assert' const { env } = process diff --git a/tasks/releases.ts b/tasks/releases.ts deleted file mode 100644 index 7e17d5b..0000000 --- a/tasks/releases.ts +++ /dev/null @@ -1,62 +0,0 @@ -import got = require('got') -import { - NodePlatform, - NodeArch, - platforms, - architectures, - NexeTarget, - getTarget, - targetsEqual, -} from '../src/target' -export { NexeTarget } - -export interface GitRelease { - tag_name: string - assets_url: string - upload_url: string - assets: Array<{ name: string }> -} - -interface NodeRelease { - version: string -} - -async function getJson (url: string) { - return JSON.parse((await got(url)).body) as T -} - -//TODO only build the latest of each major...? -function isBuildableVersion (version: string) { - const major = +version.split('.')[0] - return !~[0, 1, 2, 3, 4, 5, 7].indexOf(major) - || version === '4.8.4' -} - -export function getLatestGitRelease () { - return getJson('https://api.github.com/repos/nexe/nexe/releases/latest') -} - -export async function getUnBuiltReleases () { - const nodeReleases = (await getJson('https://nodejs.org/download/release/index.json')) - const existingVersions = (await getLatestGitRelease()) - .assets.map(x => getTarget(x.name)) - - const versionMap: { [key:string]: true } = {} - return nodeReleases.reduce((versions: NexeTarget[], { version }) => { - version = version.replace('v', '').trim() - if (!isBuildableVersion(version) || versionMap[version]) { - return versions - } - versionMap[version] = true - platforms.forEach(platform => { - architectures.forEach(arch => { - if (arch === 'x86' && platform === 'mac') return - versions.push(getTarget({ platform, arch, version })) - }) - }) - return versions - }, []) - .filter( - x => !existingVersions.some(t => targetsEqual(t, x)) - ) -}