diff options
Diffstat (limited to 'sandbox/testAppNevena/Front/node_modules/@npmcli/installed-package-contents/index.js')
-rw-r--r-- | sandbox/testAppNevena/Front/node_modules/@npmcli/installed-package-contents/index.js | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/sandbox/testAppNevena/Front/node_modules/@npmcli/installed-package-contents/index.js b/sandbox/testAppNevena/Front/node_modules/@npmcli/installed-package-contents/index.js new file mode 100644 index 00000000..30427fe2 --- /dev/null +++ b/sandbox/testAppNevena/Front/node_modules/@npmcli/installed-package-contents/index.js @@ -0,0 +1,237 @@ +// to GET CONTENTS for folder at PATH (which may be a PACKAGE): +// - if PACKAGE, read path/package.json +// - if bins in ../node_modules/.bin, add those to result +// - if depth >= maxDepth, add PATH to result, and finish +// - readdir(PATH, with file types) +// - add all FILEs in PATH to result +// - if PARENT: +// - if depth < maxDepth, add GET CONTENTS of all DIRs in PATH +// - else, add all DIRs in PATH +// - if no parent +// - if no bundled deps, +// - if depth < maxDepth, add GET CONTENTS of DIRs in path except +// node_modules +// - else, add all DIRs in path other than node_modules +// - if has bundled deps, +// - get list of bundled deps +// - add GET CONTENTS of bundled deps, PACKAGE=true, depth + 1 + +const bundled = require('npm-bundled') +const {promisify} = require('util') +const fs = require('fs') +const readFile = promisify(fs.readFile) +const readdir = promisify(fs.readdir) +const stat = promisify(fs.stat) +const lstat = promisify(fs.lstat) +const {relative, resolve, basename, dirname} = require('path') +const normalizePackageBin = require('npm-normalize-package-bin') + +const readPackage = ({ path, packageJsonCache }) => + packageJsonCache.has(path) ? Promise.resolve(packageJsonCache.get(path)) + : readFile(path).then(json => { + const pkg = normalizePackageBin(JSON.parse(json)) + packageJsonCache.set(path, pkg) + return pkg + }) + .catch(er => null) + +// just normalize bundle deps and bin, that's all we care about here. +const normalized = Symbol('package data has been normalized') +const rpj = ({ path, packageJsonCache }) => + readPackage({path, packageJsonCache}) + .then(pkg => { + if (!pkg || pkg[normalized]) + return pkg + if (pkg.bundledDependencies && !pkg.bundleDependencies) { + pkg.bundleDependencies = pkg.bundledDependencies + delete pkg.bundledDependencies + } + const bd = pkg.bundleDependencies + if (bd === true) { + pkg.bundleDependencies = [ + ...Object.keys(pkg.dependencies || {}), + ...Object.keys(pkg.optionalDependencies || {}), + ] + } + if (typeof bd === 'object' && !Array.isArray(bd)) { + pkg.bundleDependencies = Object.keys(bd) + } + pkg[normalized] = true + return pkg + }) + + +const pkgContents = async ({ + path, + depth, + currentDepth = 0, + pkg = null, + result = null, + packageJsonCache = null, +}) => { + if (!result) + result = new Set() + + if (!packageJsonCache) + packageJsonCache = new Map() + + if (pkg === true) { + return rpj({ path: path + '/package.json', packageJsonCache }) + .then(pkg => pkgContents({ + path, + depth, + currentDepth, + pkg, + result, + packageJsonCache, + })) + } + + if (pkg) { + // add all bins to result if they exist + if (pkg.bin) { + const dir = dirname(path) + const base = basename(path) + const scope = basename(dir) + const nm = /^@.+/.test(scope) ? dirname(dir) : dir + + const binFiles = [] + Object.keys(pkg.bin).forEach(b => { + const base = resolve(nm, '.bin', b) + binFiles.push(base, base + '.cmd', base + '.ps1') + }) + + const bins = await Promise.all( + binFiles.map(b => stat(b).then(() => b).catch((er) => null)) + ) + bins.filter(b => b).forEach(b => result.add(b)) + } + } + + if (currentDepth >= depth) { + result.add(path) + return result + } + + // we'll need bundle list later, so get that now in parallel + const [dirEntries, bundleDeps] = await Promise.all([ + readdir(path, { withFileTypes: true }), + currentDepth === 0 && pkg && pkg.bundleDependencies + ? bundled({ path, packageJsonCache }) : null, + ]).catch(() => []) + + // not a thing, probably a missing folder + if (!dirEntries) + return result + + // empty folder, just add the folder itself to the result + if (!dirEntries.length && !bundleDeps && currentDepth !== 0) { + result.add(path) + return result + } + + const recursePromises = [] + + // if we didn't get withFileTypes support, tack that on + if (typeof dirEntries[0] === 'string') { + // use a map so we can return a promise, but we mutate dirEntries in place + // this is much slower than getting the entries from the readdir call, + // but polyfills support for node versions before 10.10 + await Promise.all(dirEntries.map(async (name, index) => { + const p = resolve(path, name) + const st = await lstat(p) + dirEntries[index] = Object.assign(st, {name}) + })) + } + + for (const entry of dirEntries) { + const p = resolve(path, entry.name) + if (entry.isDirectory() === false) { + result.add(p) + continue + } + + if (currentDepth !== 0 || entry.name !== 'node_modules') { + if (currentDepth < depth - 1) { + recursePromises.push(pkgContents({ + path: p, + packageJsonCache, + depth, + currentDepth: currentDepth + 1, + result, + })) + } else { + result.add(p) + } + continue + } + } + + if (bundleDeps) { + // bundle deps are all folders + // we always recurse to get pkg bins, but if currentDepth is too high, + // it'll return early before walking their contents. + recursePromises.push(...bundleDeps.map(dep => { + const p = resolve(path, 'node_modules', dep) + return pkgContents({ + path: p, + packageJsonCache, + pkg: true, + depth, + currentDepth: currentDepth + 1, + result, + }) + })) + } + + if (recursePromises.length) + await Promise.all(recursePromises) + + return result +} + +module.exports = ({path, depth = 1, packageJsonCache}) => pkgContents({ + path: resolve(path), + depth, + pkg: true, + packageJsonCache, +}).then(results => [...results]) + + +if (require.main === module) { + const options = { path: null, depth: 1 } + const usage = `Usage: + installed-package-contents <path> [-d<n> --depth=<n>] + +Lists the files installed for a package specified by <path>. + +Options: + -d<n> --depth=<n> Provide a numeric value ("Infinity" is allowed) + to specify how deep in the file tree to traverse. + Default=1 + -h --help Show this usage information` + + process.argv.slice(2).forEach(arg => { + let match + if ((match = arg.match(/^--depth=([0-9]+|Infinity)/)) || + (match = arg.match(/^-d([0-9]+|Infinity)/))) + options.depth = +match[1] + else if (arg === '-h' || arg === '--help') { + console.log(usage) + process.exit(0) + } else + options.path = arg + }) + if (!options.path) { + console.error('ERROR: no path provided') + console.error(usage) + process.exit(1) + } + const cwd = process.cwd() + module.exports(options) + .then(list => list.sort().forEach(p => console.log(relative(cwd, p)))) + .catch(/* istanbul ignore next - pretty unusual */ er => { + console.error(er) + process.exit(1) + }) +} |