Browse Source

Create a bundle using `pkg` on the fly

master
Leo Lamprecht 8 years ago
parent
commit
7e37d8825c
  1. 16
      download/install.js
  2. 10
      download/src/chmod.js
  3. 148
      download/src/index.js
  4. 43
      download/src/log.js
  5. 34
      download/webpack.config.js
  6. 30
      package.json
  7. 2
      webpack.config.js
  8. 6
      yarn.lock

16
download/install.js

@ -0,0 +1,16 @@
/* eslint-disable no-var */
// Native
var path = require('path')
var fs = require('fs')
var dist = path.join(__dirname, 'dist')
var src = path.join(__dirname, 'src')
// Don't install when developing locally
if (fs.existsSync(src)) {
// eslint-disable-next-line unicorn/no-process-exit
process.exit(0)
}
require(path.join(dist, 'download.js'))

10
download/src/chmod.js

@ -0,0 +1,10 @@
// Native
import fs from 'fs'
export default function (file) {
const s = fs.statSync(file)
const newMode = s.mode | 64 | 8 | 1
if (s.mode === newMode) return
const base8 = newMode.toString(8).slice(-3)
fs.chmodSync(file, base8)
}

148
download/src/index.js

@ -0,0 +1,148 @@
/* eslint-disable unicorn/no-process-exit */
// Native
import fs from 'fs'
import path from 'path'
import zlib from 'zlib'
// Packages
import onDeath from 'death'
import fetch from 'node-fetch'
import retry from 'async-retry'
// Utilities
import plusxSync from './chmod'
import {
disableProgress,
enableProgress,
info,
showProgress,
warn
} from './log'
fetch.Promise = Promise
global.Promise = Promise
const now = path.join(__dirname, 'now')
const targetWin32 = path.join(__dirname, 'now.exe')
const target = process.platform === 'win32' ? targetWin32 : now
const partial = target + '.partial'
const packagePath = path.join(__dirname, '../../package.json')
const packageJSON = JSON.parse(fs.readFileSync(packagePath, 'utf8'))
const platformToName = {
darwin: 'now-macos',
linux: 'now-linux',
win32: 'now-win.exe'
}
async function main() {
try {
fs.writeFileSync(
now,
'#!/usr/bin/env node\n' +
'console.log("Please wait until the \'now\' installation completes!")\n'
)
} catch (err) {
if (err.code === 'EACCES') {
warn(
'Please try installing now CLI again with the `--unsafe-perm` option.'
)
info('Example: `npm i -g --unsafe-perm now`')
process.exit()
}
throw err
}
onDeath(() => {
fs.writeFileSync(
now,
'#!/usr/bin/env node\n' +
'console.log("The \'now\' installation did not complete successfully.")\n' +
'console.log("Please run \'npm i -g now\' to reinstall!")\n'
)
process.exit()
})
info('For the source code, check out: https://github.com/zeit/now-cli')
// Print an empty line
console.log('')
await retry(async () => {
enableProgress('Downloading now CLI ' + packageJSON.version)
showProgress(0)
try {
const name = platformToName[process.platform]
const url = `https://cdn.zeit.co/releases/now-cli/${packageJSON.version}/${name}`
const resp = await fetch(url, { compress: false })
if (resp.status !== 200) {
throw new Error(resp.statusText + ' ' + url)
}
const size = resp.headers.get('content-length')
const ws = fs.createWriteStream(partial)
await new Promise((resolve, reject) => {
let bytesRead = 0
resp.body
.on('error', reject)
.on('data', chunk => {
bytesRead += chunk.length
showProgress(100 * bytesRead / size)
})
const gunzip = zlib.createGunzip()
gunzip
.on('error', reject)
resp.body.pipe(gunzip).pipe(ws)
ws
.on('error', reject)
.on('close', () => {
showProgress(100)
resolve()
})
})
} finally {
disableProgress()
}
}, {
retries: 500,
onRetry: (err) => console.error(err)
})
fs.renameSync(partial, target)
if (process.platform === 'win32') {
// Now.exe is executed only
fs.unlinkSync(now)
// Workaround for https://github.com/npm/cmd-shim/pull/25
const gitBashFile = path.join(process.env.APPDATA, 'npm/now')
fs.writeFileSync(
gitBashFile,
'#!/bin/sh\n' +
'basedir=$(dirname "$(echo "$0" | sed -e \'s,\\\\,/,g\')")\n' +
'\n' +
'case `uname` in\n' +
' *CYGWIN*) basedir=`cygpath -w "$basedir"`;;\n' +
'esac\n' +
'\n' +
fs.readFileSync(gitBashFile, 'utf8')
)
} else {
plusxSync(now)
}
}
main().catch(err => {
console.error(err)
process.exit(2)
})

43
download/src/log.js

@ -0,0 +1,43 @@
// Packages
import assert from 'assert'
import chalk from 'chalk'
import Progress from 'progress'
let bar
export function enableProgress(text) {
assert(!bar)
bar = new Progress(`> ${text} [:bar] :percent`, {
stream: process.stdout,
width: 20,
complete: '=',
incomplete: ' ',
total: 100
})
}
export function info(text) {
console.log(`> ${text}`)
}
export function warn(text) {
console.log(chalk.red('> Warning!'), text)
}
export function showProgress(percentage) {
assert(bar)
bar.update(percentage / 100)
}
export function disableProgress() {
assert(bar)
// It is auto-completed once it updates to 100
// otherwise it outputs a blank line
if (!bar.complete) {
bar.terminate()
}
bar = undefined
}

34
download/webpack.config.js

@ -0,0 +1,34 @@
// Native
const path = require('path')
module.exports = {
target: 'node',
node: {
__dirname: false,
__filename: false,
process: false
},
entry: [
'./src/index.js'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'download.js'
},
module: {
loaders: [ {
test: /.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
plugins: [
'transform-async-to-generator',
'transform-runtime'
],
presets: [
'es2015'
]
}
} ]
}
}

30
package.json

@ -5,9 +5,12 @@
"scripts": {
"test": "eslint .",
"prepublish": "webpack",
"lint:staged": "lint-staged",
"dev": "webpack -w",
"precommit": "lint-staged"
"precommit": "lint-staged",
"postinstall": "node download/install.js",
"prepublish": "in-install || (npm run prepare && cp /dev/null download/dist/now)",
"pack": "pkg dist/now.js -c package.json -o packed/now",
"prepare": "webpack --context download --config download/webpack.config.js"
},
"lint-staged": {
"*.js": [
@ -16,15 +19,28 @@
"git add"
]
},
"main": "./dist/now.js",
"bin": {
"now": "download/dist/now"
},
"files": [
"dist"
"download/dist",
"download/install.js"
],
"bin": {
"now": "./dist/now.js"
"pkg": {
"scripts": [
"bin/*",
"lib/**/*"
],
"targets": [
"node7-alpine-x64",
"node7-linux-x64",
"node7-macos-x64",
"node7-win-x64"
]
},
"eslintIgnore": [
"src/providers/sh/legacy/**",
"download/**",
"dist"
],
"eslintConfig": {
@ -63,6 +79,7 @@
"ansi-escapes": "2.0.0",
"archiver": "2.0.0",
"array-unique": "0.3.2",
"assert": "1.4.1",
"async-retry": "1.1.3",
"aws-sdk": "2.98.0",
"babel-core": "6.25.0",
@ -76,6 +93,7 @@
"chalk": "2.1.0",
"clipboardy": "1.1.4",
"convert-stream": "1.0.2",
"death": "1.1.0",
"debug": "3.0.0",
"deployment-type": "1.0.1",
"docker-file-parser": "1.0.2",

2
webpack.config.js

@ -13,7 +13,7 @@ module.exports = {
loaders: [
{
test: /\.js$/,
exclude: [/node_modules/],
exclude: /node_modules/,
loaders: ['shebang-loader', 'babel-loader']
}
]

6
yarn.lock

@ -205,7 +205,7 @@ assert-plus@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
assert@^1.1.1:
assert@1.4.1, assert@^1.1.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91"
dependencies:
@ -1253,6 +1253,10 @@ date-now@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
death@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/death/-/death-1.1.0.tgz#01aa9c401edd92750514470b8266390c66c67318"
debug@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.0.0.tgz#1d2feae53349047b08b264ec41906ba17a8516e4"

Loading…
Cancel
Save