File: /home/frenchy/www/french-american.org/current/node_modules/snyk/dist/lib/monitor.js
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const Debug = require("debug");
const depGraphLib = require("@snyk/dep-graph");
const snyk = require("../lib");
const api_token_1 = require("./api-token");
const request = require("./request");
const config = require("./config");
const os = require("os");
const _ = require("lodash");
const is_ci_1 = require("./is-ci");
const analytics = require("./analytics");
const projectMetadata = require("./project-metadata");
const path = require("path");
const errors_1 = require("./errors");
const prune_1 = require("./prune");
const package_managers_1 = require("./package-managers");
const debug = Debug('snyk');
function dropEmptyDeps(node) {
if (node.dependencies) {
const keys = Object.keys(node.dependencies);
if (keys.length === 0) {
delete node.dependencies;
}
else {
for (const k of keys) {
dropEmptyDeps(node.dependencies[k]);
}
}
}
}
function countTotalDependenciesInTree(depTree) {
let count = 0;
if (depTree.dependencies) {
for (const name of Object.keys(depTree.dependencies)) {
const dep = depTree.dependencies[name];
if (dep) {
count += 1 + countTotalDependenciesInTree(dep);
}
}
}
return count;
}
function pruneTree(tree, packageManagerName) {
return __awaiter(this, void 0, void 0, function* () {
debug('pruning dep tree');
// Pruning requires conversion to the graph first.
// This is slow.
const graph = yield depGraphLib.legacy.depTreeToGraph(tree, packageManagerName);
const prunedTree = (yield depGraphLib.legacy.graphToDepTree(graph, packageManagerName, { deduplicateWithinTopLevelDeps: true }));
// Transplant pruned dependencies in the original tree (we want to keep all other fields):
tree.dependencies = prunedTree.dependencies;
debug('finished pruning dep tree');
return tree;
});
}
function filterOutMissingDeps(depTree) {
const filteredDeps = {};
const missingDeps = [];
if (!depTree.dependencies) {
return {
filteredDepTree: depTree,
missingDeps,
};
}
for (const depKey of Object.keys(depTree.dependencies)) {
const dep = depTree.dependencies[depKey];
if (dep.missingLockFileEntry) {
// TODO(kyegupov): add field to the type
missingDeps.push(`${dep.name}@${dep.version}`);
}
else {
filteredDeps[depKey] = dep;
}
}
const filteredDepTree = Object.assign({}, depTree, { dependencies: filteredDeps });
return {
filteredDepTree,
missingDeps,
};
}
function monitor(root, meta, info, targetFile) {
return __awaiter(this, void 0, void 0, function* () {
api_token_1.apiTokenExists();
const packageManager = meta.packageManager;
analytics.add('packageManager', packageManager);
analytics.add('isDocker', !!meta.isDocker);
if (meta['experimental-dep-graph'] &&
package_managers_1.GRAPH_SUPPORTED_PACKAGE_MANAGERS.includes(packageManager)) {
return yield monitorGraph(root, meta, info, targetFile);
}
let pkg = info.package;
let prePruneDepCount;
if (meta.prune) {
debug('prune used, counting total dependencies');
prePruneDepCount = countTotalDependenciesInTree(info.package);
analytics.add('prePruneDepCount', prePruneDepCount);
debug('total dependencies: %d', prePruneDepCount);
pkg = yield pruneTree(info.package, meta.packageManager);
}
const pluginMeta = info.plugin;
const policyPath = meta['policy-path'] || root;
const policyLocations = [policyPath]
.concat(pluckPolicies(pkg))
.filter(Boolean);
// docker doesn't have a policy as it can be run from anywhere
if (!meta.isDocker || !policyLocations.length) {
yield snyk.policy.create();
}
const policy = yield snyk.policy.load(policyLocations, { loose: true });
const target = yield getTarget(pkg, meta);
const targetFileRelativePath = targetFile
? path.relative(root, targetFile)
: '';
if (target && target.branch) {
analytics.add('targetBranch', target.branch);
}
dropEmptyDeps(pkg);
// TODO(kyegupov): async/await
return new Promise((resolve, reject) => {
request({
body: {
meta: {
method: meta.method,
hostname: os.hostname(),
id: snyk.id || pkg.name,
ci: is_ci_1.isCI(),
pid: process.pid,
node: process.version,
master: snyk.config.isMaster,
name: pkg.name,
version: pkg.version,
org: config.org ? decodeURIComponent(config.org) : undefined,
pluginName: pluginMeta.name,
pluginRuntime: pluginMeta.runtime,
dockerImageId: pluginMeta.dockerImageId,
dockerBaseImage: pkg.docker ? pkg.docker.baseImage : undefined,
dockerfileLayers: pkg.docker
? pkg.docker.dockerfileLayers
: undefined,
projectName: meta['project-name'],
prePruneDepCount,
},
policy: policy ? policy.toString() : undefined,
package: pkg,
// we take the targetFile from the plugin,
// because we want to send it only for specific package-managers
target,
targetFile: pluginMeta.targetFile,
targetFileRelativePath,
},
gzip: true,
method: 'PUT',
headers: {
authorization: 'token ' + snyk.api,
'content-encoding': 'gzip',
},
url: config.API + '/monitor/' + packageManager,
json: true,
}, (error, res, body) => {
if (error) {
return reject(error);
}
if (res.statusCode >= 200 && res.statusCode <= 299) {
resolve(body);
}
else {
let err;
const userMessage = body && body.userMessage;
if (!userMessage && res.statusCode === 504) {
err = new errors_1.ConnectionTimeoutError();
}
else {
err = new errors_1.MonitorError(res.statusCode, userMessage);
}
reject(err);
}
});
});
});
}
exports.monitor = monitor;
function monitorGraph(root, meta, info, targetFile) {
return __awaiter(this, void 0, void 0, function* () {
const packageManager = meta.packageManager;
let treeMissingDeps;
let pkg = info.package;
const pluginMeta = info.plugin;
const policyPath = meta['policy-path'] || root;
const policyLocations = [policyPath]
.concat(pluckPolicies(pkg))
.filter(Boolean);
if (['npm', 'yarn'].includes(meta.packageManager)) {
const { filteredDepTree, missingDeps } = filterOutMissingDeps(info.package);
pkg = filteredDepTree;
treeMissingDeps = missingDeps;
}
const depGraph = yield depGraphLib.legacy.depTreeToGraph(pkg, packageManager);
// docker doesn't have a policy as it can be run from anywhere
if (!meta.isDocker || !policyLocations.length) {
yield snyk.policy.create();
}
const policy = yield snyk.policy.load(policyLocations, { loose: true });
const target = yield getTarget(pkg, meta);
const targetFileRelativePath = targetFile
? path.relative(root, targetFile)
: '';
if (target && target.branch) {
analytics.add('targetBranch', target.branch);
}
let prunedGraph = depGraph;
let prePruneDepCount;
if (meta.prune) {
debug('Trying to prune the graph');
prePruneDepCount = prune_1.countPathsToGraphRoot(depGraph);
debug('pre prunedPathsCount: ' + prePruneDepCount);
prunedGraph = yield prune_1.pruneGraph(depGraph, packageManager);
}
return new Promise((resolve, reject) => {
request({
body: {
meta: {
method: meta.method,
hostname: os.hostname(),
id: snyk.id || pkg.name,
ci: is_ci_1.isCI(),
pid: process.pid,
node: process.version,
master: snyk.config.isMaster,
name: depGraph.rootPkg.name,
version: depGraph.rootPkg.version,
org: config.org ? decodeURIComponent(config.org) : undefined,
pluginName: pluginMeta.name,
pluginRuntime: pluginMeta.runtime,
dockerImageId: pluginMeta.dockerImageId,
dockerBaseImage: pkg.docker ? pkg.docker.baseImage : undefined,
dockerfileLayers: pkg.docker
? pkg.docker.dockerfileLayers
: undefined,
projectName: meta['project-name'],
prePruneDepCount,
missingDeps: treeMissingDeps,
},
policy: policy ? policy.toString() : undefined,
depGraphJSON: prunedGraph,
// we take the targetFile from the plugin,
// because we want to send it only for specific package-managers
target,
targetFile: pluginMeta.targetFile,
targetFileRelativePath,
},
gzip: true,
method: 'PUT',
headers: {
authorization: 'token ' + snyk.api,
'content-encoding': 'gzip',
},
url: `${config.API}/monitor/${packageManager}/graph`,
json: true,
}, (error, res, body) => {
if (error) {
return reject(error);
}
if (res.statusCode >= 200 && res.statusCode <= 299) {
resolve(body);
}
else {
let err;
const userMessage = body && body.userMessage;
if (!userMessage && res.statusCode === 504) {
err = new errors_1.ConnectionTimeoutError();
}
else {
err = new errors_1.MonitorError(res.statusCode, userMessage);
}
reject(err);
}
});
});
});
}
exports.monitorGraph = monitorGraph;
function pluckPolicies(pkg) {
if (!pkg) {
return null;
}
if (pkg.snyk) {
return pkg.snyk;
}
if (!pkg.dependencies) {
return null;
}
return _.flatten(Object.keys(pkg.dependencies)
.map((name) => {
return pluckPolicies(pkg.dependencies[name]);
})
.filter(Boolean));
}
function getTarget(pkg, meta) {
return __awaiter(this, void 0, void 0, function* () {
const target = yield projectMetadata.getInfo(pkg);
// Override the remoteUrl if the --remote-repo-url flag was set
if (meta['remote-repo-url']) {
return Object.assign({}, target, { remoteUrl: meta['remote-repo-url'] });
}
return target;
});
}
//# sourceMappingURL=monitor.js.map