New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@yarnpkg/pnpify

Package Overview
Dependencies
Maintainers
5
Versions
142
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@yarnpkg/pnpify - npm Package Compare versions

Comparing version 2.0.0-rc.12 to 2.0.0-rc.13

4

lib/boot-cli-dev.js

@@ -0,1 +1,3 @@

"use strict";
process.env.NODE_OPTIONS += ` --require ${require.resolve(`@yarnpkg/monorepo/scripts/setup-ts-execution`)}`;

@@ -5,2 +7,2 @@

require(`./cli`);
require(`./cli`);

@@ -0,1 +1,3 @@

"use strict";
process.env.NODE_OPTIONS += ` --require ${require.resolve(`@yarnpkg/monorepo/scripts/setup-ts-execution`)}`;

@@ -5,2 +7,2 @@

module.exports = require(`./index`);
module.exports = require(`./index`);
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fslib_1 = require("@yarnpkg/fslib");
const hoist_1 = require("./hoist");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.buildNodeModulesTree = exports.LinkType = void 0;
var _fslib = require("@yarnpkg/fslib");
var _hoist = require("./hoist");
// Babel doesn't support const enums, thats why we use non-const enum for LinkType in @yarnpkg/pnp
// But because of this TypeScript requires @yarnpkg/pnp during runtime
// To prevent this we redeclare LinkType enum here, to not depend on @yarnpkg/pnp during runtime
var LinkType;
let LinkType;
exports.LinkType = LinkType;
(function (LinkType) {
LinkType["HARD"] = "HARD";
LinkType["SOFT"] = "SOFT";
})(LinkType = exports.LinkType || (exports.LinkType = {}));
LinkType["HARD"] = "HARD";
LinkType["SOFT"] = "SOFT";
})(LinkType || (exports.LinkType = LinkType = {}));
;
/**
* Node modules tree - a map of every folder within the node_modules, along with their
* directory listing and whether they are a symlink and their location.
*
* Sample contents:
* /home/user/project/node_modules -> {dirList: ['foo', 'bar']}
* /home/user/project/node_modules/foo -> {target: '/home/user/project/.yarn/.cache/foo.zip/node_modules/foo', linkType: 'HARD'}
* /home/user/project/node_modules/bar -> {target: '/home/user/project/packages/bar', linkType: 'SOFT'}
*/
/** node_modules path segment */
const NODE_MODULES = fslib_1.toFilename(`node_modules`);
const NODE_MODULES = (0, _fslib.toFilename)(`node_modules`);
/** Package locator key for usage inside maps */
/**

@@ -23,5 +45,3 @@ * Returns path to archive, if package location is inside the archive.

*/
const getArchivePath = (packagePath) => packagePath.indexOf(`.zip/${NODE_MODULES}/`) >= 0 ?
fslib_1.npath.toPortablePath(packagePath.split(`/${NODE_MODULES}/`)[0]) :
null;
const getArchivePath = packagePath => packagePath.indexOf(`.zip/${NODE_MODULES}/`) >= 0 ? _fslib.npath.toPortablePath(packagePath.split(`/${NODE_MODULES}/`)[0]) : null;
/**

@@ -35,9 +55,11 @@ * Determines package's weight relative to other packages for hoisting purposes.

*/
const getPackageWeight = (packagePath, { optimizeSizeOnDisk }) => {
if (!optimizeSizeOnDisk)
return 1;
const archivePath = getArchivePath(packagePath);
if (archivePath === null)
return 1;
return fslib_1.xfs.statSync(archivePath).size;
const getPackageWeight = (packagePath, {
optimizeSizeOnDisk
}) => {
if (!optimizeSizeOnDisk) return 1;
const archivePath = getArchivePath(packagePath);
if (archivePath === null) return 1;
return _fslib.xfs.statSync(archivePath).size;
};

@@ -52,6 +74,12 @@ /**

*/
exports.buildNodeModulesTree = (pnp, options) => {
const { packageTree, packages, locators } = buildPackageTree(pnp, options);
const hoistedTree = hoist_1.hoist(packageTree, packages);
return populateNodeModulesTree(pnp, hoistedTree, locators, options);
const buildNodeModulesTree = (pnp, options) => {
const {
packageTree,
packages,
locators
} = buildPackageTree(pnp, options);
const hoistedTree = (0, _hoist.hoist)(packageTree, packages);
return populateNodeModulesTree(pnp, hoistedTree, locators, options);
};

@@ -65,63 +93,87 @@ /**

*/
exports.buildNodeModulesTree = buildNodeModulesTree;
const buildPackageTree = (pnp, options) => {
const packageTree = [];
const packages = [];
const locators = [];
const locatorToPackageMap = new Map();
const packageInfos = [];
const pnpRoots = pnp.getDependencyTreeRoots();
let lastPkgId = 0;
const getLocatorKey = (locator) => `${locator.name}:${locator.reference}`;
const assignPackageId = (locator, pkg) => {
const locatorKey = getLocatorKey(locator);
const pkgId = locatorToPackageMap.get(locatorKey);
if (typeof pkgId !== 'undefined')
return pkgId;
const newPkgId = lastPkgId++;
const packagePath = fslib_1.npath.toPortablePath(pkg.packageLocation);
const weight = getPackageWeight(packagePath, options);
locatorToPackageMap.set(locatorKey, newPkgId);
locators.push(locator);
packages.push({ name: locator.name, weight });
packageInfos.push(pkg);
return newPkgId;
const packageTree = [];
const packages = [];
const locators = [];
const locatorToPackageMap = new Map();
const packageInfos = [];
const pnpRoots = pnp.getDependencyTreeRoots();
let lastPkgId = 0;
const getLocatorKey = locator => `${locator.name}:${locator.reference}`;
const assignPackageId = (locator, pkg) => {
const locatorKey = getLocatorKey(locator);
const pkgId = locatorToPackageMap.get(locatorKey);
if (typeof pkgId !== 'undefined') return pkgId;
const newPkgId = lastPkgId++;
const packagePath = _fslib.npath.toPortablePath(pkg.packageLocation);
const weight = getPackageWeight(packagePath, options);
locatorToPackageMap.set(locatorKey, newPkgId);
locators.push(locator);
packages.push({
name: locator.name,
weight
});
packageInfos.push(pkg);
return newPkgId;
};
const addedIds = new Set();
const addPackageToTree = (pkg, pkgId, parentDepIds) => {
if (addedIds.has(pkgId)) return;
addedIds.add(pkgId);
const deps = new Set();
const peerDeps = new Set();
packageTree[pkgId] = {
deps,
peerDeps
};
const addedIds = new Set();
const addPackageToTree = (pkg, pkgId, parentDepIds) => {
if (addedIds.has(pkgId))
return;
addedIds.add(pkgId);
const deps = new Set();
const peerDeps = new Set();
packageTree[pkgId] = { deps, peerDeps };
for (const [name, referencish] of pkg.packageDependencies) {
if (referencish !== null) {
const locator = pnp.getLocator(name, referencish);
const depPkg = pnp.getPackageInformation(locator);
const depPkgId = assignPackageId(locator, depPkg);
if (pkg.packagePeers.has(name)) {
peerDeps.add(depPkgId);
}
else {
deps.add(depPkgId);
}
}
for (const [name, referencish] of pkg.packageDependencies) {
if (referencish !== null) {
const locator = pnp.getLocator(name, referencish);
const depPkg = pnp.getPackageInformation(locator);
const depPkgId = assignPackageId(locator, depPkg);
if (pkg.packagePeers.has(name)) {
peerDeps.add(depPkgId);
} else {
deps.add(depPkgId);
}
const allDepIds = new Set([...deps, ...peerDeps]);
for (const depId of allDepIds) {
const depPkg = packageInfos[depId];
addPackageToTree(depPkg, depId, allDepIds);
}
};
const pkg = pnp.getPackageInformation(pnp.topLevel);
const topLocator = pnp.findPackageLocator(pkg.packageLocation);
const topLocatorKey = getLocatorKey(topLocator);
for (const locator of pnpRoots) {
if (getLocatorKey(locator) !== topLocatorKey) {
pkg.packageDependencies.set(locator.name, locator.reference);
}
}
}
const pkgId = assignPackageId(topLocator, pkg);
addPackageToTree(pkg, pkgId, new Set());
return { packageTree, packages, locators };
const allDepIds = new Set([...deps, ...peerDeps]);
for (const depId of allDepIds) {
const depPkg = packageInfos[depId];
addPackageToTree(depPkg, depId, allDepIds);
}
};
const pkg = pnp.getPackageInformation(pnp.topLevel);
const topLocator = pnp.findPackageLocator(pkg.packageLocation);
const topLocatorKey = getLocatorKey(topLocator);
for (const locator of pnpRoots) {
if (getLocatorKey(locator) !== topLocatorKey) {
pkg.packageDependencies.set(locator.name, locator.reference);
}
}
const pkgId = assignPackageId(topLocator, pkg);
addPackageToTree(pkg, pkgId, new Set());
return {
packageTree,
packages,
locators
};
};

@@ -137,63 +189,93 @@ /**

*/
const populateNodeModulesTree = (pnp, hoistedTree, locators, options) => {
const tree = new Map();
const makeLeafNode = (locator) => {
const info = pnp.getPackageInformation(locator);
if (options.pnpifyFs) {
return { target: fslib_1.npath.toPortablePath(info.packageLocation), linkType: LinkType.SOFT };
}
else {
const truePath = pnp.resolveVirtual && locator.reference && locator.reference.startsWith('virtual:') ? pnp.resolveVirtual(info.packageLocation) : info.packageLocation;
return { target: fslib_1.npath.toPortablePath(truePath || info.packageLocation), linkType: info.linkType };
}
const tree = new Map();
const makeLeafNode = locator => {
const info = pnp.getPackageInformation(locator);
if (options.pnpifyFs) {
return {
target: _fslib.npath.toPortablePath(info.packageLocation),
linkType: LinkType.SOFT
};
} else {
const truePath = pnp.resolveVirtual && locator.reference && locator.reference.startsWith('virtual:') ? pnp.resolveVirtual(info.packageLocation) : info.packageLocation;
return {
target: _fslib.npath.toPortablePath(truePath || info.packageLocation),
linkType: info.linkType
};
}
};
const getPackageName = locator => {
const [nameOrScope, name] = locator.name.split('/');
return name ? {
scope: (0, _fslib.toFilename)(nameOrScope),
name: (0, _fslib.toFilename)(name)
} : {
scope: null,
name: (0, _fslib.toFilename)(nameOrScope)
};
const getPackageName = (locator) => {
const [nameOrScope, name] = locator.name.split('/');
return name ? { scope: fslib_1.toFilename(nameOrScope), name: fslib_1.toFilename(name) } : { scope: null, name: fslib_1.toFilename(nameOrScope) };
};
const seenPkgIds = new Set();
const buildTree = (nodeId, locationPrefix) => {
if (seenPkgIds.has(nodeId))
return;
seenPkgIds.add(nodeId);
for (const depId of hoistedTree[nodeId]) {
const locator = locators[depId];
const { name, scope } = getPackageName(locator);
const packageNameParts = scope ? [scope, name] : [name];
const nodeModulesDirPath = fslib_1.ppath.join(locationPrefix, NODE_MODULES);
const nodeModulesLocation = fslib_1.ppath.join(nodeModulesDirPath, ...packageNameParts);
const leafNode = makeLeafNode(locator);
tree.set(nodeModulesLocation, leafNode);
const segments = nodeModulesLocation.split('/');
const nodeModulesIdx = segments.indexOf(NODE_MODULES);
let segCount = segments.length - 1;
while (nodeModulesIdx >= 0 && segCount > nodeModulesIdx) {
const dirPath = fslib_1.npath.toPortablePath(segments.slice(0, segCount).join(fslib_1.ppath.sep));
const targetDir = fslib_1.toFilename(segments[segCount]);
const subdirs = tree.get(dirPath);
if (!subdirs) {
tree.set(dirPath, { dirList: new Set([targetDir]) });
}
else if (subdirs.dirList) {
if (subdirs.dirList.has(targetDir)) {
break;
}
else {
subdirs.dirList.add(targetDir);
}
}
segCount--;
}
// In case of pnpifyFs we represent modules as symlinks to archives in NodeModulesFS
// `/home/user/project/foo` is a symlink to `/home/user/project/.yarn/.cache/foo.zip/node_modules/foo`
// To make this fs layout work with legacy tools we make
// `/home/user/project/.yarn/.cache/foo.zip/node_modules/foo/node_modules` (which normally does not exist inside archive) a symlink to:
// `/home/user/project/node_modules/foo/node_modules`, so that the tools were able to access it
buildTree(depId, options.pnpifyFs ? leafNode.target : nodeModulesLocation);
};
const seenPkgIds = new Set();
const buildTree = (nodeId, locationPrefix) => {
if (seenPkgIds.has(nodeId)) return;
seenPkgIds.add(nodeId);
for (const depId of hoistedTree[nodeId]) {
const locator = locators[depId];
const {
name,
scope
} = getPackageName(locator);
const packageNameParts = scope ? [scope, name] : [name];
const nodeModulesDirPath = _fslib.ppath.join(locationPrefix, NODE_MODULES);
const nodeModulesLocation = _fslib.ppath.join(nodeModulesDirPath, ...packageNameParts);
const leafNode = makeLeafNode(locator);
tree.set(nodeModulesLocation, leafNode);
const segments = nodeModulesLocation.split('/');
const nodeModulesIdx = segments.indexOf(NODE_MODULES);
let segCount = segments.length - 1;
while (nodeModulesIdx >= 0 && segCount > nodeModulesIdx) {
const dirPath = _fslib.npath.toPortablePath(segments.slice(0, segCount).join(_fslib.ppath.sep));
const targetDir = (0, _fslib.toFilename)(segments[segCount]);
const subdirs = tree.get(dirPath);
if (!subdirs) {
tree.set(dirPath, {
dirList: new Set([targetDir])
});
} else if (subdirs.dirList) {
if (subdirs.dirList.has(targetDir)) {
break;
} else {
subdirs.dirList.add(targetDir);
}
}
};
const rootNode = makeLeafNode(locators[0]);
const rootPath = rootNode.target && rootNode.target;
buildTree(0, rootPath);
return tree;
segCount--;
} // In case of pnpifyFs we represent modules as symlinks to archives in NodeModulesFS
// `/home/user/project/foo` is a symlink to `/home/user/project/.yarn/.cache/foo.zip/node_modules/foo`
// To make this fs layout work with legacy tools we make
// `/home/user/project/.yarn/.cache/foo.zip/node_modules/foo/node_modules` (which normally does not exist inside archive) a symlink to:
// `/home/user/project/node_modules/foo/node_modules`, so that the tools were able to access it
buildTree(depId, options.pnpifyFs ? leafNode.target : nodeModulesLocation);
}
};
const rootNode = makeLeafNode(locators[0]);
const rootPath = rootNode.target && rootNode.target;
buildTree(0, rootPath);
return tree;
};

@@ -211,9 +293,12 @@ /**

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const benchmarkRawHoisting = (packageTree, packages) => {
const iterCount = 100;
const startTime = Date.now();
for (let iter = 0; iter < iterCount; iter++)
hoist_1.hoist(packageTree, packages);
const endTime = Date.now();
return (endTime - startTime) / iterCount;
const iterCount = 100;
const startTime = Date.now();
for (let iter = 0; iter < iterCount; iter++) (0, _hoist.hoist)(packageTree, packages);
const endTime = Date.now();
return (endTime - startTime) / iterCount;
};

@@ -231,12 +316,20 @@ /**

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const benchmarkBuildTree = (pnp, options) => {
const iterCount = 100;
const startTime = Date.now();
for (let iter = 0; iter < iterCount; iter++) {
const { packageTree, packages, locators } = buildPackageTree(pnp, options);
const hoistedTree = hoist_1.hoist(packageTree, packages);
populateNodeModulesTree(pnp, hoistedTree, locators, options);
}
const endTime = Date.now();
return (endTime - startTime) / iterCount;
const iterCount = 100;
const startTime = Date.now();
for (let iter = 0; iter < iterCount; iter++) {
const {
packageTree,
packages,
locators
} = buildPackageTree(pnp, options);
const hoistedTree = (0, _hoist.hoist)(packageTree, packages);
populateNodeModulesTree(pnp, hoistedTree, locators, options);
}
const endTime = Date.now();
return (endTime - startTime) / iterCount;
};

@@ -254,38 +347,52 @@ /**

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const dumpNodeModulesTree = (tree, rootPath) => {
const sortedTree = new Map();
const keys = Array.from(tree.keys()).sort();
for (const key of keys) {
const val = tree.get(key);
sortedTree.set(key, val.dirList ? { dirList: new Set(Array.from(val.dirList).sort()) } : val);
const sortedTree = new Map();
const keys = Array.from(tree.keys()).sort();
for (const key of keys) {
const val = tree.get(key);
sortedTree.set(key, val.dirList ? {
dirList: new Set(Array.from(val.dirList).sort())
} : val);
}
const seenPaths = new Set();
const dumpTree = (nodePath, prefix = '', dirPrefix = '') => {
const node = sortedTree.get(nodePath);
if (!node) return '';
seenPaths.add(nodePath);
let str = '';
if (node.dirList) {
const dirs = Array.from(node.dirList);
for (let idx = 0; idx < dirs.length; idx++) {
const dir = dirs[idx];
str += `${prefix}${idx < dirs.length - 1 ? '├─' : '└─'}${dirPrefix}${dir}\n`;
str += dumpTree(_fslib.ppath.join(nodePath, dir), `${prefix}${idx < dirs.length - 1 ? '│ ' : ' '}`);
}
} else {
const {
target,
linkType
} = node;
str += dumpTree(_fslib.ppath.join(nodePath, NODE_MODULES), `${prefix}│ `, `${NODE_MODULES}/`);
str += `${prefix}└─${linkType === LinkType.SOFT ? 's>' : '>'}${target}\n`;
}
const seenPaths = new Set();
const dumpTree = (nodePath, prefix = '', dirPrefix = '') => {
const node = sortedTree.get(nodePath);
if (!node)
return '';
seenPaths.add(nodePath);
let str = '';
if (node.dirList) {
const dirs = Array.from(node.dirList);
for (let idx = 0; idx < dirs.length; idx++) {
const dir = dirs[idx];
str += `${prefix}${idx < dirs.length - 1 ? '├─' : '└─'}${dirPrefix}${dir}\n`;
str += dumpTree(fslib_1.ppath.join(nodePath, dir), `${prefix}${idx < dirs.length - 1 ? '│ ' : ' '}`);
}
}
else {
const { target, linkType } = node;
str += dumpTree(fslib_1.ppath.join(nodePath, NODE_MODULES), `${prefix}│ `, `${NODE_MODULES}/`);
str += `${prefix}└─${linkType === LinkType.SOFT ? 's>' : '>'}${target}\n`;
}
return str;
};
let str = dumpTree(fslib_1.ppath.join(rootPath, NODE_MODULES));
for (const key of sortedTree.keys()) {
if (!seenPaths.has(key)) {
str += `${key.replace(rootPath, '')}\n${dumpTree(key)}`;
}
return str;
};
let str = dumpTree(_fslib.ppath.join(rootPath, NODE_MODULES));
for (const key of sortedTree.keys()) {
if (!seenPaths.has(key)) {
str += `${key.replace(rootPath, '')}\n${dumpTree(key)}`;
}
return str;
}
return str;
};

@@ -302,44 +409,50 @@ /**

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const dumpDepTree = (tree, locators, nodeId = 0, prefix = '', seenIds = new Set()) => {
if (seenIds.has(nodeId))
return '';
seenIds.add(nodeId);
const dumpLocator = (locator) => {
if (locator.reference === 'workspace:.') {
return '.';
}
else if (!locator.reference) {
return `${locator.name}@${locator.reference}`;
}
else {
const version = (locator.reference.indexOf('#') > 0 ? locator.reference.split('#')[1] : locator.reference).replace('npm:', '');
if (locator.reference.startsWith('virtual')) {
return `v:${locator.name}@${version}`;
}
else {
return `${locator.name}@${version}`;
}
}
};
const deps = Array.from((tree[nodeId].deps || tree[nodeId]));
const traverseIds = new Set();
for (const depId of deps) {
if (!seenIds.has(depId)) {
traverseIds.add(depId);
seenIds.add(depId);
}
if (seenIds.has(nodeId)) return '';
seenIds.add(nodeId);
const dumpLocator = locator => {
if (locator.reference === 'workspace:.') {
return '.';
} else if (!locator.reference) {
return `${locator.name}@${locator.reference}`;
} else {
const version = (locator.reference.indexOf('#') > 0 ? locator.reference.split('#')[1] : locator.reference).replace('npm:', '');
if (locator.reference.startsWith('virtual')) {
return `v:${locator.name}@${version}`;
} else {
return `${locator.name}@${version}`;
}
}
let str = '';
for (let idx = 0; idx < deps.length; idx++) {
const depId = deps[idx];
str += `${prefix}${idx < deps.length - 1 ? '├─' : '└─'}${(traverseIds.has(depId) ? '>' : '') + dumpLocator(locators[depId])}\n`;
if (traverseIds.has(depId)) {
seenIds.delete(depId);
str += dumpDepTree(tree, locators, depId, `${prefix}${idx < deps.length - 1 ? '│ ' : ' '}`, seenIds);
seenIds.add(depId);
}
};
const deps = Array.from(tree[nodeId].deps || tree[nodeId]);
const traverseIds = new Set();
for (const depId of deps) {
if (!seenIds.has(depId)) {
traverseIds.add(depId);
seenIds.add(depId);
}
for (const depId of traverseIds)
seenIds.delete(depId);
return str;
};
}
let str = '';
for (let idx = 0; idx < deps.length; idx++) {
const depId = deps[idx];
str += `${prefix}${idx < deps.length - 1 ? '├─' : '└─'}${(traverseIds.has(depId) ? '>' : '') + dumpLocator(locators[depId])}\n`;
if (traverseIds.has(depId)) {
seenIds.delete(depId);
str += dumpDepTree(tree, locators, depId, `${prefix}${idx < deps.length - 1 ? '│ ' : ' '}`, seenIds);
seenIds.add(depId);
}
}
for (const depId of traverseIds) seenIds.delete(depId);
return str;
};
#!/usr/bin/env node
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fslib_1 = require("@yarnpkg/fslib");
const cross_spawn_1 = __importDefault(require("cross-spawn"));
const dynamicRequire_1 = require("./dynamicRequire");
const generateSdk_1 = require("./generateSdk");
const [, , name, ...rest] = process.argv;
if (name === `--help` || name === `-h`)
help(false);
else if (name === `--sdk` && rest.length === 0)
sdk();
else if (typeof name !== `undefined` && name[0] !== `-`)
run(name, rest);
else
help(true);
var _fslib = require("@yarnpkg/fslib");
var _crossSpawn = _interopRequireDefault(require("cross-spawn"));
var _dynamicRequire = require("./dynamicRequire");
var _generateSdk = require("./generateSdk");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const [,, name, ...rest] = process.argv;
if (name === `--help` || name === `-h`) help(false);else if (name === `--sdk` && rest.length === 0) sdk();else if (typeof name !== `undefined` && name[0] !== `-`) run(name, rest);else help(true);
function help(error) {
const logFn = error ? console.error : console.log;
process.exitCode = error ? 1 : 0;
logFn(`Usage: yarn pnpify --sdk`);
logFn(`Usage: yarn pnpify <program> [...argv]`);
logFn();
logFn(`Setups a TypeScript sdk for use within your VSCode editor instance`);
logFn(`More info at https://next.yarnpkg.com/advanced/pnpify`);
const logFn = error ? console.error : console.log;
process.exitCode = error ? 1 : 0;
logFn(`Usage: yarn pnpify --sdk`);
logFn(`Usage: yarn pnpify <program> [...argv]`);
logFn();
logFn(`Setups a TypeScript sdk for use within your VSCode editor instance`);
logFn(`More info at https://next.yarnpkg.com/advanced/pnpify`);
}
function sdk() {
const { getPackageInformation, topLevel } = dynamicRequire_1.dynamicRequire(`pnpapi`);
const { packageLocation } = getPackageInformation(topLevel);
const projectRoot = fslib_1.npath.toPortablePath(packageLocation);
generateSdk_1.generateSdk(projectRoot).catch(error => {
console.error(error.stack);
process.exitCode = 1;
});
const {
getPackageInformation,
topLevel
} = (0, _dynamicRequire.dynamicRequire)(`pnpapi`);
const {
packageLocation
} = getPackageInformation(topLevel);
const projectRoot = _fslib.npath.toPortablePath(packageLocation);
(0, _generateSdk.generateSdk)(projectRoot).catch(error => {
console.error(error.stack);
process.exitCode = 1;
});
}
function run(name, argv) {
let { NODE_OPTIONS } = process.env;
NODE_OPTIONS = `${NODE_OPTIONS || ``} --require ${dynamicRequire_1.dynamicRequire.resolve(`@yarnpkg/pnpify`)}`.trim();
const child = cross_spawn_1.default(name, argv, {
env: Object.assign(Object.assign({}, process.env), { NODE_OPTIONS }),
stdio: `inherit`,
});
child.on(`exit`, code => {
process.exitCode = code !== null ? code : 1;
});
}
let {
NODE_OPTIONS
} = process.env;
NODE_OPTIONS = `${NODE_OPTIONS || ``} --require ${_dynamicRequire.dynamicRequire.resolve(`@yarnpkg/pnpify`)}`.trim();
const child = (0, _crossSpawn.default)(name, argv, {
env: { ...process.env,
NODE_OPTIONS
},
stdio: `inherit`
});
child.on(`exit`, code => {
process.exitCode = code !== null ? code : 1;
});
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const dynamicRequire = typeof __non_webpack_require__ !== `undefined`
? __non_webpack_require__
: require;
exports.dynamicRequire = dynamicRequire;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.dynamicRequire = void 0;
const dynamicRequire = typeof __non_webpack_require__ !== `undefined` ? __non_webpack_require__ : require;
exports.dynamicRequire = dynamicRequire;
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fslib_1 = require("@yarnpkg/fslib");
const comment_json_1 = __importDefault(require("comment-json"));
const dynamicRequire_1 = require("./dynamicRequire");
const TEMPLATE = (relPnpApiPath, module, { usePnpify }) => [
`const relPnpApiPath = ${JSON.stringify(fslib_1.npath.toPortablePath(relPnpApiPath))};\n`,
`const absPnpApiPath = require(\`path\`).resolve(__dirname, relPnpApiPath);\n`,
`\n`,
`// Setup the environment to be able to require ${module}\n`,
`require(absPnpApiPath).setup();\n`,
`\n`,
`// Prepare the environment (to be ready in case of child_process.spawn etc)\n`,
`process.env.NODE_OPTIONS = process.env.NODE_OPTIONS || \`\`;\n`,
`process.env.NODE_OPTIONS += \` -r \${absPnpApiPath}\`;\n`,
...(usePnpify ? [
`process.env.NODE_OPTIONS += \` -r \${require.resolve(\`@yarnpkg/pnpify\`)}\`;\n`,
`\n`,
`// Apply PnPify to the current process\n`,
`require(\`@yarnpkg/pnpify\`).patchFs();\n`,
] : []),
`\n`,
`// Defer to the real ${module} your application uses\n`,
`module.exports = require(\`${module}\`);\n`,
].join(``);
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.generateSdk = exports.generateEslintWrapper = void 0;
var _fslib = require("@yarnpkg/fslib");
var _commentJson = _interopRequireDefault(require("comment-json"));
var _dynamicRequire = require("./dynamicRequire");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const TEMPLATE = (relPnpApiPath, module, {
usePnpify
}) => [`const {dirname, resolve} = require(\`path\`);\n`, `\n`, `const relPnpApiPath = ${JSON.stringify(_fslib.npath.toPortablePath(relPnpApiPath))};\n`, `\n`, `const absPnpApiPath = resolve(__dirname, relPnpApiPath);\n`, `const absRootPath = dirname(absPnpApiPath);\n`, `\n`, `// Setup the environment to be able to require ${module}\n`, `require(absPnpApiPath).setup();\n`, `\n`, ...(usePnpify ? [`const pnpifyResolution = require.resolve(\`@yarnpkg/pnpify\`, {paths: [absRootPath]});\n`] : []), `const moduleResolution = require.resolve(\`${module}\`, {paths: [absRootPath]});\n`, `\n`, `// Prepare the environment (to be ready in case of child_process.spawn etc)\n`, `process.env.NODE_OPTIONS = process.env.NODE_OPTIONS || \`\`;\n`, `process.env.NODE_OPTIONS += \` -r \${absPnpApiPath}\`;\n`, ...(usePnpify ? [`process.env.NODE_OPTIONS += \` -r \${pnpifyResolution}\`;\n`, `\n`, `// Apply PnPify to the current process\n`, `require(pnpifyResolution).patchFs();\n`] : []), `\n`, `// Defer to the real ${module} your application uses\n`, `module.exports = require(moduleResolution);\n`].join(``);
const addVSCodeWorkspaceSettings = async (projectRoot, settings) => {
const settingsPath = fslib_1.ppath.join(projectRoot, `.vscode/settings.json`);
const content = await fslib_1.xfs.existsPromise(settingsPath) ? await fslib_1.xfs.readFilePromise(settingsPath, `utf8`) : `{}`;
const data = comment_json_1.default.parse(content);
const patched = `${comment_json_1.default.stringify(Object.assign(Object.assign({}, data), settings), null, 2)}\n`;
await fslib_1.xfs.mkdirpPromise(fslib_1.ppath.dirname(settingsPath));
await fslib_1.xfs.changeFilePromise(settingsPath, patched);
const settingsPath = _fslib.ppath.join(projectRoot, `.vscode/settings.json`);
const content = (await _fslib.xfs.existsPromise(settingsPath)) ? await _fslib.xfs.readFilePromise(settingsPath, `utf8`) : `{}`;
const data = _commentJson.default.parse(content);
const patched = `${_commentJson.default.stringify({ ...data,
...settings
}, null, 2)}\n`;
await _fslib.xfs.mkdirpPromise(_fslib.ppath.dirname(settingsPath));
await _fslib.xfs.changeFilePromise(settingsPath, patched);
};
const generateTypescriptWrapper = async (projectRoot, target) => {
const typescript = fslib_1.ppath.join(target, `typescript`);
const manifest = fslib_1.ppath.join(typescript, `package.json`);
const tsserver = fslib_1.ppath.join(typescript, `lib/tsserver.js`);
const relPnpApiPath = fslib_1.ppath.relative(fslib_1.ppath.dirname(tsserver), fslib_1.ppath.join(projectRoot, `.pnp.js`));
await fslib_1.xfs.mkdirpPromise(fslib_1.ppath.dirname(tsserver));
await fslib_1.xfs.writeFilePromise(manifest, JSON.stringify({ name: 'typescript', version: `${dynamicRequire_1.dynamicRequire('typescript/package.json').version}-pnpify` }, null, 2));
await fslib_1.xfs.writeFilePromise(tsserver, TEMPLATE(relPnpApiPath, "typescript/lib/tsserver", { usePnpify: true }));
await addVSCodeWorkspaceSettings(projectRoot, { 'typescript.tsdk': fslib_1.npath.fromPortablePath(fslib_1.ppath.relative(projectRoot, fslib_1.ppath.dirname(tsserver))) });
const typescript = _fslib.ppath.join(target, `typescript`);
const manifest = _fslib.ppath.join(typescript, `package.json`);
const tsserver = _fslib.ppath.join(typescript, `lib/tsserver.js`);
const relPnpApiPath = _fslib.ppath.relative(_fslib.ppath.dirname(tsserver), _fslib.ppath.join(projectRoot, `.pnp.js`));
await _fslib.xfs.mkdirpPromise(_fslib.ppath.dirname(tsserver));
await _fslib.xfs.writeFilePromise(manifest, JSON.stringify({
name: 'typescript',
version: `${(0, _dynamicRequire.dynamicRequire)('typescript/package.json').version}-pnpify`
}, null, 2));
await _fslib.xfs.writeFilePromise(tsserver, TEMPLATE(relPnpApiPath, "typescript/lib/tsserver", {
usePnpify: true
}));
await addVSCodeWorkspaceSettings(projectRoot, {
'typescript.tsdk': _fslib.npath.fromPortablePath(_fslib.ppath.relative(projectRoot, _fslib.ppath.dirname(tsserver)))
});
};
exports.generateEslintWrapper = async (projectRoot, target) => {
const eslint = fslib_1.ppath.join(target, `eslint`);
const manifest = fslib_1.ppath.join(eslint, `package.json`);
const api = fslib_1.ppath.join(eslint, `lib/api.js`);
const relPnpApiPath = fslib_1.ppath.relative(fslib_1.ppath.dirname(api), fslib_1.ppath.join(projectRoot, `.pnp.js`));
await fslib_1.xfs.mkdirpPromise(fslib_1.ppath.dirname(api));
await fslib_1.xfs.writeFilePromise(manifest, JSON.stringify({ name: 'eslint', version: `${dynamicRequire_1.dynamicRequire('eslint/package.json').version}-pnpify`, main: 'lib/api.js' }, null, 2));
await fslib_1.xfs.writeFilePromise(api, TEMPLATE(relPnpApiPath, "eslint", { usePnpify: false }));
await addVSCodeWorkspaceSettings(projectRoot, { 'eslint.nodePath': fslib_1.npath.fromPortablePath(fslib_1.ppath.relative(projectRoot, fslib_1.ppath.dirname(eslint))) });
const generateEslintWrapper = async (projectRoot, target) => {
const eslint = _fslib.ppath.join(target, `eslint`);
const manifest = _fslib.ppath.join(eslint, `package.json`);
const api = _fslib.ppath.join(eslint, `lib/api.js`);
const relPnpApiPath = _fslib.ppath.relative(_fslib.ppath.dirname(api), _fslib.ppath.join(projectRoot, `.pnp.js`));
await _fslib.xfs.mkdirpPromise(_fslib.ppath.dirname(api));
await _fslib.xfs.writeFilePromise(manifest, JSON.stringify({
name: 'eslint',
version: `${(0, _dynamicRequire.dynamicRequire)('eslint/package.json').version}-pnpify`,
main: 'lib/api.js'
}, null, 2));
await _fslib.xfs.writeFilePromise(api, TEMPLATE(relPnpApiPath, "eslint", {
usePnpify: false
}));
await addVSCodeWorkspaceSettings(projectRoot, {
'eslint.nodePath': _fslib.npath.fromPortablePath(_fslib.ppath.relative(projectRoot, _fslib.ppath.dirname(eslint)))
});
};
const isPackageInstalled = (name) => {
try {
dynamicRequire_1.dynamicRequire.resolve(name);
return true;
exports.generateEslintWrapper = generateEslintWrapper;
const isPackageInstalled = name => {
try {
_dynamicRequire.dynamicRequire.resolve(name);
return true;
} catch (e) {
if (e.code && e.code === 'MODULE_NOT_FOUND') {
return false;
} else {
throw e;
}
catch (e) {
if (e.code && e.code === 'MODULE_NOT_FOUND') {
return false;
}
else {
throw e;
}
}
}
};
exports.generateSdk = async (projectRoot) => {
const hasTypescript = isPackageInstalled('typescript');
const hasEslint = isPackageInstalled('eslint');
const targetFolder = fslib_1.ppath.join(projectRoot, `.vscode/pnpify`);
if (!hasTypescript && !hasEslint)
console.warn(`Neither 'typescript' nor 'eslint' are installed. Nothing to do.`);
else
await fslib_1.xfs.removePromise(targetFolder);
if (hasTypescript)
await generateTypescriptWrapper(projectRoot, targetFolder);
if (hasEslint) {
await exports.generateEslintWrapper(projectRoot, targetFolder);
}
const generateSdk = async projectRoot => {
const hasTypescript = isPackageInstalled('typescript');
const hasEslint = isPackageInstalled('eslint');
const targetFolder = _fslib.ppath.join(projectRoot, `.vscode/pnpify`);
if (!hasTypescript && !hasEslint) console.warn(`Neither 'typescript' nor 'eslint' are installed. Nothing to do.`);else await _fslib.xfs.removePromise(targetFolder);
if (hasTypescript) await generateTypescriptWrapper(projectRoot, targetFolder);
if (hasEslint) {
await generateEslintWrapper(projectRoot, targetFolder);
}
};
exports.generateSdk = generateSdk;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.hoist = void 0;
/**
* Package id - a number that uniquiely identifies both package and its dependencies.
* There must be package with id 0 - which contains all the other packages.
*/
/**
* Package name - a string that denotes the fact that two packages with the same name
* cannot be dependencies of the same parent package. The package with the same name
* can have multiple package ids associated with the packages, either because of the
* different package versions, or because of the different dependency sets,
* as in peer dependent package.
*/
/**
* Package weight - a number that somehow signifies which package is heavier and should have
* a priority to be hoisted. The packages having the biggest weight with all their transitive
* dependencies are hoisted first.
*/
/**
* Package tree - is simply an array, with index being package id and the value - the dependencies
* of that package. Package tree can contain cycles.
*
* Hoisted package tree has the same type, but values should be treated as not necesseraly
* dependencies, but rather hoisted packages.
*/
/**
* Initial information about the package.
*/
/**
* The results of weighting each package with its transitive dependencies in some subtree.
*/
/**
* Mapping which packages depend on a given package. It is used to determine hoisting weight,
* e.g. which one among the group of packages with the same name should be hoisted.
* The package having the biggest self-weight (including all transitive dependencies) multiplied
* by the number of ancestors using this package will be hoisted.
*/
/**
* Hoists package tree, by applying hoisting algorithm to each tree node independently.

@@ -20,19 +67,30 @@ * We first try to hoist all the packages from anywhere in the whole tree to the root package.

*/
exports.hoist = (tree, packageInfos, nohoist = new Set()) => {
// Make tree copy, which will be mutated by hoisting algorithm
const treeCopy = tree.map(({ deps, peerDeps }) => ({ deps: new Set(deps), peerDeps: new Set(peerDeps), origDeps: new Set(deps), origPeerDeps: new Set(peerDeps) }));
const seenIds = new Set();
const hoistSubTree = (nodeId, ancestorMap) => {
if (seenIds.has(nodeId))
return;
seenIds.add(nodeId);
// Apply mutating hoisting algorithm on each tree node starting from the root
hoistInplace(treeCopy, nodeId, packageInfos, ancestorMap, nohoist);
for (const depId of treeCopy[nodeId].deps) {
hoistSubTree(depId, ancestorMap);
}
};
if (treeCopy.length > 0 && treeCopy[0].deps.size > 0)
hoistSubTree(0, buildAncestorMap(tree));
return treeCopy.map(({ deps }) => deps);
const hoist = (tree, packageInfos, nohoist = new Set()) => {
// Make tree copy, which will be mutated by hoisting algorithm
const treeCopy = tree.map(({
deps,
peerDeps
}) => ({
deps: new Set(deps),
peerDeps: new Set(peerDeps),
origDeps: new Set(deps),
origPeerDeps: new Set(peerDeps)
}));
const seenIds = new Set();
const hoistSubTree = (nodeId, ancestorMap) => {
if (seenIds.has(nodeId)) return;
seenIds.add(nodeId); // Apply mutating hoisting algorithm on each tree node starting from the root
hoistInplace(treeCopy, nodeId, packageInfos, ancestorMap, nohoist);
for (const depId of treeCopy[nodeId].deps) {
hoistSubTree(depId, ancestorMap);
}
};
if (treeCopy.length > 0 && treeCopy[0].deps.size > 0) hoistSubTree(0, buildAncestorMap(tree));
return treeCopy.map(({
deps
}) => deps);
};

@@ -47,20 +105,23 @@ /**

*/
const buildAncestorMap = (tree) => {
const ancestorMap = [];
const seenIds = new Set();
const addAncestor = (nodeId) => {
if (seenIds.has(nodeId))
return;
seenIds.add(nodeId);
for (const depId of tree[nodeId].deps) {
const ancestors = ancestorMap[depId];
if (!ancestors)
ancestorMap[depId] = new Set([nodeId]);
else
ancestors.add(nodeId);
addAncestor(depId);
}
};
addAncestor(0);
return ancestorMap;
exports.hoist = hoist;
const buildAncestorMap = tree => {
const ancestorMap = [];
const seenIds = new Set();
const addAncestor = nodeId => {
if (seenIds.has(nodeId)) return;
seenIds.add(nodeId);
for (const depId of tree[nodeId].deps) {
const ancestors = ancestorMap[depId];
if (!ancestors) ancestorMap[depId] = new Set([nodeId]);else ancestors.add(nodeId);
addAncestor(depId);
}
};
addAncestor(0);
return ancestorMap;
};

@@ -77,31 +138,35 @@ /**

*/
const hoistInplace = (tree, rootId, packages, ancestorMap, nohoist) => {
// Get the list of package ids that can and should be hoisted to the subtree root
const hoistedDepIds = computeHoistCandidates(tree, rootId, packages, ancestorMap, nohoist);
const seenIds = new Set();
const removeHoistedDeps = (nodeId) => {
if (seenIds.has(nodeId))
return;
seenIds.add(nodeId);
// No need to traverse past nohoist node
if (nohoist.has(nodeId))
return;
const depIds = tree[nodeId].deps;
for (const depId of depIds) {
// First traverse to deeper levels
removeHoistedDeps(depId);
// Then remove hoisted deps from current node
if (hoistedDepIds.has(depId)) {
depIds.delete(depId);
// Remove hoisted dependency from the ancestor map
ancestorMap[depId].delete(nodeId);
}
}
};
removeHoistedDeps(rootId);
const nodeDepIds = tree[rootId].deps;
for (const depId of hoistedDepIds) {
// Add hoisted packages to the subtree root
nodeDepIds.add(depId);
// Get the list of package ids that can and should be hoisted to the subtree root
const hoistedDepIds = computeHoistCandidates(tree, rootId, packages, ancestorMap, nohoist);
const seenIds = new Set();
const removeHoistedDeps = nodeId => {
if (seenIds.has(nodeId)) return;
seenIds.add(nodeId); // No need to traverse past nohoist node
if (nohoist.has(nodeId)) return;
const depIds = tree[nodeId].deps;
for (const depId of depIds) {
// First traverse to deeper levels
removeHoistedDeps(depId); // Then remove hoisted deps from current node
if (hoistedDepIds.has(depId)) {
depIds.delete(depId); // Remove hoisted dependency from the ancestor map
ancestorMap[depId].delete(nodeId);
}
}
};
removeHoistedDeps(rootId);
const nodeDepIds = tree[rootId].deps;
for (const depId of hoistedDepIds) {
// Add hoisted packages to the subtree root
nodeDepIds.add(depId);
}
};

@@ -120,25 +185,32 @@ /**

*/
const weighPackages = (weighCanidates, tree, packages, ancestorMap, nohoist) => {
const nodeWeights = new Map();
const weighNode = (nodeId) => {
const storedWeight = nodeWeights.get(nodeId);
if (typeof storedWeight !== 'undefined')
return storedWeight;
let totalWeigth = 0;
// First add the zero entry to the weights map, so that we know we have "seen" this node
nodeWeights.set(nodeId, totalWeigth);
if (!nohoist.has(nodeId)) {
totalWeigth = packages[nodeId].weight;
for (const depId of tree[nodeId].deps)
totalWeigth += weighNode(depId);
nodeWeights.set(nodeId, totalWeigth);
}
return totalWeigth;
};
const weights = new Map();
for (const nodeId of weighCanidates)
// Total weight for hoisting purposes is a weight of the package with all transitive dependencies
// multipled by the number of package ancestors, which use the package
weights.set(nodeId, weighNode(nodeId) * ancestorMap[nodeId].size);
return weights;
const nodeWeights = new Map();
const weighNode = nodeId => {
const storedWeight = nodeWeights.get(nodeId);
if (typeof storedWeight !== 'undefined') return storedWeight;
let totalWeigth = 0; // First add the zero entry to the weights map, so that we know we have "seen" this node
nodeWeights.set(nodeId, totalWeigth);
if (!nohoist.has(nodeId)) {
totalWeigth = packages[nodeId].weight;
for (const depId of tree[nodeId].deps) totalWeigth += weighNode(depId);
nodeWeights.set(nodeId, totalWeigth);
}
return totalWeigth;
};
const weights = new Map();
for (const nodeId of weighCanidates) // Total weight for hoisting purposes is a weight of the package with all transitive dependencies
// multipled by the number of package ancestors, which use the package
weights.set(nodeId, weighNode(nodeId) * ancestorMap[nodeId].size);
return weights;
};

@@ -153,20 +225,30 @@ /**

*/
const getHeaviestPackages = (weights, packages) => {
const heaviestPackages = new Map();
for (const [pkgId, weight] of weights) {
const pkgName = packages[pkgId].name;
let heaviestPkg = heaviestPackages.get(pkgName);
if (!heaviestPkg) {
heaviestPkg = { weight, pkgId };
heaviestPackages.set(pkgName, heaviestPkg);
}
else if (weight > heaviestPkg.weight) {
heaviestPkg.weight = weight;
heaviestPkg.pkgId = pkgId;
}
const heaviestPackages = new Map();
for (const [pkgId, weight] of weights) {
const pkgName = packages[pkgId].name;
let heaviestPkg = heaviestPackages.get(pkgName);
if (!heaviestPkg) {
heaviestPkg = {
weight,
pkgId
};
heaviestPackages.set(pkgName, heaviestPkg);
} else if (weight > heaviestPkg.weight) {
heaviestPkg.weight = weight;
heaviestPkg.pkgId = pkgId;
}
const heavyPackageIds = new Set();
for (const { pkgId } of heaviestPackages.values())
heavyPackageIds.add(pkgId);
return heavyPackageIds;
}
const heavyPackageIds = new Set();
for (const {
pkgId
} of heaviestPackages.values()) heavyPackageIds.add(pkgId);
return heavyPackageIds;
};

@@ -199,102 +281,106 @@ /**

*/
const computeHoistCandidates = (tree, rootId, packages, ancestorMap, nohoist) => {
// Packages that should be hoisted for sure (they have only 1 version)
const packagesToHoist = new Set();
// Names of the packages of hoist candidates
const packagesToHoistNames = new Map();
// Hoist candidates that has no peer deps or that has all peer deps already hoisted
const pureHoistCandidates = new Set();
// Hoist candidates with peer deps
const hoistCandidatesWithPeerDeps = new Set();
const seenDepNames = new Map();
for (const depId of tree[rootId].origDeps)
seenDepNames.set(packages[depId].name, depId);
for (const depId of tree[rootId].origPeerDeps)
seenDepNames.set(packages[depId].name, depId);
const seenIds = new Set();
const findHoistCandidates = (nodeId) => {
if (seenIds.has(nodeId))
return;
seenIds.add(nodeId);
const name = packages[nodeId].name;
const seenPkgId = seenDepNames.get(name);
const pkg = tree[nodeId];
// Check rule 1
if (!tree[rootId].origPeerDeps.has(nodeId) && (!seenPkgId || seenPkgId === nodeId)) {
if (pkg.peerDeps.size > 0) {
hoistCandidatesWithPeerDeps.add(nodeId);
}
else {
const pkgId = packagesToHoistNames.get(name);
if (pkgId) {
packagesToHoist.delete(pkgId);
pureHoistCandidates.add(pkgId);
pureHoistCandidates.add(nodeId);
}
else {
packagesToHoist.add(nodeId);
packagesToHoistNames.set(name, nodeId);
}
}
// Packages that should be hoisted for sure (they have only 1 version)
const packagesToHoist = new Set(); // Names of the packages of hoist candidates
const packagesToHoistNames = new Map(); // Hoist candidates that has no peer deps or that has all peer deps already hoisted
const pureHoistCandidates = new Set(); // Hoist candidates with peer deps
const hoistCandidatesWithPeerDeps = new Set();
const seenDepNames = new Map();
for (const depId of tree[rootId].origDeps) seenDepNames.set(packages[depId].name, depId);
for (const depId of tree[rootId].origPeerDeps) seenDepNames.set(packages[depId].name, depId);
const seenIds = new Set();
const findHoistCandidates = nodeId => {
if (seenIds.has(nodeId)) return;
seenIds.add(nodeId);
const name = packages[nodeId].name;
const seenPkgId = seenDepNames.get(name);
const pkg = tree[nodeId]; // Check rule 1
if (!tree[rootId].origPeerDeps.has(nodeId) && (!seenPkgId || seenPkgId === nodeId)) {
if (pkg.peerDeps.size > 0) {
hoistCandidatesWithPeerDeps.add(nodeId);
} else {
const pkgId = packagesToHoistNames.get(name);
if (pkgId) {
packagesToHoist.delete(pkgId);
pureHoistCandidates.add(pkgId);
pureHoistCandidates.add(nodeId);
} else {
packagesToHoist.add(nodeId);
packagesToHoistNames.set(name, nodeId);
}
if (!seenPkgId)
seenDepNames.set(name, nodeId);
for (const depId of pkg.deps)
findHoistCandidates(depId);
if (!seenPkgId) {
seenDepNames.delete(name);
}
}
if (!seenPkgId) seenDepNames.set(name, nodeId);
for (const depId of pkg.deps) findHoistCandidates(depId);
if (!seenPkgId) {
seenDepNames.delete(name);
}
}; // Find packages names that are candidates for hoisting
for (const depId of tree[rootId].deps) findHoistCandidates(depId);
const pureHoistCandidatesWeights = weighPackages(pureHoistCandidates, tree, packages, ancestorMap, nohoist); // Among all pure hoist candidates choose the heaviest and add them to packages to hoist list
getHeaviestPackages(pureHoistCandidatesWeights, packages).forEach(pkgId => {
packagesToHoistNames.set(packages[pkgId].name, pkgId);
packagesToHoist.add(pkgId);
});
let newHoistCandidates = packagesToHoist; // Loop until new hoist candidates appear
while (newHoistCandidates.size > 0) {
let nextHoistCandidates = new Set();
for (const peerDepCandId of hoistCandidatesWithPeerDeps) {
// Peer dependencies that are going to be hoisted to the top, or were hoisted above the top
const nonHoistedPeerDeps = tree[peerDepCandId].peerDeps;
/* eslint-disable arca/curly */
if (nonHoistedPeerDeps.size < newHoistCandidates.size) {
for (const peerDepId of nonHoistedPeerDeps) if (newHoistCandidates.has(peerDepId)) // Remove all the packages that are going to be hoisted from current peer deps
nonHoistedPeerDeps.delete(peerDepId);
} else {
for (const candidateId of newHoistCandidates) if (nonHoistedPeerDeps.has(candidateId)) // Remove all the packages that are going to be hoisted from current peer deps
nonHoistedPeerDeps.delete(candidateId);
}
/* eslint-enable arca/curly */
if (nonHoistedPeerDeps.size === 0) {
// Check that we don't already have the package with the same name but different version
// among hoist candidates
const name = packages[peerDepCandId].name;
const hoistedPkgId = packagesToHoistNames.get(name); // Recheck rule 1 for the peer dependent package that is going to be hoisted
if (!hoistedPkgId || hoistedPkgId === peerDepCandId) {
// Peer dependent package can be hoisted if all of its peer deps are going to be hoisted
nextHoistCandidates.add(peerDepCandId);
packagesToHoist.add(peerDepCandId);
packagesToHoistNames.set(name, peerDepCandId);
hoistCandidatesWithPeerDeps.delete(peerDepCandId);
} else {
// We cannot hoist this package without breaking rule 1, stop trying
hoistCandidatesWithPeerDeps.delete(peerDepCandId);
}
};
// Find packages names that are candidates for hoisting
for (const depId of tree[rootId].deps)
findHoistCandidates(depId);
const pureHoistCandidatesWeights = weighPackages(pureHoistCandidates, tree, packages, ancestorMap, nohoist);
// Among all pure hoist candidates choose the heaviest and add them to packages to hoist list
getHeaviestPackages(pureHoistCandidatesWeights, packages).forEach(pkgId => {
packagesToHoistNames.set(packages[pkgId].name, pkgId);
packagesToHoist.add(pkgId);
});
let newHoistCandidates = packagesToHoist;
// Loop until new hoist candidates appear
while (newHoistCandidates.size > 0) {
let nextHoistCandidates = new Set();
for (const peerDepCandId of hoistCandidatesWithPeerDeps) {
// Peer dependencies that are going to be hoisted to the top, or were hoisted above the top
const nonHoistedPeerDeps = tree[peerDepCandId].peerDeps;
/* eslint-disable arca/curly */
if (nonHoistedPeerDeps.size < newHoistCandidates.size) {
for (const peerDepId of nonHoistedPeerDeps)
if (newHoistCandidates.has(peerDepId))
// Remove all the packages that are going to be hoisted from current peer deps
nonHoistedPeerDeps.delete(peerDepId);
}
else {
for (const candidateId of newHoistCandidates)
if (nonHoistedPeerDeps.has(candidateId))
// Remove all the packages that are going to be hoisted from current peer deps
nonHoistedPeerDeps.delete(candidateId);
}
/* eslint-enable arca/curly */
if (nonHoistedPeerDeps.size === 0) {
// Check that we don't already have the package with the same name but different version
// among hoist candidates
const name = packages[peerDepCandId].name;
const hoistedPkgId = packagesToHoistNames.get(name);
// Recheck rule 1 for the peer dependent package that is going to be hoisted
if (!hoistedPkgId || hoistedPkgId === peerDepCandId) {
// Peer dependent package can be hoisted if all of its peer deps are going to be hoisted
nextHoistCandidates.add(peerDepCandId);
packagesToHoist.add(peerDepCandId);
packagesToHoistNames.set(name, peerDepCandId);
hoistCandidatesWithPeerDeps.delete(peerDepCandId);
}
else {
// We cannot hoist this package without breaking rule 1, stop trying
hoistCandidatesWithPeerDeps.delete(peerDepCandId);
}
}
}
newHoistCandidates = nextHoistCandidates;
}
}
return packagesToHoist;
};
newHoistCandidates = nextHoistCandidates;
}
return packagesToHoist;
};
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fslib_1 = require("@yarnpkg/fslib");
const fs_1 = __importDefault(require("fs"));
const NodeModulesFS_1 = require("./NodeModulesFS");
exports.NodeModulesFS = NodeModulesFS_1.NodeModulesFS;
exports.PortableNodeModulesFs = NodeModulesFS_1.PortableNodeModulesFs;
const dynamicRequire_1 = require("./dynamicRequire");
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "NodeModulesFS", {
enumerable: true,
get: function () {
return _NodeModulesFS.NodeModulesFS;
}
});
Object.defineProperty(exports, "PortableNodeModulesFs", {
enumerable: true,
get: function () {
return _NodeModulesFS.PortableNodeModulesFs;
}
});
exports.patchFs = void 0;
var _fslib = require("@yarnpkg/fslib");
var _fs = _interopRequireDefault(require("fs"));
var _NodeModulesFS = require("./NodeModulesFS");
var _dynamicRequire = require("./dynamicRequire");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
let fsPatched = false;
let pnp;
try {
pnp = dynamicRequire_1.dynamicRequire('pnpapi');
}
catch (e) {
}
exports.patchFs = () => {
if (pnp && !fsPatched) {
const realFs = Object.assign({}, fs_1.default);
const nodeModulesFS = new NodeModulesFS_1.NodeModulesFS(pnp, { realFs });
fslib_1.patchFs(fs_1.default, nodeModulesFS);
fsPatched = true;
}
pnp = (0, _dynamicRequire.dynamicRequire)('pnpapi');
} catch (e) {}
const patchFs = () => {
if (pnp && !fsPatched) {
const realFs = { ..._fs.default
};
const nodeModulesFS = new _NodeModulesFS.NodeModulesFS(pnp, {
realFs
});
(0, _fslib.patchFs)(_fs.default, nodeModulesFS);
fsPatched = true;
}
};
if (!process.mainModule)
exports.patchFs();
exports.patchFs = patchFs;
if (!process.mainModule) patchFs();
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fslib_1 = require("@yarnpkg/fslib");
const fslib_2 = require("@yarnpkg/fslib");
const fslib_3 = require("@yarnpkg/fslib");
const fs_1 = __importDefault(require("fs"));
const WatchManager_1 = require("./WatchManager");
const buildNodeModulesTree_1 = require("./buildNodeModulesTree");
const resolveNodeModulesPath_1 = require("./resolveNodeModulesPath");
class NodeModulesFS extends fslib_3.ProxiedFS {
constructor(pnp, { realFs = fs_1.default, pnpifyFs = true } = {}) {
super(fslib_1.npath);
this.baseFs = new PortableNodeModulesFs(pnp, { baseFs: new fslib_3.NodeFS(realFs), pnpifyFs });
}
mapFromBase(path) {
return fslib_1.npath.fromPortablePath(path);
}
mapToBase(path) {
return fslib_1.npath.toPortablePath(path);
}
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.PortableNodeModulesFs = exports.NodeModulesFS = void 0;
var _fslib = require("@yarnpkg/fslib");
var _fs = _interopRequireDefault(require("fs"));
var _WatchManager = require("./WatchManager");
var _buildNodeModulesTree = require("./buildNodeModulesTree");
var _resolveNodeModulesPath = require("./resolveNodeModulesPath");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
class NodeModulesFS extends _fslib.ProxiedFS {
constructor(pnp, {
realFs = _fs.default,
pnpifyFs = true
} = {}) {
super(_fslib.npath);
this.baseFs = void 0;
this.baseFs = new PortableNodeModulesFs(pnp, {
baseFs: new _fslib.NodeFS(realFs),
pnpifyFs
});
}
mapFromBase(path) {
return _fslib.npath.fromPortablePath(path);
}
mapToBase(path) {
return _fslib.npath.toPortablePath(path);
}
}
exports.NodeModulesFS = NodeModulesFS;
;
class PortableNodeModulesFs extends fslib_3.FakeFS {
constructor(pnp, { baseFs = new fslib_3.NodeFS(), pnpifyFs = true, optimizeSizeOnDisk = false } = {}) {
super(fslib_1.ppath);
if (!pnp.getDependencyTreeRoots)
throw new Error('NodeModulesFS supports PnP API versions 3+, please upgrade your PnP API provider');
this.options = { baseFs, pnpifyFs, optimizeSizeOnDisk };
this.baseFs = baseFs;
this.nodeModulesTree = buildNodeModulesTree_1.buildNodeModulesTree(pnp, this.options);
this.watchManager = new WatchManager_1.WatchManager();
const pnpRootPath = fslib_1.npath.toPortablePath(pnp.getPackageInformation(pnp.topLevel).packageLocation);
this.watchPnpFile(pnpRootPath);
class PortableNodeModulesFs extends _fslib.FakeFS {
constructor(pnp, {
baseFs = new _fslib.NodeFS(),
pnpifyFs = true,
optimizeSizeOnDisk = false
} = {}) {
super(_fslib.ppath);
this.baseFs = void 0;
this.options = void 0;
this.watchManager = void 0;
this.nodeModulesTree = void 0;
if (!pnp.getDependencyTreeRoots) throw new Error('NodeModulesFS supports PnP API versions 3+, please upgrade your PnP API provider');
this.options = {
baseFs,
pnpifyFs,
optimizeSizeOnDisk
};
this.baseFs = baseFs;
this.nodeModulesTree = (0, _buildNodeModulesTree.buildNodeModulesTree)(pnp, this.options);
this.watchManager = new _WatchManager.WatchManager();
const pnpRootPath = _fslib.npath.toPortablePath(pnp.getPackageInformation(pnp.topLevel).packageLocation);
this.watchPnpFile(pnpRootPath);
}
watchPnpFile(pnpRootPath) {
const pnpFilePath = _fslib.ppath.join(pnpRootPath, (0, _fslib.toFilename)('.pnp.js'));
this.baseFs.watch(pnpRootPath, {
persistent: false
}, (_, filename) => {
if (filename === '.pnp.js') {
delete require.cache[pnpFilePath];
const pnp = require(pnpFilePath);
this.nodeModulesTree = (0, _buildNodeModulesTree.buildNodeModulesTree)(pnp, this.options);
this.watchManager.notifyWatchers(nodePath => (0, _resolveNodeModulesPath.resolveNodeModulesPath)(nodePath, this.nodeModulesTree));
}
});
}
persistPath(dir) {
const pathStack = [];
let curPath = dir;
while (!this.baseFs.existsSync(curPath)) {
pathStack.push(curPath);
curPath = _fslib.ppath.dirname(curPath);
}
watchPnpFile(pnpRootPath) {
const pnpFilePath = fslib_1.ppath.join(pnpRootPath, fslib_2.toFilename('.pnp.js'));
this.baseFs.watch(pnpRootPath, { persistent: false }, (_, filename) => {
if (filename === '.pnp.js') {
delete require.cache[pnpFilePath];
const pnp = require(pnpFilePath);
this.nodeModulesTree = buildNodeModulesTree_1.buildNodeModulesTree(pnp, this.options);
this.watchManager.notifyWatchers((nodePath) => resolveNodeModulesPath_1.resolveNodeModulesPath(nodePath, this.nodeModulesTree));
}
});
for (const fullPath of pathStack.reverse()) {
this.baseFs.mkdirSync(fullPath);
}
persistPath(dir) {
const pathStack = [];
let curPath = dir;
while (!this.baseFs.existsSync(curPath)) {
pathStack.push(curPath);
curPath = fslib_1.ppath.dirname(curPath);
}
for (const fullPath of pathStack.reverse()) {
this.baseFs.mkdirSync(fullPath);
}
}
resolve(path) {
return this.baseFs.resolve(this.resolvePath(path).resolvedPath);
}
getBaseFs() {
return this.baseFs;
}
resolvePath(p) {
if (typeof p === `number`) {
return {
resolvedPath: p,
fullOriginalPath: p
};
} else {
const fullOriginalPath = this.pathUtils.resolve(p);
return { ...(0, _resolveNodeModulesPath.resolveNodeModulesPath)(fullOriginalPath, this.nodeModulesTree),
fullOriginalPath
};
}
resolve(path) {
return this.baseFs.resolve(this.resolvePath(path).resolvedPath);
}
resolveFilePath(p) {
if (typeof p === `number`) return p;
let pnpPath = this.resolvePath(p);
return pnpPath.resolvedPath;
}
resolveDirOrFilePath(p) {
if (typeof p === `number`) return p;
let pnpPath = this.resolvePath(p);
return pnpPath.forwardedDirPath || pnpPath.resolvedPath;
}
resolveLink(p, op, onSymlink, onRealPath) {
const pnpPath = this.resolvePath(p);
if (pnpPath.isSymlink) {
let stat;
try {
stat = this.baseFs.lstatSync(pnpPath.resolvedPath);
} catch (e) {}
if (stat) {
return onSymlink(stat, this.pathUtils.relative(this.pathUtils.dirname(pnpPath.fullOriginalPath), pnpPath.resolvedPath));
}
}
getBaseFs() {
return this.baseFs;
return onRealPath(pnpPath.forwardedDirPath || pnpPath.resolvedPath);
}
static makeSymlinkStats(stats) {
return Object.assign(stats, {
isFile: () => false,
isDirectory: () => false,
isSymbolicLink: () => true
});
}
static createFsError(code, message) {
return Object.assign(new Error(`${code}: ${message}`), {
code
});
}
getRealPath() {
return this.baseFs.getRealPath();
}
async openPromise(p, flags, mode) {
return await this.baseFs.openPromise(this.resolveFilePath(p), flags, mode);
}
openSync(p, flags, mode) {
return this.baseFs.openSync(this.resolveFilePath(p), flags, mode);
}
async readPromise(fd, buffer, offset, length, position) {
return await this.baseFs.readPromise(fd, buffer, offset, length, position);
}
readSync(fd, buffer, offset, length, position) {
return this.baseFs.readSync(fd, buffer, offset, length, position);
}
async writePromise(fd, buffer, offset, length, position) {
if (typeof buffer === `string`) {
return await this.baseFs.writePromise(fd, buffer, offset);
} else {
return await this.baseFs.writePromise(fd, buffer, offset, length, position);
}
resolvePath(p) {
if (typeof p === `number`) {
return { resolvedPath: p, fullOriginalPath: p };
}
else {
const fullOriginalPath = this.pathUtils.resolve(p);
return Object.assign(Object.assign({}, resolveNodeModulesPath_1.resolveNodeModulesPath(fullOriginalPath, this.nodeModulesTree)), { fullOriginalPath });
}
}
writeSync(fd, buffer, offset, length, position) {
if (typeof buffer === `string`) {
return this.baseFs.writeSync(fd, buffer, offset);
} else {
return this.baseFs.writeSync(fd, buffer, offset, length, position);
}
resolveFilePath(p) {
if (typeof p === `number`)
return p;
let pnpPath = this.resolvePath(p);
return pnpPath.resolvedPath;
}
async closePromise(fd) {
await this.baseFs.closePromise(fd);
}
closeSync(fd) {
this.baseFs.closeSync(fd);
}
createReadStream(p, opts) {
return this.baseFs.createReadStream(p !== null ? this.resolveFilePath(p) : p, opts);
}
createWriteStream(p, opts) {
return this.baseFs.createWriteStream(p !== null ? this.resolveDirOrFilePath(p) : p, opts);
}
async realpathPromise(p) {
const pnpPath = this.resolvePath(p);
return pnpPath.dirList ? pnpPath.resolvedPath : this.baseFs.realpathPromise(pnpPath.resolvedPath);
}
realpathSync(p) {
const pnpPath = this.resolvePath(p);
return pnpPath.dirList ? pnpPath.resolvedPath : this.baseFs.realpathSync(pnpPath.resolvedPath);
}
async existsPromise(p) {
const pnpPath = this.resolvePath(p);
if (pnpPath.dirList) {
return true;
} else {
return await this.baseFs.existsPromise(pnpPath.resolvedPath);
}
resolveDirOrFilePath(p) {
if (typeof p === `number`)
return p;
let pnpPath = this.resolvePath(p);
return pnpPath.forwardedDirPath || pnpPath.resolvedPath;
}
existsSync(p) {
const pnpPath = this.resolvePath(p);
if (pnpPath.dirList) {
return true;
} else {
return this.baseFs.existsSync(pnpPath.resolvedPath);
}
resolveLink(p, op, onSymlink, onRealPath) {
const pnpPath = this.resolvePath(p);
if (pnpPath.isSymlink) {
let stat;
try {
stat = this.baseFs.lstatSync(pnpPath.resolvedPath);
}
catch (e) { }
if (stat) {
return onSymlink(stat, this.pathUtils.relative(this.pathUtils.dirname(pnpPath.fullOriginalPath), pnpPath.resolvedPath));
}
}
return onRealPath(pnpPath.forwardedDirPath || pnpPath.resolvedPath);
}
async accessPromise(p, mode) {
return await this.baseFs.accessPromise(this.resolveDirOrFilePath(p), mode);
}
accessSync(p, mode) {
return this.baseFs.accessSync(this.resolveDirOrFilePath(p), mode);
}
async statPromise(p) {
return await this.baseFs.statPromise(this.resolveDirOrFilePath(p));
}
statSync(p) {
return this.baseFs.statSync(this.resolveDirOrFilePath(p));
}
async lstatPromise(p) {
return this.resolveLink(p, 'lstat', stats => PortableNodeModulesFs.makeSymlinkStats(stats), async resolvedPath => await this.baseFs.lstatPromise(resolvedPath));
}
lstatSync(p) {
return this.resolveLink(p, 'lstat', stats => PortableNodeModulesFs.makeSymlinkStats(stats), resolvedPath => this.baseFs.lstatSync(this.resolveDirOrFilePath(resolvedPath)));
}
async chmodPromise(p, mask) {
return await this.baseFs.chmodPromise(this.resolveDirOrFilePath(p), mask);
}
chmodSync(p, mask) {
return this.baseFs.chmodSync(this.resolveDirOrFilePath(p), mask);
}
async renamePromise(oldP, newP) {
return await this.baseFs.renamePromise(this.resolveDirOrFilePath(oldP), this.resolveDirOrFilePath(newP));
}
renameSync(oldP, newP) {
return this.baseFs.renameSync(this.resolveDirOrFilePath(oldP), this.resolveDirOrFilePath(newP));
}
async copyFilePromise(sourceP, destP, flags) {
return await this.baseFs.copyFilePromise(this.resolveFilePath(sourceP), this.resolveDirOrFilePath(destP), flags);
}
copyFileSync(sourceP, destP, flags) {
return this.baseFs.copyFileSync(this.resolveFilePath(sourceP), this.resolveDirOrFilePath(destP), flags);
}
async appendFilePromise(p, content, opts) {
return await this.baseFs.appendFilePromise(this.resolveDirOrFilePath(p), content, opts);
}
appendFileSync(p, content, opts) {
return this.baseFs.appendFileSync(this.resolveDirOrFilePath(p), content, opts);
}
async writeFilePromise(p, content, opts) {
return await this.baseFs.writeFilePromise(this.resolveDirOrFilePath(p), content, opts);
}
writeFileSync(p, content, opts) {
return this.baseFs.writeFileSync(this.resolveDirOrFilePath(p), content, opts);
}
async unlinkPromise(p) {
return await this.baseFs.unlinkPromise(this.resolveDirOrFilePath(p));
}
unlinkSync(p) {
return this.baseFs.unlinkSync(this.resolveDirOrFilePath(p));
}
async utimesPromise(p, atime, mtime) {
return await this.baseFs.utimesPromise(this.resolveDirOrFilePath(p), atime, mtime);
}
utimesSync(p, atime, mtime) {
return this.baseFs.utimesSync(this.resolveDirOrFilePath(p), atime, mtime);
}
async mkdirPromise(p, opts) {
const pnpPath = this.resolvePath(p);
const parentPath = this.resolvePath(_fslib.ppath.dirname(p));
if (parentPath.dirList) this.persistPath(parentPath.resolvedPath);
return this.baseFs.mkdirPromise(pnpPath.resolvedPath, opts);
}
mkdirSync(p, opts) {
const pnpPath = this.resolvePath(p);
const parentPath = this.resolvePath(_fslib.ppath.dirname(p));
if (parentPath.dirList) this.persistPath(parentPath.resolvedPath);
return this.baseFs.mkdirSync(pnpPath.resolvedPath, opts);
}
async rmdirPromise(p) {
return await this.baseFs.rmdirPromise(this.resolveDirOrFilePath(p));
}
rmdirSync(p) {
return this.baseFs.rmdirSync(this.resolveDirOrFilePath(p));
}
async symlinkPromise(target, p) {
return await this.baseFs.symlinkPromise(this.resolveDirOrFilePath(target), this.resolveDirOrFilePath(p));
}
symlinkSync(target, p) {
return this.baseFs.symlinkSync(this.resolveDirOrFilePath(target), this.resolveDirOrFilePath(p));
}
async readFilePromise(p, encoding) {
// This weird switch is required to tell TypeScript that the signatures are proper (otherwise it thinks that only the generic one is covered)
switch (encoding) {
case `utf8`:
return await this.baseFs.readFilePromise(this.resolveFilePath(p), encoding);
default:
return await this.baseFs.readFilePromise(this.resolveFilePath(p), encoding);
}
static makeSymlinkStats(stats) {
return Object.assign(stats, {
isFile: () => false,
isDirectory: () => false,
isSymbolicLink: () => true,
}
readFileSync(p, encoding) {
// This weird switch is required to tell TypeScript that the signatures are proper (otherwise it thinks that only the generic one is covered)
switch (encoding) {
case `utf8`:
return this.baseFs.readFileSync(this.resolveFilePath(p), encoding);
default:
return this.baseFs.readFileSync(this.resolveFilePath(p), encoding);
}
}
async readdirPromise(p, {
withFileTypes
} = {}) {
const pnpPath = this.resolvePath(p);
if (pnpPath.dirList || this.resolvePath(_fslib.ppath.join(p, (0, _fslib.toFilename)('node_modules'))).dirList) {
let fsDirList = [];
try {
fsDirList = await this.baseFs.readdirPromise(pnpPath.resolvedPath);
} catch (e) {// Ignore errors
}
const entries = Array.from(pnpPath.dirList || [(0, _fslib.toFilename)('node_modules')]).concat(fsDirList).sort();
if (!withFileTypes) return entries;
return entries.map(name => {
return Object.assign(this.lstatSync(_fslib.ppath.join(p, name)), {
name
});
});
} else {
return await this.baseFs.readdirPromise(pnpPath.resolvedPath, {
withFileTypes: withFileTypes
});
}
static createFsError(code, message) {
return Object.assign(new Error(`${code}: ${message}`), { code });
}
readdirSync(p, {
withFileTypes
} = {}) {
const pnpPath = this.resolvePath(p);
if (pnpPath.dirList || this.resolvePath(_fslib.ppath.join(p, (0, _fslib.toFilename)('node_modules'))).dirList) {
let fsDirList = [];
try {
fsDirList = this.baseFs.readdirSync(pnpPath.resolvedPath);
} catch (e) {// Ignore errors
}
const entries = Array.from(pnpPath.dirList || [(0, _fslib.toFilename)('node_modules')]).concat(fsDirList).sort();
if (!withFileTypes) return entries;
return entries.map(name => {
return Object.assign(this.lstatSync(_fslib.ppath.join(p, name)), {
name
});
});
} else {
return this.baseFs.readdirSync(pnpPath.resolvedPath, {
withFileTypes: withFileTypes
});
}
getRealPath() {
return this.baseFs.getRealPath();
}
async readlinkPromise(p) {
return this.resolveLink(p, 'readlink', (_stats, targetPath) => targetPath, async targetPath => await this.baseFs.readlinkPromise(this.resolveDirOrFilePath(targetPath)));
}
readlinkSync(p) {
return this.resolveLink(p, 'readlink', (_stats, targetPath) => targetPath, targetPath => this.baseFs.readlinkSync(this.resolveDirOrFilePath(targetPath)));
}
watch(p, a, b) {
const pnpPath = this.resolvePath(p);
const watchPath = pnpPath.resolvedPath;
if (watchPath && pnpPath.dirList) {
const callback = typeof a === 'function' ? a : typeof b === 'function' ? b : () => {};
return this.watchManager.registerWatcher(watchPath, pnpPath.dirList, callback);
} else {
return this.baseFs.watch(p, // @ts-ignore
a, b);
}
async openPromise(p, flags, mode) {
return await this.baseFs.openPromise(this.resolveFilePath(p), flags, mode);
}
openSync(p, flags, mode) {
return this.baseFs.openSync(this.resolveFilePath(p), flags, mode);
}
async readPromise(fd, buffer, offset, length, position) {
return await this.baseFs.readPromise(fd, buffer, offset, length, position);
}
readSync(fd, buffer, offset, length, position) {
return this.baseFs.readSync(fd, buffer, offset, length, position);
}
async writePromise(fd, buffer, offset, length, position) {
if (typeof buffer === `string`) {
return await this.baseFs.writePromise(fd, buffer, offset);
}
else {
return await this.baseFs.writePromise(fd, buffer, offset, length, position);
}
}
writeSync(fd, buffer, offset, length, position) {
if (typeof buffer === `string`) {
return this.baseFs.writeSync(fd, buffer, offset);
}
else {
return this.baseFs.writeSync(fd, buffer, offset, length, position);
}
}
async closePromise(fd) {
await this.baseFs.closePromise(fd);
}
closeSync(fd) {
this.baseFs.closeSync(fd);
}
createReadStream(p, opts) {
return this.baseFs.createReadStream(p !== null ? this.resolveFilePath(p) : p, opts);
}
createWriteStream(p, opts) {
return this.baseFs.createWriteStream(p !== null ? this.resolveDirOrFilePath(p) : p, opts);
}
async realpathPromise(p) {
const pnpPath = this.resolvePath(p);
return pnpPath.dirList ? pnpPath.resolvedPath : this.baseFs.realpathPromise(pnpPath.resolvedPath);
}
realpathSync(p) {
const pnpPath = this.resolvePath(p);
return pnpPath.dirList ? pnpPath.resolvedPath : this.baseFs.realpathSync(pnpPath.resolvedPath);
}
async existsPromise(p) {
const pnpPath = this.resolvePath(p);
if (pnpPath.dirList) {
return true;
}
else {
return await this.baseFs.existsPromise(pnpPath.resolvedPath);
}
}
existsSync(p) {
const pnpPath = this.resolvePath(p);
if (pnpPath.dirList) {
return true;
}
else {
return this.baseFs.existsSync(pnpPath.resolvedPath);
}
}
async accessPromise(p, mode) {
return await this.baseFs.accessPromise(this.resolveDirOrFilePath(p), mode);
}
accessSync(p, mode) {
return this.baseFs.accessSync(this.resolveDirOrFilePath(p), mode);
}
async statPromise(p) {
return await this.baseFs.statPromise(this.resolveDirOrFilePath(p));
}
statSync(p) {
return this.baseFs.statSync(this.resolveDirOrFilePath(p));
}
async lstatPromise(p) {
return this.resolveLink(p, 'lstat', (stats) => PortableNodeModulesFs.makeSymlinkStats(stats), async (resolvedPath) => await this.baseFs.lstatPromise(resolvedPath));
}
lstatSync(p) {
return this.resolveLink(p, 'lstat', (stats) => PortableNodeModulesFs.makeSymlinkStats(stats), (resolvedPath) => this.baseFs.lstatSync(this.resolveDirOrFilePath(resolvedPath)));
}
async chmodPromise(p, mask) {
return await this.baseFs.chmodPromise(this.resolveDirOrFilePath(p), mask);
}
chmodSync(p, mask) {
return this.baseFs.chmodSync(this.resolveDirOrFilePath(p), mask);
}
async renamePromise(oldP, newP) {
return await this.baseFs.renamePromise(this.resolveDirOrFilePath(oldP), this.resolveDirOrFilePath(newP));
}
renameSync(oldP, newP) {
return this.baseFs.renameSync(this.resolveDirOrFilePath(oldP), this.resolveDirOrFilePath(newP));
}
async copyFilePromise(sourceP, destP, flags) {
return await this.baseFs.copyFilePromise(this.resolveFilePath(sourceP), this.resolveDirOrFilePath(destP), flags);
}
copyFileSync(sourceP, destP, flags) {
return this.baseFs.copyFileSync(this.resolveFilePath(sourceP), this.resolveDirOrFilePath(destP), flags);
}
async appendFilePromise(p, content, opts) {
return await this.baseFs.appendFilePromise(this.resolveDirOrFilePath(p), content, opts);
}
appendFileSync(p, content, opts) {
return this.baseFs.appendFileSync(this.resolveDirOrFilePath(p), content, opts);
}
async writeFilePromise(p, content, opts) {
return await this.baseFs.writeFilePromise(this.resolveDirOrFilePath(p), content, opts);
}
writeFileSync(p, content, opts) {
return this.baseFs.writeFileSync(this.resolveDirOrFilePath(p), content, opts);
}
async unlinkPromise(p) {
return await this.baseFs.unlinkPromise(this.resolveDirOrFilePath(p));
}
unlinkSync(p) {
return this.baseFs.unlinkSync(this.resolveDirOrFilePath(p));
}
async utimesPromise(p, atime, mtime) {
return await this.baseFs.utimesPromise(this.resolveDirOrFilePath(p), atime, mtime);
}
utimesSync(p, atime, mtime) {
return this.baseFs.utimesSync(this.resolveDirOrFilePath(p), atime, mtime);
}
async mkdirPromise(p, opts) {
const pnpPath = this.resolvePath(p);
const parentPath = this.resolvePath(fslib_1.ppath.dirname(p));
if (parentPath.dirList)
this.persistPath(parentPath.resolvedPath);
return this.baseFs.mkdirPromise(pnpPath.resolvedPath, opts);
}
mkdirSync(p, opts) {
const pnpPath = this.resolvePath(p);
const parentPath = this.resolvePath(fslib_1.ppath.dirname(p));
if (parentPath.dirList)
this.persistPath(parentPath.resolvedPath);
return this.baseFs.mkdirSync(pnpPath.resolvedPath, opts);
}
async rmdirPromise(p) {
return await this.baseFs.rmdirPromise(this.resolveDirOrFilePath(p));
}
rmdirSync(p) {
return this.baseFs.rmdirSync(this.resolveDirOrFilePath(p));
}
async symlinkPromise(target, p) {
return await this.baseFs.symlinkPromise(this.resolveDirOrFilePath(target), this.resolveDirOrFilePath(p));
}
symlinkSync(target, p) {
return this.baseFs.symlinkSync(this.resolveDirOrFilePath(target), this.resolveDirOrFilePath(p));
}
async readFilePromise(p, encoding) {
// This weird switch is required to tell TypeScript that the signatures are proper (otherwise it thinks that only the generic one is covered)
switch (encoding) {
case `utf8`:
return await this.baseFs.readFilePromise(this.resolveFilePath(p), encoding);
default:
return await this.baseFs.readFilePromise(this.resolveFilePath(p), encoding);
}
}
readFileSync(p, encoding) {
// This weird switch is required to tell TypeScript that the signatures are proper (otherwise it thinks that only the generic one is covered)
switch (encoding) {
case `utf8`:
return this.baseFs.readFileSync(this.resolveFilePath(p), encoding);
default:
return this.baseFs.readFileSync(this.resolveFilePath(p), encoding);
}
}
async readdirPromise(p, { withFileTypes } = {}) {
const pnpPath = this.resolvePath(p);
if (pnpPath.dirList || this.resolvePath(fslib_1.ppath.join(p, fslib_2.toFilename('node_modules'))).dirList) {
let fsDirList = [];
try {
fsDirList = await this.baseFs.readdirPromise(pnpPath.resolvedPath);
}
catch (e) {
// Ignore errors
}
const entries = Array.from(pnpPath.dirList || [fslib_2.toFilename('node_modules')]).concat(fsDirList).sort();
if (!withFileTypes)
return entries;
return entries.map(name => {
return Object.assign(this.lstatSync(fslib_1.ppath.join(p, name)), {
name,
});
});
}
else {
return await this.baseFs.readdirPromise(pnpPath.resolvedPath, { withFileTypes: withFileTypes });
}
}
readdirSync(p, { withFileTypes } = {}) {
const pnpPath = this.resolvePath(p);
if (pnpPath.dirList || this.resolvePath(fslib_1.ppath.join(p, fslib_2.toFilename('node_modules'))).dirList) {
let fsDirList = [];
try {
fsDirList = this.baseFs.readdirSync(pnpPath.resolvedPath);
}
catch (e) {
// Ignore errors
}
const entries = Array.from(pnpPath.dirList || [fslib_2.toFilename('node_modules')]).concat(fsDirList).sort();
if (!withFileTypes)
return entries;
return entries.map(name => {
return Object.assign(this.lstatSync(fslib_1.ppath.join(p, name)), {
name,
});
});
}
else {
return this.baseFs.readdirSync(pnpPath.resolvedPath, { withFileTypes: withFileTypes });
}
}
async readlinkPromise(p) {
return this.resolveLink(p, 'readlink', (_stats, targetPath) => targetPath, async (targetPath) => await this.baseFs.readlinkPromise(this.resolveDirOrFilePath(targetPath)));
}
readlinkSync(p) {
return this.resolveLink(p, 'readlink', (_stats, targetPath) => targetPath, (targetPath) => this.baseFs.readlinkSync(this.resolveDirOrFilePath(targetPath)));
}
watch(p, a, b) {
const pnpPath = this.resolvePath(p);
const watchPath = pnpPath.resolvedPath;
if (watchPath && pnpPath.dirList) {
const callback = typeof a === 'function' ? a : typeof b === 'function' ? b : () => { };
return this.watchManager.registerWatcher(watchPath, pnpPath.dirList, callback);
}
else {
return this.baseFs.watch(p,
// @ts-ignore
a, b);
}
}
}
}
exports.PortableNodeModulesFs = PortableNodeModulesFs;
exports.PortableNodeModulesFs = PortableNodeModulesFs;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fslib_1 = require("@yarnpkg/fslib");
const fslib_2 = require("@yarnpkg/fslib");
const buildNodeModulesTree_1 = require("./buildNodeModulesTree");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.resolveNodeModulesPath = void 0;
var _fslib = require("@yarnpkg/fslib");
var _buildNodeModulesTree = require("./buildNodeModulesTree");
const NODE_MODULES = 'node_modules';
/**
* Resolved `/node_modules` path inside PnP project info.
*
* Dirs ending with '/node_modules/foo/node_modules' or '.../node_modules/foo/node_modules/@scope'
* do not physically exist, but we must pretend they do exist if package `foo` has dependencies
* and there is some package `@scope/bar` inside these dependencies. We need two things to emulate
* these dirs existence:
*
* 1. List of entries in these dirs. We retrieve them by calling PnP API and getting dependencies
* for the issuer `.../foo/` and store into `dirList` field
* 2. And we need either fake stats or we can forward underlying fs to stat the issuer dir.
* The issuer dir exists on fs. We store issuer dir into `statPath` field
*/
/**
* Resolves paths containing `/node_modules` inside PnP projects. If path is outside PnP

@@ -15,53 +35,58 @@ * project it is not changed.

*/
exports.resolveNodeModulesPath = (inputPath, nodeModulesTree) => {
const result = { resolvedPath: inputPath };
const segments = inputPath.split(fslib_2.ppath.sep);
const firstIdx = segments.indexOf(NODE_MODULES);
if (firstIdx < 0)
return result;
let lastIdx = segments.lastIndexOf(NODE_MODULES);
if (typeof segments[lastIdx + 1] !== 'undefined')
// We have the situation .../node_modules/{something or @something}
lastIdx++;
if (segments[lastIdx][0] === '@' && typeof segments[lastIdx + 1] !== 'undefined')
// We have the situation .../node_modules/@something/{foo}
lastIdx++;
// We lookup all the path substrings that end on [firstIdx..lastIdx] in the node_modules tree
// and follow them if they are symlinks
let locationCandidate = fslib_2.npath.toPortablePath(segments.slice(0, firstIdx).join(fslib_2.ppath.sep));
let node, lastNode, lastNodeLocation;
let curIdx = firstIdx;
let request = fslib_1.PortablePath.dot;
while (curIdx <= lastIdx) {
const curSegment = fslib_2.toFilename(segments[curIdx]);
locationCandidate = fslib_2.ppath.join(locationCandidate, curSegment);
node = nodeModulesTree.get(locationCandidate);
if (node) {
if (node.linkType === buildNodeModulesTree_1.LinkType.SOFT)
locationCandidate = node.target;
lastNode = node;
request = fslib_1.PortablePath.dot;
lastNodeLocation = locationCandidate;
}
else {
request = fslib_2.ppath.join(request, curSegment);
}
curIdx++;
const resolveNodeModulesPath = (inputPath, nodeModulesTree) => {
const result = {
resolvedPath: inputPath
};
const segments = inputPath.split(_fslib.ppath.sep);
const firstIdx = segments.indexOf(NODE_MODULES);
if (firstIdx < 0) return result;
let lastIdx = segments.lastIndexOf(NODE_MODULES);
if (typeof segments[lastIdx + 1] !== 'undefined') // We have the situation .../node_modules/{something or @something}
lastIdx++;
if (segments[lastIdx][0] === '@' && typeof segments[lastIdx + 1] !== 'undefined') // We have the situation .../node_modules/@something/{foo}
lastIdx++; // We lookup all the path substrings that end on [firstIdx..lastIdx] in the node_modules tree
// and follow them if they are symlinks
let locationCandidate = _fslib.npath.toPortablePath(segments.slice(0, firstIdx).join(_fslib.ppath.sep));
let node, lastNode, lastNodeLocation;
let curIdx = firstIdx;
let request = _fslib.PortablePath.dot;
while (curIdx <= lastIdx) {
const curSegment = (0, _fslib.toFilename)(segments[curIdx]);
locationCandidate = _fslib.ppath.join(locationCandidate, curSegment);
node = nodeModulesTree.get(locationCandidate);
if (node) {
if (node.linkType === _buildNodeModulesTree.LinkType.SOFT) locationCandidate = node.target;
lastNode = node;
request = _fslib.PortablePath.dot;
lastNodeLocation = locationCandidate;
} else {
request = _fslib.ppath.join(request, curSegment);
}
request = fslib_2.ppath.join(request, ...segments.slice(lastIdx + 1).map(x => fslib_2.toFilename(x)));
if (lastNode) {
if (!lastNode.dirList || request !== fslib_1.PortablePath.dot) {
result.resolvedPath = fslib_2.ppath.join(lastNodeLocation, request);
result.isSymlink = lastNode && lastNode.linkType === buildNodeModulesTree_1.LinkType.SOFT && request === fslib_1.PortablePath.dot;
}
else if (request === fslib_1.PortablePath.dot) {
result.dirList = lastNode.dirList;
result.forwardedDirPath = fslib_2.npath.toPortablePath(segments.slice(0, firstIdx).join(fslib_2.ppath.sep));
// If node_modules is inside .zip archive, we use parent folder as a statPath instead
if (result.forwardedDirPath.endsWith('.zip')) {
result.forwardedDirPath = fslib_2.ppath.dirname(result.forwardedDirPath);
}
}
curIdx++;
}
request = _fslib.ppath.join(request, ...segments.slice(lastIdx + 1).map(x => (0, _fslib.toFilename)(x)));
if (lastNode) {
if (!lastNode.dirList || request !== _fslib.PortablePath.dot) {
result.resolvedPath = _fslib.ppath.join(lastNodeLocation, request);
result.isSymlink = lastNode && lastNode.linkType === _buildNodeModulesTree.LinkType.SOFT && request === _fslib.PortablePath.dot;
} else if (request === _fslib.PortablePath.dot) {
result.dirList = lastNode.dirList;
result.forwardedDirPath = _fslib.npath.toPortablePath(segments.slice(0, firstIdx).join(_fslib.ppath.sep)); // If node_modules is inside .zip archive, we use parent folder as a statPath instead
if (result.forwardedDirPath.endsWith('.zip')) {
result.forwardedDirPath = _fslib.ppath.dirname(result.forwardedDirPath);
}
}
return result;
}
return result;
};
exports.resolveNodeModulesPath = resolveNodeModulesPath;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const events_1 = require("events");
class WatchEventEmitter extends events_1.EventEmitter {
constructor(dirWatchers, watchPath, watcherId) {
super();
this.dirWatchers = dirWatchers;
this.watchPath = watchPath;
this.watcherId = watcherId;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.WatchManager = void 0;
var _events = require("events");
class WatchEventEmitter extends _events.EventEmitter {
constructor(dirWatchers, watchPath, watcherId) {
super();
this.dirWatchers = void 0;
this.watchPath = void 0;
this.watcherId = void 0;
this.dirWatchers = dirWatchers;
this.watchPath = watchPath;
this.watcherId = watcherId;
}
close() {
const dirWatcher = this.dirWatchers.get(this.watchPath);
dirWatcher.eventEmitters.delete(this.watcherId);
if (dirWatcher.eventEmitters.size === 0) {
this.dirWatchers.delete(this.watchPath);
}
close() {
const dirWatcher = this.dirWatchers.get(this.watchPath);
dirWatcher.eventEmitters.delete(this.watcherId);
if (dirWatcher.eventEmitters.size === 0) {
this.dirWatchers.delete(this.watchPath);
}
}
}
}
class WatchManager extends events_1.EventEmitter {
constructor() {
super(...arguments);
this.dirWatchers = new Map();
this.lastWatcherId = 0;
class WatchManager extends _events.EventEmitter {
constructor(...args) {
super(...args);
this.dirWatchers = new Map();
this.lastWatcherId = 0;
}
registerWatcher(watchPath, dirList, callback) {
let dirWatcher = this.dirWatchers.get(watchPath);
if (!dirWatcher) {
dirWatcher = {
eventEmitters: new Map(),
dirEntries: dirList
};
this.dirWatchers.set(watchPath, dirWatcher);
}
registerWatcher(watchPath, dirList, callback) {
let dirWatcher = this.dirWatchers.get(watchPath);
if (!dirWatcher) {
dirWatcher = { eventEmitters: new Map(), dirEntries: dirList };
this.dirWatchers.set(watchPath, dirWatcher);
const watcherId = this.lastWatcherId++;
const watchEventEmitter = new WatchEventEmitter(this.dirWatchers, watchPath, watcherId);
dirWatcher.eventEmitters.set(watcherId, watchEventEmitter);
watchEventEmitter.on('rename', filename => callback('rename', filename));
return watchEventEmitter;
}
notifyWatchers(resolvePath) {
for (const [watchPath, dirWatcher] of this.dirWatchers) {
const newDirEntries = resolvePath(watchPath).dirList || new Set(); // Difference between new and old directory contents
const dirEntryDiff = new Set();
for (const entry of newDirEntries) {
if (!dirWatcher.dirEntries.has(entry)) {
dirEntryDiff.add(entry);
}
const watcherId = this.lastWatcherId++;
const watchEventEmitter = new WatchEventEmitter(this.dirWatchers, watchPath, watcherId);
dirWatcher.eventEmitters.set(watcherId, watchEventEmitter);
watchEventEmitter.on('rename', (filename) => callback('rename', filename));
return watchEventEmitter;
}
notifyWatchers(resolvePath) {
for (const [watchPath, dirWatcher] of this.dirWatchers) {
const newDirEntries = resolvePath(watchPath).dirList || new Set();
// Difference between new and old directory contents
const dirEntryDiff = new Set();
for (const entry of newDirEntries) {
if (!dirWatcher.dirEntries.has(entry)) {
dirEntryDiff.add(entry);
}
}
for (const entry of dirWatcher.dirEntries) {
if (!newDirEntries.has(entry)) {
dirEntryDiff.add(entry);
}
}
for (const entry of dirEntryDiff) {
for (const watchEventEmitter of dirWatcher.eventEmitters.values()) {
watchEventEmitter.emit('rename', entry);
}
}
dirWatcher.dirEntries = newDirEntries;
}
for (const entry of dirWatcher.dirEntries) {
if (!newDirEntries.has(entry)) {
dirEntryDiff.add(entry);
}
}
for (const entry of dirEntryDiff) {
for (const watchEventEmitter of dirWatcher.eventEmitters.values()) {
watchEventEmitter.emit('rename', entry);
}
}
dirWatcher.dirEntries = newDirEntries;
}
}
}
exports.WatchManager = WatchManager;
exports.WatchManager = WatchManager;
{
"name": "@yarnpkg/pnpify",
"version": "2.0.0-rc.12",
"version": "2.0.0-rc.13",
"main": "./lib/index.js",

@@ -9,3 +9,3 @@ "bin": "./lib/cli.js",

"dependencies": {
"@yarnpkg/fslib": "2.0.0-rc.12",
"@yarnpkg/fslib": "^2.0.0-rc.12",
"comment-json": "^2.2.0",

@@ -17,7 +17,6 @@ "cross-spawn": "^6.0.5"

"@types/cross-spawn": "6.0.0",
"@types/node": "^12.12.8",
"@yarnpkg/monorepo": "0.0.0",
"@yarnpkg/pnp": "2.0.0-rc.12",
"@yarnpkg/pnp": "^2.0.0-rc.12",
"eslint": "^5.16.0",
"typescript": "next"
"typescript": "^3.7.4"
},

@@ -24,0 +23,0 @@ "peerDependencies": {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc