npm-packlist 10.0.3 → 11.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -30
- package/lib/index.js +47 -46
- package/package.json +10 -8
package/README.md
CHANGED
|
@@ -30,11 +30,9 @@ arborist.loadActual().then((tree) => {
|
|
|
30
30
|
This uses the following rules:
|
|
31
31
|
|
|
32
32
|
1. If a `package.json` file is found, and it has a `files` list,
|
|
33
|
-
then ignore everything that isn't
|
|
34
|
-
readme, license, licence and copying files, if they exist, as well
|
|
35
|
-
as the package.json file itself.
|
|
36
|
-
copying files are included by default, but can be excluded using the
|
|
37
|
-
`files` list e.g. `"!readme"`.
|
|
33
|
+
then ignore everything that isn't matched by `files`. Always include the
|
|
34
|
+
root readme, license, licence and copying files, if they exist, as well
|
|
35
|
+
as the package.json file itself.
|
|
38
36
|
2. If there's no `package.json` file (or it has no `files` list), and
|
|
39
37
|
there is a `.npmignore` file, then ignore all the files in the
|
|
40
38
|
`.npmignore` file.
|
|
@@ -45,7 +43,7 @@ This uses the following rules:
|
|
|
45
43
|
bundled dependency. If it IS a bundled dependency, and it's a
|
|
46
44
|
symbolic link, then the target of the link is included, not the
|
|
47
45
|
symlink itself.
|
|
48
|
-
|
|
46
|
+
5. Unless they're explicitly included (by being in a `files` list, or
|
|
49
47
|
a `!negated` rule in a relevant `.npmignore` or `.gitignore`),
|
|
50
48
|
always ignore certain common cruft files:
|
|
51
49
|
|
|
@@ -58,48 +56,65 @@ This uses the following rules:
|
|
|
58
56
|
6. Darwin's `.DS_Store` files because wtf are those even
|
|
59
57
|
7. `npm-debug.log` files at the root of a project
|
|
60
58
|
|
|
61
|
-
You can explicitly re-include
|
|
62
|
-
|
|
59
|
+
You can explicitly re-include most of these with a negated ignore file rule.
|
|
60
|
+
A small set of files are always ignored regardless of `files` rules:
|
|
61
|
+
`.git`, `.npmrc`, and `node_modules`.
|
|
63
62
|
|
|
64
63
|
Only the `package.json` file in the very root of the project is ever
|
|
65
64
|
inspected for a `files` list. Below the top level of the root package,
|
|
66
65
|
`package.json` is treated as just another file, and no package-specific
|
|
67
66
|
semantics are applied.
|
|
68
67
|
|
|
69
|
-
###
|
|
68
|
+
### Interpretation of the `files` list
|
|
70
69
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
Each entry in the `package.json` `files` list is interpreted as a glob
|
|
71
|
+
pattern, expanded against the package root using node's built-in
|
|
72
|
+
[`fs.globSync`](https://nodejs.org/api/fs.html#fsglobsyncpattern-options).
|
|
73
|
+
Literal paths (`lib`, `src/index.js`) are valid globs and resolve to
|
|
74
|
+
themselves; pattern entries (`dist-*`, `**/*.js`) resolve to every
|
|
75
|
+
matching entry on disk; entries that match nothing are silently dropped.
|
|
74
76
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
When an entry matches a directory, the directory and all of its contents
|
|
78
|
+
are included. This is a documented convenience: writing
|
|
79
|
+
`"files": ["dist"]` does not require also writing `"dist/**"`.
|
|
77
80
|
|
|
78
|
-
|
|
81
|
+
A leading `!` makes the entry a negation, removing matches from the
|
|
82
|
+
result. Negations are evaluated in order, so a later positive entry
|
|
83
|
+
can re-include something a previous negation excluded.
|
|
79
84
|
|
|
80
|
-
|
|
85
|
+
#### Pattern semantics are anchored to the package root
|
|
81
86
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
"files": [ "dir" ]
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
+
Glob patterns are evaluated as paths relative to the package root, not as
|
|
88
|
+
basename-anywhere matchers. In particular:
|
|
87
89
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
90
|
+
* `"*.js"` matches `.js` files at the package root, not at every depth.
|
|
91
|
+
Use `"**/*.js"` to match at every depth.
|
|
92
|
+
* `"!readme.md"` removes only the root `readme.md`. Use
|
|
93
|
+
`"!**/readme.md"` to remove `readme.md` at every depth.
|
|
91
94
|
|
|
92
|
-
|
|
95
|
+
Negations only exclude paths that exist on disk at packlist time: a `!path`
|
|
96
|
+
entry that matches nothing is silently dropped, same as a positive entry
|
|
97
|
+
that matches nothing. A typo'd negation has no effect.
|
|
93
98
|
|
|
94
|
-
|
|
99
|
+
#### Interaction with `.npmignore`
|
|
100
|
+
|
|
101
|
+
If a `package.json` `files` array is present, any **top-level**
|
|
102
|
+
`.npmignore` and `.gitignore` files are ignored: the `files` array is
|
|
103
|
+
the sole source of inclusion at the package root.
|
|
104
|
+
|
|
105
|
+
`.npmignore` files in subdirectories are still honored within their
|
|
106
|
+
subtree. For example, with this package.json:
|
|
107
|
+
|
|
108
|
+
```json
|
|
95
109
|
{
|
|
96
|
-
"files": ["dir
|
|
110
|
+
"files": [ "dir" ]
|
|
97
111
|
}
|
|
98
112
|
```
|
|
99
113
|
|
|
100
|
-
a `.npmignore`
|
|
101
|
-
|
|
102
|
-
|
|
114
|
+
a `.npmignore` at `dir/.npmignore` (and any nested subdirectory) will
|
|
115
|
+
be applied. This means a file listed both in `files` and excluded by a
|
|
116
|
+
nested `.npmignore` will be excluded from the tarball; if you need such
|
|
117
|
+
a file to ship, remove the `.npmignore` rule.
|
|
103
118
|
|
|
104
119
|
## API
|
|
105
120
|
|
package/lib/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { Walker: IgnoreWalker } = require('ignore-walk')
|
|
4
|
-
const {
|
|
5
|
-
const {
|
|
4
|
+
const { globSync } = require('glob')
|
|
5
|
+
const { readFileSync: readFile } = require('node:fs')
|
|
6
|
+
const { basename, dirname, extname, join, relative, resolve, sep } = require('node:path')
|
|
6
7
|
const { log } = require('proc-log')
|
|
7
8
|
|
|
8
9
|
// symbols used to represent synthetic rule sets
|
|
@@ -97,7 +98,6 @@ class PackWalker extends IgnoreWalker {
|
|
|
97
98
|
this.isPackage = options.isPackage
|
|
98
99
|
this.seen = options.seen || new Set()
|
|
99
100
|
this.tree = tree
|
|
100
|
-
this.requiredFiles = options.requiredFiles || []
|
|
101
101
|
|
|
102
102
|
const additionalDefaults = []
|
|
103
103
|
if (options.prefix && options.workspaces) {
|
|
@@ -125,12 +125,8 @@ class PackWalker extends IgnoreWalker {
|
|
|
125
125
|
this.injectRules(defaultRules, [...defaults, ...additionalDefaults])
|
|
126
126
|
|
|
127
127
|
if (!this.isPackage) {
|
|
128
|
-
// if this instance is not a package, then place some strict default rules
|
|
129
|
-
|
|
130
|
-
this.injectRules(strictRules, [
|
|
131
|
-
...strictDefaults,
|
|
132
|
-
...this.requiredFiles.map((file) => `!${file}`),
|
|
133
|
-
])
|
|
128
|
+
// if this instance is not a package, then place some strict default rules
|
|
129
|
+
this.injectRules(strictRules, [...strictDefaults])
|
|
134
130
|
}
|
|
135
131
|
}
|
|
136
132
|
|
|
@@ -170,7 +166,7 @@ class PackWalker extends IgnoreWalker {
|
|
|
170
166
|
} else if (this.ignoreRules['.npmignore']) {
|
|
171
167
|
// .npmignore means no .gitignore
|
|
172
168
|
this.ignoreRules['.gitignore'] = null
|
|
173
|
-
} else if (this.ignoreRules['.gitignore'] && !this.ignoreRules['.npmignore']) {
|
|
169
|
+
} else if (this.ignoreRules['.gitignore'] && !this.ignoreRules['.npmignore'] && !this.parent) {
|
|
174
170
|
log.warn(
|
|
175
171
|
'gitignore-fallback',
|
|
176
172
|
'No .npmignore file found, using .gitignore for file exclusion. Consider creating a .npmignore file to explicitly control published files.'
|
|
@@ -234,15 +230,6 @@ class PackWalker extends IgnoreWalker {
|
|
|
234
230
|
return {
|
|
235
231
|
...super.walkerOpt(entry, opts),
|
|
236
232
|
ignoreFiles,
|
|
237
|
-
// we map over our own requiredFiles and pass ones that are within this entry
|
|
238
|
-
requiredFiles: this.requiredFiles
|
|
239
|
-
.map((file) => {
|
|
240
|
-
if (relative(file, entry) === '..') {
|
|
241
|
-
return relative(entry, file).replace(/\\/g, '/')
|
|
242
|
-
}
|
|
243
|
-
return false
|
|
244
|
-
})
|
|
245
|
-
.filter(Boolean),
|
|
246
233
|
}
|
|
247
234
|
}
|
|
248
235
|
|
|
@@ -295,46 +282,60 @@ class PackWalker extends IgnoreWalker {
|
|
|
295
282
|
'/node_modules',
|
|
296
283
|
'.npmrc',
|
|
297
284
|
'/package-lock.json',
|
|
285
|
+
'/npm-shrinkwrap.json',
|
|
298
286
|
'/yarn.lock',
|
|
299
287
|
'/pnpm-lock.yaml',
|
|
300
288
|
'/bun.lockb',
|
|
289
|
+
'/bun.lock',
|
|
301
290
|
]
|
|
302
291
|
|
|
303
292
|
// if we have a files array in our package, we need to pull rules from it
|
|
304
293
|
if (files) {
|
|
305
|
-
for (
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
294
|
+
for (const entry of files) {
|
|
295
|
+
const isNegation = entry.startsWith('!')
|
|
296
|
+
// normalize: strip leading `!`s, `./`, a single leading `/`, and trailing slashes.
|
|
297
|
+
// trailing slashes confuse glob; the leading forms are equivalent to their stripped versions for glob expansion.
|
|
298
|
+
const pattern = (isNegation ? entry.replace(/^!+/, '') : entry)
|
|
299
|
+
.replace(/^\.?\//, '')
|
|
300
|
+
.replace(/\/+$/, '')
|
|
301
|
+
if (!pattern) {
|
|
302
|
+
continue
|
|
312
303
|
}
|
|
313
|
-
|
|
304
|
+
|
|
305
|
+
// expand the entry as a glob against the package root.
|
|
306
|
+
// literal paths (e.g. `lib`, `lib/foo.js`) are valid globs and resolve to themselves;
|
|
307
|
+
// patterns (e.g. `dist-*`, `**/*.js`) resolve to all matching entries;
|
|
308
|
+
// typos and non-existent entries resolve to nothing.
|
|
309
|
+
let matches = []
|
|
314
310
|
try {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
//
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
311
|
+
matches = globSync(pattern, { cwd: this.path, withFileTypes: true, dot: true })
|
|
312
|
+
} catch {
|
|
313
|
+
// unparseable globs produce no matches and drop silently.
|
|
314
|
+
// (Pre-v11 instead fell through to push the raw entry as an ignore-walk pattern rule; we deliberately don't preserve that.)
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// a positive entry produces `!path` rules (un-ignore from the surrounding `*` deny-all); a negation produces `path` rules (re-ignore them).
|
|
318
|
+
// directory matches expand to also include their contents; this is documented `files[]` behavior, not a glob hack.
|
|
319
|
+
const prefix = isNegation ? '' : '!'
|
|
320
|
+
for (const match of matches) {
|
|
321
|
+
const rel = match.relativePosix()
|
|
322
|
+
// istanbul ignore next -- defensive: glob with withFileTypes returns the cwd as an entry with an empty relative path; skip it.
|
|
323
|
+
if (!rel) {
|
|
324
|
+
continue
|
|
325
|
+
}
|
|
326
|
+
if (match.isDirectory()) {
|
|
327
|
+
ignores.push(`${prefix}/${rel}`)
|
|
328
|
+
ignores.push(`${prefix}/${rel}/**`)
|
|
329
|
+
continue
|
|
330
|
+
}
|
|
331
|
+
// istanbul ignore else -- non-file-non-dir matches (sockets, fifos, broken symlinks) drop silently.
|
|
332
|
+
if (match.isFile()) {
|
|
333
|
+
ignores.push(`${prefix}/${rel}`)
|
|
328
334
|
}
|
|
329
|
-
// if the thing exists, but is neither a file or a directory, we don't want it at all
|
|
330
|
-
} catch (err) {
|
|
331
|
-
// if lstat throws, then we assume we're looking at a pattern and treat it as a default
|
|
332
|
-
ignores.push(inverse)
|
|
333
335
|
}
|
|
334
336
|
}
|
|
335
337
|
|
|
336
|
-
// we prepend a '*' to exclude everything, followed by our inverted file rules
|
|
337
|
-
// which now mean to include those
|
|
338
|
+
// we prepend a '*' to exclude everything, followed by our inverted file rules which now mean to include those
|
|
338
339
|
this.injectRules('package.json', ['*', ...ignores])
|
|
339
340
|
}
|
|
340
341
|
|
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "npm-packlist",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "11.0.0",
|
|
4
4
|
"description": "Get a list of the files to add from a folder into an npm package",
|
|
5
5
|
"directories": {
|
|
6
6
|
"test": "test"
|
|
7
7
|
},
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"
|
|
11
|
-
"
|
|
10
|
+
"glob": "^13.0.6",
|
|
11
|
+
"ignore-walk": "^9.0.0",
|
|
12
|
+
"proc-log": "^7.0.0"
|
|
12
13
|
},
|
|
13
14
|
"author": "GitHub Inc.",
|
|
14
15
|
"license": "ISC",
|
|
@@ -18,8 +19,8 @@
|
|
|
18
19
|
],
|
|
19
20
|
"devDependencies": {
|
|
20
21
|
"@npmcli/arborist": "^9.0.0",
|
|
21
|
-
"@npmcli/eslint-config": "^
|
|
22
|
-
"@npmcli/template-oss": "
|
|
22
|
+
"@npmcli/eslint-config": "^6.0.0",
|
|
23
|
+
"@npmcli/template-oss": "5.1.0",
|
|
23
24
|
"mutate-fs": "^2.1.1",
|
|
24
25
|
"tap": "^16.0.1"
|
|
25
26
|
},
|
|
@@ -52,11 +53,12 @@
|
|
|
52
53
|
]
|
|
53
54
|
},
|
|
54
55
|
"engines": {
|
|
55
|
-
"node": "^
|
|
56
|
+
"node": "^22.22.2 || ^24.15.0 || >=26.0.0"
|
|
56
57
|
},
|
|
57
58
|
"templateOSS": {
|
|
58
59
|
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
|
|
59
|
-
"version": "
|
|
60
|
-
"publish": true
|
|
60
|
+
"version": "5.1.0",
|
|
61
|
+
"publish": true,
|
|
62
|
+
"updateNpm": false
|
|
61
63
|
}
|
|
62
64
|
}
|