Comparing version 1.2.18 to 1.2.19-a7a5e1c75a2013bab800a8a6b52ecc5ef95223d1
{ | ||
"name": "task", | ||
"version": "1.2.18", | ||
"version": "1.2.19-a7a5e1c75a2013bab800a8a6b52ecc5ef95223d1", | ||
"main": "src/index.js", | ||
@@ -23,3 +23,3 @@ "bin": { | ||
"detect-import-require": "^2.0.0", | ||
"hub.js": "^0.3.0", | ||
"hub.js": "0", | ||
"is-builtin-module": "^1.0.0", | ||
@@ -26,0 +26,0 @@ "node-fetch": "^2.0.0-alpha.5", |
@@ -1,151 +0,97 @@ | ||
const { isAbsolute, join } = require('path') | ||
'use strict' | ||
const { join, sep: separator } = require('path') | ||
const { exec } = require('child_process') | ||
const fs = require('fs') | ||
const cache = {} | ||
const absolute = (path, cwd) => isAbsolute(path) ? path : join(cwd, path) | ||
const makeEnvName = name => 'SERVICE_' + name.toUpperCase().replace(/[^A-Z0-9_]/g, '_') | ||
const envVar = string => { | ||
var i = 0 | ||
string = string.toUpperCase().replace(/[^a-zA-Z0-9_]/g, '_') | ||
while (string[i] === '_') i++ | ||
return string.slice(i) | ||
const currentDir = path => { | ||
const arr = path.split(separator) | ||
return arr[arr.length - 1] | ||
} | ||
const merge = (a, b) => { | ||
if (typeof a !== 'object') return b | ||
const obj = {} | ||
for (let i in b) { | ||
obj[i] = merge(a[i], b[i]) | ||
const getPkg = path => new Promise((resolve, reject) => { | ||
try { | ||
resolve(require(path)) | ||
} catch (err) { | ||
reject(Error(`failed to require package.json @ ${path}: ${err.stack}`)) | ||
} | ||
for (let i in a) { | ||
if (!(i in obj) && i !== 'package' && i !== 'targets') { | ||
obj[i] = a[i] | ||
}) | ||
exports.types = { | ||
'deploy-services': (task, hub, cwd) => { | ||
const path = { | ||
full: cwd, | ||
name: '' | ||
} | ||
deployServices(path).then(({result}) => task.set({ | ||
result, | ||
done: true | ||
})).catch(err => hub.emit('error', new Error(`Failed to deploy services: ${err.stack}`))) | ||
} | ||
return obj | ||
} | ||
const collect = ({ name, services }, store, cwd, dependent) => { | ||
if (!name) throw new Error(`no name defined in package.json: ${cwd}`) | ||
const service = store[name] || (store[name] = { | ||
name, | ||
env: envVar(name), | ||
url: {}, | ||
cwd, | ||
services: [] | ||
}) | ||
function deployServices (path, result) { | ||
if (!result) { | ||
result = {} | ||
} | ||
return getPkg(join(path.full, 'package.json')).then( | ||
pkg => { | ||
const services = pkg.services | ||
const deploys = [] | ||
for (let name in services) { | ||
const pointer = services[name] | ||
const servicePath = { | ||
full: join(path.full, pointer), | ||
name: join(path.name, pointer) | ||
} | ||
deploys.push(deploy(servicePath, result)) | ||
} | ||
return Promise.all(deploys) | ||
} | ||
).then(subServices => ({ subServices, result })) | ||
/* subServices is direct subservices for now ENV vars, result is cache for all service deploys */ | ||
} | ||
if (dependent) dependent.services.push(service) | ||
else service.isEntry = true | ||
return Promise.all(Object.keys(services || {}).map(key => { | ||
const dir = absolute(services[key], cwd) | ||
const path = join(dir, 'package.json') | ||
return cache[path] || (cache[path] = new Promise((resolve, reject) => { | ||
fs.readFile(path, (err, data) => { | ||
if (err) reject(err) | ||
else resolve(collect(JSON.parse(data), store, dir, service)) | ||
function deploy (path, result) { | ||
return result[path.name] || ( | ||
result[path.name] = deployServices(path, result).then( | ||
({ subServices }) => now(path.full, subServices) | ||
).then( | ||
url => { | ||
result[path.name] = url | ||
return [ path.name, url ] | ||
}) | ||
})) | ||
})) | ||
) | ||
} | ||
const deployNow = (service, cmd, gaurd) => { | ||
if (gaurd[service.name]) { | ||
console.log('😡 allready deploying', service.name) | ||
return | ||
} | ||
console.log('☄️☄️☄️ DEPLOY', service.name) | ||
gaurd[service.name] = exec(cmd, { cwd: service.cwd }) | ||
return gaurd[service.name] | ||
} | ||
const deploy = (services, opts, gaurd) => Promise.all(services.map(service => { | ||
const { name, env } = opts | ||
if (!(name in service.url)) { | ||
if (service.services.every(({ url }) => name in url)) { | ||
return new Promise((resolve, reject) => { | ||
var cmd = service.services.reduce( | ||
(cmd, { env, url }) => cmd + ` -e ${env}=${url[name]}`, | ||
'now --forward-npm -e PORT=80') | ||
for (let i in env) { | ||
cmd += ` -e ${i}=${env[i]}` | ||
} | ||
const child = deployNow(service, cmd, gaurd) | ||
if (!child) { | ||
resolve() | ||
} else { | ||
child.stderr.on('data', err => { | ||
reject(Error(`error deploying ${service.name}: ${err.stack}`)) | ||
}) | ||
child.stdout.on('data', function grabUrl (data) { | ||
const [ url ] = /https?:\/\/.+\.[a-z]{1,20}/.exec(data) | ||
if (url) { | ||
service.url[name] = url | ||
child.stdout.removeListener('data', grabUrl) | ||
// elegant until you run into the same service and start to deploy it multiple times | ||
resolve(deploy(services, opts, gaurd)) | ||
} | ||
}) | ||
} | ||
}) | ||
function now (cwd, subServices) { | ||
let command = 'now --forward-npm -e PORT=80' | ||
// let command = `label=${cwd} node /Users/marcus/Desktop/fake-deploy.js` | ||
if (subServices) { | ||
for (let [ name, url ] of subServices) { | ||
const envName = makeEnvName(name) | ||
command += ` -e ${envName}=${url}` | ||
} | ||
} | ||
})) | ||
const options = (task, cwd) => { | ||
const opts = Object.assign({ | ||
targets: [{ name: 'default' }] | ||
}, task.get('options', {}).serialize(true)) | ||
if (!opts.package) { // make this async | ||
opts.package = fs.readFileSync(join(cwd, 'package.json')).toString() | ||
} | ||
if (typeof opts.package === 'string') { | ||
opts.package = JSON.parse(opts.package) | ||
} | ||
if (!Array.isArray(opts.targets)) { | ||
opts.targets = Object.keys(opts.targets).map(name => { | ||
const target = opts.targets[name] | ||
if (!('name' in target)) target.name = name | ||
return target | ||
return new Promise((resolve, reject) => { | ||
console.log(`\n> in ${cwd}\n> execute ${command}`) | ||
const nowing = exec(command, { cwd }, | ||
(err, stdout, stderr) => reject(nowError(err, stdout, stderr)) | ||
) | ||
nowing.stdout.on('data', function grabUrl (data) { | ||
const [ url ] = /https?:\/\/.+\.[a-z]{1,20}/.exec(data) | ||
if (url) { | ||
nowing.stdout.removeListener('data', grabUrl) | ||
resolve(url) | ||
} | ||
}) | ||
} | ||
opts.targets = opts.targets.map((target, i) => Object.assign({ | ||
name: i, | ||
env: {} | ||
}, merge(opts, target))) | ||
return opts | ||
}) | ||
} | ||
exports.types = { | ||
'deploy-services': (task, hub, cwd) => new Promise((resolve, reject) => { | ||
const { targets, package: pkg } = options(task, cwd) | ||
const store = {} | ||
const gaurd = {} | ||
collect(pkg, store, cwd).then(() => { | ||
const services = Object.keys(store) | ||
.map(name => store[name]) | ||
.filter(service => !service.isEntry) | ||
return Promise.all(targets.map(opts => deploy(services, opts, gaurd))).then(() => { | ||
const services = store[pkg.name].services | ||
if (services) { | ||
services.forEach(({ url, env: envName }) => { | ||
targets.forEach(({ name, env }) => { env[envName] = url[name] }) | ||
}) | ||
} | ||
resolve({ | ||
result: targets, | ||
done: true | ||
}) | ||
}) | ||
}) | ||
}) | ||
function nowError (err, stdout, stderr) { | ||
return err | ||
? new Error(`failed to now: ${err.stack}\nstderr output:\n${stderr}`) | ||
: new Error(`failed to read URL from now output:\n${stdout}`) | ||
} |
Sorry, the diff of this file is not supported yet
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
54246
64
1774
2
11
+ Addedansi-regex@6.0.1(transitive)
- Removedansi-regex@6.1.0(transitive)
Updatedhub.js@0