|
|
@@ -6,8 +6,10 @@ import { hideBin } from "yargs/helpers";
|
|
|
|
|
|
|
|
|
type FormatValue = "tree" | "csv";
|
|
|
-type Format = { header: string, apply: (node: PackageLockTree, parents: string[]) => string }
|
|
|
+type Format = { header: string, apply: (node: PackageLockTree, parents: string[], audit: AuditResult) => string }
|
|
|
type FilterValue = "none" | "oracle";
|
|
|
+type Filter = (node: PackageLockTree, parents: string[]) => boolean;
|
|
|
+type Audit = (node: PackageLockTree) => Promise<AuditResult>;
|
|
|
|
|
|
const args = yargs(hideBin(process.argv))
|
|
|
.option("package", {
|
|
|
@@ -16,28 +18,37 @@ const args = yargs(hideBin(process.argv))
|
|
|
require: true
|
|
|
})
|
|
|
.option("format", {
|
|
|
+ type: "string",
|
|
|
describe: "Possible values are 'tree' and 'csv'",
|
|
|
- default: "tree",
|
|
|
+ default: "csv",
|
|
|
coerce: (value: FormatValue): Format =>
|
|
|
value === "tree"
|
|
|
? {
|
|
|
header: "",
|
|
|
- apply: (node: PackageLockTree, parents: string[]) =>
|
|
|
- `${" ".repeat(parents.length)}${node.value.name}@${node.value.version}${node.value.dev ? " (dev)" : ""}`
|
|
|
+ apply: (node, parents, audit) =>
|
|
|
+ `${" ".repeat(parents.length)}${node.value.name}@${node.value.version}${node.value.dev ? " (dev)" : ""} audit:${audit}`
|
|
|
}
|
|
|
: {
|
|
|
- header: "name,version,root,parent,type",
|
|
|
- apply: (node: PackageLockTree, parents: string[]) =>
|
|
|
- `${node.value.name},${node.value.version},${parents[0] ?? ""},${parents[parents.length - 1] ?? ""},${node.value.dev ? "devDependency" : "dependency"}`
|
|
|
+ header: "name,version,root,parent,type,audit",
|
|
|
+ apply: (node, parents, audit) =>
|
|
|
+ `${node.value.name},${node.value.version},${parents[0] ?? ""},${parents[parents.length - 1] ?? ""},${node.value.dev ? "devDependency" : "dependency"},${audit}`
|
|
|
}
|
|
|
})
|
|
|
.option("filter", {
|
|
|
+ type: "string",
|
|
|
describe: "Possible values are 'none' and 'oracle'",
|
|
|
- default: "none",
|
|
|
- coerce: (value: FilterValue) =>
|
|
|
+ default: "oracle",
|
|
|
+ coerce: (value: FilterValue): Filter =>
|
|
|
value === "oracle"
|
|
|
- ? (node: PackageLockTree, parents: string[]) => (parents.length === 0 && !node.value.name.startsWith("@os")) || (!node.value.name.startsWith("@o") && parents.length > 1 && parents.every(p => p.startsWith("@os")))
|
|
|
- : (node: PackageLockTree, parents: string[]) => true
|
|
|
+ ? (node, parents) => (parents.length === 0 && !node.value.name.startsWith("@os")) || (!node.value.name.startsWith("@o") && parents.length > 1 && parents.every(p => p.startsWith("@os")))
|
|
|
+ : (_, __) => true
|
|
|
+ })
|
|
|
+ .option("audit", {
|
|
|
+ type: "boolean",
|
|
|
+ describe: "Open Source Compliance Service audit",
|
|
|
+ default: false,
|
|
|
+ coerce: (value: boolean): Audit =>
|
|
|
+ _ => Promise.resolve(AuditResult.NA)
|
|
|
})
|
|
|
.help()
|
|
|
.argv;
|
|
|
@@ -97,22 +108,27 @@ const constructDepTree = (packageName: string, context: PackageLockDependencies,
|
|
|
};
|
|
|
}
|
|
|
|
|
|
+const enum AuditResult {
|
|
|
+ OK = "registered",
|
|
|
+ NOK = "not registered",
|
|
|
+ NA = "n/a"
|
|
|
+}
|
|
|
+
|
|
|
const displayDepTree = (format: Format) => {
|
|
|
if (format.header) {
|
|
|
console.log(format.header);
|
|
|
}
|
|
|
- return (filter: (node: PackageLockTree, parents: string[]) => boolean) =>
|
|
|
- (tree: PackageLockTree) => {
|
|
|
- const iter = (tree: PackageLockTree, stack: string[] = []) => {
|
|
|
- if (filter(tree, stack)) {
|
|
|
- console.log(format.apply(tree, stack));
|
|
|
- }
|
|
|
- if (tree.type === "node") {
|
|
|
- tree.children.forEach(t => iter(t, [...stack, `${tree.value.name}@${tree.value.version}`]))
|
|
|
- }
|
|
|
+ return (filter: Filter) => (action: Audit) => (tree: PackageLockTree) => {
|
|
|
+ const iter = (tree: PackageLockTree, stack: string[] = []) => {
|
|
|
+ if (filter(tree, stack)) {
|
|
|
+ action(tree).then(auditResult => console.log(format.apply(tree, stack, auditResult)));
|
|
|
}
|
|
|
- iter(tree);
|
|
|
- };
|
|
|
+ if (tree.type === "node") {
|
|
|
+ tree.children.forEach(t => iter(t, [...stack, `${tree.value.name}@${tree.value.version}`]))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ iter(tree);
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -125,7 +141,7 @@ Promise.all<Package, PackageLock>([
|
|
|
const dependencyTree = Object.keys(json.dependencies)
|
|
|
.concat(Object.keys(json.devDependencies ?? {}))
|
|
|
.map(depName => constructDepTree(depName, jsonLock.dependencies));
|
|
|
- const display = displayDepTree(args.format)(args.filter);
|
|
|
+ const display = displayDepTree(args.format)(args.filter)(args.audit);
|
|
|
dependencyTree.forEach(t => display(t));
|
|
|
})
|
|
|
.catch(reson => {
|