eslint-plugin-node-dependencies 1.1.1 → 1.2.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 CHANGED
@@ -158,6 +158,7 @@ The rules with the following star :star: are included in the `plugin:node-depend
158
158
  | [node-dependencies/absolute-version](https://ota-meshi.github.io/eslint-plugin-node-dependencies/rules/absolute-version.html) | require or disallow absolute version of dependency. | |
159
159
  | [node-dependencies/no-deprecated](https://ota-meshi.github.io/eslint-plugin-node-dependencies/rules/no-deprecated.html) | disallow having dependencies on deprecate packages. | |
160
160
  | [node-dependencies/no-restricted-deps](https://ota-meshi.github.io/eslint-plugin-node-dependencies/rules/no-restricted-deps.html) | Disallows dependence on the specified package. | |
161
+ | [node-dependencies/require-provenance-deps](https://ota-meshi.github.io/eslint-plugin-node-dependencies/rules/require-provenance-deps.html) | Require provenance information for dependencies | |
161
162
 
162
163
  ### Stylistic Issues
163
164
 
@@ -1,4 +1,4 @@
1
- import type { ESLint, Linter } from "eslint";
1
+ import type { ESLint } from "eslint";
2
2
  import * as jsonParser from "jsonc-eslint-parser";
3
3
  export declare const recommendedConfig: ({
4
4
  plugins: {
@@ -12,6 +12,6 @@ export declare const recommendedConfig: ({
12
12
  languageOptions: {
13
13
  parser: typeof jsonParser;
14
14
  };
15
- rules: Linter.RulesRecord;
15
+ rules: import("@eslint/core").RulesConfig;
16
16
  plugins?: undefined;
17
17
  })[];
@@ -3,7 +3,7 @@ declare const _default: {
3
3
  overrides: {
4
4
  files: string[];
5
5
  parser: string;
6
- rules: import("eslint").Linter.RulesRecord;
6
+ rules: import("@eslint/core").RulesConfig;
7
7
  }[];
8
8
  };
9
9
  export = _default;
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ declare const _default: {
8
8
  overrides: {
9
9
  files: string[];
10
10
  parser: string;
11
- rules: import("eslint").Linter.RulesRecord;
11
+ rules: import("@eslint/core").RulesConfig;
12
12
  }[];
13
13
  };
14
14
  "flat/recommended": ({
@@ -23,7 +23,7 @@ declare const _default: {
23
23
  languageOptions: {
24
24
  parser: typeof import("jsonc-eslint-parser");
25
25
  };
26
- rules: import("eslint").Linter.RulesRecord;
26
+ rules: import("@eslint/core").RulesConfig;
27
27
  plugins?: undefined;
28
28
  })[];
29
29
  };
@@ -0,0 +1,2 @@
1
+ declare const _default: import("../types").RuleModule;
2
+ export default _default;
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("../utils");
4
+ const jsonc_eslint_parser_1 = require("jsonc-eslint-parser");
5
+ const ast_utils_1 = require("../utils/ast-utils");
6
+ const meta_1 = require("../utils/meta");
7
+ exports.default = (0, utils_1.createRule)("require-provenance-deps", {
8
+ meta: {
9
+ docs: {
10
+ description: "Require provenance information for dependencies",
11
+ category: "Best Practices",
12
+ recommended: false,
13
+ },
14
+ schema: [
15
+ {
16
+ type: "object",
17
+ properties: {
18
+ devDependencies: { type: "boolean" },
19
+ allows: {
20
+ type: "array",
21
+ items: { type: "string" },
22
+ uniqueItems: true,
23
+ },
24
+ },
25
+ additionalProperties: false,
26
+ },
27
+ ],
28
+ messages: {
29
+ missingProvenance: 'Dependency "{{name}}" has versions without provenance information: {{versions}}.',
30
+ },
31
+ type: "suggestion",
32
+ },
33
+ create(context) {
34
+ var _a;
35
+ const sourceCode = context.getSourceCode();
36
+ if (!sourceCode.parserServices.isJSON) {
37
+ return {};
38
+ }
39
+ const devDependencies = Boolean((_a = context.options[0]) === null || _a === void 0 ? void 0 : _a.devDependencies);
40
+ function extractNoProvenanceRanges(meta) {
41
+ var _a, _b;
42
+ const noProvenanceRanges = [];
43
+ let prev = null;
44
+ for (let index = 0; index < meta.length; index++) {
45
+ const m = meta[index];
46
+ if ((_b = (_a = m.dist) === null || _a === void 0 ? void 0 : _a.attestations) === null || _b === void 0 ? void 0 : _b.provenance) {
47
+ prev = null;
48
+ continue;
49
+ }
50
+ if (prev == null) {
51
+ prev = [m.version, m.version];
52
+ noProvenanceRanges.push(prev);
53
+ }
54
+ else {
55
+ prev[1] = m.version;
56
+ }
57
+ }
58
+ return noProvenanceRanges;
59
+ }
60
+ return (0, utils_1.defineJsonVisitor)({
61
+ [devDependencies
62
+ ? "dependencies, peerDependencies, devDependencies"
63
+ : "dependencies, peerDependencies"](node) {
64
+ var _a, _b;
65
+ const name = (0, ast_utils_1.getKeyFromJSONProperty)(node);
66
+ const ver = (0, jsonc_eslint_parser_1.getStaticJSONValue)(node.value);
67
+ if (typeof name !== "string" || typeof ver !== "string" || !ver) {
68
+ return;
69
+ }
70
+ if ((_b = (_a = context.options[0]) === null || _a === void 0 ? void 0 : _a.allows) === null || _b === void 0 ? void 0 : _b.includes(name)) {
71
+ return;
72
+ }
73
+ const meta = (0, meta_1.getMetaFromNpm)(name, ver).get();
74
+ if (!meta || !meta.length) {
75
+ return;
76
+ }
77
+ const noProvenanceRanges = extractNoProvenanceRanges(meta);
78
+ if (noProvenanceRanges.length === 0) {
79
+ return;
80
+ }
81
+ context.report({
82
+ loc: node.loc,
83
+ messageId: "missingProvenance",
84
+ data: {
85
+ name,
86
+ versions: formatList(noProvenanceRanges.map(([from, to]) => from === to ? `${from}` : `${from} - ${to}`)),
87
+ },
88
+ });
89
+ },
90
+ });
91
+ function formatList(items) {
92
+ return items.length <= 2
93
+ ? items.join(" and ")
94
+ : `${items.slice(0, -1).join(", ")}, and ${items[items.length - 1]}`;
95
+ }
96
+ },
97
+ });
@@ -12,6 +12,11 @@ export type NpmPackageMeta = PackageMeta & {
12
12
  "dist-tags": {
13
13
  [key: string]: string | void;
14
14
  } | undefined;
15
+ dist?: {
16
+ attestations?: {
17
+ provenance?: Record<string, unknown>;
18
+ };
19
+ };
15
20
  };
16
21
  export declare function getMetaFromNodeModules(name: string, ver: string, options: {
17
22
  context: Rule.RuleContext;
@@ -48,6 +48,7 @@ const semver_2 = require("semver");
48
48
  const npm_package_arg_1 = __importDefault(require("npm-package-arg"));
49
49
  const package_json_1 = require("./package-json");
50
50
  const TTL = 1000 * 60 * 60;
51
+ const CACHE_VERSION = 2;
51
52
  const CACHED_META_ROOT = path_1.default.join(__dirname, `../../.cached_meta`);
52
53
  function getMetaFromNodeModules(name, ver, options) {
53
54
  try {
@@ -176,7 +177,10 @@ function getMetaFromName(name, cachedFilePath) {
176
177
  return null;
177
178
  }
178
179
  const data = require(cachedFilePath);
179
- if (data.meta == null) {
180
+ if (!data || data.meta == null) {
181
+ return null;
182
+ }
183
+ if (data.v !== CACHE_VERSION) {
180
184
  return null;
181
185
  }
182
186
  const alive = Boolean((typeof data.expired === "number" && data.expired >= Date.now()) ||
@@ -202,6 +206,7 @@ function getMetaFromNameWithoutCache(name, cachedFilePath) {
202
206
  optionalDependencies: vm.optionalDependencies,
203
207
  "dist-tags": allMeta["dist-tags"],
204
208
  deprecated: vm.deprecated,
209
+ dist: vm.dist,
205
210
  };
206
211
  });
207
212
  }
@@ -210,6 +215,7 @@ function getMetaFromNameWithoutCache(name, cachedFilePath) {
210
215
  }
211
216
  const timestamp = Date.now();
212
217
  const content = {
218
+ v: CACHE_VERSION,
213
219
  meta,
214
220
  timestamp,
215
221
  expired: timestamp + Math.floor(Math.random() * 1000 * 60),
@@ -11,6 +11,7 @@ const no_dupe_deps_1 = __importDefault(require("../rules/no-dupe-deps"));
11
11
  const no_restricted_deps_1 = __importDefault(require("../rules/no-restricted-deps"));
12
12
  const prefer_caret_range_version_1 = __importDefault(require("../rules/prefer-caret-range-version"));
13
13
  const prefer_tilde_range_version_1 = __importDefault(require("../rules/prefer-tilde-range-version"));
14
+ const require_provenance_deps_1 = __importDefault(require("../rules/require-provenance-deps"));
14
15
  const valid_engines_1 = __importDefault(require("../rules/valid-engines"));
15
16
  const valid_semver_1 = __importDefault(require("../rules/valid-semver"));
16
17
  exports.rules = [
@@ -21,6 +22,7 @@ exports.rules = [
21
22
  no_restricted_deps_1.default,
22
23
  prefer_caret_range_version_1.default,
23
24
  prefer_tilde_range_version_1.default,
25
+ require_provenance_deps_1.default,
24
26
  valid_engines_1.default,
25
27
  valid_semver_1.default,
26
28
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-node-dependencies",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "ESLint plugin to check Node.js dependencies.",
5
5
  "repository": "git+https://github.com/ota-meshi/eslint-plugin-node-dependencies.git",
6
6
  "homepage": "https://github.com/ota-meshi/eslint-plugin-node-dependencies#readme",
@@ -29,9 +29,6 @@
29
29
  "dependencies",
30
30
  "json"
31
31
  ],
32
- "scripts": {
33
- "preinstall": "npx only-allow npm"
34
- },
35
32
  "peerDependencies": {
36
33
  "eslint": ">=6.0.0"
37
34
  },