UNPKG

@yarnpkg/pnpify

Version:
469 lines (468 loc) 18.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PortableNodeModulesFS = exports.NodeModulesFS = void 0; const tslib_1 = require("tslib"); const fslib_1 = require("@yarnpkg/fslib"); const fslib_2 = require("@yarnpkg/fslib"); const fslib_3 = require("@yarnpkg/fslib"); const nm_1 = require("@yarnpkg/nm"); const fs_1 = tslib_1.__importDefault(require("fs")); const WatchManager_1 = require("./WatchManager"); const dynamicRequire_1 = require("./dynamicRequire"); const resolveNodeModulesPath_1 = require("./resolveNodeModulesPath"); class NodeModulesFS extends fslib_3.ProxiedFS { constructor(pnp, { realFs = fs_1.default, pnpifyFs = true } = {}) { super(fslib_2.npath); this.baseFs = new PortableNodeModulesFS(pnp, { baseFs: new fslib_3.NodeFS(realFs), pnpifyFs }); } mapFromBase(path) { return fslib_2.npath.fromPortablePath(path); } mapToBase(path) { return fslib_2.npath.toPortablePath(path); } } exports.NodeModulesFS = NodeModulesFS; const WRITE_FLAGS_REGEX = /[+wa]/; class PortableNodeModulesFS extends fslib_3.FakeFS { constructor(pnp, { baseFs = new fslib_3.NodeFS(), pnpifyFs = true } = {}) { super(fslib_2.ppath); if (!pnp.getDependencyTreeRoots) throw new Error(`NodeModulesFS supports PnP API versions 3+, please upgrade your PnP API provider`); this.options = { baseFs, pnpifyFs }; this.baseFs = baseFs; const { tree, errors } = (0, nm_1.buildNodeModulesTree)(pnp, this.options); if (!tree) throw new Error(`Assertion failed. Have got non-persistable node_modules graph, errors:\n${JSON.stringify(errors)}`); this.nodeModulesTree = tree; this.watchManager = new WatchManager_1.WatchManager(); const pnpRootPath = fslib_2.npath.toPortablePath(pnp.getPackageInformation(pnp.topLevel).packageLocation); this.pnpFilePath = fslib_2.ppath.join(pnpRootPath, fslib_1.Filename.pnpCjs); this.watchPnpFile(pnpRootPath); } watchPnpFile(pnpRootPath) { this.baseFs.watch(pnpRootPath, { persistent: false }, (_, filename) => { if (filename === fslib_1.Filename.pnpCjs) { const pnp = (0, dynamicRequire_1.dynamicRequireNoCache)(this.pnpFilePath); const nodeModulesTree = (0, nm_1.buildNodeModulesTree)(pnp, this.options); if (!nodeModulesTree) throw new Error(`Assertion failed. Have got non-persistable node_modules graph`); this.watchManager.notifyWatchers((nodePath) => (0, resolveNodeModulesPath_1.resolveNodeModulesPath)(nodePath, this.nodeModulesTree)); } }); } persistPath(dir) { const pathStack = []; let curPath = dir; while (!this.baseFs.existsSync(curPath)) { pathStack.push(curPath); curPath = fslib_2.ppath.dirname(curPath); } for (const fullPath of pathStack.reverse()) { this.baseFs.mkdirSync(fullPath); } } persistVirtualParentFolder(p) { if (typeof p !== `number`) { const parentPath = this.resolvePath(fslib_2.ppath.dirname(p)); if (parentPath.dirList) { this.persistPath(parentPath.resolvedPath); } } } getExtractHint(hints) { return this.baseFs.getExtractHint(hints); } 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_1.resolveNodeModulesPath)(fullOriginalPath, this.nodeModulesTree), fullOriginalPath }; } } resolveFilePath(p) { if (typeof p === `number`) return p; const pnpPath = this.resolvePath(p); return pnpPath.resolvedPath; } resolveDirOrFilePath(p) { if (typeof p === `number`) return p; const pnpPath = this.resolvePath(p); return pnpPath.forwardedDirPath || pnpPath.resolvedPath; } resolveLink(opts) { const { p, onSymlink, onRealPath, statOptions } = opts; const pnpPath = this.resolvePath(p); if (pnpPath.isSymlink) { let stat; try { stat = this.baseFs.lstatSync(pnpPath.resolvedPath, statOptions); } catch { } if (stat) { return onSymlink(stat, this.pathUtils.relative(this.pathUtils.dirname(pnpPath.fullOriginalPath), pnpPath.resolvedPath)); } } return onRealPath(pnpPath.forwardedDirPath || pnpPath.resolvedPath); } static makeSymlinkStats(stats) { return Object.assign(stats, { isFile: () => false, isDirectory: () => false, isSymbolicLink: () => true, }); } getRealPath() { return this.baseFs.getRealPath(); } async openPromise(p, flags, mode) { if (WRITE_FLAGS_REGEX.test(flags)) this.persistVirtualParentFolder(p); return await this.baseFs.openPromise(this.resolveFilePath(p), flags, mode); } openSync(p, flags, mode) { if (WRITE_FLAGS_REGEX.test(flags)) this.persistVirtualParentFolder(p); return this.baseFs.openSync(this.resolveFilePath(p), flags, mode); } async opendirPromise(p, opts) { const pnpPath = this.resolvePath(p); if (pnpPath.dirList || this.resolvePath(fslib_2.ppath.join(p, `node_modules`)).dirList) { let fsDirList = []; try { fsDirList = await this.baseFs.readdirPromise(pnpPath.resolvedPath); } catch { } const entries = Array.from(pnpPath.dirList || [`node_modules`]).concat(fsDirList).sort(); return (0, fslib_2.opendir)(this, p, entries); } else { return await this.baseFs.opendirPromise(pnpPath.resolvedPath, opts); } } opendirSync(p, opts) { const pnpPath = this.resolvePath(p); if (pnpPath.dirList || this.resolvePath(fslib_2.ppath.join(p, `node_modules`)).dirList) { let fsDirList = []; try { fsDirList = this.baseFs.readdirSync(pnpPath.resolvedPath); } catch { } const entries = Array.from(pnpPath.dirList || [`node_modules`]).concat(fsDirList).sort(); return (0, fslib_2.opendir)(this, p, entries); } else { return this.baseFs.opendirSync(pnpPath.resolvedPath, opts); } } 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, opts) { return await this.baseFs.statPromise(this.resolveDirOrFilePath(p), opts); } statSync(p, opts) { return this.baseFs.statSync(this.resolveDirOrFilePath(p), opts); } async fstatPromise(fd, opts) { return await this.baseFs.fstatPromise(fd, opts); } fstatSync(fd, opts) { return this.baseFs.fstatSync(fd, opts); } async lstatPromise(p, opts) { return this.resolveLink({ p, op: `lstat`, onSymlink: stats => PortableNodeModulesFS.makeSymlinkStats(stats), onRealPath: async (resolvedPath) => await this.baseFs.lstatPromise(resolvedPath, opts), statOptions: opts, }); } lstatSync(p, opts) { return this.resolveLink({ p, op: `lstat`, onSymlink: stats => PortableNodeModulesFS.makeSymlinkStats(stats), onRealPath: resolvedPath => this.baseFs.lstatSync(resolvedPath, opts), statOptions: opts, }); } async fchmodPromise(fd, mask) { return this.baseFs.fchmodPromise(this.resolveDirOrFilePath(fd), mask); } fchmodSync(fd, mask) { return this.baseFs.fchmodSync(this.resolveDirOrFilePath(fd), mask); } 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 fchownPromise(fd, uid, gid) { return this.baseFs.fchownPromise(this.resolveDirOrFilePath(fd), uid, gid); } fchownSync(fd, uid, gid) { return this.baseFs.fchownSync(this.resolveDirOrFilePath(fd), uid, gid); } async chownPromise(p, uid, gid) { return await this.baseFs.chownPromise(this.resolveDirOrFilePath(p), uid, gid); } chownSync(p, uid, gid) { return this.baseFs.chownSync(this.resolveDirOrFilePath(p), uid, gid); } 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 lutimesPromise(p, atime, mtime) { return await this.baseFs.lutimesPromise(this.resolveDirOrFilePath(p), atime, mtime); } lutimesSync(p, atime, mtime) { return this.baseFs.lutimesSync(this.resolveDirOrFilePath(p), atime, mtime); } async mkdirPromise(p, opts) { const pnpPath = this.resolvePath(p); this.persistVirtualParentFolder(p); return this.baseFs.mkdirPromise(pnpPath.resolvedPath, opts); } mkdirSync(p, opts) { const pnpPath = this.resolvePath(p); this.persistVirtualParentFolder(p); return this.baseFs.mkdirSync(pnpPath.resolvedPath, opts); } async rmdirPromise(p, opts) { return await this.baseFs.rmdirPromise(this.resolveDirOrFilePath(p), opts); } rmdirSync(p, opts) { return this.baseFs.rmdirSync(this.resolveDirOrFilePath(p), opts); } async rmPromise(p, opts) { return await this.baseFs.rmPromise(this.resolveDirOrFilePath(p), opts); } rmSync(p, opts) { return this.baseFs.rmSync(this.resolveDirOrFilePath(p), opts); } async linkPromise(existingP, newP) { return await this.baseFs.linkPromise(this.resolveDirOrFilePath(existingP), this.resolveDirOrFilePath(newP)); } linkSync(existingP, newP) { return this.baseFs.linkSync(this.resolveDirOrFilePath(existingP), this.resolveDirOrFilePath(newP)); } 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) { return await this.baseFs.readFilePromise(this.resolveFilePath(p), encoding); } readFileSync(p, encoding) { return this.baseFs.readFileSync(this.resolveFilePath(p), encoding); } async readdirPromise(p, opts) { const pnpPath = this.resolvePath(p); if (pnpPath.dirList || this.resolvePath(fslib_2.ppath.join(p, `node_modules`)).dirList) { if (opts?.recursive) throw new Error(`Unsupported option 'recursive' for NodeModulesFS.readdirPromise`); let fsDirList = []; try { fsDirList = await this.baseFs.readdirPromise(pnpPath.resolvedPath); } catch { } const entries = Array.from(pnpPath.dirList || [`node_modules`]).concat(fsDirList).sort(); if (!opts?.withFileTypes) return entries; return entries.map(name => { return Object.assign(this.lstatSync(fslib_2.ppath.join(p, name)), { name, path: undefined, }); }); } else { return await this.baseFs.readdirPromise(pnpPath.resolvedPath, opts); } } readdirSync(p, opts) { const pnpPath = this.resolvePath(p); if (pnpPath.dirList || this.resolvePath(fslib_2.ppath.join(p, `node_modules`)).dirList) { if (opts?.recursive) throw new Error(`Unsupported option 'recursive' for NodeModulesFS.readdirSync`); let fsDirList = []; try { fsDirList = this.baseFs.readdirSync(pnpPath.resolvedPath); } catch { } const entries = Array.from(pnpPath.dirList || [`node_modules`]).concat(fsDirList).sort(); if (!opts?.withFileTypes) return entries; return entries.map(name => { return Object.assign(this.lstatSync(fslib_2.ppath.join(p, name)), { name, path: undefined, }); }); } else { return this.baseFs.readdirSync(pnpPath.resolvedPath, opts); } } async readlinkPromise(p) { return this.resolveLink({ p, op: `readlink`, onSymlink: (_stats, targetPath) => targetPath, onRealPath: async (targetPath) => await this.baseFs.readlinkPromise(this.resolveDirOrFilePath(targetPath)), }); } readlinkSync(p) { return this.resolveLink({ p, op: `readlink`, onSymlink: (_stats, targetPath) => targetPath, onRealPath: targetPath => this.baseFs.readlinkSync(this.resolveDirOrFilePath(targetPath)), }); } async truncatePromise(p, len) { return await this.baseFs.truncatePromise(this.resolveDirOrFilePath(p), len); } truncateSync(p, len) { return this.baseFs.truncateSync(this.resolveDirOrFilePath(p), len); } async ftruncatePromise(fd, len) { return await this.baseFs.ftruncatePromise(fd, len); } ftruncateSync(fd, len) { return this.baseFs.ftruncateSync(fd, len); } 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(this.resolveDirOrFilePath(p), // @ts-expect-error a, b); } } watchFile(p, a, b) { return this.baseFs.watchFile(this.resolveDirOrFilePath(p), // @ts-expect-error a, b); } unwatchFile(p, cb) { return this.baseFs.unwatchFile(this.resolveDirOrFilePath(p), cb); } } exports.PortableNodeModulesFS = PortableNodeModulesFS;