Updated the files.

This commit is contained in:
Batuhan Berk Başoğlu 2024-02-08 19:38:41 -05:00
parent 1553e6b971
commit 753967d4f5
23418 changed files with 3784666 additions and 0 deletions

View file

@ -0,0 +1,15 @@
The ISC License
Copyright (c) npm, Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View file

@ -0,0 +1,109 @@
# @npmcli/installed-package-contents
Get the list of files installed in a package in node_modules, including
bundled dependencies.
This is useful if you want to remove a package node from the tree _without_
removing its child nodes, for example to extract a new version of the
dependency into place safely.
It's sort of the reflection of [npm-packlist](http://npm.im/npm-packlist),
but for listing out the _installed_ files rather than the files that _will_
be installed. This is of course a much simpler operation, because we don't
have to handle ignore files or package.json `files` lists.
## USAGE
```js
// programmatic usage
const pkgContents = require('@npmcli/installed-package-contents')
pkgContents({ path: 'node_modules/foo', depth: 1 }).then(files => {
// files is an array of items that need to be passed to
// rimraf or moved out of the way to make the folder empty
// if foo bundled dependencies, those will be included.
// It will not traverse into child directories, because we set
// depth:1 in the options.
// If the folder doesn't exist, this returns an empty array.
})
pkgContents({ path: 'node_modules/foo', depth: Infinity }).then(files => {
// setting depth:Infinity tells it to keep walking forever
// until it hits something that isn't a directory, so we'll
// just get the list of all files, but not their containing
// directories.
})
```
As a CLI:
```bash
$ installed-package-contents node_modules/bundle-some -d1
node_modules/.bin/some
node_modules/bundle-some/package.json
node_modules/bundle-some/node_modules/@scope/baz
node_modules/bundle-some/node_modules/.bin/foo
node_modules/bundle-some/node_modules/foo
```
CLI options:
```
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
```
## OPTIONS
* `depth` Number, default `1`. How deep to traverse through folders to get
contents. Typically you'd want to set this to either `1` (to get the
surface files and folders) or `Infinity` (to get all files), but any
other positive number is supported as well. If set to `0` or a
negative number, returns the path provided and (if it is a package) its
set of linked bins.
* `path` Required. Path to the package in `node_modules` where traversal
should begin.
## RETURN VALUE
A Promise that resolves to an array of fully-resolved files and folders
matching the criteria. This includes all bundled dependencies in
`node_modules`, and any linked executables in `node_modules/.bin` that the
package caused to be installed.
An empty or missing package folder will return an empty array. Empty
directories _within_ package contents are listed, even if the `depth`
argument would cause them to be traversed into.
## CAVEAT
If using this module to generate a list of files that should be recursively
removed to clear away the package, note that this will leave empty
directories behind in certain cases:
- If all child packages are bundled dependencies, then the
`node_modules` folder will remain.
- If all child packages within a given scope were bundled dependencies,
then the `node_modules/@scope` folder will remain.
- If all linked bin scripts were removed, then an empty `node_modules/.bin`
folder will remain.
In the interest of speed and algorithmic complexity, this module does _not_
do a subsequent readdir to see if it would remove all directory entries,
though it would be easier to look at if it returned `node_modules` or
`.bin` in that case rather than the contents. However, if the intent is to
pass these arguments to `rimraf`, it hardly makes sense to do _two_
`readdir` calls just so that we can have the luxury of having to make a
third.
Since the primary use case is to delete a package's contents so that they
can be re-filled with a new version of that package, this caveat does not
pose a problem. Empty directories are already ignored by both npm and git.

View file

@ -0,0 +1,242 @@
#! /usr/bin/env node
// 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(p => pkgContents({
path,
depth,
currentDepth,
pkg: p,
result,
packageJsonCache,
}))
}
if (pkg) {
// add all bins to result if they exist
if (pkg.bin) {
const dir = dirname(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)
})
}

View file

@ -0,0 +1,51 @@
{
"name": "@npmcli/installed-package-contents",
"version": "2.0.2",
"description": "Get the list of files installed in a package in node_modules, including bundled dependencies",
"author": "GitHub Inc.",
"main": "lib/index.js",
"bin": {
"installed-package-contents": "lib/index.js"
},
"license": "ISC",
"scripts": {
"test": "tap",
"snap": "tap",
"lint": "eslint \"**/*.js\"",
"postlint": "template-oss-check",
"template-oss-apply": "template-oss-apply --force",
"lintfix": "npm run lint -- --fix",
"posttest": "npm run lint"
},
"devDependencies": {
"@npmcli/eslint-config": "^4.0.0",
"@npmcli/template-oss": "4.11.4",
"require-inject": "^1.4.4",
"tap": "^16.3.0"
},
"dependencies": {
"npm-bundled": "^3.0.0",
"npm-normalize-package-bin": "^3.0.0"
},
"repository": {
"type": "git",
"url": "https://github.com/npm/installed-package-contents.git"
},
"files": [
"bin/",
"lib/"
],
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
"version": "4.11.4"
},
"tap": {
"nyc-arg": [
"--exclude",
"tap-snapshots/**"
]
}
}