|
|
@@ -3,6 +3,12 @@ import path from "path";
|
|
|
|
|
|
import { hideBin } from "yargs/helpers";
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+type FormatValue = "tree" | "csv";
|
|
|
+type Format = { header: string, apply: (node: PackageLockTree, parents: string[]) => string }
|
|
|
+type FilterValue = "none" | "oracle";
|
|
|
+
|
|
|
const args = yargs(hideBin(process.argv))
|
|
|
.option("package", {
|
|
|
type: "string",
|
|
|
@@ -10,19 +16,34 @@ const args = yargs(hideBin(process.argv))
|
|
|
require: true
|
|
|
})
|
|
|
.option("format", {
|
|
|
- choices: ["tree", "csv"],
|
|
|
- demandOption: true,
|
|
|
- default: "tree"
|
|
|
+ describe: "Possible values are 'tree' and 'csv'",
|
|
|
+ default: "tree",
|
|
|
+ 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)" : ""}`
|
|
|
+ }
|
|
|
+ : {
|
|
|
+ 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"}`
|
|
|
+ }
|
|
|
})
|
|
|
.option("filter", {
|
|
|
- choices: ["none", "oracle"],
|
|
|
- demandOption: true,
|
|
|
- default: "none"
|
|
|
+ describe: "Possible values are 'none' and 'oracle'",
|
|
|
+ default: "none",
|
|
|
+ coerce: (value: FilterValue) =>
|
|
|
+ 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
|
|
|
})
|
|
|
.help()
|
|
|
.argv;
|
|
|
|
|
|
|
|
|
+
|
|
|
interface Dictionary<T> {
|
|
|
[index: string]: T
|
|
|
}
|
|
|
@@ -76,19 +97,22 @@ const constructDepTree = (packageName: string, context: PackageLockDependencies,
|
|
|
};
|
|
|
}
|
|
|
|
|
|
-const displayDepTree = (format: (node: PackageLockTree, parents: string[]) => string) =>
|
|
|
- (filter: (node: PackageLockTree, parents: string[]) => boolean) =>
|
|
|
+const displayDepTree = (format: Format) => {
|
|
|
+ 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(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}`]))
|
|
|
}
|
|
|
}
|
|
|
iter(tree);
|
|
|
- }
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
|
|
|
Promise.all<Package, PackageLock>([
|
|
|
@@ -99,16 +123,7 @@ Promise.all<Package, PackageLock>([
|
|
|
const dependencyTree = Object.keys(json.dependencies)
|
|
|
.concat(Object.keys(json.devDependencies ?? {}))
|
|
|
.map(depName => constructDepTree(depName, jsonLock.dependencies));
|
|
|
- if (args.format === "csv") {
|
|
|
- console.log("name,version,root,parent,type");
|
|
|
- }
|
|
|
- const format = args.format === "tree"
|
|
|
- ? (node: PackageLockTree, parents: string[]) => `${" ".repeat(parents.length)}${node.value.name}@${node.value.version}${node.value.dev ? " (dev)" : ""}`
|
|
|
- : (node: PackageLockTree, parents: string[]) => `${node.value.name},${node.value.version},${parents[0] ?? ""},${parents[parents.length - 1] ?? ""},${node.value.dev ? "devDependency" : "dependency"}`;
|
|
|
- const filter = args.filter === "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;
|
|
|
- const display = displayDepTree(format)(filter);
|
|
|
+ const display = displayDepTree(args.format)(args.filter);
|
|
|
dependencyTree.forEach(t => display(t));
|
|
|
})
|
|
|
.catch(reson => {
|