@hanseltime/esm-interop-tools 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -0
- package/dist/bin/get-esm-packages.js +17 -0
- package/dist/bin/get-esm-packages.js.map +1 -0
- package/dist/cjs/bin/get-esm-packages.js +73 -0
- package/dist/cjs/bin/get-esm-packages.js.map +1 -0
- package/dist/cjs/index.js +21 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/operations/getESMPackages.js +105 -0
- package/dist/cjs/operations/getESMPackages.js.map +1 -0
- package/dist/cjs/operations/index.js +21 -0
- package/dist/cjs/operations/index.js.map +1 -0
- package/dist/cjs/operations/jest.js +52 -0
- package/dist/cjs/operations/jest.js.map +1 -0
- package/dist/cjs/packageGraphs/Graph.js +130 -0
- package/dist/cjs/packageGraphs/Graph.js.map +1 -0
- package/dist/cjs/packageGraphs/PackageGraph.js +42 -0
- package/dist/cjs/packageGraphs/PackageGraph.js.map +1 -0
- package/dist/cjs/packageGraphs/getYarnInfoPackageGraph.js +128 -0
- package/dist/cjs/packageGraphs/getYarnInfoPackageGraph.js.map +1 -0
- package/dist/cjs/packageGraphs/index.js +23 -0
- package/dist/cjs/packageGraphs/index.js.map +1 -0
- package/dist/cjs/packageGraphs/types.js +6 -0
- package/dist/cjs/packageGraphs/types.js.map +1 -0
- package/dist/esm/bin/get-esm-packages.mjs +86 -0
- package/dist/esm/bin/get-esm-packages.mjs.map +1 -0
- package/dist/esm/index.mjs +4 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/operations/getESMPackages.mjs +118 -0
- package/dist/esm/operations/getESMPackages.mjs.map +1 -0
- package/dist/esm/operations/index.mjs +4 -0
- package/dist/esm/operations/index.mjs.map +1 -0
- package/dist/esm/operations/jest.mjs +45 -0
- package/dist/esm/operations/jest.mjs.map +1 -0
- package/dist/esm/packageGraphs/Graph.mjs +173 -0
- package/dist/esm/packageGraphs/Graph.mjs.map +1 -0
- package/dist/esm/packageGraphs/PackageGraph.mjs +28 -0
- package/dist/esm/packageGraphs/PackageGraph.mjs.map +1 -0
- package/dist/esm/packageGraphs/getYarnInfoPackageGraph.mjs +142 -0
- package/dist/esm/packageGraphs/getYarnInfoPackageGraph.mjs.map +1 -0
- package/dist/esm/packageGraphs/index.mjs +6 -0
- package/dist/esm/packageGraphs/index.mjs.map +1 -0
- package/dist/esm/packageGraphs/types.mjs +8 -0
- package/dist/esm/packageGraphs/types.mjs.map +1 -0
- package/dist/types/bin/get-esm-packages.d.ts +2 -0
- package/dist/types/bin/get-esm-packages.d.ts.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/operations/getESMPackages.d.ts +8 -0
- package/dist/types/operations/getESMPackages.d.ts.map +1 -0
- package/dist/types/operations/index.d.ts +3 -0
- package/dist/types/operations/index.d.ts.map +1 -0
- package/dist/types/operations/jest.d.ts +40 -0
- package/dist/types/operations/jest.d.ts.map +1 -0
- package/dist/types/packageGraphs/Graph.d.ts +72 -0
- package/dist/types/packageGraphs/Graph.d.ts.map +1 -0
- package/dist/types/packageGraphs/PackageGraph.d.ts +19 -0
- package/dist/types/packageGraphs/PackageGraph.d.ts.map +1 -0
- package/dist/types/packageGraphs/getYarnInfoPackageGraph.d.ts +9 -0
- package/dist/types/packageGraphs/getYarnInfoPackageGraph.d.ts.map +1 -0
- package/dist/types/packageGraphs/index.d.ts +5 -0
- package/dist/types/packageGraphs/index.d.ts.map +1 -0
- package/dist/types/packageGraphs/types.d.ts +9 -0
- package/dist/types/packageGraphs/types.d.ts.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "writeESMModuleOutput", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return writeESMModuleOutput;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
function _commander() {
|
|
12
|
+
const data = require("commander");
|
|
13
|
+
_commander = function() {
|
|
14
|
+
return data;
|
|
15
|
+
};
|
|
16
|
+
return data;
|
|
17
|
+
}
|
|
18
|
+
const _operations = require("../operations");
|
|
19
|
+
const _packageGraphs = require("../packageGraphs");
|
|
20
|
+
function _fs() {
|
|
21
|
+
const data = require("fs");
|
|
22
|
+
_fs = function() {
|
|
23
|
+
return data;
|
|
24
|
+
};
|
|
25
|
+
return data;
|
|
26
|
+
}
|
|
27
|
+
_commander().program.addOption(new (_commander()).Option("-p, --pkgManager <pkgManager>", "The package manager that you are running under - will be used to resolve modules").choices([
|
|
28
|
+
"yarnv2+"
|
|
29
|
+
]).makeOptionMandatory()).addOption(new (_commander()).Option("-o, --output <output>", "How to output the package info").choices([
|
|
30
|
+
"json",
|
|
31
|
+
"console",
|
|
32
|
+
"none"
|
|
33
|
+
]).default("console", "writes each package to the a line")).option("--cwd <cwd>").option("-r, --recurse", "get all dependencies and not just direct ones", false).option("-f, --file <file>", "the file to output json to").option("-q, --quiet", "if we should not output any values", false);
|
|
34
|
+
const options = _commander().program.parse(process.argv).opts();
|
|
35
|
+
async function main(options) {
|
|
36
|
+
const { pkgManager, cwd = process.cwd(), recurse, output, file, quiet } = options;
|
|
37
|
+
let packageGraph;
|
|
38
|
+
switch(pkgManager){
|
|
39
|
+
case "yarnv2+":
|
|
40
|
+
packageGraph = await (0, _packageGraphs.getYarnInfoPackageGraph)(cwd, recurse);
|
|
41
|
+
break;
|
|
42
|
+
default:
|
|
43
|
+
throw new Error("Unimplemented package manager GetPackagesGraphFn mapping!");
|
|
44
|
+
}
|
|
45
|
+
packageGraph.validate();
|
|
46
|
+
const packages = (await (0, _operations.getESMPackages)(packageGraph)).sort();
|
|
47
|
+
if (!quiet) {
|
|
48
|
+
switch(output){
|
|
49
|
+
case "json":
|
|
50
|
+
console.log(JSON.stringify(packages));
|
|
51
|
+
break;
|
|
52
|
+
case "console":
|
|
53
|
+
console.log(packages.join("\n"));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (file) {
|
|
57
|
+
writeESMModuleOutput(packages, file);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function writeESMModuleOutput(packages, file) {
|
|
61
|
+
(0, _fs().writeFileSync)(file, JSON.stringify({
|
|
62
|
+
description: `This is a programmatically created file via ${process.argv.join(" ")}`,
|
|
63
|
+
packages: packages
|
|
64
|
+
}, null, 4));
|
|
65
|
+
}
|
|
66
|
+
void main(options).then(()=>{
|
|
67
|
+
process.exit();
|
|
68
|
+
}).catch((err)=>{
|
|
69
|
+
console.error(err);
|
|
70
|
+
process.exit(5);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
//# sourceMappingURL=get-esm-packages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/bin/get-esm-packages.ts"],"sourcesContent":["import { program, Option } from \"commander\";\nimport { EsmPackagesFile, getESMPackages } from \"../operations\";\nimport { getYarnInfoPackageGraph, PackageGraph } from \"../packageGraphs\";\nimport { writeFileSync } from \"fs\";\n\nprogram\n\t.addOption(\n\t\tnew Option(\n\t\t\t\"-p, --pkgManager <pkgManager>\",\n\t\t\t\"The package manager that you are running under - will be used to resolve modules\",\n\t\t)\n\t\t\t.choices([\"yarnv2+\"])\n\t\t\t.makeOptionMandatory(),\n\t)\n\t.addOption(\n\t\tnew Option(\"-o, --output <output>\", \"How to output the package info\")\n\t\t\t.choices([\"json\", \"console\", \"none\"])\n\t\t\t.default(\"console\", \"writes each package to the a line\"),\n\t)\n\t.option(\"--cwd <cwd>\")\n\t.option(\n\t\t\"-r, --recurse\",\n\t\t\"get all dependencies and not just direct ones\",\n\t\tfalse,\n\t)\n\t.option(\"-f, --file <file>\", \"the file to output json to\")\n\t.option(\"-q, --quiet\", \"if we should not output any values\", false);\n\nconst options = program.parse(process.argv).opts<CliOpts>();\n\ninterface CliOpts {\n\tpkgManager: \"yarnv2+\" | \"npm\";\n\tcwd?: string;\n\trecurse: boolean;\n\toutput: \"console\" | \"json\";\n\tfile?: string;\n\tquiet: boolean;\n}\n\nasync function main(options: CliOpts) {\n\tconst {\n\t\tpkgManager,\n\t\tcwd = process.cwd(),\n\t\trecurse,\n\t\toutput,\n\t\tfile,\n\t\tquiet,\n\t} = options;\n\tlet packageGraph: PackageGraph;\n\tswitch (pkgManager) {\n\t\tcase \"yarnv2+\":\n\t\t\tpackageGraph = await getYarnInfoPackageGraph(cwd, recurse);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthrow new Error(\n\t\t\t\t\"Unimplemented package manager GetPackagesGraphFn mapping!\",\n\t\t\t);\n\t}\n\tpackageGraph.validate();\n\n\tconst packages = (await getESMPackages(packageGraph)).sort();\n\n\tif (!quiet) {\n\t\tswitch (output) {\n\t\t\tcase \"json\":\n\t\t\t\tconsole.log(JSON.stringify(packages));\n\t\t\t\tbreak;\n\t\t\tcase \"console\":\n\t\t\t\tconsole.log(packages.join(\"\\n\"));\n\t\t}\n\t}\n\n\tif (file) {\n\t\twriteESMModuleOutput(packages, file);\n\t}\n}\n\nexport function writeESMModuleOutput(packages: string[], file: string) {\n\twriteFileSync(\n\t\tfile,\n\t\tJSON.stringify(\n\t\t\t{\n\t\t\t\tdescription: `This is a programmatically created file via ${process.argv.join(\" \")}`,\n\t\t\t\tpackages: packages,\n\t\t\t} as EsmPackagesFile,\n\t\t\tnull,\n\t\t\t4,\n\t\t),\n\t);\n}\n\nvoid main(options)\n\t.then(() => {\n\t\tprocess.exit();\n\t})\n\t.catch((err) => {\n\t\tconsole.error(err);\n\t\tprocess.exit(5);\n\t});\n"],"names":["writeESMModuleOutput","program","addOption","Option","choices","makeOptionMandatory","default","option","options","parse","process","argv","opts","main","pkgManager","cwd","recurse","output","file","quiet","packageGraph","getYarnInfoPackageGraph","Error","validate","packages","getESMPackages","sort","console","log","JSON","stringify","join","writeFileSync","description","then","exit","catch","err","error"],"mappings":";;;;+BA6EgBA;;;eAAAA;;;;yBA7EgB;;;;;;4BACgB;+BACM;;yBACxB;;;;;;AAE9BC,oBAAO,CACLC,SAAS,CACT,IAAIC,CAAAA,YAAK,QAAC,CACT,iCACA,oFAECC,OAAO,CAAC;IAAC;CAAU,EACnBC,mBAAmB,IAErBH,SAAS,CACT,IAAIC,CAAAA,YAAK,QAAC,CAAC,yBAAyB,kCAClCC,OAAO,CAAC;IAAC;IAAQ;IAAW;CAAO,EACnCE,OAAO,CAAC,WAAW,sCAErBC,MAAM,CAAC,eACPA,MAAM,CACN,iBACA,iDACA,OAEAA,MAAM,CAAC,qBAAqB,8BAC5BA,MAAM,CAAC,eAAe,sCAAsC;AAE9D,MAAMC,UAAUP,oBAAO,CAACQ,KAAK,CAACC,QAAQC,IAAI,EAAEC,IAAI;AAWhD,eAAeC,KAAKL,OAAgB;IACnC,MAAM,EACLM,UAAU,EACVC,MAAML,QAAQK,GAAG,EAAE,EACnBC,OAAO,EACPC,MAAM,EACNC,IAAI,EACJC,KAAK,EACL,GAAGX;IACJ,IAAIY;IACJ,OAAQN;QACP,KAAK;YACJM,eAAe,MAAMC,IAAAA,sCAAuB,EAACN,KAAKC;YAClD;QACD;YACC,MAAM,IAAIM,MACT;IAEH;IACAF,aAAaG,QAAQ;IAErB,MAAMC,WAAW,AAAC,CAAA,MAAMC,IAAAA,0BAAc,EAACL,aAAY,EAAGM,IAAI;IAE1D,IAAI,CAACP,OAAO;QACX,OAAQF;YACP,KAAK;gBACJU,QAAQC,GAAG,CAACC,KAAKC,SAAS,CAACN;gBAC3B;YACD,KAAK;gBACJG,QAAQC,GAAG,CAACJ,SAASO,IAAI,CAAC;QAC5B;IACD;IAEA,IAAIb,MAAM;QACTlB,qBAAqBwB,UAAUN;IAChC;AACD;AAEO,SAASlB,qBAAqBwB,QAAkB,EAAEN,IAAY;IACpEc,IAAAA,mBAAa,EACZd,MACAW,KAAKC,SAAS,CACb;QACCG,aAAa,CAAC,4CAA4C,EAAEvB,QAAQC,IAAI,CAACoB,IAAI,CAAC,MAAM;QACpFP,UAAUA;IACX,GACA,MACA;AAGH;AAEA,KAAKX,KAAKL,SACR0B,IAAI,CAAC;IACLxB,QAAQyB,IAAI;AACb,GACCC,KAAK,CAAC,CAACC;IACPV,QAAQW,KAAK,CAACD;IACd3B,QAAQyB,IAAI,CAAC;AACd"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
_export_star(require("./operations"), exports);
|
|
6
|
+
_export_star(require("./packageGraphs"), exports);
|
|
7
|
+
function _export_star(from, to) {
|
|
8
|
+
Object.keys(from).forEach(function(k) {
|
|
9
|
+
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
|
10
|
+
Object.defineProperty(to, k, {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: function() {
|
|
13
|
+
return from[k];
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
return from;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export * from \"./operations\";\nexport * from \"./packageGraphs\";\n"],"names":[],"mappings":";;;;qBAAc;qBACA"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "getESMPackages", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return getESMPackages;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
function _promises() {
|
|
12
|
+
const data = require("fs/promises");
|
|
13
|
+
_promises = function() {
|
|
14
|
+
return data;
|
|
15
|
+
};
|
|
16
|
+
return data;
|
|
17
|
+
}
|
|
18
|
+
function _resolvepackagepath() {
|
|
19
|
+
const data = /*#__PURE__*/ _interop_require_default(require("resolve-package-path"));
|
|
20
|
+
_resolvepackagepath = function() {
|
|
21
|
+
return data;
|
|
22
|
+
};
|
|
23
|
+
return data;
|
|
24
|
+
}
|
|
25
|
+
function _path() {
|
|
26
|
+
const data = require("path");
|
|
27
|
+
_path = function() {
|
|
28
|
+
return data;
|
|
29
|
+
};
|
|
30
|
+
return data;
|
|
31
|
+
}
|
|
32
|
+
function _interop_require_default(obj) {
|
|
33
|
+
return obj && obj.__esModule ? obj : {
|
|
34
|
+
default: obj
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function resolvePkgPath(pkgDir, pkgName, options) {
|
|
38
|
+
const { optionalDepsFromParent, isPatch, isRoot } = options;
|
|
39
|
+
const path = (0, _resolvepackagepath().default)(pkgName, pkgDir);
|
|
40
|
+
if (!path && !optionalDepsFromParent?.[pkgName] && !isPatch) {
|
|
41
|
+
if (isRoot) {
|
|
42
|
+
// Accounts for an unresolvable root project since we're in it
|
|
43
|
+
return (0, _path().join)(pkgDir, "package.json");
|
|
44
|
+
}
|
|
45
|
+
throw new Error(`Non-optional dependency could not be found: ${pkgName} when looking from ${pkgDir}`);
|
|
46
|
+
}
|
|
47
|
+
return path;
|
|
48
|
+
}
|
|
49
|
+
async function getESMPackages(pkgGraph) {
|
|
50
|
+
const packagePathsMap = {};
|
|
51
|
+
// We need to resolve the packageJsons and are fine with optional dependencies missing since we can't tell if we need them
|
|
52
|
+
async function resolvePackageJsons(currentNode, previousOptions) {
|
|
53
|
+
// Look up the package.json
|
|
54
|
+
const jsonPath = resolvePkgPath(previousOptions?.parentPkgPath ?? pkgGraph.pkgDir, currentNode.value.name, {
|
|
55
|
+
optionalDepsFromParent: previousOptions?.optionalDependencies,
|
|
56
|
+
isPatch: currentNode.value.isPatch,
|
|
57
|
+
isRoot: currentNode.value.isRoot
|
|
58
|
+
});
|
|
59
|
+
// If we didn't throw any resolution errors, then we can assume this was optional - we shouldn't resolve down that path
|
|
60
|
+
if (!jsonPath) {
|
|
61
|
+
return [
|
|
62
|
+
{},
|
|
63
|
+
true
|
|
64
|
+
];
|
|
65
|
+
}
|
|
66
|
+
let pkgInfos = packagePathsMap[currentNode.value.name];
|
|
67
|
+
if (pkgInfos) {
|
|
68
|
+
if (pkgInfos.some((info)=>info.packageJsonPath === jsonPath)) {
|
|
69
|
+
return [
|
|
70
|
+
{},
|
|
71
|
+
false
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
pkgInfos = [];
|
|
76
|
+
packagePathsMap[currentNode.value.name] = pkgInfos;
|
|
77
|
+
}
|
|
78
|
+
const contents = await (0, _promises().readFile)(jsonPath);
|
|
79
|
+
const json = JSON.parse(contents.toString());
|
|
80
|
+
pkgInfos.push({
|
|
81
|
+
packageJsonPath: jsonPath,
|
|
82
|
+
isModule: json.type === "module"
|
|
83
|
+
});
|
|
84
|
+
return [
|
|
85
|
+
{
|
|
86
|
+
optionalDependencies: json.optionalDependencies,
|
|
87
|
+
parentPkgPath: jsonPath
|
|
88
|
+
},
|
|
89
|
+
false
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
// Iterate the packages and resolve all non-optional packages and existing optionals
|
|
93
|
+
await pkgGraph.topDownVisitAsync(resolvePackageJsons);
|
|
94
|
+
return Array.from(Object.keys(packagePathsMap).reduce((mods, p)=>{
|
|
95
|
+
const infos = packagePathsMap[p];
|
|
96
|
+
infos.forEach((info)=>{
|
|
97
|
+
if (info.isModule) {
|
|
98
|
+
mods.add(p);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
return mods;
|
|
102
|
+
}, new Set()));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
//# sourceMappingURL=getESMPackages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/operations/getESMPackages.ts"],"sourcesContent":["import { readFile } from \"fs/promises\";\nimport resolvePackagePath from \"resolve-package-path\";\nimport {\n\tPackageGraph,\n\tPackageInfo,\n\tNode,\n\tPackageInfoKey,\n} from \"../packageGraphs\";\nimport { join } from \"path\";\n\nfunction resolvePkgPath(\n\tpkgDir: string,\n\tpkgName: string,\n\toptions: {\n\t\toptionalDepsFromParent?: {\n\t\t\t[dep: string]: string;\n\t\t};\n\t\t// If this was a patch, we probably can't find a package.json (or at least, I didn't solve this)\n\t\tisPatch: boolean;\n\t\tisRoot: boolean;\n\t},\n) {\n\tconst { optionalDepsFromParent, isPatch, isRoot } = options;\n\tconst path = resolvePackagePath(pkgName, pkgDir);\n\tif (!path && !optionalDepsFromParent?.[pkgName] && !isPatch) {\n\t\tif (isRoot) {\n\t\t\t// Accounts for an unresolvable root project since we're in it\n\t\t\treturn join(pkgDir, \"package.json\");\n\t\t}\n\t\tthrow new Error(\n\t\t\t`Non-optional dependency could not be found: ${pkgName} when looking from ${pkgDir}`,\n\t\t);\n\t}\n\treturn path;\n}\n// options: {\n// /**\n// * Depending on the integrity of your packages, you may get failures due to some packages saying\n// */\n// ignorePackages: string[]\n// }\ninterface VisitReturn {\n\t/**\n\t * The resolved path of the package.json that's requesting this. This is specifically for multi-version resolutions\n\t */\n\tparentPkgPath?: string;\n\toptionalDependencies?: {\n\t\t[dep: string]: string;\n\t};\n}\n\ninterface PkgInfo {\n\tpackageJsonPath: string;\n\tisModule: boolean;\n}\n\n/**\n * Returns the esm packages from a PackageGraph - Assumes we can read package.json (may not work with yarn plug'n'play)\n * @param pkgGraph\n * @returns\n */\nexport async function getESMPackages(pkgGraph: PackageGraph) {\n\tconst packagePathsMap: {\n\t\t// Since packages can be multiply referenced via nested modules, we can have multiple of these\n\t\t[pkgName: string]: PkgInfo[];\n\t} = {};\n\t// We need to resolve the packageJsons and are fine with optional dependencies missing since we can't tell if we need them\n\tasync function resolvePackageJsons(\n\t\tcurrentNode: Node<PackageInfo, PackageInfoKey>,\n\t\tpreviousOptions?: VisitReturn,\n\t): Promise<[VisitReturn, boolean]> {\n\t\t// Look up the package.json\n\t\tconst jsonPath = resolvePkgPath(\n\t\t\tpreviousOptions?.parentPkgPath ?? pkgGraph.pkgDir,\n\t\t\tcurrentNode.value.name,\n\t\t\t{\n\t\t\t\toptionalDepsFromParent: previousOptions?.optionalDependencies,\n\t\t\t\tisPatch: currentNode.value.isPatch,\n\t\t\t\tisRoot: currentNode.value.isRoot,\n\t\t\t},\n\t\t);\n\t\t// If we didn't throw any resolution errors, then we can assume this was optional - we shouldn't resolve down that path\n\t\tif (!jsonPath) {\n\t\t\treturn [{}, true];\n\t\t}\n\t\tlet pkgInfos: PkgInfo[] | undefined =\n\t\t\tpackagePathsMap[currentNode.value.name];\n\t\tif (pkgInfos) {\n\t\t\tif (pkgInfos.some((info) => info.packageJsonPath === jsonPath)) {\n\t\t\t\treturn [{}, false];\n\t\t\t}\n\t\t} else {\n\t\t\tpkgInfos = [] as PkgInfo[];\n\t\t\tpackagePathsMap[currentNode.value.name] = pkgInfos;\n\t\t}\n\n\t\tconst contents = await readFile(jsonPath);\n\t\tconst json = JSON.parse(contents.toString());\n\t\tpkgInfos.push({\n\t\t\tpackageJsonPath: jsonPath,\n\t\t\tisModule: json.type === \"module\",\n\t\t});\n\t\treturn [\n\t\t\t{\n\t\t\t\toptionalDependencies: json.optionalDependencies,\n\t\t\t\tparentPkgPath: jsonPath,\n\t\t\t},\n\t\t\tfalse,\n\t\t];\n\t}\n\n\t// Iterate the packages and resolve all non-optional packages and existing optionals\n\tawait pkgGraph.topDownVisitAsync(resolvePackageJsons);\n\n\treturn Array.from(\n\t\tObject.keys(packagePathsMap).reduce((mods, p) => {\n\t\t\tconst infos = packagePathsMap[p];\n\t\t\tinfos.forEach((info) => {\n\t\t\t\tif (info.isModule) {\n\t\t\t\t\tmods.add(p);\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn mods;\n\t\t}, new Set<string>()),\n\t);\n}\n"],"names":["getESMPackages","resolvePkgPath","pkgDir","pkgName","options","optionalDepsFromParent","isPatch","isRoot","path","resolvePackagePath","join","Error","pkgGraph","packagePathsMap","resolvePackageJsons","currentNode","previousOptions","jsonPath","parentPkgPath","value","name","optionalDependencies","pkgInfos","some","info","packageJsonPath","contents","readFile","json","JSON","parse","toString","push","isModule","type","topDownVisitAsync","Array","from","Object","keys","reduce","mods","p","infos","forEach","add","Set"],"mappings":";;;;+BA6DsBA;;;eAAAA;;;;yBA7DG;;;;;;;gEACM;;;;;;;yBAOV;;;;;;;;;;;AAErB,SAASC,eACRC,MAAc,EACdC,OAAe,EACfC,OAOC;IAED,MAAM,EAAEC,sBAAsB,EAAEC,OAAO,EAAEC,MAAM,EAAE,GAAGH;IACpD,MAAMI,OAAOC,IAAAA,6BAAkB,EAACN,SAASD;IACzC,IAAI,CAACM,QAAQ,CAACH,wBAAwB,CAACF,QAAQ,IAAI,CAACG,SAAS;QAC5D,IAAIC,QAAQ;YACX,8DAA8D;YAC9D,OAAOG,IAAAA,YAAI,EAACR,QAAQ;QACrB;QACA,MAAM,IAAIS,MACT,CAAC,4CAA4C,EAAER,QAAQ,mBAAmB,EAAED,QAAQ;IAEtF;IACA,OAAOM;AACR;AA2BO,eAAeR,eAAeY,QAAsB;IAC1D,MAAMC,kBAGF,CAAC;IACL,0HAA0H;IAC1H,eAAeC,oBACdC,WAA8C,EAC9CC,eAA6B;QAE7B,2BAA2B;QAC3B,MAAMC,WAAWhB,eAChBe,iBAAiBE,iBAAiBN,SAASV,MAAM,EACjDa,YAAYI,KAAK,CAACC,IAAI,EACtB;YACCf,wBAAwBW,iBAAiBK;YACzCf,SAASS,YAAYI,KAAK,CAACb,OAAO;YAClCC,QAAQQ,YAAYI,KAAK,CAACZ,MAAM;QACjC;QAED,uHAAuH;QACvH,IAAI,CAACU,UAAU;YACd,OAAO;gBAAC,CAAC;gBAAG;aAAK;QAClB;QACA,IAAIK,WACHT,eAAe,CAACE,YAAYI,KAAK,CAACC,IAAI,CAAC;QACxC,IAAIE,UAAU;YACb,IAAIA,SAASC,IAAI,CAAC,CAACC,OAASA,KAAKC,eAAe,KAAKR,WAAW;gBAC/D,OAAO;oBAAC,CAAC;oBAAG;iBAAM;YACnB;QACD,OAAO;YACNK,WAAW,EAAE;YACbT,eAAe,CAACE,YAAYI,KAAK,CAACC,IAAI,CAAC,GAAGE;QAC3C;QAEA,MAAMI,WAAW,MAAMC,IAAAA,oBAAQ,EAACV;QAChC,MAAMW,OAAOC,KAAKC,KAAK,CAACJ,SAASK,QAAQ;QACzCT,SAASU,IAAI,CAAC;YACbP,iBAAiBR;YACjBgB,UAAUL,KAAKM,IAAI,KAAK;QACzB;QACA,OAAO;YACN;gBACCb,sBAAsBO,KAAKP,oBAAoB;gBAC/CH,eAAeD;YAChB;YACA;SACA;IACF;IAEA,oFAAoF;IACpF,MAAML,SAASuB,iBAAiB,CAACrB;IAEjC,OAAOsB,MAAMC,IAAI,CAChBC,OAAOC,IAAI,CAAC1B,iBAAiB2B,MAAM,CAAC,CAACC,MAAMC;QAC1C,MAAMC,QAAQ9B,eAAe,CAAC6B,EAAE;QAChCC,MAAMC,OAAO,CAAC,CAACpB;YACd,IAAIA,KAAKS,QAAQ,EAAE;gBAClBQ,KAAKI,GAAG,CAACH;YACV;QACD;QACA,OAAOD;IACR,GAAG,IAAIK;AAET"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
_export_star(require("./getESMPackages"), exports);
|
|
6
|
+
_export_star(require("./jest"), exports);
|
|
7
|
+
function _export_star(from, to) {
|
|
8
|
+
Object.keys(from).forEach(function(k) {
|
|
9
|
+
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
|
10
|
+
Object.defineProperty(to, k, {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: function() {
|
|
13
|
+
return from[k];
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
return from;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/operations/index.ts"],"sourcesContent":["export * from \"./getESMPackages\";\nexport * from \"./jest\";\n"],"names":[],"mappings":";;;;qBAAc;qBACA"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: all[name]
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
createNodeModulesTransformIgnore: function() {
|
|
13
|
+
return createNodeModulesTransformIgnore;
|
|
14
|
+
},
|
|
15
|
+
getJestNodeModulesTransformIgnore: function() {
|
|
16
|
+
return getJestNodeModulesTransformIgnore;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
function _fs() {
|
|
20
|
+
const data = require("fs");
|
|
21
|
+
_fs = function() {
|
|
22
|
+
return data;
|
|
23
|
+
};
|
|
24
|
+
return data;
|
|
25
|
+
}
|
|
26
|
+
function getJestNodeModulesTransformIgnore(options) {
|
|
27
|
+
const { file, extraExceptions = [] } = options;
|
|
28
|
+
const modules = getModulesFromFile(file);
|
|
29
|
+
// Dedup
|
|
30
|
+
const modSet = new Set([
|
|
31
|
+
...modules,
|
|
32
|
+
...extraExceptions
|
|
33
|
+
]);
|
|
34
|
+
return createNodeModulesTransformIgnore(Array.from(modSet));
|
|
35
|
+
}
|
|
36
|
+
function getModulesFromFile(file) {
|
|
37
|
+
try {
|
|
38
|
+
const esmModules = JSON.parse((0, _fs().readFileSync)(file).toString());
|
|
39
|
+
if (!esmModules.packages || !Array.isArray(esmModules.packages)) {
|
|
40
|
+
throw new Error("Esm packages file object is missing the expected packages field!");
|
|
41
|
+
}
|
|
42
|
+
return esmModules.packages;
|
|
43
|
+
} catch (err) {
|
|
44
|
+
console.error(`Malformed esm modules file: ${file}`);
|
|
45
|
+
throw err;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function createNodeModulesTransformIgnore(packageExceptions) {
|
|
49
|
+
return `node_modules/(?!${packageExceptions.map((p)=>`${p}/`).join("|")})`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=jest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/operations/jest.ts"],"sourcesContent":["import { readFileSync } from \"fs\";\n\nexport interface EsmPackagesFile {\n\tdescription: string;\n\t/**\n\t * Package names that are esm modules\n\t */\n\tpackages: string[];\n}\n\n/**\n * You can use this function to get get a transformIgnore pattern for jest that excludes node_modules\n * from a file where we have written all esm files that were detected.\n *\n * This is specifically designed for a \"post-install\" script that scans on install and overwrites the file\n * if there are new esm module types - thereby reducing the cost of tests to just a file read instead of a\n * tree scan.\n *\n * @param options\n * @returns\n */\nexport function getJestNodeModulesTransformIgnore(options: {\n\t/**\n\t * The file location where we have written the esm module info to\n\t *\n\t * default (esm-modules.json)\n\t */\n\tfile: string;\n\t/**\n\t * Extra packages for an exception for node modules\n\t */\n\textraExceptions?: string[];\n}) {\n\tconst { file, extraExceptions = [] } = options;\n\tconst modules = getModulesFromFile(file);\n\t// Dedup\n\tconst modSet = new Set<string>([...modules, ...extraExceptions]);\n\treturn createNodeModulesTransformIgnore(Array.from(modSet));\n}\n\nfunction getModulesFromFile(file: string) {\n\ttry {\n\t\tconst esmModules = JSON.parse(\n\t\t\treadFileSync(file).toString(),\n\t\t) as EsmPackagesFile;\n\t\tif (!esmModules.packages || !Array.isArray(esmModules.packages)) {\n\t\t\tthrow new Error(\n\t\t\t\t\"Esm packages file object is missing the expected packages field!\",\n\t\t\t);\n\t\t}\n\t\treturn esmModules.packages;\n\t} catch (err) {\n\t\tconsole.error(`Malformed esm modules file: ${file}`);\n\t\tthrow err;\n\t}\n}\n\n/**\n * Given a set of package names, this constructs a node_modules ignore string that exempts the\n * targeted modules from jest transform.\n *\n * It should be used with the transformIgnore configuration.\n * @param packageExceptions\n * @returns\n */\nexport function createNodeModulesTransformIgnore(packageExceptions: string[]) {\n\treturn `node_modules/(?!${packageExceptions.map((p) => `${p}/`).join(\"|\")})`;\n}\n"],"names":["createNodeModulesTransformIgnore","getJestNodeModulesTransformIgnore","options","file","extraExceptions","modules","getModulesFromFile","modSet","Set","Array","from","esmModules","JSON","parse","readFileSync","toString","packages","isArray","Error","err","console","error","packageExceptions","map","p","join"],"mappings":";;;;;;;;;;;IAiEgBA,gCAAgC;eAAhCA;;IA5CAC,iCAAiC;eAAjCA;;;;yBArBa;;;;;;AAqBtB,SAASA,kCAAkCC,OAWjD;IACA,MAAM,EAAEC,IAAI,EAAEC,kBAAkB,EAAE,EAAE,GAAGF;IACvC,MAAMG,UAAUC,mBAAmBH;IACnC,QAAQ;IACR,MAAMI,SAAS,IAAIC,IAAY;WAAIH;WAAYD;KAAgB;IAC/D,OAAOJ,iCAAiCS,MAAMC,IAAI,CAACH;AACpD;AAEA,SAASD,mBAAmBH,IAAY;IACvC,IAAI;QACH,MAAMQ,aAAaC,KAAKC,KAAK,CAC5BC,IAAAA,kBAAY,EAACX,MAAMY,QAAQ;QAE5B,IAAI,CAACJ,WAAWK,QAAQ,IAAI,CAACP,MAAMQ,OAAO,CAACN,WAAWK,QAAQ,GAAG;YAChE,MAAM,IAAIE,MACT;QAEF;QACA,OAAOP,WAAWK,QAAQ;IAC3B,EAAE,OAAOG,KAAK;QACbC,QAAQC,KAAK,CAAC,CAAC,4BAA4B,EAAElB,MAAM;QACnD,MAAMgB;IACP;AACD;AAUO,SAASnB,iCAAiCsB,iBAA2B;IAC3E,OAAO,CAAC,gBAAgB,EAAEA,kBAAkBC,GAAG,CAAC,CAACC,IAAM,GAAGA,EAAE,CAAC,CAAC,EAAEC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC7E"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// TODO: it would be nice to split this into a package for reuse
|
|
2
|
+
/**
|
|
3
|
+
* Describes a node in a graph that has a value of a specific type
|
|
4
|
+
* and then points to values of others nodes
|
|
5
|
+
*/ "use strict";
|
|
6
|
+
Object.defineProperty(exports, "__esModule", {
|
|
7
|
+
value: true
|
|
8
|
+
});
|
|
9
|
+
Object.defineProperty(exports, "Graph", {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: function() {
|
|
12
|
+
return Graph;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
function _define_property(obj, key, value) {
|
|
16
|
+
if (key in obj) {
|
|
17
|
+
Object.defineProperty(obj, key, {
|
|
18
|
+
value: value,
|
|
19
|
+
enumerable: true,
|
|
20
|
+
configurable: true,
|
|
21
|
+
writable: true
|
|
22
|
+
});
|
|
23
|
+
} else {
|
|
24
|
+
obj[key] = value;
|
|
25
|
+
}
|
|
26
|
+
return obj;
|
|
27
|
+
}
|
|
28
|
+
let Graph = class Graph {
|
|
29
|
+
getNodeKeyStr(nodeKey) {
|
|
30
|
+
return this.keySerializer ? this.keySerializer(nodeKey) : nodeKey;
|
|
31
|
+
}
|
|
32
|
+
addDownstreamNode(node) {
|
|
33
|
+
const nodeKeyStr = this.getNodeKeyStr(node.self);
|
|
34
|
+
// If a previous node prestubbed in the next node, we add it here
|
|
35
|
+
if (this.map.has(nodeKeyStr)) {
|
|
36
|
+
const preStubbedNode = this.map.get(nodeKeyStr);
|
|
37
|
+
if (preStubbedNode.value !== undefined) {
|
|
38
|
+
throw new Error(`Already added a downstream node of same key: ${nodeKeyStr} - Can't add ${JSON.stringify(node)}`);
|
|
39
|
+
}
|
|
40
|
+
preStubbedNode.to.push(...node.to);
|
|
41
|
+
preStubbedNode.value = node.value;
|
|
42
|
+
} else {
|
|
43
|
+
this.map.set(nodeKeyStr, {
|
|
44
|
+
from: [],
|
|
45
|
+
...node
|
|
46
|
+
});
|
|
47
|
+
this.noFrom.add(nodeKeyStr);
|
|
48
|
+
}
|
|
49
|
+
// Add to or pre-stub some nodes
|
|
50
|
+
node.to.forEach((n)=>{
|
|
51
|
+
const nkStr = this.getNodeKeyStr(n);
|
|
52
|
+
if (this.map.has(nkStr)) {
|
|
53
|
+
const existingNode = this.map.get(nkStr);
|
|
54
|
+
existingNode.from.push(node.self);
|
|
55
|
+
if (existingNode.from.length === 1) {
|
|
56
|
+
// We were wrong about this package
|
|
57
|
+
this.noFrom.delete(nkStr);
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
this.map.set(nkStr, {
|
|
61
|
+
self: n,
|
|
62
|
+
from: [
|
|
63
|
+
node.self
|
|
64
|
+
],
|
|
65
|
+
to: [],
|
|
66
|
+
value: undefined
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
validate() {
|
|
72
|
+
const errors = [];
|
|
73
|
+
for (let [k, node] of this.map.entries()){
|
|
74
|
+
if (!node.value) {
|
|
75
|
+
errors.push(`Unregistered node: ${k}! Node was pointed to by: ${JSON.stringify(node.from)}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (errors.length > 0) {
|
|
79
|
+
throw new Error(errors.join("\n"));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
*
|
|
84
|
+
* @param visit
|
|
85
|
+
* @param firstArrivalOnly - if set to true, we are saying that we do not care about from where we get to the node, just the first arrival matters
|
|
86
|
+
* This will depend on your visit function, since the visit function can pass parent -> child info that may change based on the node
|
|
87
|
+
* it is coming from
|
|
88
|
+
*/ async topDownVisitAsync(visit, firstArrivalOnly) {
|
|
89
|
+
const guestBook = firstArrivalOnly ? new Set() : undefined;
|
|
90
|
+
for (const noFrom of this.noFrom){
|
|
91
|
+
const node = this.map.get(noFrom);
|
|
92
|
+
await this.visitDownNodeAsync(node, visit, guestBook);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
*
|
|
97
|
+
* @param nodeKey - the key that we used to retrieve this node
|
|
98
|
+
* @param node - the node itself
|
|
99
|
+
* @param visit - the visit function
|
|
100
|
+
* @param guestBook - This is used to track if we have already visited the node - note this means we don't expect the visit function to change results
|
|
101
|
+
* regardless of the node that we come from
|
|
102
|
+
* @param prevResult - the result of the last node that got here
|
|
103
|
+
* @returns
|
|
104
|
+
*/ async visitDownNodeAsync(node, visit, guestBook, prevResult) {
|
|
105
|
+
if (guestBook?.has(this.getNodeKeyStr(node.self))) {
|
|
106
|
+
// We already visited this node
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const [result, stop] = await visit(node, prevResult);
|
|
110
|
+
if (stop) {
|
|
111
|
+
// We let the visitor control travel
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
await Promise.all(node.to.map((n)=>{
|
|
115
|
+
return this.visitDownNodeAsync(this.map.get(this.getNodeKeyStr(n)), visit, guestBook, result);
|
|
116
|
+
}));
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
*
|
|
120
|
+
* @param keySerializer - if the graph has a compound key, then you must supply a function that converts a compound key to a string
|
|
121
|
+
*/ constructor(keySerializer){
|
|
122
|
+
// This map is partially filled so we allow undefined values internally
|
|
123
|
+
_define_property(this, "map", new Map());
|
|
124
|
+
_define_property(this, "noFrom", new Set());
|
|
125
|
+
_define_property(this, "keySerializer", void 0);
|
|
126
|
+
this.keySerializer = keySerializer;
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
//# sourceMappingURL=Graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/packageGraphs/Graph.ts"],"sourcesContent":["// TODO: it would be nice to split this into a package for reuse\n\n/**\n * Describes a node in a graph that has a value of a specific type\n * and then points to values of others nodes\n */\nexport interface Node<T, NodeKey> {\n\tself: NodeKey;\n\tfrom: NodeKey[];\n\tto: NodeKey[];\n\tvalue: T;\n}\n\n/**\n * A node that we only know where it goes to at the moment\n */\nexport interface DownstreamNode<T, NodeKey> {\n\tself: NodeKey;\n\tvalue: T;\n\tto: NodeKey[];\n}\n\n/**\n * If using a compound node key, then we require a node key serializer to get a base string out of it\n */\ntype NodeKeySerializer<T> = T extends string ? undefined : (t: T) => string;\n\n/**\n * Mnimal \"graph\" class that takes in a bunch of nodes and then allows you to visit them in a particular order.\n *\n * The value of the node <T> is used as the unique node key for referencing other nodes.\n */\nexport class Graph<\n\tT,\n\tNodeKey,\n\tNKSerializer extends NodeKeySerializer<NodeKey> = NodeKeySerializer<NodeKey>,\n> {\n\t// This map is partially filled so we allow undefined values internally\n\treadonly map = new Map<string, Node<T | undefined, NodeKey>>();\n\tprivate readonly noFrom = new Set<string>();\n\treadonly keySerializer: NKSerializer;\n\n\t/**\n\t *\n\t * @param keySerializer - if the graph has a compound key, then you must supply a function that converts a compound key to a string\n\t */\n\tconstructor(keySerializer: NKSerializer) {\n\t\tthis.keySerializer = keySerializer;\n\t}\n\n\tprivate getNodeKeyStr(nodeKey: NodeKey): string {\n\t\treturn this.keySerializer\n\t\t\t? this.keySerializer(nodeKey)\n\t\t\t: (nodeKey as string);\n\t}\n\n\taddDownstreamNode(node: DownstreamNode<T, NodeKey>) {\n\t\tconst nodeKeyStr = this.getNodeKeyStr(node.self);\n\n\t\t// If a previous node prestubbed in the next node, we add it here\n\t\tif (this.map.has(nodeKeyStr)) {\n\t\t\tconst preStubbedNode = this.map.get(nodeKeyStr)!;\n\t\t\tif (preStubbedNode.value !== undefined) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Already added a downstream node of same key: ${nodeKeyStr} - Can't add ${JSON.stringify(node)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tpreStubbedNode.to.push(...node.to);\n\t\t\tpreStubbedNode.value = node.value;\n\t\t} else {\n\t\t\tthis.map.set(nodeKeyStr, {\n\t\t\t\tfrom: [],\n\t\t\t\t...node,\n\t\t\t});\n\t\t\tthis.noFrom.add(nodeKeyStr);\n\t\t}\n\n\t\t// Add to or pre-stub some nodes\n\t\tnode.to.forEach((n) => {\n\t\t\tconst nkStr = this.getNodeKeyStr(n);\n\t\t\tif (this.map.has(nkStr)) {\n\t\t\t\tconst existingNode = this.map.get(nkStr)!;\n\t\t\t\texistingNode.from.push(node.self);\n\t\t\t\tif (existingNode.from.length === 1) {\n\t\t\t\t\t// We were wrong about this package\n\t\t\t\t\tthis.noFrom.delete(nkStr);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.map.set(nkStr, {\n\t\t\t\t\tself: n,\n\t\t\t\t\tfrom: [node.self],\n\t\t\t\t\tto: [],\n\t\t\t\t\tvalue: undefined,\n\t\t\t\t} as Node<T | undefined, NodeKey>);\n\t\t\t}\n\t\t});\n\t}\n\n\tvalidate() {\n\t\tconst errors = [];\n\t\tfor (let [k, node] of this.map.entries()) {\n\t\t\tif (!node.value) {\n\t\t\t\terrors.push(\n\t\t\t\t\t`Unregistered node: ${k}! Node was pointed to by: ${JSON.stringify(node.from)}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (errors.length > 0) {\n\t\t\tthrow new Error(errors.join(\"\\n\"));\n\t\t}\n\t}\n\n\t/**\n\t *\n\t * @param visit\n\t * @param firstArrivalOnly - if set to true, we are saying that we do not care about from where we get to the node, just the first arrival matters\n\t * This will depend on your visit function, since the visit function can pass parent -> child info that may change based on the node\n\t * it is coming from\n\t */\n\tasync topDownVisitAsync<R>(\n\t\tvisit: VisitFunction<Node<T, NodeKey>, R>,\n\t\tfirstArrivalOnly?: boolean,\n\t) {\n\t\tconst guestBook = firstArrivalOnly ? new Set<string>() : undefined;\n\t\tfor (const noFrom of this.noFrom) {\n\t\t\tconst node = this.map.get(noFrom)!;\n\t\t\tawait this.visitDownNodeAsync(node as Node<T, NodeKey>, visit, guestBook);\n\t\t}\n\t}\n\n\t/**\n\t *\n\t * @param nodeKey - the key that we used to retrieve this node\n\t * @param node - the node itself\n\t * @param visit - the visit function\n\t * @param guestBook - This is used to track if we have already visited the node - note this means we don't expect the visit function to change results\n\t * regardless of the node that we come from\n\t * @param prevResult - the result of the last node that got here\n\t * @returns\n\t */\n\tasync visitDownNodeAsync<R>(\n\t\tnode: Node<T, NodeKey>,\n\t\tvisit: VisitFunction<Node<T, NodeKey>, R>,\n\t\tguestBook?: Set<string>,\n\t\tprevResult?: R,\n\t) {\n\t\tif (guestBook?.has(this.getNodeKeyStr(node.self))) {\n\t\t\t// We already visited this node\n\t\t\treturn;\n\t\t}\n\t\tconst [result, stop] = await visit(node, prevResult);\n\t\tif (stop) {\n\t\t\t// We let the visitor control travel\n\t\t\treturn;\n\t\t}\n\t\tawait Promise.all(\n\t\t\tnode.to.map((n) => {\n\t\t\t\treturn this.visitDownNodeAsync(\n\t\t\t\t\tthis.map.get(this.getNodeKeyStr(n))! as Node<T, NodeKey>,\n\t\t\t\t\tvisit,\n\t\t\t\t\tguestBook,\n\t\t\t\t\tresult,\n\t\t\t\t);\n\t\t\t}),\n\t\t);\n\t}\n}\n\ntype StopVisiting = boolean;\n\n/**\n * This function will be called for each visit while traversing along the \"to\" nodes. You can return\n * a result from the visit function that will be provided to any of the \"to\" visitors as the previous result.\n *\n * Additionally, if you return a boolean value in the second tuple, it can stop any further downstream visits from this\n * particular visitor function. (Keep in mind that a visitor can only stop further travel from itself, so if there are\n * multiple visits from multiple nodes each visitor will need to stop further travel. If you do use a guestbook, in a\n * visiting function, that would stop travel fromm the visitor function that first calls stop.)\n */\ntype VisitFunction<Node, R> = (\n\tcurrentNode: Node,\n\tpreviousResult?: R,\n) => Promise<[R, StopVisiting]>;\n"],"names":["Graph","getNodeKeyStr","nodeKey","keySerializer","addDownstreamNode","node","nodeKeyStr","self","map","has","preStubbedNode","get","value","undefined","Error","JSON","stringify","to","push","set","from","noFrom","add","forEach","n","nkStr","existingNode","length","delete","validate","errors","k","entries","join","topDownVisitAsync","visit","firstArrivalOnly","guestBook","Set","visitDownNodeAsync","prevResult","result","stop","Promise","all","constructor","Map"],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "PackageGraph", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return PackageGraph;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
function _path() {
|
|
12
|
+
const data = require("path");
|
|
13
|
+
_path = function() {
|
|
14
|
+
return data;
|
|
15
|
+
};
|
|
16
|
+
return data;
|
|
17
|
+
}
|
|
18
|
+
const _Graph = require("./Graph");
|
|
19
|
+
function _define_property(obj, key, value) {
|
|
20
|
+
if (key in obj) {
|
|
21
|
+
Object.defineProperty(obj, key, {
|
|
22
|
+
value: value,
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
writable: true
|
|
26
|
+
});
|
|
27
|
+
} else {
|
|
28
|
+
obj[key] = value;
|
|
29
|
+
}
|
|
30
|
+
return obj;
|
|
31
|
+
}
|
|
32
|
+
let PackageGraph = class PackageGraph extends _Graph.Graph {
|
|
33
|
+
constructor(pkgDir){
|
|
34
|
+
super((node)=>`${node.name}@${node.version}`), _define_property(this, "pkgDir", void 0);
|
|
35
|
+
if (!pkgDir) {
|
|
36
|
+
throw new Error("Must supply a pkgDir!");
|
|
37
|
+
}
|
|
38
|
+
this.pkgDir = (0, _path().resolve)(pkgDir);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=PackageGraph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/packageGraphs/PackageGraph.ts"],"sourcesContent":["import { resolve } from \"path\";\nimport { Graph } from \"./Graph\";\n\nexport interface PackageInfo {\n\tname: string;\n\tversion: string;\n\t// We need this because some patches will register as dependencies but won't be able to resolve things\n\tisPatch: boolean;\n\t// We need this because some trees will contain the base package which won't self-resolve\n\tisRoot: boolean;\n}\n\nexport interface PackageInfoKey {\n\tname: string;\n\tversion: string;\n}\n\n/**\n * A graph of package names and their dependencies\n */\nexport class PackageGraph extends Graph<PackageInfo, PackageInfoKey> {\n\treadonly pkgDir: string;\n\tconstructor(pkgDir: string) {\n\t\tsuper((node: PackageInfoKey) => `${node.name}@${node.version}`);\n\n\t\tif (!pkgDir) {\n\t\t\tthrow new Error(\"Must supply a pkgDir!\");\n\t\t}\n\t\tthis.pkgDir = resolve(pkgDir);\n\t}\n}\n"],"names":["PackageGraph","Graph","constructor","pkgDir","node","name","version","Error","resolve"],"mappings":";;;;+BAoBaA;;;eAAAA;;;;yBApBW;;;;;;uBACF;;;;;;;;;;;;;;AAmBf,IAAA,AAAMA,eAAN,MAAMA,qBAAqBC,YAAK;IAEtCC,YAAYC,MAAc,CAAE;QAC3B,KAAK,CAAC,CAACC,OAAyB,GAAGA,KAAKC,IAAI,CAAC,CAAC,EAAED,KAAKE,OAAO,EAAE,GAF/D,uBAASH,UAAT,KAAA;QAIC,IAAI,CAACA,QAAQ;YACZ,MAAM,IAAII,MAAM;QACjB;QACA,IAAI,CAACJ,MAAM,GAAGK,IAAAA,eAAO,EAACL;IACvB;AACD"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "getYarnInfoPackageGraph", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return getYarnInfoPackageGraph;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
function _child_process() {
|
|
12
|
+
const data = require("child_process");
|
|
13
|
+
_child_process = function() {
|
|
14
|
+
return data;
|
|
15
|
+
};
|
|
16
|
+
return data;
|
|
17
|
+
}
|
|
18
|
+
const _PackageGraph = require("./PackageGraph");
|
|
19
|
+
function _fs() {
|
|
20
|
+
const data = require("fs");
|
|
21
|
+
_fs = function() {
|
|
22
|
+
return data;
|
|
23
|
+
};
|
|
24
|
+
return data;
|
|
25
|
+
}
|
|
26
|
+
function _path() {
|
|
27
|
+
const data = require("path");
|
|
28
|
+
_path = function() {
|
|
29
|
+
return data;
|
|
30
|
+
};
|
|
31
|
+
return data;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Gets the first package.json that can be found
|
|
35
|
+
*/ function getRootPackageJson(start, curDir) {
|
|
36
|
+
const dir = curDir ?? start;
|
|
37
|
+
const testPath = (0, _path().join)(dir, "package.json");
|
|
38
|
+
if ((0, _fs().existsSync)(testPath)) {
|
|
39
|
+
return testPath;
|
|
40
|
+
}
|
|
41
|
+
const oneUp = (0, _path().dirname)(dir);
|
|
42
|
+
if (!oneUp) {
|
|
43
|
+
throw new Error(`Could not find package.json traveling up from start dir at ${start}`);
|
|
44
|
+
}
|
|
45
|
+
return getRootPackageJson(start, oneUp);
|
|
46
|
+
}
|
|
47
|
+
async function getYarnInfoPackageGraph(pkgDir, recurse) {
|
|
48
|
+
const query = (0, _child_process().execSync)(`yarn info ${recurse ? "-R" : ""} --json`, {
|
|
49
|
+
cwd: pkgDir,
|
|
50
|
+
stdio: "pipe"
|
|
51
|
+
});
|
|
52
|
+
// Get the current package name so we can determine the root
|
|
53
|
+
const rootPkgJsonPath = getRootPackageJson(pkgDir);
|
|
54
|
+
let rootPkgName = "";
|
|
55
|
+
try {
|
|
56
|
+
rootPkgName = JSON.parse((0, _fs().readFileSync)(rootPkgJsonPath).toString()).name;
|
|
57
|
+
} catch (e) {
|
|
58
|
+
console.error("Error retrieving root package name!");
|
|
59
|
+
throw e;
|
|
60
|
+
}
|
|
61
|
+
const packageGraph = new _PackageGraph.PackageGraph(pkgDir);
|
|
62
|
+
// Since the info shows multiple versions we keep a dedup set of the serialized key to avoid longer times
|
|
63
|
+
const dedupSet = new Set();
|
|
64
|
+
return query.toString().split("\n").reduce((pkgGraph, q)=>{
|
|
65
|
+
// Make sure we have an actual value
|
|
66
|
+
if (q.trim()) {
|
|
67
|
+
const pkgInfo = JSON.parse(q);
|
|
68
|
+
const { name, version, isPatch } = parsePackage(pkgInfo.value);
|
|
69
|
+
const nameKey = packageGraph.keySerializer({
|
|
70
|
+
name,
|
|
71
|
+
version
|
|
72
|
+
});
|
|
73
|
+
if (!dedupSet.has(nameKey)) {
|
|
74
|
+
dedupSet.add(nameKey);
|
|
75
|
+
// List of package names as dependencies
|
|
76
|
+
let deps;
|
|
77
|
+
if (recurse) {
|
|
78
|
+
deps = pkgInfo.children?.Dependencies?.map((deps)=>{
|
|
79
|
+
const info = parsePackage(deps.locator);
|
|
80
|
+
return {
|
|
81
|
+
name: info.name,
|
|
82
|
+
version: info.version
|
|
83
|
+
};
|
|
84
|
+
}) ?? [];
|
|
85
|
+
} else {
|
|
86
|
+
// We don't actually set up the dependencies because that would make the graph incomplete
|
|
87
|
+
deps = [];
|
|
88
|
+
}
|
|
89
|
+
packageGraph.addDownstreamNode({
|
|
90
|
+
self: {
|
|
91
|
+
name,
|
|
92
|
+
version
|
|
93
|
+
},
|
|
94
|
+
value: {
|
|
95
|
+
name,
|
|
96
|
+
version,
|
|
97
|
+
isPatch,
|
|
98
|
+
isRoot: name === rootPkgName
|
|
99
|
+
},
|
|
100
|
+
to: deps ?? []
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return pkgGraph;
|
|
105
|
+
}, packageGraph);
|
|
106
|
+
}
|
|
107
|
+
function parsePackage(pkgAndVersion) {
|
|
108
|
+
const versionIdx = pkgAndVersion.indexOf("@", 1);
|
|
109
|
+
if (versionIdx < 0) {
|
|
110
|
+
throw new Error(`could not find version from name: ${pkgAndVersion}`);
|
|
111
|
+
}
|
|
112
|
+
let version = pkgAndVersion.substring(versionIdx + 1);
|
|
113
|
+
// Parse out virtual versions since those are just file directors used by yarn
|
|
114
|
+
if (version.startsWith("virtual:")) {
|
|
115
|
+
const hashIdx = version.lastIndexOf("#");
|
|
116
|
+
if (hashIdx < 1) {
|
|
117
|
+
throw new Error(`could not find the expected # for virtual locator information`);
|
|
118
|
+
}
|
|
119
|
+
version = version.substring(hashIdx + 1);
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
name: pkgAndVersion.substring(0, versionIdx),
|
|
123
|
+
version,
|
|
124
|
+
isPatch: version.includes("patch")
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
//# sourceMappingURL=getYarnInfoPackageGraph.js.map
|