npm-packlist 5.1.3 → 6.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 +13 -56
- package/lib/index.js +359 -412
- package/package.json +11 -12
package/README.md
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# npm-packlist
|
|
2
2
|
|
|
3
|
-
[](https://travis-ci.com/npm/npm-packlist)
|
|
4
|
-
|
|
5
3
|
Get a list of the files to add from a folder into an npm package.
|
|
6
4
|
|
|
7
5
|
These can be handed to [tar](http://npm.im/tar) like so to make an npm
|
|
@@ -29,8 +27,8 @@ This uses the following rules:
|
|
|
29
27
|
|
|
30
28
|
1. If a `package.json` file is found, and it has a `files` list,
|
|
31
29
|
then ignore everything that isn't in `files`. Always include the
|
|
32
|
-
readme, license,
|
|
33
|
-
|
|
30
|
+
readme, license, licence and copying files, if they exist, as well
|
|
31
|
+
as the package.json file itself.
|
|
34
32
|
2. If there's no `package.json` file (or it has no `files` list), and
|
|
35
33
|
there is a `.npmignore` file, then ignore all the files in the
|
|
36
34
|
`.npmignore` file.
|
|
@@ -64,17 +62,14 @@ semantics are applied.
|
|
|
64
62
|
|
|
65
63
|
### Interaction between `package.json` and `.npmignore` rules
|
|
66
64
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
In previous versions of this library, the `files` list in `package.json`
|
|
66
|
+
was used as an initial filter to drive further tree walking. That is no
|
|
67
|
+
longer the case as of version 6.0.0.
|
|
70
68
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
exploring that level.
|
|
69
|
+
If you have a `package.json` file with a `files` array within, any top
|
|
70
|
+
level `.npmignore` and `.gitignore` files *will be ignored*.
|
|
74
71
|
|
|
75
|
-
|
|
76
|
-
_directory_ is listed in `files`, then any rules in a root or nested
|
|
77
|
-
`.npmignore` files will be honored.
|
|
72
|
+
If a _directory_ is listed in `files`, then any rules in nested `.npmignore` files within that directory will be honored.
|
|
78
73
|
|
|
79
74
|
For example, with this package.json:
|
|
80
75
|
|
|
@@ -88,7 +83,7 @@ a `.npmignore` file at `dir/.npmignore` (and any subsequent
|
|
|
88
83
|
sub-directories) will be honored. However, a `.npmignore` at the root
|
|
89
84
|
level will be skipped.
|
|
90
85
|
|
|
91
|
-
|
|
86
|
+
Additionally, with this package.json:
|
|
92
87
|
|
|
93
88
|
```
|
|
94
89
|
{
|
|
@@ -96,51 +91,13 @@ Conversely, with this package.json:
|
|
|
96
91
|
}
|
|
97
92
|
```
|
|
98
93
|
|
|
99
|
-
a `.npmignore` file at `dir/.npmignore` will
|
|
100
|
-
|
|
101
|
-
Any specific file matched by
|
|
102
|
-
list will be included, and cannot be excluded by any `.npmignore` files in
|
|
103
|
-
nested directories, or by a `.npmignore` file in the root package
|
|
104
|
-
directory, unless that root `.npmignore` file is also in the `files` list.
|
|
105
|
-
|
|
106
|
-
The previous (v1) implementation used in npm 6 and below treated
|
|
107
|
-
`package.json` as a special sort of "reverse ignore" file. That is, it was
|
|
108
|
-
parsed and handled as if it was a `.npmignore` file with `!` prepended to
|
|
109
|
-
all of the globs in the `files` list. In order to include children of a
|
|
110
|
-
directory listed in `files`, they would _also_ have `/**` appended to them.
|
|
111
|
-
|
|
112
|
-
This is tricky to explain, but is a significant improvement over the
|
|
113
|
-
previous (v1) implementation used in npm 6 and below, with the following
|
|
114
|
-
beneficial properties:
|
|
115
|
-
|
|
116
|
-
- If you have `{"files":["lib"]}` in `package.json`, then the walker will
|
|
117
|
-
still ignore files such as `lib/.DS_Store` and `lib/.foo.swp`. The
|
|
118
|
-
previous implementation would include these files, as they'd be matched
|
|
119
|
-
by the computed `!lib/**` ignore rule.
|
|
120
|
-
- If you have `{"files":["lib/a.js","lib/b.js"]}` in `package.json`, and a
|
|
121
|
-
`lib/.npmignore` containing `a.js`, then the walker will still include
|
|
122
|
-
the two files indicated in `package.json`, and ignore the
|
|
123
|
-
`lib/.npmignore` file. The previous implementation would mark these
|
|
124
|
-
files for inclusion, but then _exclude_ them when it came to the nested
|
|
125
|
-
`.npmignore` file. (Ignore file semantics dictate that a "closer" ignore
|
|
126
|
-
file always takes precedence.)
|
|
127
|
-
- A file in `lib/pkg-template/package.json` will be included, and its
|
|
128
|
-
`files` list will not have any bearing on other files being included or
|
|
129
|
-
skipped. When treating `package.json` as just Yet Another ignore file,
|
|
130
|
-
this was not the case, leading to difficulty for modules that aim to
|
|
131
|
-
initialize a project.
|
|
132
|
-
|
|
133
|
-
In general, this walk should work as a reasonable developer would expect.
|
|
134
|
-
Matching human expectation is tricky business, and if you find cases where
|
|
135
|
-
it violates those expectations, [please let us
|
|
136
|
-
know](https://github.com/npm/npm-packlist/issues).
|
|
94
|
+
a `.npmignore` file at `dir/.npmignore` will be honored, as well as `dir/subdir/.npmignore`.
|
|
95
|
+
|
|
96
|
+
Any specific file matched by an exact filename in the package.json `files` list will be included, and cannot be excluded, by any `.npmignore` files.
|
|
137
97
|
|
|
138
98
|
## API
|
|
139
99
|
|
|
140
100
|
Same API as [ignore-walk](http://npm.im/ignore-walk), just hard-coded
|
|
141
101
|
file list and rule sets.
|
|
142
102
|
|
|
143
|
-
The `Walker`
|
|
144
|
-
is a list of package names to include from node_modules. When calling
|
|
145
|
-
the top-level `packlist()` and `packlist.sync()` functions, this
|
|
146
|
-
module calls into `npm-bundled` directly.
|
|
103
|
+
The `Walker` class will load an [arborist](https://github.com/npm/cli/tree/latest/workspaces/arborist) tree, and if any bundled dependencies are found will include them as well as their own dependencies in the resulting file set.
|
package/lib/index.js
CHANGED
|
@@ -1,87 +1,19 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const Arborist = require('@npmcli/arborist')
|
|
4
|
+
const { Walker: IgnoreWalker } = require('ignore-walk')
|
|
5
|
+
const { lstatSync: lstat, readFileSync: readFile } = require('fs')
|
|
6
|
+
const { basename, dirname, extname, join, relative, resolve, sep } = require('path')
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
const
|
|
8
|
+
// symbols used to represent synthetic rule sets
|
|
9
|
+
const defaultRules = Symbol('npm-packlist.rules.default')
|
|
10
|
+
const strictRules = Symbol('npm-packlist.rules.strict')
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
const rootBuiltinRules = Symbol('root-builtin-rules')
|
|
15
|
-
const packageNecessaryRules = Symbol('package-necessary-rules')
|
|
16
|
-
const path = require('path')
|
|
17
|
-
|
|
18
|
-
const normalizePackageBin = require('npm-normalize-package-bin')
|
|
19
|
-
|
|
20
|
-
// Weird side-effect of this: a readme (etc) file will be included
|
|
21
|
-
// if it exists anywhere within a folder with a package.json file.
|
|
22
|
-
// The original intent was only to include these files in the root,
|
|
23
|
-
// but now users in the wild are dependent on that behavior for
|
|
24
|
-
// localized documentation and other use cases. Adding a `/` to
|
|
25
|
-
// these rules, while tempting and arguably more "correct", is a
|
|
26
|
-
// significant change that will break existing use cases.
|
|
27
|
-
const packageMustHaveFileNames = 'readme|copying|license|licence'
|
|
28
|
-
|
|
29
|
-
const packageMustHaves = `@(${packageMustHaveFileNames}){,.*[^~$]}`
|
|
30
|
-
const packageMustHavesRE = new RegExp(`^(${packageMustHaveFileNames})(\\..*[^~$])?$`, 'i')
|
|
31
|
-
|
|
32
|
-
const fs = require('fs')
|
|
33
|
-
const glob = require('glob')
|
|
34
|
-
const globify = pattern => pattern.split('\\').join('/')
|
|
35
|
-
|
|
36
|
-
const readOutOfTreeIgnoreFiles = (root, rel, result = '') => {
|
|
37
|
-
for (const file of ['.npmignore', '.gitignore']) {
|
|
38
|
-
try {
|
|
39
|
-
const ignoreContent = fs.readFileSync(path.join(root, file), { encoding: 'utf8' })
|
|
40
|
-
result += ignoreContent + '\n'
|
|
41
|
-
// break the loop immediately after concatting, this allows us to prioritize the
|
|
42
|
-
// .npmignore and discard the .gitignore if one exists
|
|
43
|
-
break
|
|
44
|
-
} catch (err) {
|
|
45
|
-
// we ignore ENOENT errors completely because we don't care if the file doesn't exist
|
|
46
|
-
// but we throw everything else because failing to read a file that does exist is
|
|
47
|
-
// something that the user likely wants to know about. we don't need to test this.
|
|
48
|
-
/* istanbul ignore next */
|
|
49
|
-
if (err.code !== 'ENOENT') {
|
|
50
|
-
throw err
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (!rel) {
|
|
56
|
-
return result
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const firstRel = rel.split(path.sep)[0]
|
|
60
|
-
const newRoot = path.join(root, firstRel)
|
|
61
|
-
const newRel = path.relative(newRoot, path.join(root, rel))
|
|
62
|
-
|
|
63
|
-
return readOutOfTreeIgnoreFiles(newRoot, newRel, result)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const pathHasPkg = (input) => {
|
|
67
|
-
if (!input.startsWith('node_modules/')) {
|
|
68
|
-
return false
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const segments = input.slice('node_modules/'.length).split('/', 2)
|
|
72
|
-
return segments[0].startsWith('@')
|
|
73
|
-
? segments.length === 2
|
|
74
|
-
: true
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const pkgFromPath = (input) => {
|
|
78
|
-
const segments = input.slice('node_modules/'.length).split('/', 2)
|
|
79
|
-
return segments[0].startsWith('@')
|
|
80
|
-
? segments.join('/')
|
|
81
|
-
: segments[0]
|
|
82
|
-
}
|
|
12
|
+
// There may be others, but :?|<> are handled by node-tar
|
|
13
|
+
const nameIsBadForWindows = file => /\*/.test(file)
|
|
83
14
|
|
|
84
|
-
|
|
15
|
+
// these are the default rules that are applied to everything except for non-link bundled deps
|
|
16
|
+
const defaults = [
|
|
85
17
|
'.npmignore',
|
|
86
18
|
'.gitignore',
|
|
87
19
|
'**/.git',
|
|
@@ -103,410 +35,425 @@ const defaultRules = [
|
|
|
103
35
|
'._*',
|
|
104
36
|
'**/._*/**',
|
|
105
37
|
'*.orig',
|
|
106
|
-
'/package-lock.json',
|
|
107
|
-
'/yarn.lock',
|
|
108
|
-
'/pnpm-lock.yaml',
|
|
109
38
|
'/archived-packages/**',
|
|
110
39
|
]
|
|
111
40
|
|
|
112
|
-
|
|
113
|
-
|
|
41
|
+
const strictDefaults = [
|
|
42
|
+
// these are forcibly included at all levels
|
|
43
|
+
'!/readme{,.*[^~$]}',
|
|
44
|
+
'!/copying{,.*[^~$]}',
|
|
45
|
+
'!/license{,.*[^~$]}',
|
|
46
|
+
'!/licence{,.*[^~$]}',
|
|
47
|
+
// these are forcibly excluded
|
|
48
|
+
'/.git',
|
|
49
|
+
]
|
|
114
50
|
|
|
115
|
-
|
|
116
|
-
constructor (opt) {
|
|
117
|
-
opt = opt || {}
|
|
51
|
+
const normalizePath = (path) => path.split('\\').join('/')
|
|
118
52
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
'
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
// This regexp tests to see that we're either a node_modules folder,
|
|
135
|
-
// or a @scope within a node_modules folder, in the root's node_modules
|
|
136
|
-
// hierarchy (ie, not in test/foo/node_modules/ or something).
|
|
137
|
-
const followRe = /^(?:\/node_modules\/(?:@[^/]+\/[^/]+|[^/]+)\/)*\/node_modules(?:\/@[^/]+)?$/
|
|
138
|
-
const rootPath = opt.parent ? opt.parent.root : opt.path
|
|
139
|
-
const followTestPath = opt.path.replace(/\\/g, '/').slice(rootPath.length)
|
|
140
|
-
opt.follow = followRe.test(followTestPath)
|
|
141
|
-
|
|
142
|
-
super(opt)
|
|
143
|
-
|
|
144
|
-
// ignore a bunch of things by default at the root level.
|
|
145
|
-
// also ignore anything in the main project node_modules hierarchy,
|
|
146
|
-
// except bundled dependencies
|
|
147
|
-
if (this.isProject) {
|
|
148
|
-
this.bundled = opt.bundled || []
|
|
149
|
-
this.bundledScopes = Array.from(new Set(
|
|
150
|
-
this.bundled.filter(f => /^@/.test(f))
|
|
151
|
-
.map(f => f.split('/')[0])))
|
|
152
|
-
this.packageJsonCache = this.parent ? this.parent.packageJsonCache
|
|
153
|
-
: (opt.packageJsonCache || new Map())
|
|
154
|
-
let rules = defaultRules.join('\n') + '\n'
|
|
155
|
-
|
|
156
|
-
if (opt.prefix && opt.workspaces) {
|
|
157
|
-
const gPath = globify(opt.path)
|
|
158
|
-
const gPrefix = globify(opt.prefix)
|
|
159
|
-
const gWorkspaces = opt.workspaces.map((ws) => globify(ws))
|
|
160
|
-
// if opt.path and opt.prefix are not the same directory, and opt.workspaces has opt.path
|
|
161
|
-
// in it, then we know that opt.path is a workspace directory. in order to not drop ignore
|
|
162
|
-
// rules from directories between the workspace root (opt.prefix) and the workspace itself
|
|
163
|
-
// (opt.path), we need to find and read those now
|
|
164
|
-
/* istanbul ignore else */
|
|
165
|
-
if (gPath !== gPrefix && gWorkspaces.includes(gPath)) {
|
|
166
|
-
// relpath is the relative path between the prefix and the parent of opt.path
|
|
167
|
-
// we use the parent because ignore-walk will read the files in opt.path already
|
|
168
|
-
const relpath = path.relative(opt.prefix, path.dirname(opt.path))
|
|
169
|
-
rules += readOutOfTreeIgnoreFiles(opt.prefix, relpath)
|
|
170
|
-
} else if (gPath === gPrefix) {
|
|
171
|
-
// on the other hand, if the path and the prefix are the same, then we ignore workspaces
|
|
172
|
-
// so that we don't pack workspaces inside of a root project
|
|
173
|
-
rules += opt.workspaces.map((ws) => globify(path.relative(opt.path, ws))).join('\n')
|
|
174
|
-
}
|
|
53
|
+
const readOutOfTreeIgnoreFiles = (root, rel, result = []) => {
|
|
54
|
+
for (const file of ['.npmignore', '.gitignore']) {
|
|
55
|
+
try {
|
|
56
|
+
const ignoreContent = readFile(join(root, file), { encoding: 'utf8' })
|
|
57
|
+
result.push(ignoreContent)
|
|
58
|
+
// break the loop immediately after reading, this allows us to prioritize
|
|
59
|
+
// the .npmignore and discard the .gitignore if one is present
|
|
60
|
+
break
|
|
61
|
+
} catch (err) {
|
|
62
|
+
// we ignore ENOENT errors completely because we don't care if the file doesn't exist
|
|
63
|
+
// but we throw everything else because failing to read a file that does exist is
|
|
64
|
+
// something that the user likely wants to know about
|
|
65
|
+
// istanbul ignore next -- we do not need to test a thrown error
|
|
66
|
+
if (err.code !== 'ENOENT') {
|
|
67
|
+
throw err
|
|
175
68
|
}
|
|
176
|
-
|
|
177
|
-
super.onReadIgnoreFile(rootBuiltinRules, rules, _ => _)
|
|
178
|
-
} else {
|
|
179
|
-
this.bundled = []
|
|
180
|
-
this.bundledScopes = []
|
|
181
|
-
this.packageJsonCache = this.parent.packageJsonCache
|
|
182
69
|
}
|
|
183
70
|
}
|
|
184
71
|
|
|
185
|
-
|
|
186
|
-
return
|
|
72
|
+
if (!rel) {
|
|
73
|
+
return result
|
|
187
74
|
}
|
|
188
75
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
76
|
+
const firstRel = rel.split(sep, 1)[0]
|
|
77
|
+
const newRoot = join(root, firstRel)
|
|
78
|
+
const newRel = relative(newRoot, join(root, rel))
|
|
79
|
+
|
|
80
|
+
return readOutOfTreeIgnoreFiles(newRoot, newRel, result)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
class PackWalker extends IgnoreWalker {
|
|
84
|
+
constructor (opts) {
|
|
85
|
+
const options = {
|
|
86
|
+
...opts,
|
|
87
|
+
includeEmpty: false,
|
|
88
|
+
follow: false,
|
|
195
89
|
}
|
|
196
90
|
|
|
197
|
-
//
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
91
|
+
// we path.resolve() here because ignore-walk doesn't do it and we want full paths
|
|
92
|
+
options.path = resolve(options.path || process.cwd()).replace(/\\/g, '/')
|
|
93
|
+
|
|
94
|
+
if (!options.ignoreFiles) {
|
|
95
|
+
options.ignoreFiles = [
|
|
96
|
+
defaultRules,
|
|
97
|
+
'package.json',
|
|
98
|
+
'.npmignore',
|
|
99
|
+
'.gitignore',
|
|
100
|
+
strictRules,
|
|
101
|
+
]
|
|
205
102
|
}
|
|
206
103
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
104
|
+
super(options)
|
|
105
|
+
this.isPackage = options.isPackage
|
|
106
|
+
this.seen = options.seen || new Set()
|
|
107
|
+
this.tree = options.tree // no default, we'll load the tree later if we need to
|
|
108
|
+
this.requiredFiles = options.requiredFiles || []
|
|
109
|
+
|
|
110
|
+
const additionalDefaults = []
|
|
111
|
+
if (options.prefix && options.workspaces) {
|
|
112
|
+
const path = normalizePath(options.path)
|
|
113
|
+
const prefix = normalizePath(options.prefix)
|
|
114
|
+
const workspaces = options.workspaces.map((ws) => normalizePath(ws))
|
|
115
|
+
|
|
116
|
+
// istanbul ignore else - this does nothing unless we need it to
|
|
117
|
+
if (path !== prefix && workspaces.includes(path)) {
|
|
118
|
+
// if path and prefix are not the same directory, and workspaces has path in it
|
|
119
|
+
// then we know path is a workspace directory. in order to not drop ignore rules
|
|
120
|
+
// from directories between the workspaces root (prefix) and the workspace itself
|
|
121
|
+
// (path) we need to find and read those now
|
|
122
|
+
const relpath = relative(options.prefix, dirname(options.path))
|
|
123
|
+
additionalDefaults.push(...readOutOfTreeIgnoreFiles(options.prefix, relpath))
|
|
124
|
+
} else if (path === prefix) {
|
|
125
|
+
// on the other hand, if the path and prefix are the same, then we ignore workspaces
|
|
126
|
+
// so that we don't pack a workspace as part of the root project. append them as
|
|
127
|
+
// normalized relative paths from the root
|
|
128
|
+
additionalDefaults.push(...workspaces.map((w) => normalizePath(relative(options.path, w))))
|
|
129
|
+
}
|
|
130
|
+
}
|
|
210
131
|
|
|
211
|
-
|
|
212
|
-
|
|
132
|
+
// go ahead and inject the default rules now
|
|
133
|
+
this.injectRules(defaultRules, [...defaults, ...additionalDefaults])
|
|
213
134
|
|
|
214
|
-
|
|
215
|
-
if
|
|
216
|
-
|
|
217
|
-
|
|
135
|
+
if (!this.isPackage) {
|
|
136
|
+
// if this instance is not a package, then place some strict default rules, and append
|
|
137
|
+
// known required files for this directory
|
|
138
|
+
this.injectRules(strictRules, [
|
|
139
|
+
...strictDefaults,
|
|
140
|
+
...this.requiredFiles.map((file) => `!${file}`),
|
|
141
|
+
])
|
|
142
|
+
}
|
|
143
|
+
}
|
|
218
144
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
145
|
+
// overridden method: we intercept the reading of the package.json file here so that we can
|
|
146
|
+
// process it into both the package.json file rules as well as the strictRules synthetic rule set
|
|
147
|
+
addIgnoreFile (file, callback) {
|
|
148
|
+
// if we're adding anything other than package.json, then let ignore-walk handle it
|
|
149
|
+
if (file !== 'package.json' || !this.isPackage) {
|
|
150
|
+
return super.addIgnoreFile(file, callback)
|
|
222
151
|
}
|
|
223
152
|
|
|
224
|
-
this.
|
|
153
|
+
return this.processPackage(callback)
|
|
225
154
|
}
|
|
226
155
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
156
|
+
// overridden method: if we're done, but we're a package, then we also need to evaluate bundles
|
|
157
|
+
// before we actually emit our done event
|
|
158
|
+
emit (ev, data) {
|
|
159
|
+
if (ev !== 'done' || !this.isPackage) {
|
|
160
|
+
return super.emit(ev, data)
|
|
232
161
|
}
|
|
162
|
+
|
|
163
|
+
// we intentionally delay the done event while keeping the function sync here
|
|
164
|
+
// eslint-disable-next-line promise/catch-or-return, promise/always-return
|
|
165
|
+
this.gatherBundles().then(() => {
|
|
166
|
+
super.emit('done', this.result)
|
|
167
|
+
})
|
|
168
|
+
return true
|
|
233
169
|
}
|
|
234
170
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
for (const key in pkg.bin) {
|
|
246
|
-
files.push('/' + pkg.bin[key])
|
|
247
|
-
}
|
|
171
|
+
// overridden method: before actually filtering, we make sure that we've removed the rules for
|
|
172
|
+
// files that should no longer take effect due to our order of precedence
|
|
173
|
+
filterEntries () {
|
|
174
|
+
if (this.ignoreRules['package.json']) {
|
|
175
|
+
// package.json means no .npmignore or .gitignore
|
|
176
|
+
this.ignoreRules['.npmignore'] = null
|
|
177
|
+
this.ignoreRules['.gitignore'] = null
|
|
178
|
+
} else if (this.ignoreRules['.npmignore']) {
|
|
179
|
+
// .npmignore means no .gitignore
|
|
180
|
+
this.ignoreRules['.gitignore'] = null
|
|
248
181
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
'/npm-shrinkwrap.json',
|
|
252
|
-
'!/package-lock.json',
|
|
253
|
-
packageMustHaves
|
|
254
|
-
)
|
|
255
|
-
return files
|
|
182
|
+
|
|
183
|
+
return super.filterEntries()
|
|
256
184
|
}
|
|
257
185
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
// the test for bundleDependencies and bundledDependencies later.
|
|
263
|
-
// HOWEVER if we do this, we need to be sure that we're careful
|
|
264
|
-
// about what we write back out since rpj-fast removes some fields
|
|
265
|
-
// that the user likely wants to keep. it also would add a second
|
|
266
|
-
// file read that we would want to optimize away.
|
|
267
|
-
pkg = normalizePackageBin(JSON.parse(pkg.toString()))
|
|
268
|
-
} catch (er) {
|
|
269
|
-
// not actually a valid package.json
|
|
270
|
-
return super.onReaddir(entries)
|
|
186
|
+
// overridden method: we never want to include anything that isn't a file or directory
|
|
187
|
+
onstat (opts, callback) {
|
|
188
|
+
if (!opts.st.isFile() && !opts.st.isDirectory()) {
|
|
189
|
+
return callback()
|
|
271
190
|
}
|
|
272
191
|
|
|
273
|
-
|
|
274
|
-
|
|
192
|
+
return super.onstat(opts, callback)
|
|
193
|
+
}
|
|
275
194
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
195
|
+
// overridden method: we want to refuse to pack files that are invalid, node-tar protects us from
|
|
196
|
+
// a lot of them but not all
|
|
197
|
+
stat (opts, callback) {
|
|
198
|
+
if (nameIsBadForWindows(opts.entry)) {
|
|
199
|
+
return callback()
|
|
279
200
|
}
|
|
280
201
|
|
|
281
|
-
|
|
202
|
+
return super.stat(opts, callback)
|
|
203
|
+
}
|
|
282
204
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
205
|
+
// overridden method: we need to load the arborist tree before we actually start running
|
|
206
|
+
start () {
|
|
207
|
+
if (this.isPackage && !this.tree) {
|
|
208
|
+
const arborist = new Arborist({ path: this.path })
|
|
209
|
+
// loading the tree is async while the start function depends on being sync
|
|
210
|
+
// eslint-disable-next-line promise/catch-or-return, promise/always-return
|
|
211
|
+
arborist.loadActual().then((tree) => {
|
|
212
|
+
this.tree = tree
|
|
213
|
+
super.start()
|
|
214
|
+
})
|
|
215
|
+
return this
|
|
290
216
|
}
|
|
291
217
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
const set = new Set()
|
|
307
|
-
const negates = new Set()
|
|
308
|
-
const results = []
|
|
309
|
-
const then = (pattern, negate, er, fileList, i) => {
|
|
310
|
-
if (er) {
|
|
311
|
-
return this.emit('error', er)
|
|
312
|
-
}
|
|
218
|
+
return super.start()
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// overridden method: this is called to create options for a child walker when we step
|
|
222
|
+
// in to a normal child directory (this will never be a bundle). the default method here
|
|
223
|
+
// copies the root's `ignoreFiles` value, but we don't want to respect package.json for
|
|
224
|
+
// subdirectories, so we override it with a list that intentionally omits package.json
|
|
225
|
+
walkerOpt (entry, opts) {
|
|
226
|
+
let ignoreFiles = [
|
|
227
|
+
defaultRules,
|
|
228
|
+
'.npmignore',
|
|
229
|
+
'.gitignore',
|
|
230
|
+
strictRules,
|
|
231
|
+
]
|
|
313
232
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
233
|
+
// however, if we have a tree, and we have workspaces, and the directory we're about
|
|
234
|
+
// to step into is a workspace, then we _do_ want to respect its package.json
|
|
235
|
+
if (this.tree && this.tree.workspaces) {
|
|
236
|
+
const workspaceDirs = [...this.tree.workspaces.values()]
|
|
237
|
+
.map((dir) => dir.replace(/\\/g, '/'))
|
|
238
|
+
|
|
239
|
+
const entryPath = join(this.path, entry).replace(/\\/g, '/')
|
|
240
|
+
if (workspaceDirs.includes(entryPath)) {
|
|
241
|
+
ignoreFiles = [
|
|
242
|
+
defaultRules,
|
|
243
|
+
'package.json',
|
|
244
|
+
'.npmignore',
|
|
245
|
+
'.gitignore',
|
|
246
|
+
strictRules,
|
|
247
|
+
]
|
|
317
248
|
}
|
|
318
249
|
}
|
|
319
|
-
const processResults = processed => {
|
|
320
|
-
for (const { negate, fileList } of processed) {
|
|
321
|
-
if (negate) {
|
|
322
|
-
fileList.forEach(f => {
|
|
323
|
-
f = f.replace(/\/+$/, '')
|
|
324
|
-
set.delete(f)
|
|
325
|
-
negates.add(f)
|
|
326
|
-
})
|
|
327
|
-
} else {
|
|
328
|
-
fileList.forEach(f => {
|
|
329
|
-
f = f.replace(/\/+$/, '')
|
|
330
|
-
set.add(f)
|
|
331
|
-
negates.delete(f)
|
|
332
|
-
})
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
250
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
251
|
+
return {
|
|
252
|
+
...super.walkerOpt(entry, opts),
|
|
253
|
+
ignoreFiles,
|
|
254
|
+
// we map over our own requiredFiles and pass ones that are within this entry
|
|
255
|
+
requiredFiles: this.requiredFiles
|
|
256
|
+
.map((file) => {
|
|
257
|
+
if (relative(file, entry) === '..') {
|
|
258
|
+
return relative(entry, file).replace(/\\/g, '/')
|
|
259
|
+
}
|
|
260
|
+
return false
|
|
261
|
+
})
|
|
262
|
+
.filter(Boolean),
|
|
343
263
|
}
|
|
264
|
+
}
|
|
344
265
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
patterns.forEach(({ pattern, negate }, i) =>
|
|
349
|
-
this.globFiles(pattern, (er, res) => then(pattern, negate, er, res, i)))
|
|
266
|
+
// overridden method: we want child walkers to be instances of this class, not ignore-walk
|
|
267
|
+
walker (entry, opts, callback) {
|
|
268
|
+
new PackWalker(this.walkerOpt(entry, opts)).on('done', callback).start()
|
|
350
269
|
}
|
|
351
270
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
const
|
|
360
|
-
const
|
|
361
|
-
|
|
362
|
-
return (
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
this.basename + '/' + entry, partial)
|
|
366
|
-
|
|
367
|
-
// if package is bundled, all files included
|
|
368
|
-
// also include @scope dirs for bundled scoped deps
|
|
369
|
-
// they'll be ignored if no files end up in them.
|
|
370
|
-
// However, this only matters if we're in the root.
|
|
371
|
-
// node_modules folders elsewhere, like lib/node_modules,
|
|
372
|
-
// should be included normally unless ignored.
|
|
373
|
-
: pkg ? this.bundled.indexOf(pkg) !== -1 ||
|
|
374
|
-
this.bundledScopes.indexOf(pkg) !== -1
|
|
375
|
-
|
|
376
|
-
// only walk top node_modules if we want to bundle something
|
|
377
|
-
: rootNM ? !!this.bundled.length
|
|
378
|
-
|
|
379
|
-
// always include package.json at the root.
|
|
380
|
-
: rootPJ ? true
|
|
381
|
-
|
|
382
|
-
// always include readmes etc in any included dir
|
|
383
|
-
: packageMustHavesRE.test(entry) ? true
|
|
384
|
-
|
|
385
|
-
// npm-shrinkwrap and package.json always included in the root pkg
|
|
386
|
-
: isProject && (entry === 'npm-shrinkwrap.json' || entry === 'package.json')
|
|
387
|
-
? true
|
|
388
|
-
|
|
389
|
-
// package-lock never included
|
|
390
|
-
: isProject && entry === 'package-lock.json' ? false
|
|
391
|
-
|
|
392
|
-
// otherwise, follow ignore-walk's logic
|
|
393
|
-
: super.filterEntry(entry, partial)
|
|
394
|
-
)
|
|
271
|
+
// overridden method: we use a custom sort method to help compressibility
|
|
272
|
+
sort (a, b) {
|
|
273
|
+
// optimize for compressibility
|
|
274
|
+
// extname, then basename, then locale alphabetically
|
|
275
|
+
// https://twitter.com/isntitvacant/status/1131094910923231232
|
|
276
|
+
const exta = extname(a).toLowerCase()
|
|
277
|
+
const extb = extname(b).toLowerCase()
|
|
278
|
+
const basea = basename(a).toLowerCase()
|
|
279
|
+
const baseb = basename(b).toLowerCase()
|
|
280
|
+
|
|
281
|
+
return exta.localeCompare(extb, 'en') ||
|
|
282
|
+
basea.localeCompare(baseb, 'en') ||
|
|
283
|
+
a.localeCompare(b, 'en')
|
|
395
284
|
}
|
|
396
285
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
}
|
|
401
|
-
this.filterEntries = super.filterEntries
|
|
402
|
-
super.filterEntries()
|
|
286
|
+
// convenience method: this joins the given rules with newlines, appends a trailing newline,
|
|
287
|
+
// and calls the internal onReadIgnoreFile method
|
|
288
|
+
injectRules (filename, rules, callback = () => {}) {
|
|
289
|
+
this.onReadIgnoreFile(filename, `${rules.join('\n')}\n`, callback)
|
|
403
290
|
}
|
|
404
291
|
|
|
405
|
-
addIgnoreFile
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
292
|
+
// custom method: this is called by addIgnoreFile when we find a package.json, it uses the
|
|
293
|
+
// arborist tree to pull both default rules and strict rules for the package
|
|
294
|
+
processPackage (callback) {
|
|
295
|
+
const {
|
|
296
|
+
bin,
|
|
297
|
+
browser,
|
|
298
|
+
files,
|
|
299
|
+
main,
|
|
300
|
+
} = this.tree.package
|
|
301
|
+
|
|
302
|
+
// rules in these arrays are inverted since they are patterns we want to _not_ ignore
|
|
303
|
+
const ignores = []
|
|
304
|
+
const strict = [
|
|
305
|
+
...strictDefaults,
|
|
306
|
+
'!/package.json',
|
|
307
|
+
'!/npm-shrinkwrap.json',
|
|
308
|
+
'/.git',
|
|
309
|
+
'/node_modules',
|
|
310
|
+
'/package-lock.json',
|
|
311
|
+
'/yarn.lock',
|
|
312
|
+
'/pnpm-lock.yaml',
|
|
313
|
+
]
|
|
314
|
+
|
|
315
|
+
// if we have a files array in our package, we need to pull rules from it
|
|
316
|
+
if (files) {
|
|
317
|
+
for (const file of files) {
|
|
318
|
+
// invert the rule because these are things we want to include
|
|
319
|
+
const inverse = `!${file}`
|
|
320
|
+
try {
|
|
321
|
+
// if an entry in the files array is a specific file, then we need to include it as a
|
|
322
|
+
// strict requirement for this package. if it's a directory or a pattern, it's a default
|
|
323
|
+
// pattern instead. this is ugly, but we have to stat to find out if it's a file
|
|
324
|
+
const stat = lstat(join(this.path, file.replace(/^!+/, '')).replace(/\\/g, '/'))
|
|
325
|
+
// if we have a file and we know that, it's strictly required
|
|
326
|
+
if (stat.isFile()) {
|
|
327
|
+
strict.unshift(inverse)
|
|
328
|
+
this.requiredFiles.push(file.startsWith('/') ? file.slice(1) : file)
|
|
329
|
+
} else if (stat.isDirectory()) {
|
|
330
|
+
// otherwise, it's a default ignore, and since we got here we know it's not a pattern
|
|
331
|
+
// so we include the directory contents
|
|
332
|
+
ignores.push(inverse)
|
|
333
|
+
ignores.push(`${inverse}/**`)
|
|
334
|
+
}
|
|
335
|
+
// if the thing exists, but is neither a file or a directory, we don't want it at all
|
|
336
|
+
} catch (err) {
|
|
337
|
+
// if lstat throws, then we assume we're looking at a pattern and treat it as a default
|
|
338
|
+
ignores.push(inverse)
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// we prepend a '*' to exclude everything, followed by our inverted file rules
|
|
343
|
+
// which now mean to include those
|
|
344
|
+
this.injectRules('package.json', ['*', ...ignores])
|
|
413
345
|
}
|
|
414
|
-
}
|
|
415
346
|
|
|
416
|
-
|
|
417
|
-
|
|
347
|
+
// browser is required
|
|
348
|
+
if (browser) {
|
|
349
|
+
strict.push(`!/${browser}`)
|
|
350
|
+
}
|
|
418
351
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
f => '!' + f
|
|
423
|
-
).join('\n') + '\n', then)
|
|
424
|
-
} else {
|
|
425
|
-
// if there's a bin, browser or main, make sure we don't ignore it
|
|
426
|
-
// also, don't ignore the package.json itself, or any files that
|
|
427
|
-
// must be included in the package.
|
|
428
|
-
const rules = this.mustHaveFilesFromPackage(pkg).map(f => `!${f}`)
|
|
429
|
-
const data = rules.join('\n') + '\n'
|
|
430
|
-
super.onReadIgnoreFile(packageNecessaryRules, data, then)
|
|
352
|
+
// main is required
|
|
353
|
+
if (main) {
|
|
354
|
+
strict.push(`!/${main}`)
|
|
431
355
|
}
|
|
432
|
-
}
|
|
433
356
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
then()
|
|
440
|
-
} else {
|
|
441
|
-
super.stat({ entry, file, dir }, then)
|
|
357
|
+
// each bin is required
|
|
358
|
+
if (bin) {
|
|
359
|
+
for (const key in bin) {
|
|
360
|
+
strict.push(`!/${bin[key]}`)
|
|
361
|
+
}
|
|
442
362
|
}
|
|
363
|
+
|
|
364
|
+
// and now we add all of the strict rules to our synthetic file
|
|
365
|
+
this.injectRules(strictRules, strict, callback)
|
|
443
366
|
}
|
|
444
367
|
|
|
445
|
-
//
|
|
446
|
-
//
|
|
447
|
-
|
|
448
|
-
if (
|
|
449
|
-
|
|
450
|
-
} else {
|
|
451
|
-
super.onstat({ st, entry, file, dir, isSymbolicLink }, then)
|
|
368
|
+
// custom method: after we've finished gathering the files for the root package, we call this
|
|
369
|
+
// before emitting the 'done' event in order to gather all of the files for bundled deps
|
|
370
|
+
async gatherBundles () {
|
|
371
|
+
if (this.tree && this.seen.has(this.tree)) {
|
|
372
|
+
return
|
|
452
373
|
}
|
|
453
|
-
}
|
|
454
374
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
}
|
|
375
|
+
// add this node to our seen tracker
|
|
376
|
+
this.seen.add(this.tree)
|
|
377
|
+
|
|
378
|
+
// if we're the project root, then we look at our bundleDependencies, otherwise we got here
|
|
379
|
+
// because we're a bundled dependency of the root, which means we need to include all prod
|
|
380
|
+
// and optional dependencies in the bundle
|
|
381
|
+
let toBundle
|
|
382
|
+
if (this.tree.isProjectRoot) {
|
|
383
|
+
const { bundleDependencies } = this.tree.package
|
|
384
|
+
toBundle = bundleDependencies || []
|
|
464
385
|
} else {
|
|
465
|
-
|
|
386
|
+
const { dependencies, optionalDependencies } = this.tree.package
|
|
387
|
+
toBundle = Object.keys(dependencies || {}).concat(Object.keys(optionalDependencies || {}))
|
|
466
388
|
}
|
|
467
|
-
}
|
|
468
389
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
const baseb = path.basename(b).toLowerCase()
|
|
390
|
+
for (const dep of toBundle) {
|
|
391
|
+
const edge = this.tree.edgesOut.get(dep)
|
|
392
|
+
// no edgeOut = missing node, so skip it. we can't pack it if it's not here
|
|
393
|
+
// we also refuse to pack peer dependencies and dev dependencies
|
|
394
|
+
if (!edge || edge.peer || edge.dev) {
|
|
395
|
+
continue
|
|
396
|
+
}
|
|
477
397
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
398
|
+
// get a reference to the node we're bundling
|
|
399
|
+
const node = this.tree.edgesOut.get(dep).to
|
|
400
|
+
// and start building options to be passed to the walker for this package
|
|
401
|
+
const walkerOpts = {
|
|
402
|
+
// we use node.path for the path because we want the location the node was linked to,
|
|
403
|
+
// not where it actually lives on disk
|
|
404
|
+
path: node.path,
|
|
405
|
+
// but link nodes don't have edgesOut, so we need to pass in the target of the node
|
|
406
|
+
// in order to make sure we correctly traverse its dependencies
|
|
407
|
+
tree: node.target,
|
|
408
|
+
isPackage: true,
|
|
409
|
+
ignoreFiles: [],
|
|
410
|
+
seen: this.seen, // pass through seen so we can prevent infinite circular loops
|
|
411
|
+
}
|
|
482
412
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
413
|
+
// if our node is a link, we apply defaultRules. we don't do this for regular bundled
|
|
414
|
+
// deps because their .npmignore and .gitignore files are excluded by default and may
|
|
415
|
+
// override defaults
|
|
416
|
+
if (node.isLink) {
|
|
417
|
+
walkerOpts.ignoreFiles.push(defaultRules)
|
|
418
|
+
}
|
|
486
419
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
420
|
+
// _all_ nodes will follow package.json rules from their package root
|
|
421
|
+
walkerOpts.ignoreFiles.push('package.json')
|
|
422
|
+
|
|
423
|
+
// only link nodes will obey .npmignore or .gitignore
|
|
424
|
+
if (node.isLink) {
|
|
425
|
+
walkerOpts.ignoreFiles.push('.npmignore')
|
|
426
|
+
walkerOpts.ignoreFiles.push('.gitignore')
|
|
427
|
+
}
|
|
491
428
|
|
|
492
|
-
|
|
493
|
-
|
|
429
|
+
// _all_ nodes follow strict rules
|
|
430
|
+
walkerOpts.ignoreFiles.push(strictRules)
|
|
431
|
+
|
|
432
|
+
// create a walker for this dependency and gather its results
|
|
433
|
+
const walker = new PackWalker(walkerOpts)
|
|
434
|
+
const bundled = await new Promise((pResolve, pReject) => {
|
|
435
|
+
walker.on('error', pReject)
|
|
436
|
+
walker.on('done', pResolve)
|
|
437
|
+
walker.start()
|
|
438
|
+
})
|
|
439
|
+
|
|
440
|
+
// now we make sure we have our paths correct from the root, and accumulate everything into
|
|
441
|
+
// our own result set to deduplicate
|
|
442
|
+
const relativeFrom = relative(this.root, walker.path)
|
|
443
|
+
for (const file of bundled) {
|
|
444
|
+
this.result.add(join(relativeFrom, file).replace(/\\/g, '/'))
|
|
445
|
+
}
|
|
446
|
+
}
|
|
494
447
|
}
|
|
495
448
|
}
|
|
496
449
|
|
|
497
450
|
const walk = (options, callback) => {
|
|
498
|
-
options = options
|
|
499
|
-
const p = new Promise((
|
|
500
|
-
|
|
501
|
-
bw.on('done', bundled => {
|
|
502
|
-
options.bundled = bundled
|
|
503
|
-
options.packageJsonCache = bw.packageJsonCache
|
|
504
|
-
new Walker(options).on('done', resolve).on('error', reject).start()
|
|
505
|
-
})
|
|
506
|
-
bw.start()
|
|
451
|
+
options = { ...options, isPackage: true }
|
|
452
|
+
const p = new Promise((pResolve, pReject) => {
|
|
453
|
+
new PackWalker(options).on('done', pResolve).on('error', pReject).start()
|
|
507
454
|
})
|
|
508
455
|
return callback ? p.then(res => callback(null, res), callback) : p
|
|
509
456
|
}
|
|
510
457
|
|
|
511
458
|
module.exports = walk
|
|
512
|
-
walk.Walker =
|
|
459
|
+
walk.Walker = PackWalker
|
package/package.json
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "npm-packlist",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.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
|
-
"main": "lib",
|
|
8
|
+
"main": "lib/index.js",
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"
|
|
11
|
-
"ignore-walk": "^5.0.1"
|
|
12
|
-
"npm-bundled": "^2.0.0",
|
|
13
|
-
"npm-normalize-package-bin": "^2.0.0"
|
|
10
|
+
"@npmcli/arborist": "^5.0.4",
|
|
11
|
+
"ignore-walk": "^5.0.1"
|
|
14
12
|
},
|
|
15
13
|
"author": "GitHub Inc.",
|
|
16
14
|
"license": "ISC",
|
|
@@ -20,7 +18,7 @@
|
|
|
20
18
|
],
|
|
21
19
|
"devDependencies": {
|
|
22
20
|
"@npmcli/eslint-config": "^3.0.1",
|
|
23
|
-
"@npmcli/template-oss": "3.
|
|
21
|
+
"@npmcli/template-oss": "4.3.2",
|
|
24
22
|
"mutate-fs": "^2.1.1",
|
|
25
23
|
"tap": "^16.0.1"
|
|
26
24
|
},
|
|
@@ -29,9 +27,6 @@
|
|
|
29
27
|
"posttest": "npm run lint",
|
|
30
28
|
"snap": "tap",
|
|
31
29
|
"postsnap": "npm run lintfix --",
|
|
32
|
-
"preversion": "npm test",
|
|
33
|
-
"postversion": "npm publish",
|
|
34
|
-
"prepublishOnly": "git push origin --follow-tags",
|
|
35
30
|
"eslint": "eslint",
|
|
36
31
|
"lint": "eslint \"**/*.js\"",
|
|
37
32
|
"lintfix": "npm run lint -- --fix",
|
|
@@ -46,16 +41,20 @@
|
|
|
46
41
|
"tap": {
|
|
47
42
|
"test-env": [
|
|
48
43
|
"LC_ALL=sk"
|
|
44
|
+
],
|
|
45
|
+
"nyc-arg": [
|
|
46
|
+
"--exclude",
|
|
47
|
+
"tap-snapshots/**"
|
|
49
48
|
]
|
|
50
49
|
},
|
|
51
50
|
"bin": {
|
|
52
51
|
"npm-packlist": "bin/index.js"
|
|
53
52
|
},
|
|
54
53
|
"engines": {
|
|
55
|
-
"node": "^
|
|
54
|
+
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
|
56
55
|
},
|
|
57
56
|
"templateOSS": {
|
|
58
57
|
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
|
|
59
|
-
"version": "3.
|
|
58
|
+
"version": "4.3.2"
|
|
60
59
|
}
|
|
61
60
|
}
|