@tianjos/eslint-plugin-elegant 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Thiago
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,139 @@
1
+ # @tianjos/eslint-plugin-elegant
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@tianjos/eslint-plugin-elegant.svg)](https://www.npmjs.com/package/@tianjos/eslint-plugin-elegant)
4
+ [![license](https://img.shields.io/npm/l/@tianjos/eslint-plugin-elegant.svg)](./LICENSE)
5
+ [![CI](https://github.com/tianjos/eslint-plugin-elegant/actions/workflows/ci.yml/badge.svg)](https://github.com/tianjos/eslint-plugin-elegant/actions/workflows/ci.yml)
6
+
7
+ Opinionated ESLint rules for **elegant, behavior-rich TypeScript**. The plugin
8
+ pushes code toward intention-revealing functions, honest types, and
9
+ encapsulated domain models — the kind of constraints that pay off in NestJS
10
+ services and DDD-style codebases.
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ npm install --save-dev @tianjos/eslint-plugin-elegant
16
+ ```
17
+
18
+ ```bash
19
+ pnpm add -D @tianjos/eslint-plugin-elegant
20
+ ```
21
+
22
+ ```bash
23
+ yarn add -D @tianjos/eslint-plugin-elegant
24
+ ```
25
+
26
+ ### Peer dependencies
27
+
28
+ This plugin does not bundle ESLint or the TypeScript toolchain. Install them
29
+ alongside it:
30
+
31
+ | Peer | Required version |
32
+ | ----------------------------- | ---------------- |
33
+ | `eslint` | `>=9` |
34
+ | `typescript` | `>=5` |
35
+ | `@typescript-eslint/parser` | `>=8` |
36
+
37
+ ```bash
38
+ npm install --save-dev eslint typescript @typescript-eslint/parser
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ This plugin targets **flat config** (`eslint.config.mjs`). The fastest way to
44
+ adopt it is to spread the `recommended` ruleset:
45
+
46
+ ```js
47
+ // eslint.config.mjs
48
+ import parser from '@typescript-eslint/parser';
49
+ import elegant from '@tianjos/eslint-plugin-elegant';
50
+
51
+ export default [
52
+ {
53
+ files: ['src/**/*.ts'],
54
+ languageOptions: {
55
+ parser,
56
+ parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
57
+ },
58
+ plugins: { elegant },
59
+ rules: {
60
+ ...elegant.configs.recommended.rules,
61
+ },
62
+ },
63
+ ];
64
+ ```
65
+
66
+ A complete, copy-pasteable example (including test-file overrides) lives in
67
+ [`eslint.config.example.mjs`](./eslint.config.example.mjs).
68
+
69
+ ## Rules
70
+
71
+ The `recommended` config enables every custom rule plus the native
72
+ [`max-params`](https://eslint.org/docs/latest/rules/max-params) rule.
73
+
74
+ | Rule | Source | What it catches | `recommended` |
75
+ | -------------------------------------- | ------ | ------------------------------------------------------------------------------- | ------------- |
76
+ | `elegant/no-boolean-param` | custom | Boolean parameters (flag arguments) on functions, methods, and constructors | `error` |
77
+ | `elegant/max-class-methods` | custom | Classes with more methods than the configured `max` (constructors excluded) | `warn` (max 10) |
78
+ | `elegant/no-type-assertion` | custom | `value as T` and `<T>value` assertions (`as const` is allowed) | `error` |
79
+ | `elegant/no-null-return` | custom | `return null` statements | `error` |
80
+ | `elegant/no-public-mutable-props` | custom | Public, non-`readonly` class properties and public constructor parameter props | `error` |
81
+ | `max-params` | native | Functions declaring more than `max` parameters | `warn` (max 3) |
82
+
83
+ ### Rule details
84
+
85
+ - **`no-boolean-param`** — a boolean argument almost always means the callee
86
+ does two things. Prefer two intention-revealing functions or an options
87
+ object. Flags both annotated (`flag: boolean`) and boolean-defaulted
88
+ (`flag = false`) parameters.
89
+ - **`max-class-methods`** — a proxy for the Single Responsibility Principle.
90
+ Constructors are not counted; getters and setters are.
91
+ - **`no-type-assertion`** — assertions silence the type checker. Reach for a
92
+ type guard, a generic, or a correctly typed value instead. `as const` is
93
+ permitted because it narrows rather than widens.
94
+ - **`no-null-return`** — keeps absence out of return values; model it with an
95
+ explicit domain type or throw.
96
+ - **`no-public-mutable-props`** — public state should be `readonly` so callers
97
+ cannot break an aggregate's invariants. `private`/`protected` members and
98
+ `readonly` members are allowed.
99
+
100
+ ## Configuration
101
+
102
+ ### Overriding thresholds
103
+
104
+ `max-class-methods` and the native `max-params` both take a `max` option:
105
+
106
+ ```js
107
+ rules: {
108
+ ...elegant.configs.recommended.rules,
109
+ 'elegant/max-class-methods': ['warn', { max: 15 }],
110
+ 'max-params': ['warn', { max: 4 }],
111
+ }
112
+ ```
113
+
114
+ ### Relaxing rules in test files
115
+
116
+ Tests routinely use flag arguments and larger fixtures. Add a second config
117
+ block scoped to your spec globs:
118
+
119
+ ```js
120
+ {
121
+ files: ['**/*.spec.ts', '**/*.test.ts', '**/*.e2e-spec.ts'],
122
+ rules: {
123
+ 'elegant/no-boolean-param': 'off',
124
+ 'elegant/max-class-methods': 'off',
125
+ 'max-params': 'off',
126
+ },
127
+ }
128
+ ```
129
+
130
+ ## Compatibility
131
+
132
+ The package ships a single CommonJS build that is consumable as both
133
+ `require('@tianjos/eslint-plugin-elegant')` and an ESM
134
+ `import elegant from '@tianjos/eslint-plugin-elegant'`. The exported object
135
+ exposes `{ meta, rules, configs }`.
136
+
137
+ ## License
138
+
139
+ [MIT](./LICENSE) © Thiago
@@ -0,0 +1,36 @@
1
+ import type { TSESLint } from '@typescript-eslint/utils';
2
+ declare const rules: {
3
+ 'no-boolean-param': TSESLint.RuleModule<"booleanParam", [], unknown, TSESLint.RuleListener> & {
4
+ name: string;
5
+ };
6
+ 'max-class-methods': TSESLint.RuleModule<"tooManyMethods", [{
7
+ max: number;
8
+ }], unknown, TSESLint.RuleListener> & {
9
+ name: string;
10
+ };
11
+ 'no-type-assertion': TSESLint.RuleModule<"noAssertion", [], unknown, TSESLint.RuleListener> & {
12
+ name: string;
13
+ };
14
+ 'no-null-return': TSESLint.RuleModule<"noNullReturn", [], unknown, TSESLint.RuleListener> & {
15
+ name: string;
16
+ };
17
+ 'no-public-mutable-props': TSESLint.RuleModule<"mutableProp", [], unknown, TSESLint.RuleListener> & {
18
+ name: string;
19
+ };
20
+ };
21
+ type Plugin = {
22
+ meta: {
23
+ name: string;
24
+ version: string;
25
+ };
26
+ rules: typeof rules;
27
+ configs: Record<string, TSESLint.FlatConfig.Config>;
28
+ /**
29
+ * Self-reference so the package resolves identically whether consumers reach
30
+ * it via `require('...')`, `require('...').default`, or an ESM
31
+ * `import elegant from '...'`. This sidesteps the CJS/ESM interop hazard.
32
+ */
33
+ default?: Plugin;
34
+ };
35
+ declare const plugin: Plugin;
36
+ export = plugin;
package/dist/index.js ADDED
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ const max_class_methods_1 = __importDefault(require("./rules/max-class-methods"));
6
+ const no_boolean_param_1 = __importDefault(require("./rules/no-boolean-param"));
7
+ const no_null_return_1 = __importDefault(require("./rules/no-null-return"));
8
+ const no_public_mutable_props_1 = __importDefault(require("./rules/no-public-mutable-props"));
9
+ const no_type_assertion_1 = __importDefault(require("./rules/no-type-assertion"));
10
+ const { name, version } = require('../package.json');
11
+ const rules = {
12
+ 'no-boolean-param': no_boolean_param_1.default,
13
+ 'max-class-methods': max_class_methods_1.default,
14
+ 'no-type-assertion': no_type_assertion_1.default,
15
+ 'no-null-return': no_null_return_1.default,
16
+ 'no-public-mutable-props': no_public_mutable_props_1.default,
17
+ };
18
+ const plugin = {
19
+ meta: { name, version },
20
+ rules,
21
+ configs: {},
22
+ };
23
+ plugin.configs.recommended = {
24
+ name: 'elegant/recommended',
25
+ plugins: { elegant: plugin },
26
+ rules: {
27
+ 'elegant/no-boolean-param': 'error',
28
+ 'elegant/max-class-methods': ['warn', { max: 10 }],
29
+ 'elegant/no-type-assertion': 'error',
30
+ 'elegant/no-null-return': 'error',
31
+ 'elegant/no-public-mutable-props': 'error',
32
+ 'max-params': ['warn', { max: 3 }],
33
+ },
34
+ };
35
+ plugin.default = plugin;
36
+ module.exports = plugin;
@@ -0,0 +1,7 @@
1
+ type Options = [{
2
+ max: number;
3
+ }];
4
+ declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"tooManyMethods", Options, unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
5
+ name: string;
6
+ };
7
+ export default _default;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("@typescript-eslint/utils");
4
+ const createRule_1 = require("../utils/createRule");
5
+ const DEFAULT_MAX = 10;
6
+ exports.default = (0, createRule_1.createRule)({
7
+ name: 'max-class-methods',
8
+ meta: {
9
+ type: 'suggestion',
10
+ docs: {
11
+ description: 'Enforce a maximum number of methods per class to keep classes cohesive and single-purpose.',
12
+ },
13
+ messages: {
14
+ tooManyMethods: "Class '{{name}}' has {{count}} methods (max {{max}}). Consider splitting its responsibilities.",
15
+ },
16
+ schema: [
17
+ {
18
+ type: 'object',
19
+ properties: {
20
+ max: { type: 'integer', minimum: 1 },
21
+ },
22
+ additionalProperties: false,
23
+ },
24
+ ],
25
+ },
26
+ defaultOptions: [{ max: DEFAULT_MAX }],
27
+ create(context, [{ max }]) {
28
+ return {
29
+ ClassBody(node) {
30
+ const methods = node.body.filter((member) => member.type === utils_1.AST_NODE_TYPES.MethodDefinition &&
31
+ member.kind !== 'constructor');
32
+ if (methods.length <= max) {
33
+ return;
34
+ }
35
+ const classNode = node.parent;
36
+ const name = classNode.id?.name ?? '(anonymous)';
37
+ context.report({
38
+ node: classNode.id ?? node,
39
+ messageId: 'tooManyMethods',
40
+ data: { name, count: methods.length, max },
41
+ });
42
+ },
43
+ };
44
+ },
45
+ });
@@ -0,0 +1,4 @@
1
+ declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"booleanParam", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
2
+ name: string;
3
+ };
4
+ export default _default;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("@typescript-eslint/utils");
4
+ const createRule_1 = require("../utils/createRule");
5
+ const isBooleanAnnotation = (annotation) => annotation?.type === utils_1.AST_NODE_TYPES.TSBooleanKeyword;
6
+ const isBooleanLiteral = (node) => node.type === utils_1.AST_NODE_TYPES.Literal && typeof node.value === 'boolean';
7
+ exports.default = (0, createRule_1.createRule)({
8
+ name: 'no-boolean-param',
9
+ meta: {
10
+ type: 'suggestion',
11
+ docs: {
12
+ description: 'Disallow boolean parameters, which are flag arguments signalling a function that does more than one thing.',
13
+ },
14
+ messages: {
15
+ booleanParam: "Boolean parameter '{{name}}' is a flag argument. Prefer two intention-revealing functions or an options object.",
16
+ },
17
+ schema: [],
18
+ },
19
+ defaultOptions: [],
20
+ create(context) {
21
+ const checkParam = (param) => {
22
+ const target = param.type === utils_1.AST_NODE_TYPES.TSParameterProperty
23
+ ? param.parameter
24
+ : param;
25
+ let name;
26
+ let annotation;
27
+ let defaultsToBoolean = false;
28
+ if (target.type === utils_1.AST_NODE_TYPES.Identifier) {
29
+ name = target;
30
+ annotation = target.typeAnnotation?.typeAnnotation;
31
+ }
32
+ else if (target.type === utils_1.AST_NODE_TYPES.AssignmentPattern &&
33
+ target.left.type === utils_1.AST_NODE_TYPES.Identifier) {
34
+ name = target.left;
35
+ annotation = target.left.typeAnnotation?.typeAnnotation;
36
+ defaultsToBoolean = isBooleanLiteral(target.right);
37
+ }
38
+ if (!name) {
39
+ return;
40
+ }
41
+ if (isBooleanAnnotation(annotation) || defaultsToBoolean) {
42
+ context.report({
43
+ node: name,
44
+ messageId: 'booleanParam',
45
+ data: { name: name.name },
46
+ });
47
+ }
48
+ };
49
+ const checkFunction = (node) => {
50
+ node.params.forEach(checkParam);
51
+ };
52
+ return {
53
+ FunctionDeclaration: checkFunction,
54
+ FunctionExpression: checkFunction,
55
+ ArrowFunctionExpression: checkFunction,
56
+ };
57
+ },
58
+ });
@@ -0,0 +1,4 @@
1
+ declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"noNullReturn", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
2
+ name: string;
3
+ };
4
+ export default _default;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("@typescript-eslint/utils");
4
+ const createRule_1 = require("../utils/createRule");
5
+ exports.default = (0, createRule_1.createRule)({
6
+ name: 'no-null-return',
7
+ meta: {
8
+ type: 'suggestion',
9
+ docs: {
10
+ description: 'Disallow returning null. Model absence with an explicit type, an Optional/Maybe, or by throwing.',
11
+ },
12
+ messages: {
13
+ noNullReturn: 'Returning null leaks absence into callers. Return an explicit empty value, a domain type, or throw.',
14
+ },
15
+ schema: [],
16
+ },
17
+ defaultOptions: [],
18
+ create(context) {
19
+ return {
20
+ ReturnStatement(node) {
21
+ const { argument } = node;
22
+ if (argument?.type === utils_1.AST_NODE_TYPES.Literal &&
23
+ argument.value === null &&
24
+ argument.raw === 'null') {
25
+ context.report({ node, messageId: 'noNullReturn' });
26
+ }
27
+ },
28
+ };
29
+ },
30
+ });
@@ -0,0 +1,4 @@
1
+ declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"mutableProp", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
2
+ name: string;
3
+ };
4
+ export default _default;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("@typescript-eslint/utils");
4
+ const createRule_1 = require("../utils/createRule");
5
+ const isHidden = (accessibility) => accessibility === 'private' || accessibility === 'protected';
6
+ const keyName = (key) => {
7
+ if (key.type === utils_1.AST_NODE_TYPES.Identifier) {
8
+ return key.name;
9
+ }
10
+ if (key.type === utils_1.AST_NODE_TYPES.Literal) {
11
+ return String(key.value);
12
+ }
13
+ return 'property';
14
+ };
15
+ exports.default = (0, createRule_1.createRule)({
16
+ name: 'no-public-mutable-props',
17
+ meta: {
18
+ type: 'suggestion',
19
+ docs: {
20
+ description: 'Disallow public mutable class properties. Public state should be readonly to protect invariants and preserve encapsulation.',
21
+ },
22
+ messages: {
23
+ mutableProp: "Public property '{{name}}' is mutable. Make it readonly or expose it through a method that protects the invariant.",
24
+ },
25
+ schema: [],
26
+ },
27
+ defaultOptions: [],
28
+ create(context) {
29
+ return {
30
+ PropertyDefinition(node) {
31
+ if (node.readonly || isHidden(node.accessibility)) {
32
+ return;
33
+ }
34
+ context.report({
35
+ node: node.key,
36
+ messageId: 'mutableProp',
37
+ data: { name: keyName(node.key) },
38
+ });
39
+ },
40
+ TSParameterProperty(node) {
41
+ // Only constructor parameter properties carry an accessibility modifier.
42
+ if (node.accessibility !== 'public' ||
43
+ node.readonly) {
44
+ return;
45
+ }
46
+ const target = node.parameter.type === utils_1.AST_NODE_TYPES.AssignmentPattern
47
+ ? node.parameter.left
48
+ : node.parameter;
49
+ if (target.type !== utils_1.AST_NODE_TYPES.Identifier) {
50
+ return;
51
+ }
52
+ context.report({
53
+ node: target,
54
+ messageId: 'mutableProp',
55
+ data: { name: target.name },
56
+ });
57
+ },
58
+ };
59
+ },
60
+ });
@@ -0,0 +1,4 @@
1
+ declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"noAssertion", [], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener> & {
2
+ name: string;
3
+ };
4
+ export default _default;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("@typescript-eslint/utils");
4
+ const createRule_1 = require("../utils/createRule");
5
+ const isAsConst = (node) => node.typeAnnotation.type === utils_1.AST_NODE_TYPES.TSTypeReference &&
6
+ node.typeAnnotation.typeName.type === utils_1.AST_NODE_TYPES.Identifier &&
7
+ node.typeAnnotation.typeName.name === 'const';
8
+ exports.default = (0, createRule_1.createRule)({
9
+ name: 'no-type-assertion',
10
+ meta: {
11
+ type: 'suggestion',
12
+ docs: {
13
+ description: 'Disallow type assertions, which bypass the type checker. Prefer type guards, generics, or honest types. `as const` is allowed.',
14
+ },
15
+ messages: {
16
+ noAssertion: 'Type assertions silence the type checker. Use a type guard, a generic, or a correctly typed value instead.',
17
+ },
18
+ schema: [],
19
+ },
20
+ defaultOptions: [],
21
+ create(context) {
22
+ return {
23
+ TSAsExpression(node) {
24
+ if (isAsConst(node)) {
25
+ return;
26
+ }
27
+ context.report({ node, messageId: 'noAssertion' });
28
+ },
29
+ TSTypeAssertion(node) {
30
+ context.report({ node, messageId: 'noAssertion' });
31
+ },
32
+ };
33
+ },
34
+ });
@@ -0,0 +1,8 @@
1
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
+ /**
3
+ * Factory for all rules in this plugin. Centralises the docs URL convention so
4
+ * every rule links back to its documentation by name.
5
+ */
6
+ export declare const createRule: <Options extends readonly unknown[], MessageIds extends string>({ meta, name, ...rule }: Readonly<ESLintUtils.RuleWithMetaAndName<Options, MessageIds, unknown>>) => ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener> & {
7
+ name: string;
8
+ };
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createRule = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ /**
6
+ * Factory for all rules in this plugin. Centralises the docs URL convention so
7
+ * every rule links back to its documentation by name.
8
+ */
9
+ exports.createRule = utils_1.ESLintUtils.RuleCreator((name) => `https://github.com/tianjos/eslint-plugin-elegant/blob/main/docs/rules/${name}.md`);
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@tianjos/eslint-plugin-elegant",
3
+ "version": "0.1.0",
4
+ "description": "Opinionated ESLint rules for elegant, behavior-rich TypeScript: no flag arguments, no type assertions, no null returns, no public mutable state, and small focused classes.",
5
+ "keywords": [
6
+ "eslint",
7
+ "eslint-plugin",
8
+ "typescript",
9
+ "nestjs",
10
+ "code-quality",
11
+ "linting"
12
+ ],
13
+ "author": "Thiago <thiago@bullcredtech.com>",
14
+ "license": "MIT",
15
+ "homepage": "https://github.com/tianjos/eslint-plugin-elegant#readme",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/tianjos/eslint-plugin-elegant.git"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/tianjos/eslint-plugin-elegant/issues"
22
+ },
23
+ "main": "./dist/index.js",
24
+ "types": "./dist/index.d.ts",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "import": "./dist/index.js",
29
+ "require": "./dist/index.js",
30
+ "default": "./dist/index.js"
31
+ },
32
+ "./package.json": "./package.json"
33
+ },
34
+ "files": [
35
+ "dist",
36
+ "README.md",
37
+ "LICENSE"
38
+ ],
39
+ "engines": {
40
+ "node": ">=18"
41
+ },
42
+ "scripts": {
43
+ "build": "tsc -p tsconfig.json",
44
+ "typecheck": "tsc -p tsconfig.test.json",
45
+ "test": "jest",
46
+ "release": "standard-version",
47
+ "prepublishOnly": "npm run build && npm test"
48
+ },
49
+ "dependencies": {
50
+ "@typescript-eslint/utils": "^8.0.0"
51
+ },
52
+ "peerDependencies": {
53
+ "@typescript-eslint/parser": ">=8",
54
+ "eslint": ">=9",
55
+ "typescript": ">=5"
56
+ },
57
+ "devDependencies": {
58
+ "@types/jest": "^29.5.12",
59
+ "@types/node": "^20.14.0",
60
+ "@typescript-eslint/parser": "^8.0.0",
61
+ "@typescript-eslint/rule-tester": "^8.0.0",
62
+ "@typescript-eslint/utils": "^8.0.0",
63
+ "eslint": "^9.0.0",
64
+ "jest": "^29.7.0",
65
+ "standard-version": "^9.5.0",
66
+ "ts-jest": "^29.2.0",
67
+ "typescript": "^5.6.0"
68
+ },
69
+ "publishConfig": {
70
+ "access": "public"
71
+ }
72
+ }