From a6c240de244b0e94ace4a518f2c67876a91f5882 Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Tue, 26 Dec 2023 22:35:15 +0100 Subject: [PATCH 01/14] feat!: Set default `schema: []`, drop support for function-style rules (#139) * drop support for function-style rules * implement schema changes * add unit tests for ConfigValidator#getRuleOptionsSchema * add regression tests for ConfigValidator#validateRuleOptions * add tests for error code * update fixture rules to use object-style --- lib/config-array/config-array.js | 19 +- lib/shared/config-validator.js | 81 ++++-- tests/fixtures/rules/custom-rule.cjs | 24 +- tests/fixtures/rules/dir1/no-strings.cjs | 17 +- tests/fixtures/rules/dir2/no-literals.cjs | 15 +- .../fixtures/rules/make-syntax-error-rule.cjs | 30 +- tests/fixtures/rules/wrong/custom-rule.cjs | 8 +- tests/lib/shared/config-validator.js | 256 ++++++++++++++++++ 8 files changed, 374 insertions(+), 76 deletions(-) create mode 100644 tests/lib/shared/config-validator.js diff --git a/lib/config-array/config-array.js b/lib/config-array/config-array.js index 133f5a24..5766fc46 100644 --- a/lib/config-array/config-array.js +++ b/lib/config-array/config-array.js @@ -319,31 +319,18 @@ function createConfig(instance, indices) { * @param {string} pluginId The plugin ID for prefix. * @param {Record} defs The definitions to collect. * @param {Map} map The map to output. - * @param {function(T): U} [normalize] The normalize function for each value. * @returns {void} */ -function collect(pluginId, defs, map, normalize) { +function collect(pluginId, defs, map) { if (defs) { const prefix = pluginId && `${pluginId}/`; for (const [key, value] of Object.entries(defs)) { - map.set( - `${prefix}${key}`, - normalize ? normalize(value) : value - ); + map.set(`${prefix}${key}`, value); } } } -/** - * Normalize a rule definition. - * @param {Function|Rule} rule The rule definition to normalize. - * @returns {Rule} The normalized rule definition. - */ -function normalizePluginRule(rule) { - return typeof rule === "function" ? { create: rule } : rule; -} - /** * Delete the mutation methods from a given map. * @param {Map} map The map object to delete. @@ -385,7 +372,7 @@ function initPluginMemberMaps(elements, slots) { collect(pluginId, plugin.environments, slots.envMap); collect(pluginId, plugin.processors, slots.processorMap); - collect(pluginId, plugin.rules, slots.ruleMap, normalizePluginRule); + collect(pluginId, plugin.rules, slots.ruleMap); } } diff --git a/lib/shared/config-validator.js b/lib/shared/config-validator.js index 32174a56..531ccbf7 100644 --- a/lib/shared/config-validator.js +++ b/lib/shared/config-validator.js @@ -5,6 +5,12 @@ /* eslint class-methods-use-this: "off" */ +//------------------------------------------------------------------------------ +// Typedefs +//------------------------------------------------------------------------------ + +/** @typedef {import("../shared/types").Rule} Rule */ + //------------------------------------------------------------------------------ // Requirements //------------------------------------------------------------------------------ @@ -33,6 +39,13 @@ const severityMap = { const validated = new WeakSet(); +// JSON schema that disallows passing any options +const noOptionsSchema = Object.freeze({ + type: "array", + minItems: 0, + maxItems: 0 +}); + //----------------------------------------------------------------------------- // Exports //----------------------------------------------------------------------------- @@ -44,17 +57,36 @@ export default class ConfigValidator { /** * Gets a complete options schema for a rule. - * @param {{create: Function, schema: (Array|null)}} rule A new-style rule object - * @returns {Object} JSON Schema for the rule's options. + * @param {Rule} rule A rule object + * @throws {TypeError} If `meta.schema` is specified but is not an array, object or `false`. + * @returns {Object|null} JSON Schema for the rule's options. + * `null` if rule wasn't passed or its `meta.schema` is `false`. */ getRuleOptionsSchema(rule) { if (!rule) { return null; } - const schema = rule.schema || rule.meta && rule.meta.schema; + if (!rule.meta) { + return { ...noOptionsSchema }; // default if `meta.schema` is not specified + } - // Given a tuple of schemas, insert warning level at the beginning + const schema = rule.meta.schema; + + if (typeof schema === "undefined") { + return { ...noOptionsSchema }; // default if `meta.schema` is not specified + } + + // `schema:false` is an allowed explicit opt-out of options validation for the rule + if (schema === false) { + return null; + } + + if (typeof schema !== "object" || schema === null) { + throw new TypeError("Rule's `meta.schema` must be an array or object"); + } + + // ESLint-specific array form needs to be converted into a valid JSON Schema definition if (Array.isArray(schema)) { if (schema.length) { return { @@ -64,16 +96,13 @@ export default class ConfigValidator { maxItems: schema.length }; } - return { - type: "array", - minItems: 0, - maxItems: 0 - }; + // `schema:[]` is an explicit way to specify that the rule does not accept any options + return { ...noOptionsSchema }; } - // Given a full schema, leave it alone - return schema || null; + // `schema:` is assumed to be a valid JSON Schema definition + return schema; } /** @@ -101,10 +130,18 @@ export default class ConfigValidator { */ validateRuleSchema(rule, localOptions) { if (!ruleValidators.has(rule)) { - const schema = this.getRuleOptionsSchema(rule); + try { + const schema = this.getRuleOptionsSchema(rule); + + if (schema) { + ruleValidators.set(rule, ajv.compile(schema)); + } + } catch (err) { + const errorWithCode = new Error(err.message, { cause: err }); - if (schema) { - ruleValidators.set(rule, ajv.compile(schema)); + errorWithCode.code = "ESLINT_INVALID_RULE_OPTIONS_SCHEMA"; + + throw errorWithCode; } } @@ -137,13 +174,21 @@ export default class ConfigValidator { this.validateRuleSchema(rule, Array.isArray(options) ? options.slice(1) : []); } } catch (err) { - const enhancedMessage = `Configuration for rule "${ruleId}" is invalid:\n${err.message}`; + let enhancedMessage = err.code === "ESLINT_INVALID_RULE_OPTIONS_SCHEMA" + ? `Error while processing options validation schema of rule '${ruleId}': ${err.message}` + : `Configuration for rule "${ruleId}" is invalid:\n${err.message}`; if (typeof source === "string") { - throw new Error(`${source}:\n\t${enhancedMessage}`); - } else { - throw new Error(enhancedMessage); + enhancedMessage = `${source}:\n\t${enhancedMessage}`; } + + const enhancedError = new Error(enhancedMessage, { cause: err }); + + if (err.code) { + enhancedError.code = err.code; + } + + throw enhancedError; } } diff --git a/tests/fixtures/rules/custom-rule.cjs b/tests/fixtures/rules/custom-rule.cjs index 6d8b662b..a7cc1340 100644 --- a/tests/fixtures/rules/custom-rule.cjs +++ b/tests/fixtures/rules/custom-rule.cjs @@ -1,15 +1,17 @@ -module.exports = function(context) { +"use strict"; - "use strict"; +module.exports = { + meta: { + schema: [] + }, - return { - "Identifier": function(node) { - if (node.name === "foo") { - context.report(node, "Identifier cannot be named 'foo'."); + create(context) { + return { + "Identifier": function(node) { + if (node.name === "foo") { + context.report(node, "Identifier cannot be named 'foo'."); + } } - } - }; - + }; + } }; - -module.exports.schema = []; diff --git a/tests/fixtures/rules/dir1/no-strings.cjs b/tests/fixtures/rules/dir1/no-strings.cjs index 1f566ac0..4997bbbe 100644 --- a/tests/fixtures/rules/dir1/no-strings.cjs +++ b/tests/fixtures/rules/dir1/no-strings.cjs @@ -1,14 +1,15 @@ "use strict"; -module.exports = function(context) { +module.exports = { + create(context) { + return { - return { + "Literal": function(node) { + if (typeof node.value === 'string') { + context.report(node, "String!"); + } - "Literal": function(node) { - if (typeof node.value === 'string') { - context.report(node, "String!"); } - - } - }; + }; + } }; diff --git a/tests/fixtures/rules/dir2/no-literals.cjs b/tests/fixtures/rules/dir2/no-literals.cjs index fdaa2d08..d872718a 100644 --- a/tests/fixtures/rules/dir2/no-literals.cjs +++ b/tests/fixtures/rules/dir2/no-literals.cjs @@ -1,11 +1,12 @@ "use strict"; -module.exports = function(context) { +module.exports = { + create (context) { + return { - return { - - "Literal": function(node) { - context.report(node, "Literal!"); - } - }; + "Literal": function(node) { + context.report(node, "Literal!"); + } + }; + } }; diff --git a/tests/fixtures/rules/make-syntax-error-rule.cjs b/tests/fixtures/rules/make-syntax-error-rule.cjs index 528b4b0f..3d34d9d1 100644 --- a/tests/fixtures/rules/make-syntax-error-rule.cjs +++ b/tests/fixtures/rules/make-syntax-error-rule.cjs @@ -1,14 +1,18 @@ -module.exports = function(context) { - return { - Program: function(node) { - context.report({ - node: node, - message: "ERROR", - fix: function(fixer) { - return fixer.insertTextAfter(node, "this is a syntax error."); - } - }); - } - }; +module.exports = { + meta: { + schema: [] + }, + create(context) { + return { + Program: function(node) { + context.report({ + node: node, + message: "ERROR", + fix: function(fixer) { + return fixer.insertTextAfter(node, "this is a syntax error."); + } + }); + } + }; + } }; -module.exports.schema = []; diff --git a/tests/fixtures/rules/wrong/custom-rule.cjs b/tests/fixtures/rules/wrong/custom-rule.cjs index 9a64230c..b3923e4d 100644 --- a/tests/fixtures/rules/wrong/custom-rule.cjs +++ b/tests/fixtures/rules/wrong/custom-rule.cjs @@ -1,5 +1,7 @@ -module.exports = function() { +"use strict"; - "use strict"; - return (null).something; +module.exports = { + create() { + return (null).something; + } }; diff --git a/tests/lib/shared/config-validator.js b/tests/lib/shared/config-validator.js new file mode 100644 index 00000000..abed9832 --- /dev/null +++ b/tests/lib/shared/config-validator.js @@ -0,0 +1,256 @@ +/** + * @fileoverview Tests for ConfigValidator class + */ + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +import { assert } from "chai"; +import nodeAssert from "assert"; + +import ConfigValidator from "../../../lib/shared/config-validator.js"; + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +const mockRule = { + meta: { + schema: [{ + enum: ["first", "second"] + }] + }, + create(context) { + return { + Program(node) { + context.report(node, "Expected a validation error."); + } + }; + } +}; + +const mockObjectRule = { + meta: { + schema: { + enum: ["first", "second"] + } + }, + create(context) { + return { + Program(node) { + context.report(node, "Expected a validation error."); + } + }; + } +}; + +const mockInvalidSchemaTypeRule = { + meta: { + schema: true + }, + create(context) { + return { + Program(node) { + context.report(node, "Expected a validation error."); + } + }; + } +}; + +const mockInvalidJSONSchemaRule = { + meta: { + schema: { + minItems: [] + } + }, + create(context) { + return { + Program(node) { + context.report(node, "Expected a validation error."); + } + }; + } +}; + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +describe("ConfigValidator", () => { + let validator; + + beforeEach(() => { + validator = new ConfigValidator(); + }); + + describe("getRuleOptionsSchema", () => { + + const noOptionsSchema = { + type: "array", + minItems: 0, + maxItems: 0 + }; + + it("should return null for a missing rule", () => { + assert.strictEqual(validator.getRuleOptionsSchema(void 0), null); + assert.strictEqual(validator.getRuleOptionsSchema(null), null); + }); + + it("should not modify object schema", () => { + assert.deepStrictEqual(validator.getRuleOptionsSchema(mockObjectRule), { + enum: ["first", "second"] + }); + }); + + it("should return schema that doesn't accept options if rule doesn't have `meta`", () => { + const rule = {}; + const result = validator.getRuleOptionsSchema(rule); + + assert.deepStrictEqual(result, noOptionsSchema); + }); + + it("should return schema that doesn't accept options if rule doesn't have `meta.schema`", () => { + const rule = { meta: {} }; + const result = validator.getRuleOptionsSchema(rule); + + assert.deepStrictEqual(result, noOptionsSchema); + }); + + it("should return schema that doesn't accept options if `meta.schema` is `undefined`", () => { + const rule = { meta: { schema: void 0 } }; + const result = validator.getRuleOptionsSchema(rule); + + assert.deepStrictEqual(result, noOptionsSchema); + }); + + it("should return schema that doesn't accept options if `meta.schema` is `[]`", () => { + const rule = { meta: { schema: [] } }; + const result = validator.getRuleOptionsSchema(rule); + + assert.deepStrictEqual(result, noOptionsSchema); + }); + + it("should return JSON Schema definition object if `meta.schema` is in the array form", () => { + const firstOption = { enum: ["always", "never"] }; + const rule = { meta: { schema: [firstOption] } }; + const result = validator.getRuleOptionsSchema(rule); + + assert.deepStrictEqual( + result, + { + type: "array", + items: [firstOption], + minItems: 0, + maxItems: 1 + } + ); + }); + + it("should return `meta.schema` as is if `meta.schema` is an object", () => { + const schema = { + type: "array", + items: [{ + enum: ["always", "never"] + }] + }; + const rule = { meta: { schema } }; + const result = validator.getRuleOptionsSchema(rule); + + assert.deepStrictEqual(result, schema); + }); + + it("should return `null` if `meta.schema` is `false`", () => { + const rule = { meta: { schema: false } }; + const result = validator.getRuleOptionsSchema(rule); + + assert.strictEqual(result, null); + }); + + [null, true, 0, 1, "", "always", () => {}].forEach(schema => { + it(`should throw an error if \`meta.schema\` is ${typeof schema} ${schema}`, () => { + const rule = { meta: { schema } }; + + assert.throws(() => { + validator.getRuleOptionsSchema(rule); + }, "Rule's `meta.schema` must be an array or object"); + }); + }); + + it("should ignore top-level `schema` property", () => { + const rule = { schema: { enum: ["always", "never"] } }; + const result = validator.getRuleOptionsSchema(rule); + + assert.deepStrictEqual(result, noOptionsSchema); + }); + + }); + + describe("validateRuleOptions", () => { + + it("should throw for incorrect warning level number", () => { + const fn = validator.validateRuleOptions.bind(validator, mockRule, "mock-rule", 3, "tests"); + + assert.throws(fn, "tests:\n\tConfiguration for rule \"mock-rule\" is invalid:\n\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '3').\n"); + }); + + it("should throw for incorrect warning level string", () => { + const fn = validator.validateRuleOptions.bind(validator, mockRule, "mock-rule", "booya", "tests"); + + assert.throws(fn, "tests:\n\tConfiguration for rule \"mock-rule\" is invalid:\n\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '\"booya\"').\n"); + }); + + it("should throw for invalid-type warning level", () => { + const fn = validator.validateRuleOptions.bind(validator, mockRule, "mock-rule", [["error"]], "tests"); + + assert.throws(fn, "tests:\n\tConfiguration for rule \"mock-rule\" is invalid:\n\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '[ \"error\" ]').\n"); + }); + + it("should only check warning level for nonexistent rules", () => { + const fn1 = validator.validateRuleOptions.bind(validator, void 0, "non-existent-rule", [3, "foobar"], "tests"); + + assert.throws(fn1, "tests:\n\tConfiguration for rule \"non-existent-rule\" is invalid:\n\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '3').\n"); + + const fn2 = validator.validateRuleOptions.bind(validator, null, "non-existent-rule", [3, "foobar"], "tests"); + + assert.throws(fn2, "tests:\n\tConfiguration for rule \"non-existent-rule\" is invalid:\n\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '3').\n"); + }); + + it("should throw for incorrect configuration values", () => { + const fn = validator.validateRuleOptions.bind(validator, mockRule, "mock-rule", [2, "frist"], "tests"); + + assert.throws(fn, "tests:\n\tConfiguration for rule \"mock-rule\" is invalid:\n\tValue \"frist\" should be equal to one of the allowed values.\n"); + }); + + it("should throw for too many configuration values", () => { + const fn = validator.validateRuleOptions.bind(validator, mockRule, "mock-rule", [2, "first", "second"], "tests"); + + assert.throws(fn, "tests:\n\tConfiguration for rule \"mock-rule\" is invalid:\n\tValue [\"first\",\"second\"] should NOT have more than 1 items.\n"); + }); + + it("should throw with error code ESLINT_INVALID_RULE_OPTIONS_SCHEMA for rule with an invalid schema type", () => { + const fn = validator.validateRuleOptions.bind(validator, mockInvalidSchemaTypeRule, "invalid-schema-rule", [2], "tests"); + + nodeAssert.throws( + fn, + { + code: "ESLINT_INVALID_RULE_OPTIONS_SCHEMA", + message: "tests:\n\tError while processing options validation schema of rule 'invalid-schema-rule': Rule's `meta.schema` must be an array or object" + } + ); + }); + + it("should throw with error code ESLINT_INVALID_RULE_OPTIONS_SCHEMA for rule with an invalid JSON schema", () => { + const fn = validator.validateRuleOptions.bind(validator, mockInvalidJSONSchemaRule, "invalid-schema-rule", [2], "tests"); + + nodeAssert.throws( + fn, + { + code: "ESLINT_INVALID_RULE_OPTIONS_SCHEMA", + message: "tests:\n\tError while processing options validation schema of rule 'invalid-schema-rule': minItems must be number" + } + ); + }); + + }); +}); From 737eb25ac686550020b838ccf6efd5cd2aaa449e Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Wed, 27 Dec 2023 00:46:03 +0100 Subject: [PATCH 02/14] feat!: Require Node.js `^18.18.0 || ^20.9.0 || >=21.1.0` (#142) * feat!: Require Node.js `^18.18.0 || ^20.9.0 || >=21.1.0` * use lts for Verify Files --- .github/workflows/ci.yml | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4909f16e..41c2f4cc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: '16.x' + node-version: "lts/*" - name: Install Packages run: npm install - name: Lint Files @@ -24,12 +24,12 @@ jobs: strategy: matrix: os: [ubuntu-latest] - node: [21.x, 20.x, 19.x, 18.x, 17.x, 16.x, 14.x, 12.x, "12.22.0"] + node: [21.x, 20.x, 18.x, "18.18.0"] include: - os: windows-latest - node: "12.x" + node: "lts/*" - os: macOS-latest - node: "12.x" + node: "lts/*" runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 diff --git a/package.json b/package.json index aa43e756..68700f34 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,6 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } } From de34fafed28aaf1936845d51309f28484ed29e2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=AF=E7=84=B6?= Date: Wed, 27 Dec 2023 20:16:48 +0800 Subject: [PATCH 03/14] chore: upgrade github actions (#143) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update ci.yml --------- Signed-off-by: 唯然 --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 41c2f4cc..90cd76da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,8 +10,8 @@ jobs: name: Verify Files runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: "lts/*" - name: Install Packages @@ -32,8 +32,8 @@ jobs: node: "lts/*" runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} - name: Install Packages From 0b7b6a594c38434a76dfc0ff943d3f070aacdd1e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 27 Dec 2023 18:59:34 +0100 Subject: [PATCH 04/14] chore: release 3.0.0 (#141) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- CHANGELOG.md | 18 ++++++++++++++++++ package.json | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d7bd5c0..365569a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## [3.0.0](https://github.com/eslint/eslintrc/compare/v2.1.4...v3.0.0) (2023-12-27) + + +### ⚠ BREAKING CHANGES + +* Require Node.js `^18.18.0 || ^20.9.0 || >=21.1.0` ([#142](https://github.com/eslint/eslintrc/issues/142)) +* Set default `schema: []`, drop support for function-style rules ([#139](https://github.com/eslint/eslintrc/issues/139)) + +### Features + +* Require Node.js `^18.18.0 || ^20.9.0 || >=21.1.0` ([#142](https://github.com/eslint/eslintrc/issues/142)) ([737eb25](https://github.com/eslint/eslintrc/commit/737eb25ac686550020b838ccf6efd5cd2aaa449e)) +* Set default `schema: []`, drop support for function-style rules ([#139](https://github.com/eslint/eslintrc/issues/139)) ([a6c240d](https://github.com/eslint/eslintrc/commit/a6c240de244b0e94ace4a518f2c67876a91f5882)) + + +### Chores + +* upgrade github actions ([#143](https://github.com/eslint/eslintrc/issues/143)) ([de34faf](https://github.com/eslint/eslintrc/commit/de34fafed28aaf1936845d51309f28484ed29e2f)) + ## [2.1.4](https://github.com/eslint/eslintrc/compare/v2.1.3...v2.1.4) (2023-11-27) diff --git a/package.json b/package.json index 68700f34..bc7dd3ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@eslint/eslintrc", - "version": "2.1.4", + "version": "3.0.0", "description": "The legacy ESLintRC config file format for ESLint", "type": "module", "main": "./dist/eslintrc.cjs", From a61384731aff386a8260a80d9710c912e4f62aaa Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Tue, 2 Jan 2024 03:18:00 +0100 Subject: [PATCH 05/14] docs: fix changelog for v3.0.0 (#144) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 365569a8..4d5da711 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ ### Features -* Require Node.js `^18.18.0 || ^20.9.0 || >=21.1.0` ([#142](https://github.com/eslint/eslintrc/issues/142)) ([737eb25](https://github.com/eslint/eslintrc/commit/737eb25ac686550020b838ccf6efd5cd2aaa449e)) +* Require Node.js `^18.18.0 || ^20.9.0 || >=21.1.0` ([#142](https://github.com/eslint/eslintrc/issues/142)) ([737eb25](https://github.com/eslint/eslintrc/commit/737eb25ac686550020b838ccf6efd5cd2aaa449e)) * Set default `schema: []`, drop support for function-style rules ([#139](https://github.com/eslint/eslintrc/issues/139)) ([a6c240d](https://github.com/eslint/eslintrc/commit/a6c240de244b0e94ace4a518f2c67876a91f5882)) From 0fabc7406e5a281a4e72be33de6e3bf8642aa746 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Fri, 26 Jan 2024 21:28:27 -0700 Subject: [PATCH 06/14] docs: More explicit about all and recommended configs (#150) --- README.md | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7641c741..b23d22b6 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,8 @@ const __dirname = path.dirname(__filename); const compat = new FlatCompat({ baseDirectory: __dirname, // optional; default: process.cwd() resolvePluginsRelativeTo: __dirname, // optional - recommendedConfig: js.configs.recommended, // optional - allConfig: js.configs.all, // optional + recommendedConfig: js.configs.recommended, // optional unless you're using "eslint:recommended" + allConfig: js.configs.all, // optional unless you're using "eslint:all" }); export default [ @@ -77,8 +77,8 @@ const js = require("@eslint/js"); const compat = new FlatCompat({ baseDirectory: __dirname, // optional; default: process.cwd() resolvePluginsRelativeTo: __dirname, // optional - recommendedConfig: js.configs.recommended, // optional - allConfig: js.configs.all, // optional + recommendedConfig: js.configs.recommended, // optional unless using "eslint:recommended" + allConfig: js.configs.all, // optional unless using "eslint:all" }); module.exports = [ @@ -110,6 +110,17 @@ module.exports = [ ]; ``` +## Troubleshooting + +**TypeError: Missing parameter 'recommendedConfig' in FlatCompat constructor** + +The `recommendedConfig` option is required when any config uses `eslint:recommended`, including any config in an `extends` clause. To fix this, follow the example above using `@eslint/js` to provide the `eslint:recommended` config. + +**TypeError: Missing parameter 'allConfig' in FlatCompat constructor** + +The `allConfig` option is required when any config uses `eslint:all`, including any config in an `extends` clause. To fix this, follow the example above using `@eslint/js` to provide the `eslint:all` config. + + ## License MIT License From 8c399441f47009344888e181c6aa2ecdc74ce8ea Mon Sep 17 00:00:00 2001 From: Milos Djermanovic Date: Sat, 10 Feb 2024 00:02:35 +0100 Subject: [PATCH 07/14] chore: upgrade espree@10.0.1 (#151) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bc7dd3ba..1e323118 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", + "espree": "^10.0.1", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", From 52d63e32c0bc2b5e81b390be236447fd5e7f9878 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 10 Feb 2024 00:10:01 +0100 Subject: [PATCH 08/14] chore: release 3.0.1 (#145) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- CHANGELOG.md | 13 +++++++++++++ package.json | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d5da711..86a28ad6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [3.0.1](https://github.com/eslint/eslintrc/compare/v3.0.0...v3.0.1) (2024-02-09) + + +### Documentation + +* fix changelog for v3.0.0 ([#144](https://github.com/eslint/eslintrc/issues/144)) ([a613847](https://github.com/eslint/eslintrc/commit/a61384731aff386a8260a80d9710c912e4f62aaa)) +* More explicit about all and recommended configs ([#150](https://github.com/eslint/eslintrc/issues/150)) ([0fabc74](https://github.com/eslint/eslintrc/commit/0fabc7406e5a281a4e72be33de6e3bf8642aa746)) + + +### Chores + +* upgrade espree@10.0.1 ([#151](https://github.com/eslint/eslintrc/issues/151)) ([8c39944](https://github.com/eslint/eslintrc/commit/8c399441f47009344888e181c6aa2ecdc74ce8ea)) + ## [3.0.0](https://github.com/eslint/eslintrc/compare/v2.1.4...v3.0.0) (2023-12-27) diff --git a/package.json b/package.json index 1e323118..79fa36fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@eslint/eslintrc", - "version": "3.0.0", + "version": "3.0.1", "description": "The legacy ESLintRC config file format for ESLint", "type": "module", "main": "./dist/eslintrc.cjs", From 4151865b09084369e89d591eb2e01b9617287982 Mon Sep 17 00:00:00 2001 From: Pelle Wessman Date: Mon, 12 Feb 2024 18:49:55 +0100 Subject: [PATCH 09/14] chore: maintenance update of `globals` to `v14` (#152) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maintenance update of `globals` to `v14` Only breaking change is the dropping of old Node.js versions but it still support all versions that `@eslint/eslintrc` supports. The one impactful thing it does though is that it removes the only dependency – replacing an outdated `type-fest` module with built-in types – making it so that everyone that installs `eslint` doesn't also get an outdated `type-fest` and thus doesn't have to contend with it in their `npm` deduping and hoisting. Relevant PR: https://github.com/sindresorhus/globals/pull/209 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 79fa36fd..dad45816 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", - "globals": "^13.19.0", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", From fb8d7ffbb27214686318a07e16ac8878aaafc805 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 23 Feb 2024 22:21:58 +0100 Subject: [PATCH 10/14] chore: release 3.0.2 (#153) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86a28ad6..3e3259ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [3.0.2](https://github.com/eslint/eslintrc/compare/v3.0.1...v3.0.2) (2024-02-12) + + +### Chores + +* maintenance update of `globals` to `v14` ([#152](https://github.com/eslint/eslintrc/issues/152)) ([4151865](https://github.com/eslint/eslintrc/commit/4151865b09084369e89d591eb2e01b9617287982)) + ## [3.0.1](https://github.com/eslint/eslintrc/compare/v3.0.0...v3.0.1) (2024-02-09) diff --git a/package.json b/package.json index dad45816..f67cc557 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@eslint/eslintrc", - "version": "3.0.1", + "version": "3.0.2", "description": "The legacy ESLintRC config file format for ESLint", "type": "module", "main": "./dist/eslintrc.cjs", From 5e526f2e2897b87d7a704391cec74702d4bed38c Mon Sep 17 00:00:00 2001 From: Francesco Trotta Date: Thu, 25 Apr 2024 08:49:52 +0200 Subject: [PATCH 11/14] ci: run tests in Node.js 22 (#154) --- .github/workflows/ci.yml | 2 +- .github/workflows/release-please.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90cd76da..965ba37e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - node: [21.x, 20.x, 18.x, "18.18.0"] + node: [22.x, 21.x, 20.x, 18.x, "18.18.0"] include: - os: windows-latest node: "lts/*" diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index c60c453b..adaacf93 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -29,9 +29,9 @@ jobs: { "type": "refactor", "section": "Chores", "hidden": false }, { "type": "test", "section": "Chores", "hidden": false } ] - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 if: ${{ steps.release.outputs.release_created }} - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: lts/* registry-url: https://registry.npmjs.org From 903b8875581ee731fd1a9424f83f785359cfb22e Mon Sep 17 00:00:00 2001 From: Francesco Trotta Date: Thu, 25 Apr 2024 11:22:40 +0200 Subject: [PATCH 12/14] chore: update dependency shelljs to ^0.8.5 (#156) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f67cc557..8ff14ba9 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "fs-teardown": "^0.1.3", "mocha": "^9.0.3", "rollup": "^2.70.1", - "shelljs": "^0.8.4", + "shelljs": "^0.8.5", "sinon": "^11.1.2", "temp-dir": "^2.0.0" }, From 59e890fcd9e03663ac185640d5bed5f1a85bd39b Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Fri, 17 May 2024 14:11:47 -0400 Subject: [PATCH 13/14] feat: Expose loadConfigFile() function (#160) --- lib/config-array-factory.js | 6 +++++- lib/index.js | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/config-array-factory.js b/lib/config-array-factory.js index 58c1e808..e4b18ebd 100644 --- a/lib/config-array-factory.js +++ b/lib/config-array-factory.js @@ -1148,4 +1148,8 @@ class ConfigArrayFactory { } } -export { ConfigArrayFactory, createContext }; +export { + ConfigArrayFactory, + createContext, + loadConfigFile +}; diff --git a/lib/index.js b/lib/index.js index 9e3d13f5..a37e5746 100644 --- a/lib/index.js +++ b/lib/index.js @@ -8,7 +8,8 @@ import { ConfigArrayFactory, - createContext as createConfigArrayFactoryContext + createContext as createConfigArrayFactoryContext, + loadConfigFile } from "./config-array-factory.js"; import { CascadingConfigArrayFactory } from "./cascading-config-array-factory.js"; @@ -39,6 +40,7 @@ const Legacy = { OverrideTester, getUsedExtractedConfigs, environments, + loadConfigFile, // shared ConfigOps, From 5c93cc828d7cc6dfae7c97aa5081d6fb56516ce9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 22:08:10 +0200 Subject: [PATCH 14/14] chore: release 3.1.0 (#155) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- CHANGELOG.md | 13 +++++++++++++ package.json | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e3259ac..c7d6a030 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## [3.1.0](https://github.com/eslint/eslintrc/compare/v3.0.2...v3.1.0) (2024-05-17) + + +### Features + +* Expose loadConfigFile() function ([#160](https://github.com/eslint/eslintrc/issues/160)) ([59e890f](https://github.com/eslint/eslintrc/commit/59e890fcd9e03663ac185640d5bed5f1a85bd39b)) + + +### Chores + +* run tests in Node.js 22 ([#154](https://github.com/eslint/eslintrc/issues/154)) ([5e526f2](https://github.com/eslint/eslintrc/commit/5e526f2e2897b87d7a704391cec74702d4bed38c)) +* update dependency shelljs to ^0.8.5 ([#156](https://github.com/eslint/eslintrc/issues/156)) ([903b887](https://github.com/eslint/eslintrc/commit/903b8875581ee731fd1a9424f83f785359cfb22e)) + ## [3.0.2](https://github.com/eslint/eslintrc/compare/v3.0.1...v3.0.2) (2024-02-12) diff --git a/package.json b/package.json index 8ff14ba9..fea77e2d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@eslint/eslintrc", - "version": "3.0.2", + "version": "3.1.0", "description": "The legacy ESLintRC config file format for ESLint", "type": "module", "main": "./dist/eslintrc.cjs",