@camaro/eslint-config 0.1.1 → 0.1.3

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.3](https://github.com/camarojs/camaro/compare/eslint-config-v0.1.2...eslint-config-v0.1.3) (2026-02-09)
4
+
5
+
6
+ ### Features
7
+
8
+ * **eslint-config:** update common and typescript lint configurations to use defineConfig ([#36](https://github.com/camarojs/camaro/issues/36)) ([11719df](https://github.com/camarojs/camaro/commit/11719df051cade69427c6ddfdad79e0558bcf372))
9
+
10
+ ## [0.1.2](https://github.com/camarojs/camaro/compare/eslint-config-v0.1.1...eslint-config-v0.1.2) (2026-01-30)
11
+
12
+
13
+ ### Features
14
+
15
+ * **eslint-config:** enable jsx default ([#33](https://github.com/camarojs/camaro/issues/33)) ([7f5a8ff](https://github.com/camarojs/camaro/commit/7f5a8ffe6a53d2110c38e2deeb95f6c81c6fe006))
16
+
3
17
  ## [0.1.1](https://github.com/camarojs/camaro/compare/eslint-config-v0.1.0...eslint-config-v0.1.1) (2026-01-23)
4
18
 
5
19
 
package/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # @camaro/eslint-config
2
+
3
+ A shareable ESLint configuration preset for modern JavaScript and TypeScript projects.
4
+
5
+ ## Features
6
+
7
+ - 🚀 Modern ESLint 9+ support with flat config
8
+ - 📘 TypeScript support with type-checked rules
9
+ - 🎨 Stylistic rules for consistent code formatting
10
+ - ⚡ Zero-config experience with sensible defaults
11
+ - 📦 Modular design with optional dependencies
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install --save-dev @camaro/eslint-config eslint
17
+ ```
18
+
19
+ For TypeScript support:
20
+
21
+ ```bash
22
+ npm install --save-dev @camaro/eslint-config eslint typescript-eslint
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ### Basic Configuration (JavaScript)
28
+
29
+ Create `eslint.config.js`:
30
+
31
+ ```javascript
32
+ import config from '@camaro/eslint-config';
33
+
34
+ export default config;
35
+ ```
36
+
37
+ ### TypeScript Configuration
38
+
39
+ Create `eslint.config.js`:
40
+
41
+ ```javascript
42
+ import { createTypescriptLintConfig } from '@camaro/eslint-config/typescript';
43
+
44
+ export default createTypescriptLintConfig({
45
+ files: ['**/*.ts', '**/*.tsx']
46
+ });
47
+ ```
48
+
49
+ ## Configuration Details
50
+
51
+ ### Common Config
52
+
53
+ The base configuration includes:
54
+
55
+ - ESLint recommended rules
56
+ - Stylistic rules (code formatting, line breaks, spacing)
57
+ - Quality rules (eqeqeq, prefer-const)
58
+ - 4-space indentation
59
+ - Double quotes
60
+ - Semicolons required
61
+
62
+ ### TypeScript Config
63
+
64
+ The TypeScript configuration extends the common config and adds:
65
+
66
+ - TypeScript ESLint recommended, strict, and stylistic rules
67
+ - Type-aware linting with `projectService`
68
+ - Support for `.ts` and `.tsx` files
69
+ - Consistent type import rules
70
+
71
+ ## Rules
72
+
73
+ ### Stylistic Rules
74
+
75
+ - `array-bracket-newline`: Enforce consistent newlines in array brackets
76
+ - `array-element-newline`: Enforce consistent newlines between array elements
77
+ - `function-call-spacing`: Enforce no spacing between function names and invocations
78
+ - `function-paren-newline`: Enforce multiline function arguments
79
+ - `max-len`: Enforce 120 character line limit
80
+ - `object-curly-newline`: Enforce consistent newlines in object brackets
81
+
82
+ ### Quality Rules
83
+
84
+ - `eqeqeq`: Require strict equality operators
85
+ - `prefer-const`: Prefer `const` declarations
86
+ - `@typescript-eslint/consistent-type-imports`: Enforce consistent type import style
87
+
88
+ ## Requirements
89
+
90
+ - **eslint**: >= 9.0.0
91
+ - **typescript-eslint**: >= 8.0.0 (optional, only needed for TypeScript projects)
92
+
93
+ ## License
94
+
95
+ MIT
package/lib/common.d.ts CHANGED
@@ -1,2 +1 @@
1
- import { type Linter } from "eslint";
2
- export declare const common: Linter.Config[];
1
+ export declare const common: import("eslint/config").Config[];
package/lib/common.js CHANGED
@@ -1,24 +1,20 @@
1
1
  import eslintJS from "@eslint/js";
2
2
  import stylistic from "@stylistic/eslint-plugin";
3
- const styleLint = stylistic.configs.customize({
3
+ import { defineConfig } from "eslint/config";
4
+ const styleLintConfig = stylistic.configs.customize({
4
5
  indent: 4,
5
- jsx: false,
6
6
  quotes: "double",
7
7
  semi: true,
8
8
  });
9
- export const common = [
10
- eslintJS.configs.recommended,
11
- styleLint,
12
- {
13
- rules: {
14
- "eqeqeq": "error",
15
- "prefer-const": ["error", { destructuring: "all" }],
16
- "@stylistic/array-bracket-newline": "error",
17
- "@stylistic/array-element-newline": ["error", "consistent"],
18
- "@stylistic/function-call-spacing": ["error", "never"],
19
- "@stylistic/function-paren-newline": ["error", "multiline-arguments"],
20
- "@stylistic/max-len": ["error", { code: 120 }],
21
- "@stylistic/object-curly-newline": "error",
22
- },
9
+ export const common = defineConfig(eslintJS.configs.recommended, styleLintConfig, {
10
+ rules: {
11
+ "eqeqeq": "error",
12
+ "prefer-const": ["error", { destructuring: "all" }],
13
+ "@stylistic/array-bracket-newline": "error",
14
+ "@stylistic/array-element-newline": ["error", "consistent"],
15
+ "@stylistic/function-call-spacing": ["error", "never"],
16
+ "@stylistic/function-paren-newline": ["error", "multiline-arguments"],
17
+ "@stylistic/max-len": ["error", { code: 120 }],
18
+ "@stylistic/object-curly-newline": "error",
23
19
  },
24
- ];
20
+ });
@@ -1,2 +1,5 @@
1
1
  import type { TSESLint } from "@typescript-eslint/utils";
2
- export declare const ts: TSESLint.FlatConfig.ConfigArray;
2
+ export interface TypescriptLintConfigOptions {
3
+ files: string[];
4
+ }
5
+ export declare const createTypescriptLintConfig: (options: TypescriptLintConfigOptions) => TSESLint.FlatConfig.ConfigArray;
package/lib/typescript.js CHANGED
@@ -1,22 +1,20 @@
1
1
  import eslintTS from "typescript-eslint";
2
2
  import { common } from "./common.js";
3
- const eslintTsRules = [
4
- ...eslintTS.configs.recommendedTypeChecked,
5
- ...eslintTS.configs.strictTypeChecked,
6
- ...eslintTS.configs.stylisticTypeChecked,
7
- ].reduce((acc, config) => ({ ...acc, ...config.rules }), {});
8
- export const ts = [
9
- ...common,
10
- {
11
- files: ["**/*.ts"],
3
+ import { defineConfig } from "eslint/config";
4
+ export const createTypescriptLintConfig = (options) => {
5
+ return defineConfig(common, {
6
+ files: options.files,
7
+ extends: [
8
+ eslintTS.configs.recommendedTypeChecked,
9
+ eslintTS.configs.strictTypeChecked,
10
+ eslintTS.configs.stylisticTypeChecked,
11
+ ],
12
12
  languageOptions: {
13
13
  parser: eslintTS.parser,
14
14
  parserOptions: { projectService: true },
15
15
  },
16
- plugins: { "@typescript-eslint": eslintTS.plugin },
17
16
  rules: {
18
- ...eslintTsRules,
19
17
  "@typescript-eslint/consistent-type-imports": ["error", { fixStyle: "inline-type-imports" }],
20
18
  },
21
- },
22
- ];
19
+ });
20
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camaro/eslint-config",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "A shareable eslint config.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -12,7 +12,16 @@
12
12
  "test": "tsx ./test/index.ts",
13
13
  "type-check": "tsc --noEmit && tsc -p test/tsconfig.json --noEmit"
14
14
  },
15
- "keywords": [],
15
+ "keywords": [
16
+ "eslint",
17
+ "eslint-config",
18
+ "eslint-config-airbnb",
19
+ "shared-config",
20
+ "typescript",
21
+ "stylistic",
22
+ "code-style",
23
+ "linting"
24
+ ],
16
25
  "dependencies": {
17
26
  "@eslint/js": "^9.39.1",
18
27
  "@stylistic/eslint-plugin": "^5.6.1"
package/src/common.ts DELETED
@@ -1,28 +0,0 @@
1
- import eslintJS from "@eslint/js";
2
- import stylistic from "@stylistic/eslint-plugin";
3
- import { type Linter } from "eslint";
4
-
5
- const styleLint = stylistic.configs.customize({
6
- indent: 4,
7
- jsx: false,
8
- quotes: "double",
9
- semi: true,
10
- });
11
-
12
- export const common: Linter.Config[] = [
13
- eslintJS.configs.recommended,
14
- styleLint,
15
- {
16
- rules: {
17
- "eqeqeq": "error",
18
- "prefer-const": ["error", { destructuring: "all" }],
19
-
20
- "@stylistic/array-bracket-newline": "error",
21
- "@stylistic/array-element-newline": ["error", "consistent"],
22
- "@stylistic/function-call-spacing": ["error", "never"],
23
- "@stylistic/function-paren-newline": ["error", "multiline-arguments"],
24
- "@stylistic/max-len": ["error", { code: 120 }],
25
- "@stylistic/object-curly-newline": "error",
26
- },
27
- },
28
- ];
package/src/typescript.ts DELETED
@@ -1,25 +0,0 @@
1
- import type { TSESLint } from "@typescript-eslint/utils";
2
- import eslintTS from "typescript-eslint";
3
- import { common } from "./common.js";
4
-
5
- const eslintTsRules = [
6
- ...eslintTS.configs.recommendedTypeChecked,
7
- ...eslintTS.configs.strictTypeChecked,
8
- ...eslintTS.configs.stylisticTypeChecked,
9
- ].reduce<TSESLint.FlatConfig.Rules>((acc, config) => ({ ...acc, ...config.rules }), {});
10
-
11
- export const ts: TSESLint.FlatConfig.ConfigArray = [
12
- ...common,
13
- {
14
- files: ["**/*.ts"],
15
- languageOptions: {
16
- parser: eslintTS.parser,
17
- parserOptions: { projectService: true },
18
- },
19
- plugins: { "@typescript-eslint": eslintTS.plugin },
20
- rules: {
21
- ...eslintTsRules,
22
- "@typescript-eslint/consistent-type-imports": ["error", { fixStyle: "inline-type-imports" }],
23
- },
24
- },
25
- ];
@@ -1,23 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import { lintText } from "../util.js";
3
-
4
- const ruleId = "@stylistic/array-bracket-newline";
5
-
6
- void describe(ruleId, () => {
7
- void it("should report errors for array with incorrect line breaks", async () => {
8
- await lintText(
9
- "const a = [1,\n" + " 2,\n" + "];",
10
- { errorCount: 1, ruleId, messageIds: ["missingOpeningLinebreak"] },
11
- );
12
-
13
- await lintText(
14
- "const b = [\n 1,\n];",
15
- { errorCount: 2, ruleId, messageIds: ["unexpectedOpeningLinebreak", "unexpectedClosingLinebreak"] },
16
- );
17
- });
18
-
19
- void it("should not report errors for correctly formatted arrays", async () => {
20
- await lintText("const a = [1, 2];", { errorCount: 0, ruleId });
21
- await lintText("const d = [\n 1,\n 2,\n];", { errorCount: 0, ruleId });
22
- });
23
- });
@@ -1,17 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import { lintText } from "../util.js";
3
-
4
- const ruleId = "@stylistic/array-element-newline";
5
-
6
- void describe(ruleId, () => {
7
- void it("should report missing line break error", async () => {
8
- await lintText(
9
- "const a = [\n 2, 4,\n 3,\n];",
10
- { errorCount: 1, ruleId, messageIds: ["missingLineBreak"] },
11
- );
12
- });
13
-
14
- void it("should not report line break error", async () => {
15
- await lintText("const a = [1, 2, 3];", { errorCount: 0, ruleId });
16
- });
17
- });
@@ -1,14 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import { lintText } from "../util.js";
3
-
4
- const ruleId = "@stylistic/function-call-spacing";
5
-
6
- void describe(ruleId, () => {
7
- void it("", async () => {
8
- await lintText("const a = new Date ();", { errorCount: 1, ruleId, messageIds: ["unexpectedWhitespace"] });
9
- });
10
-
11
- void it("", async () => {
12
- await lintText("const a = new Date();", { errorCount: 0, ruleId });
13
- });
14
- });
@@ -1,28 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import { lintText } from "../util.js";
3
-
4
- const ruleId = "@stylistic/function-paren-newline";
5
-
6
- void describe(ruleId, () => {
7
- void it("reports error if param is on new line but closing paren isn't", async () => {
8
- await lintText(
9
- "function foo(\n bar) {}",
10
- { errorCount: 1, ruleId, messageIds: ["expectedBefore"] },
11
- );
12
- });
13
-
14
- void it("reports error if multiple params are on new lines but closing paren isn't", async () => {
15
- await lintText(
16
- "function foo(\n bar, baz) { }",
17
- { errorCount: 1, ruleId, messageIds: ["unexpectedAfter"] },
18
- );
19
- });
20
-
21
- void it("should allow function parentheses to be on the same line", async () => {
22
- await lintText("function foo(bar) { }", { errorCount: 0, ruleId });
23
- });
24
-
25
- void it("should allow function parentheses to be on the next line", async () => {
26
- await lintText("function foo(\n bar,\n) { }", { errorCount: 0, ruleId });
27
- });
28
- });
@@ -1,14 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import { lintText } from "../util.js";
3
-
4
- const ruleId = "@stylistic/max-len";
5
-
6
- void describe(ruleId, () => {
7
- void it("should report error for exceeding max length", async () => {
8
- await lintText(
9
- "const str = \"this is a very long string that exceeds the maximum length, "
10
- + "this is a very long string that exceeds the maximum length, \";",
11
- { errorCount: 1, ruleId, messageIds: ["max"] },
12
- );
13
- });
14
- });
@@ -1,20 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import { lintText } from "../util.js";
3
-
4
- const ruleId = "@stylistic/object-curly-newline";
5
-
6
- void describe(ruleId, () => {
7
- void it("should report error for inconsistent object curly newlines", async () => {
8
- await lintText(
9
- "const obj = { a: 1, b: 2, c: 3 \n};",
10
- { errorCount: 1, ruleId, messageIds: ["unexpectedLinebreakBeforeClosingBrace"] },
11
- );
12
- });
13
-
14
- void it("should not report error for consistent object curly newlines", async () => {
15
- await lintText(
16
- "const obj = { a: 1, b: 2, c: 3 };",
17
- { errorCount: 0, ruleId },
18
- );
19
- });
20
- });
@@ -1,27 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import { lintText } from "../util.js";
3
-
4
- const ruleId = "@typescript-eslint/consistent-type-imports";
5
-
6
- void describe(ruleId, () => {
7
- void it("should report errors when using regular imports for types", async () => {
8
- await lintText(
9
- "import { SomeType } from './types';\ntype Foo = SomeType;",
10
- { errorCount: 1, ruleId, messageIds: ["typeOverValue"] },
11
- );
12
- });
13
-
14
- void it("should not report errors when using type imports", async () => {
15
- await lintText(
16
- "import type { SomeType } from './types';\ntype Foo = SomeType;",
17
- { errorCount: 0, ruleId },
18
- );
19
- });
20
-
21
- void it("should not report errors for value imports", async () => {
22
- await lintText(
23
- "import { someFunction } from './utils';\nsomeFunction();",
24
- { errorCount: 0, ruleId },
25
- );
26
- });
27
- });
package/test/dummy.ts DELETED
@@ -1,4 +0,0 @@
1
- /**
2
- * This empty file is present to ensure that `test/dummy.ts` is actually in the filesystem during the test.
3
- * @see https://github.com/typescript-eslint/typescript-eslint/issues/4360
4
- */
@@ -1,14 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import { lintText } from "../util.js";
3
-
4
- const ruleId = "eqeqeq";
5
-
6
- void describe(ruleId, () => {
7
- void it("should report an error when using '=='", async () => {
8
- await lintText("0 == 0", { errorCount: 1, ruleId, messageIds: ["unexpected"] });
9
- });
10
-
11
- void it("should report an error when using '!='", async () => {
12
- await lintText("0 != 0", { errorCount: 1, ruleId, messageIds: ["unexpected"] });
13
- });
14
- });
@@ -1,14 +0,0 @@
1
- import { describe, it } from "node:test";
2
- import { lintText } from "../util.js";
3
-
4
- const ruleId = "prefer-const";
5
-
6
- void describe(ruleId, () => {
7
- void it("should report an error when 'let' can be replaced with 'const'", async () => {
8
- await lintText("let { a } = { a: 1 };", { errorCount: 1, ruleId, messageIds: ["useConst"] });
9
- });
10
-
11
- void it("should not report errors when a variable is reassigned", async () => {
12
- await lintText("let { a, b } = { a: 1, b: 2 };\na = 2;", { errorCount: 0, ruleId });
13
- });
14
- });
package/test/index.ts DELETED
@@ -1,17 +0,0 @@
1
- import { run } from "node:test";
2
- import { spec } from "node:test/reporters";
3
-
4
- const stream = run({
5
- concurrency: true,
6
- execArgv: ["--enable-source-maps"],
7
- globPatterns: ["test/**/*.test.ts"],
8
- isolation: "none",
9
-
10
- setup(reporter) {
11
- reporter.on("test:fail", () => {
12
- process.exitCode = 1;
13
- });
14
- },
15
- });
16
-
17
- stream.compose(spec).pipe(process.stdout);
@@ -1,3 +0,0 @@
1
- {
2
- "extends": "@camaro/tsconfig/base.json"
3
- }
package/test/util.ts DELETED
@@ -1,39 +0,0 @@
1
- import { ESLint, type Linter } from "eslint";
2
- import assert from "node:assert";
3
- import path from "node:path";
4
- import { ts } from "../src/typescript.js";
5
-
6
- const eslint = new ESLint({
7
- overrideConfigFile: true,
8
- baseConfig: ts as Linter.Config,
9
- });
10
-
11
- const dummyFilePath = path.resolve(import.meta.dirname, "dummy.ts");
12
-
13
- interface LintTextOptions {
14
- /** The expected error count */
15
- errorCount: number;
16
- /** The rule ID to check for */
17
- ruleId: string;
18
- /** The expected warning count */
19
- messageIds?: string[];
20
- }
21
-
22
- export const lintText = async (code: string, options: LintTextOptions) => {
23
- const results = await eslint.lintText(code, { filePath: dummyFilePath });
24
- const result = (results as [ESLint.LintResult])[0];
25
-
26
- assert.strictEqual(results.length, 1, "Expected exactly one result");
27
-
28
- const messages = result.messages.filter(message => message.ruleId === options.ruleId);
29
-
30
- assert.strictEqual(messages.length, options.errorCount);
31
-
32
- messages.forEach((message, index) => {
33
- assert.strictEqual(message.severity, 2);
34
-
35
- if (options.messageIds?.length) {
36
- assert.strictEqual(message.messageId, options.messageIds[index]);
37
- }
38
- });
39
- };
package/tsconfig.json DELETED
@@ -1,11 +0,0 @@
1
- {
2
- "extends": "@camaro/tsconfig/base.json",
3
- "compilerOptions": {
4
- "outDir": "./lib",
5
- "rootDir": "./src",
6
- "tsBuildInfoFile": "./lib/tsconfig.tsbuildinfo"
7
- },
8
- "include": [
9
- "src/**/*.ts"
10
- ]
11
- }