npm-pkg-lint 3.3.0 → 3.4.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 +31 -25
- package/dist/index.js +79 -35
- package/dist/index.js.map +3 -3
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -19,7 +19,8 @@ Core principles:
|
|
|
19
19
|
|
|
20
20
|
```
|
|
21
21
|
usage: index.js [-h] [-v] [-t TARBALL] [-p PKGFILE] [--cache CACHE]
|
|
22
|
-
[--allow-
|
|
22
|
+
[--allow-dependency DEPENDENCY] [--allow-types-dependencies]
|
|
23
|
+
[--ignore-missing-fields]
|
|
23
24
|
|
|
24
25
|
Opiniated linter for NPM package tarball and package.json metadata
|
|
25
26
|
|
|
@@ -31,8 +32,11 @@ optional arguments:
|
|
|
31
32
|
-p PKGFILE, --pkgfile PKGFILE
|
|
32
33
|
specify package.json location
|
|
33
34
|
--cache CACHE specify cache directory
|
|
35
|
+
--allow-dependency DEPENDENCY
|
|
36
|
+
explicitly allow given dependency (can be given
|
|
37
|
+
multiple times or as a comma-separated list)
|
|
34
38
|
--allow-types-dependencies
|
|
35
|
-
allow dependencies to `@types/*`
|
|
39
|
+
allow production dependencies to `@types/*`
|
|
36
40
|
--ignore-missing-fields
|
|
37
41
|
ignore errors for missing fields (but still checks for
|
|
38
42
|
empty and valid)
|
|
@@ -99,29 +103,7 @@ Examples of disallowed packages:
|
|
|
99
103
|
|
|
100
104
|
By default `@types/*` is disallowed but this can be disabled with `--allow-types-dependencies`.
|
|
101
105
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
Disallows certain packages from being included as `dependencies`, `devDependencies` or `peerDependencies` entirely.
|
|
105
|
-
These dependencies have native replacements supported by all supported NodeJS versions.
|
|
106
|
-
|
|
107
|
-
**Why?** Obsolete packages have native replacements and thus only clutter the dependency graphs thus increasing the time to install, the size on disk and produces noise with tools analyzing `package-lock.json`.
|
|
108
|
-
|
|
109
|
-
Examples of obsolete packages:
|
|
110
|
-
|
|
111
|
-
- `mkdirp` - `fs#mkdir` supports the `recursive` flag since NodeJS v10.
|
|
112
|
-
- `stable` - `Array#sort` is stable since NodeJS v12.
|
|
113
|
-
|
|
114
|
-
## Deprecated dependencies
|
|
115
|
-
|
|
116
|
-
Disallows deprecated packages from being included as `dependencies`, `devDependencies` or `peerDependencies` entirely.
|
|
117
|
-
These dependences are explicitly marked as deprecated by the package author.
|
|
118
|
-
|
|
119
|
-
**Why?** Deprecated packages should be removed or replaced with alternatives as they are often unmaintained and might contain security vulnerabilities.
|
|
120
|
-
|
|
121
|
-
Examples of obsolete packages:
|
|
122
|
-
|
|
123
|
-
- `mkdirp` - `fs#mkdir` supports the `recursive` flag since NodeJS v10.
|
|
124
|
-
- `stable` - `Array#sort` is stable since NodeJS v12.
|
|
106
|
+
If needed, `--allow-dependency` can be used to ignore one or more dependencies.
|
|
125
107
|
|
|
126
108
|
### ESLint
|
|
127
109
|
|
|
@@ -210,6 +192,30 @@ If your `package.json` contains the `"prettier"` keyword the Prettier packages c
|
|
|
210
192
|
}
|
|
211
193
|
```
|
|
212
194
|
|
|
195
|
+
## Obsolete dependencies
|
|
196
|
+
|
|
197
|
+
Disallows certain packages from being included as `dependencies`, `devDependencies` or `peerDependencies` entirely.
|
|
198
|
+
These dependencies have native replacements supported by all supported NodeJS versions.
|
|
199
|
+
|
|
200
|
+
**Why?** Obsolete packages have native replacements and thus only clutter the dependency graphs thus increasing the time to install, the size on disk and produces noise with tools analyzing `package-lock.json`.
|
|
201
|
+
|
|
202
|
+
Examples of obsolete packages:
|
|
203
|
+
|
|
204
|
+
- `mkdirp` - `fs#mkdir` supports the `recursive` flag since NodeJS v10.
|
|
205
|
+
- `stable` - `Array#sort` is stable since NodeJS v12.
|
|
206
|
+
|
|
207
|
+
## Deprecated dependencies
|
|
208
|
+
|
|
209
|
+
Disallows deprecated packages from being included as `dependencies`, `devDependencies` or `peerDependencies` entirely.
|
|
210
|
+
These dependences are explicitly marked as deprecated by the package author.
|
|
211
|
+
|
|
212
|
+
**Why?** Deprecated packages should be removed or replaced with alternatives as they are often unmaintained and might contain security vulnerabilities.
|
|
213
|
+
|
|
214
|
+
Examples of obsolete packages:
|
|
215
|
+
|
|
216
|
+
- `mkdirp` - `fs#mkdir` supports the `recursive` flag since NodeJS v10.
|
|
217
|
+
- `stable` - `Array#sort` is stable since NodeJS v12.
|
|
218
|
+
|
|
213
219
|
## Shebang
|
|
214
220
|
|
|
215
221
|
Require all binaries to have UNIX-style shebang at the beginning of the file.
|
package/dist/index.js
CHANGED
|
@@ -12365,7 +12365,7 @@ var require_merge_stream = __commonJS({
|
|
|
12365
12365
|
var import_argparse = __toESM(require_argparse(), 1);
|
|
12366
12366
|
import { existsSync, createWriteStream as createWriteStream2, readFileSync as readFileSync2, promises as fs4 } from "fs";
|
|
12367
12367
|
import path7 from "path";
|
|
12368
|
-
import { fileURLToPath as
|
|
12368
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
12369
12369
|
|
|
12370
12370
|
// node_modules/find-up/index.js
|
|
12371
12371
|
import path2 from "path";
|
|
@@ -13327,14 +13327,14 @@ function validateUrl(key, value) {
|
|
|
13327
13327
|
if (value !== value.trim()) {
|
|
13328
13328
|
throw new Error(`"${key}.url" must not have leading or trailing whitespace`);
|
|
13329
13329
|
}
|
|
13330
|
-
const
|
|
13331
|
-
if (
|
|
13330
|
+
const url = new URL(value);
|
|
13331
|
+
if (url.protocol === "git+http:" || url.protocol === "http:") {
|
|
13332
13332
|
throw new Error(`"${key}.url" must use "git+https://" instead of "http://"`);
|
|
13333
13333
|
}
|
|
13334
|
-
if (
|
|
13334
|
+
if (url.protocol !== "git+https:") {
|
|
13335
13335
|
throw new Error(`"${key}.url" must use "git+https://" protocol`);
|
|
13336
13336
|
}
|
|
13337
|
-
if (
|
|
13337
|
+
if (url.host === "") {
|
|
13338
13338
|
throw new Error(`"${key}.url" be a valid url`);
|
|
13339
13339
|
}
|
|
13340
13340
|
}
|
|
@@ -13407,7 +13407,7 @@ function stripFinalNewline(input) {
|
|
|
13407
13407
|
// node_modules/execa/node_modules/npm-run-path/index.js
|
|
13408
13408
|
import process3 from "process";
|
|
13409
13409
|
import path3 from "path";
|
|
13410
|
-
import
|
|
13410
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
13411
13411
|
|
|
13412
13412
|
// node_modules/execa/node_modules/path-key/index.js
|
|
13413
13413
|
function pathKey(options = {}) {
|
|
@@ -13422,31 +13422,43 @@ function pathKey(options = {}) {
|
|
|
13422
13422
|
}
|
|
13423
13423
|
|
|
13424
13424
|
// node_modules/execa/node_modules/npm-run-path/index.js
|
|
13425
|
-
|
|
13426
|
-
|
|
13427
|
-
|
|
13428
|
-
|
|
13429
|
-
|
|
13430
|
-
|
|
13431
|
-
|
|
13432
|
-
const cwdString = cwd instanceof URL ?
|
|
13433
|
-
|
|
13425
|
+
var npmRunPath = ({
|
|
13426
|
+
cwd = process3.cwd(),
|
|
13427
|
+
path: pathOption = process3.env[pathKey()],
|
|
13428
|
+
preferLocal = true,
|
|
13429
|
+
execPath = process3.execPath,
|
|
13430
|
+
addExecPath = true
|
|
13431
|
+
} = {}) => {
|
|
13432
|
+
const cwdString = cwd instanceof URL ? fileURLToPath3(cwd) : cwd;
|
|
13433
|
+
const cwdPath = path3.resolve(cwdString);
|
|
13434
13434
|
const result = [];
|
|
13435
|
+
if (preferLocal) {
|
|
13436
|
+
applyPreferLocal(result, cwdPath);
|
|
13437
|
+
}
|
|
13438
|
+
if (addExecPath) {
|
|
13439
|
+
applyExecPath(result, execPath, cwdPath);
|
|
13440
|
+
}
|
|
13441
|
+
return [...result, pathOption].join(path3.delimiter);
|
|
13442
|
+
};
|
|
13443
|
+
var applyPreferLocal = (result, cwdPath) => {
|
|
13444
|
+
let previous;
|
|
13435
13445
|
while (previous !== cwdPath) {
|
|
13436
13446
|
result.push(path3.join(cwdPath, "node_modules/.bin"));
|
|
13437
13447
|
previous = cwdPath;
|
|
13438
13448
|
cwdPath = path3.resolve(cwdPath, "..");
|
|
13439
13449
|
}
|
|
13440
|
-
|
|
13441
|
-
|
|
13442
|
-
|
|
13443
|
-
|
|
13450
|
+
};
|
|
13451
|
+
var applyExecPath = (result, execPath, cwdPath) => {
|
|
13452
|
+
const execPathString = execPath instanceof URL ? fileURLToPath3(execPath) : execPath;
|
|
13453
|
+
result.push(path3.resolve(cwdPath, execPathString, ".."));
|
|
13454
|
+
};
|
|
13455
|
+
var npmRunPathEnv = ({ env = process3.env, ...options } = {}) => {
|
|
13444
13456
|
env = { ...env };
|
|
13445
|
-
const
|
|
13446
|
-
options.path = env[
|
|
13447
|
-
env[
|
|
13457
|
+
const pathName = pathKey({ env });
|
|
13458
|
+
options.path = env[pathName];
|
|
13459
|
+
env[pathName] = npmRunPath(options);
|
|
13448
13460
|
return env;
|
|
13449
|
-
}
|
|
13461
|
+
};
|
|
13450
13462
|
|
|
13451
13463
|
// node_modules/execa/node_modules/mimic-fn/index.js
|
|
13452
13464
|
var copyProperty = (to, from, property, ignoreNonConfigurable) => {
|
|
@@ -15076,7 +15088,12 @@ var ruleId2 = "no-deprecated-dependency";
|
|
|
15076
15088
|
function* getDependencies(pkg) {
|
|
15077
15089
|
const { dependencies = {}, devDependencies = {}, peerDependencies = {} } = pkg;
|
|
15078
15090
|
const allDependencies = { ...dependencies, ...devDependencies, ...peerDependencies };
|
|
15079
|
-
for (
|
|
15091
|
+
for (let [key, version2] of Object.entries(allDependencies)) {
|
|
15092
|
+
if (version2.startsWith("npm:")) {
|
|
15093
|
+
const [newKey, newVersion] = version2.slice("npm:".length).split("@", 2);
|
|
15094
|
+
key = newKey;
|
|
15095
|
+
version2 = newVersion;
|
|
15096
|
+
}
|
|
15080
15097
|
if (key === "@types/node") {
|
|
15081
15098
|
continue;
|
|
15082
15099
|
}
|
|
@@ -15297,8 +15314,8 @@ function* outdatedEngines(pkg) {
|
|
|
15297
15314
|
if (!import_semver2.default.satisfies(expanded, range)) {
|
|
15298
15315
|
continue;
|
|
15299
15316
|
}
|
|
15300
|
-
const nodeRelease = ((parsed == null ? void 0 : parsed.major) ?? 0) || `0.${(parsed == null ? void 0 : parsed.minor) ?? ""}`;
|
|
15301
|
-
const message = `engines.node is satisfied by Node ${nodeRelease} (EOL since ${descriptor.eol})`;
|
|
15317
|
+
const nodeRelease = ((parsed == null ? void 0 : parsed.major) ?? 0) || `0.${String((parsed == null ? void 0 : parsed.minor) ?? "")}`;
|
|
15318
|
+
const message = `engines.node is satisfied by Node ${String(nodeRelease)} (EOL since ${descriptor.eol})`;
|
|
15302
15319
|
yield {
|
|
15303
15320
|
ruleId: ruleId4,
|
|
15304
15321
|
severity: severity2,
|
|
@@ -15318,7 +15335,12 @@ async function* getDeepDependencies(pkg, dependency) {
|
|
|
15318
15335
|
if (!pkgData) {
|
|
15319
15336
|
return;
|
|
15320
15337
|
}
|
|
15321
|
-
for (
|
|
15338
|
+
for (let [key, version2] of Object.entries(pkgData.dependencies ?? {})) {
|
|
15339
|
+
if (version2.startsWith("npm:")) {
|
|
15340
|
+
const [newKey, newVersion] = version2.slice("npm:".length).split("@", 2);
|
|
15341
|
+
key = newKey;
|
|
15342
|
+
version2 = newVersion;
|
|
15343
|
+
}
|
|
15322
15344
|
if (key === "@types/node") {
|
|
15323
15345
|
continue;
|
|
15324
15346
|
}
|
|
@@ -15412,10 +15434,12 @@ function* typesNodeMatchingEngine(pkg) {
|
|
|
15412
15434
|
return;
|
|
15413
15435
|
}
|
|
15414
15436
|
if (typesVersion.major !== nodeVersion.major) {
|
|
15437
|
+
const actualVersion = `v${String(typesVersion.major)}`;
|
|
15438
|
+
const expectedVersion = `v${String(nodeVersion.major)}`;
|
|
15415
15439
|
yield {
|
|
15416
15440
|
ruleId: ruleId6,
|
|
15417
15441
|
severity: severity3,
|
|
15418
|
-
message: `@types/node
|
|
15442
|
+
message: `@types/node ${actualVersion} does not equal engines.node ${expectedVersion}`,
|
|
15419
15443
|
line: 1,
|
|
15420
15444
|
column: 1
|
|
15421
15445
|
};
|
|
@@ -15458,19 +15482,31 @@ function verifyFields(pkg, options) {
|
|
|
15458
15482
|
}
|
|
15459
15483
|
return messages;
|
|
15460
15484
|
}
|
|
15485
|
+
function getActualDependency(key, version2) {
|
|
15486
|
+
if (version2.startsWith("npm:")) {
|
|
15487
|
+
const [name] = version2.slice("npm:".length).split("@", 2);
|
|
15488
|
+
return name;
|
|
15489
|
+
}
|
|
15490
|
+
return key;
|
|
15491
|
+
}
|
|
15461
15492
|
function verifyDependencies(pkg, options) {
|
|
15462
15493
|
const messages = [];
|
|
15463
15494
|
const { dependencies = {}, devDependencies = {}, peerDependencies = {} } = pkg;
|
|
15464
15495
|
const allDependencies = { ...dependencies, ...devDependencies, ...peerDependencies };
|
|
15465
|
-
for (const
|
|
15496
|
+
for (const [key, version2] of Object.entries(dependencies)) {
|
|
15497
|
+
const dependency = getActualDependency(key, version2);
|
|
15498
|
+
if (options.allowedDependencies.has(dependency)) {
|
|
15499
|
+
continue;
|
|
15500
|
+
}
|
|
15466
15501
|
if (options.allowTypesDependencies && dependency.match(/^@types\//)) {
|
|
15467
15502
|
continue;
|
|
15468
15503
|
}
|
|
15469
15504
|
if (isDisallowedDependency(pkg, dependency)) {
|
|
15505
|
+
const name = key === dependency ? dependency : `"${key}" ("npm:${dependency}")`;
|
|
15470
15506
|
messages.push({
|
|
15471
15507
|
ruleId: "disallowed-dependency",
|
|
15472
15508
|
severity: 2,
|
|
15473
|
-
message:
|
|
15509
|
+
message: `"${name}" should be a devDependency`,
|
|
15474
15510
|
line: 1,
|
|
15475
15511
|
column: 1
|
|
15476
15512
|
});
|
|
@@ -15482,7 +15518,7 @@ function verifyDependencies(pkg, options) {
|
|
|
15482
15518
|
messages.push({
|
|
15483
15519
|
ruleId: "obsolete-dependency",
|
|
15484
15520
|
severity: 2,
|
|
15485
|
-
message:
|
|
15521
|
+
message: `"${dependency}" is obsolete and should no longer be used: ${obsolete2.message}`,
|
|
15486
15522
|
line: 1,
|
|
15487
15523
|
column: 1
|
|
15488
15524
|
});
|
|
@@ -15490,7 +15526,7 @@ function verifyDependencies(pkg, options) {
|
|
|
15490
15526
|
}
|
|
15491
15527
|
return messages;
|
|
15492
15528
|
}
|
|
15493
|
-
async function verifyPackageJson(pkg, filePath, options = {}) {
|
|
15529
|
+
async function verifyPackageJson(pkg, filePath, options = { allowedDependencies: /* @__PURE__ */ new Set() }) {
|
|
15494
15530
|
const messages = [
|
|
15495
15531
|
...await deprecatedDependency(pkg),
|
|
15496
15532
|
...await verifyEngineConstraint(pkg),
|
|
@@ -15552,7 +15588,7 @@ async function verifyShebang(pkg, tarball) {
|
|
|
15552
15588
|
}
|
|
15553
15589
|
|
|
15554
15590
|
// src/verify.ts
|
|
15555
|
-
async function verify(pkg, pkgPath, tarball, options
|
|
15591
|
+
async function verify(pkg, pkgPath, tarball, options) {
|
|
15556
15592
|
return [
|
|
15557
15593
|
...await verifyTarball(pkg, tarball),
|
|
15558
15594
|
...await verifyPackageJson(pkg, pkgPath, options),
|
|
@@ -15571,7 +15607,7 @@ function tarballLocation(pkg, pkgPath) {
|
|
|
15571
15607
|
}
|
|
15572
15608
|
|
|
15573
15609
|
// src/index.ts
|
|
15574
|
-
var pkgFilepath =
|
|
15610
|
+
var pkgFilepath = fileURLToPath4(new URL("../package.json", import.meta.url));
|
|
15575
15611
|
var { version } = JSON.parse(readFileSync2(pkgFilepath, "utf-8"));
|
|
15576
15612
|
var PACKAGE_JSON = "package.json";
|
|
15577
15613
|
async function preloadStdin() {
|
|
@@ -15628,15 +15664,22 @@ async function run() {
|
|
|
15628
15664
|
parser.add_argument("-t", "--tarball", { help: "specify tarball location" });
|
|
15629
15665
|
parser.add_argument("-p", "--pkgfile", { help: "specify package.json location" });
|
|
15630
15666
|
parser.add_argument("--cache", { help: "specify cache directory" });
|
|
15667
|
+
parser.add_argument("--allow-dependency", {
|
|
15668
|
+
action: "append",
|
|
15669
|
+
default: [],
|
|
15670
|
+
metavar: "DEPENDENCY",
|
|
15671
|
+
help: "explicitly allow given dependency (can be given multiple times or as a comma-separated list)"
|
|
15672
|
+
});
|
|
15631
15673
|
parser.add_argument("--allow-types-dependencies", {
|
|
15632
15674
|
action: "store_true",
|
|
15633
|
-
help: "allow dependencies to `@types/*`"
|
|
15675
|
+
help: "allow production dependencies to `@types/*`"
|
|
15634
15676
|
});
|
|
15635
15677
|
parser.add_argument("--ignore-missing-fields", {
|
|
15636
15678
|
action: "store_true",
|
|
15637
15679
|
help: "ignore errors for missing fields (but still checks for empty and valid)"
|
|
15638
15680
|
});
|
|
15639
15681
|
const args = parser.parse_args();
|
|
15682
|
+
const allowedDependencies2 = new Set(args.allow_dependency.map((it) => it.split(",")).flat());
|
|
15640
15683
|
if (args.cache) {
|
|
15641
15684
|
await setCacheDirecory(args.cache);
|
|
15642
15685
|
}
|
|
@@ -15662,6 +15705,7 @@ async function run() {
|
|
|
15662
15705
|
}
|
|
15663
15706
|
setupBlacklist(pkg.name);
|
|
15664
15707
|
const options = {
|
|
15708
|
+
allowedDependencies: allowedDependencies2,
|
|
15665
15709
|
allowTypesDependencies: args.allow_types_dependencies,
|
|
15666
15710
|
ignoreMissingFields: args.ignore_missing_fields
|
|
15667
15711
|
};
|