eslint-plugin-ai-rules 0.3.1 → 0.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/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 eslint-plugin-ai-rules
3
+ Copyright (c) 2026 Lucas Souza
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -94,6 +94,7 @@ npx eslint --fix .
94
94
  - [Structure DSL](#structure-dsl)
95
95
  - [Limitations](#limitations)
96
96
  - [Rules](#rules)
97
+ - [Disabling or changing rules](#disabling-or-changing-rules)
97
98
  - [What runs automatically](#what-runs-automatically)
98
99
  - [Recommended preset](#recommended-preset)
99
100
  - [Troubleshooting](#troubleshooting)
@@ -101,19 +102,19 @@ npx eslint --fix .
101
102
  - [Migrating from 0.2.x](#migrating-from-02x)
102
103
  - [Development](#development)
103
104
  - [Publishing](#publishing)
104
- - [Legacy](#legacy)
105
+ - [Articles](#articles)
106
+ - [Contributing](#contributing)
107
+ - [Security](#security)
105
108
 
106
109
  ## Configuration warning
107
110
 
108
- If you install the plugin and use `aiRules.configs.recommended` without configuring the project structure, the plugin prints a warning the first time it lints a file:
111
+ If you install the plugin and use `aiRules.configs.recommended` without configuring the project structure, `ai-rules/project-setup` reports a warning the first time it lints a file:
109
112
 
110
113
  ```text
111
- [eslint-plugin-ai-rules] Project structure validation is not configured.
112
- Configure it with aiRules.configs.projects([{ rootFolder: '.', preset: 'frontend' | 'backend' }]).
113
- If this project is not a frontend/backend, use preset: 'other' to disable this warning.
114
+ Project structure validation is not configured. Configure it with aiRules.configs.projects([{ rootFolder: ".", preset: "frontend" | "backend" }]). If this project is not a frontend/backend, use preset: "other" to disable this warning. ai-rules/project-setup
114
115
  ```
115
116
 
116
- The warning exists only to make sure the new structure rules are actually configured. It is printed once per process.
117
+ The warning exists only to make sure the new structure rules are actually configured. It is reported once per process.
117
118
 
118
119
  It disappears when you provide a valid configuration:
119
120
 
@@ -123,7 +124,7 @@ It disappears when you provide a valid configuration:
123
124
  - a custom non-empty `structure`
124
125
  - a `relations` configuration
125
126
 
126
- A project containing only `rootFolder` and an empty `structure` is still considered unconfigured and will warn.
127
+ A project containing only `rootFolder` and an empty `structure` is still considered unconfigured and will report.
127
128
 
128
129
  For CI or temporary runs, silence the warning without changing the config:
129
130
 
@@ -131,6 +132,16 @@ For CI or temporary runs, silence the warning without changing the config:
131
132
  AI_RULES_SILENT=1 npx eslint .
132
133
  ```
133
134
 
135
+ You can also disable the rule or change its severity like any other ESLint rule:
136
+
137
+ ```ts
138
+ {
139
+ rules: {
140
+ 'ai-rules/project-setup': 'off',
141
+ },
142
+ }
143
+ ```
144
+
134
145
  The warning is still recommended as a setup check, so prefer `preset: 'other'` for projects that intentionally do not use structure validation.
135
146
 
136
147
  ## Features
@@ -167,6 +178,7 @@ interface IProjectDefinition {
167
178
  preset?: 'frontend' | 'backend' | 'other'
168
179
  structure?: IProjectStructure
169
180
  relations?: IRelationsConfig
181
+ rules?: Linter.RulesRecord
170
182
  }
171
183
  ```
172
184
 
@@ -178,6 +190,7 @@ interface IProjectDefinition {
178
190
  - `preset` provides a base structure.
179
191
  - `structure` is merged on top of the preset.
180
192
  - `relations` enables architecture dependency policies with `eslint-plugin-boundaries`.
193
+ - `rules` overrides rule severities and options for that project using the standard ESLint rule format.
181
194
  - `preset: 'other'` disables structure validation unless a custom `structure` is provided.
182
195
 
183
196
  `aiRules.configs.projects([...])` generates one flat config per project. Each config:
@@ -186,9 +199,10 @@ interface IProjectDefinition {
186
199
  - sets `settings['ai-rules'].project`;
187
200
  - enables `ai-rules/project-structure`;
188
201
  - adds `ignores` from `ignoredPaths`;
189
- - includes the recommended rules;
202
+ - includes the recommended rules, overridable by `rules`;
190
203
  - disables `ai-rules/filename-pascal-case`, because file naming is handled by `project-structure`;
191
- - when `relations` is present, registers `boundaries` and enables `boundaries/dependencies`.
204
+ - when `relations` is present, registers `boundaries` and enables `boundaries/dependencies`;
205
+ - applies `rules` last, so a project can disable or change any rule.
192
206
 
193
207
  ## Examples
194
208
 
@@ -961,12 +975,12 @@ Validates the configured hierarchy, folder names and file names.
961
975
 
962
976
  ### `ai-rules/project-setup`
963
977
 
964
- Prints the configuration warning described above.
978
+ Reports the configuration warning described above as a regular ESLint diagnostic.
965
979
 
966
980
  - Type: `suggestion`
967
981
  - Enabled as `warn` in `recommended`
968
- - Does not report lint messages
969
- - Warns once per process
982
+ - Reports once per process
983
+ - Respects the configured severity (`off`, `warn`, `error`)
970
984
  - Suppressed by `preset: 'other'`, `frontend`, `backend` or a non-empty custom structure
971
985
 
972
986
  ### `ai-rules/filename-pascal-case`
@@ -1038,20 +1052,82 @@ The plugin also configures the `import-x` resolver with:
1038
1052
  extensions: ['.ts', '.tsx', '.d.ts', '.js', '.jsx']
1039
1053
  ```
1040
1054
 
1041
- Override any bundled rule after the preset:
1055
+ ## Disabling or changing rules
1056
+
1057
+ Every rule is controlled through the standard ESLint `rules` object. Any entry accepts `'off'`, `'warn'`, `'error'`, or `['error', options]`.
1058
+
1059
+ ### Option 1: override after the generated config
1060
+
1061
+ Flat config is evaluated in order, so a config placed after `projects()` or `recommended` wins:
1042
1062
 
1043
1063
  ```ts
1044
1064
  export default defineConfig([
1045
- ...aiRules.configs.projects([{ rootFolder: '.', preset: 'frontend' }]),
1065
+ ...tseslint.configs.recommended,
1066
+ ...aiRules.configs.projects([
1067
+ { rootFolder: '.', preset: 'frontend' },
1068
+ ]),
1046
1069
  {
1047
1070
  rules: {
1048
- '@stylistic/semi': ['error', 'always'],
1071
+ 'ai-rules/sort-imports': 'off',
1072
+ 'ai-rules/project-structure': 'warn',
1073
+ 'ai-rules/filename-pascal-case': 'error',
1074
+ '@stylistic/semi': ['warn', 'always'],
1049
1075
  'import-x/no-default-export': 'off',
1076
+ 'boundaries/dependencies': 'off',
1050
1077
  },
1051
1078
  },
1052
1079
  ])
1053
1080
  ```
1054
1081
 
1082
+ To apply an override only to part of the repository, use `files`:
1083
+
1084
+ ```ts
1085
+ {
1086
+ files: ['scripts/**/*', '*.config.*'],
1087
+ rules: {
1088
+ 'ai-rules/filename-pascal-case': 'off',
1089
+ },
1090
+ }
1091
+ ```
1092
+
1093
+ ### Option 2: per-project `rules`
1094
+
1095
+ When using `projects()`, pass `rules` in the project definition. These rules are applied after the recommended rules, the preset rules and the automatic structure/relations rules:
1096
+
1097
+ ```ts
1098
+ aiRules.configs.projects([
1099
+ {
1100
+ rootFolder: 'apps/api',
1101
+ preset: 'backend',
1102
+ rules: {
1103
+ 'ai-rules/sort-imports': 'off',
1104
+ 'ai-rules/project-structure': 'warn',
1105
+ '@stylistic/semi': ['warn', 'always'],
1106
+ 'boundaries/dependencies': 'off',
1107
+ },
1108
+ },
1109
+ ])
1110
+ ```
1111
+
1112
+ Precedence inside `projects()` is:
1113
+
1114
+ 1. `recommended` rules
1115
+ 2. automatic `project-structure`, `filename-pascal-case` and `boundaries/dependencies` rules
1116
+ 3. `preset.rules`
1117
+ 4. project `rules`
1118
+ 5. any flat config placed after `projects()` in the ESLint config array
1119
+
1120
+ The `rules` option uses the same shape as ESLint, including options arrays:
1121
+
1122
+ ```ts
1123
+ rules: {
1124
+ 'ai-rules/filename-pascal-case': [
1125
+ 'error',
1126
+ { ignore: ['\\.config\\.'], ignoreMiddleExtensions: false },
1127
+ ],
1128
+ }
1129
+ ```
1130
+
1055
1131
  ## What runs automatically
1056
1132
 
1057
1133
  | You use | What is enabled |
@@ -1107,6 +1183,16 @@ Or explicitly opt out:
1107
1183
 
1108
1184
  A project with only `rootFolder` and an empty `structure` still warns.
1109
1185
 
1186
+ If you intentionally do not want this check, disable the rule:
1187
+
1188
+ ```ts
1189
+ {
1190
+ rules: {
1191
+ 'ai-rules/project-setup': 'off',
1192
+ },
1193
+ }
1194
+ ```
1195
+
1110
1196
  For temporary runs or CI, use:
1111
1197
 
1112
1198
  ```bash
@@ -1210,34 +1296,36 @@ If you intentionally do not want structure validation:
1210
1296
  ## Development
1211
1297
 
1212
1298
  ```bash
1213
- git clone <repo>
1299
+ git clone https://github.com/lvsouza/eslint-ai-guard.git
1214
1300
  cd eslint-ai-guard
1215
- npm install
1216
-
1217
- npm run typecheck # tsc --noEmit
1218
- npm test # node:test against dist
1219
- npm run lint # eslint .
1220
- npm run lint -- --fix
1221
- npm run build # tsup -> ESM + CJS + declarations
1222
- npm run dev # tsup --watch
1223
- npm run verify # typecheck + test + lint + pack
1224
- npm run test:coverage # c8 coverage with thresholds
1225
- npm run test:consumer # install packed tarball in a temp project
1226
- npm run test:package # publint + arethetypeswrong
1227
- npm run test:release # consumer + package checks
1228
- npm pack --dry-run # verify published files
1301
+ corepack enable
1302
+ yarn install --frozen-lockfile
1303
+
1304
+ yarn typecheck # tsc --noEmit
1305
+ yarn test # node:test against dist
1306
+ yarn test:watch # node:test in watch mode
1307
+ yarn lint # eslint .
1308
+ yarn lint --fix
1309
+ yarn build # tsup -> ESM + CJS + declarations
1310
+ yarn dev # tsup --watch
1311
+ yarn verify # typecheck + test + lint + pack
1312
+ yarn test:coverage # c8 coverage with thresholds
1313
+ yarn test:consumer # install packed tarball in a temp project
1314
+ yarn test:package # publint + arethetypeswrong
1315
+ yarn test:release # full validation before release
1316
+ npm pack --dry-run # verify published files
1229
1317
  ```
1230
1318
 
1231
- `test:consumer` and `test:package` are release checks and are not part of `verify`. They may use the network.
1319
+ `test:consumer` and `test:package` are release checks and are not part of `verify`. They may use the network. `test:release` runs the complete validation: `verify`, coverage, consumer and package checks.
1232
1320
 
1233
1321
  The consumer smoke test covers structure validation, relations with aliases and type-only imports, warning/suppression, ESM and CJS. It accepts `ESLINT_VERSION`:
1234
1322
 
1235
1323
  ```bash
1236
- ESLINT_VERSION=9.22.0 npm run test:consumer
1237
- ESLINT_VERSION='^10.0.0' npm run test:consumer
1324
+ ESLINT_VERSION=9.22.0 yarn test:consumer
1325
+ ESLINT_VERSION='^10.0.0' yarn test:consumer
1238
1326
  ```
1239
1327
 
1240
- CI runs `verify`, coverage and consumer checks on Node 20, 22 and 24.
1328
+ The full validation runs in `.github/workflows/release.yml` on version tags: `verify` on Node 20, 22 and 24, coverage and package checks on Node 24, and consumer tests on Node 20/24 with ESLint 9.22 and 10. Pull requests keep dependency review and CodeQL.
1241
1329
 
1242
1330
  ### Project structure
1243
1331
 
@@ -1260,13 +1348,9 @@ eslint-ai-guard/
1260
1348
  │ │ ├── validateRelations.ts
1261
1349
  │ │ ├── validateStructure.ts
1262
1350
  │ │ └── presets/
1263
- │ │ ├── frontend.ts
1264
- │ │ ├── backend.ts
1265
- │ │ ├── other.ts
1266
- │ │ ├── helpers.ts
1267
- │ │ └── index.ts
1268
1351
  │ ├── utils/
1269
1352
  │ └── rules/
1353
+ │ ├── constants.ts
1270
1354
  │ ├── FilenamePascalCase.ts
1271
1355
  │ ├── NoMultilineImports.ts
1272
1356
  │ ├── ProjectSetup.ts
@@ -1276,11 +1360,18 @@ eslint-ai-guard/
1276
1360
  ├── test/
1277
1361
  ├── scripts/
1278
1362
  │ └── TestConsumer.mjs
1363
+ ├── docs/
1279
1364
  ├── .github/
1280
- │ └── workflows/
1281
- │ └── ci.yml
1282
- ├── eslint/
1365
+ │ ├── workflows/
1366
+ │ │ ├── codeql.yml
1367
+ │ │ ├── dependency-review.yml
1368
+ │ │ └── release.yml
1369
+ │ ├── ISSUE_TEMPLATE/
1370
+ │ └── dependabot.yml
1283
1371
  ├── CHANGELOG.md
1372
+ ├── CONTRIBUTING.md
1373
+ ├── SECURITY.md
1374
+ ├── CODE_OF_CONDUCT.md
1284
1375
  ├── eslint.config.mjs
1285
1376
  ├── tsconfig.json
1286
1377
  ├── tsup.config.ts
@@ -1290,31 +1381,53 @@ eslint-ai-guard/
1290
1381
 
1291
1382
  ### Adding a new rule
1292
1383
 
1293
- 1. Create `src/rules/MyRule.ts`.
1294
- 2. Export it from `src/rules/index.ts`.
1295
- 3. Register it in `src/plugin.ts`.
1296
- 4. Add it to `src/configs/recommended.ts` if it should be enabled by default.
1297
- 5. Add tests in `test/`.
1298
- 6. Run `npm run verify`.
1384
+ 1. Create `src/rules/MyRule.ts` in PascalCase.
1385
+ 2. Add the rule name to `src/rules/constants.ts`.
1386
+ 3. Export it from `src/rules/index.ts`.
1387
+ 4. Register it in `src/plugin.ts`.
1388
+ 5. Add it to `src/configs/recommended.ts` if it should be enabled by default.
1389
+ 6. Provide `meta.docs.description`, `meta.docs.url`, `meta.docs.recommended`, `meta.schema` and `meta.messages`.
1390
+ 7. Add `meta.defaultOptions` when the rule accepts options.
1391
+ 8. Add tests in `test/`.
1392
+ 9. Run `yarn verify`.
1299
1393
 
1300
1394
  ## Publishing
1301
1395
 
1302
- 1. Change `version` in `package.json`.
1303
- 2. Optionally run `yarn build` to check the build and generated version.
1304
- 3. Run `npm publish`.
1396
+ Releases are driven by a version tag. The workflow validates that the tag matches `package.json`, runs all checks, publishes to npm with provenance and creates a GitHub release.
1397
+
1398
+ 1. Update `version` in `package.json`.
1399
+ 2. Update `CHANGELOG.md`.
1400
+ 3. Run `yarn test:release`.
1401
+ 4. Commit and push the changes.
1402
+ 5. Create and push a tag:
1305
1403
 
1306
- `prepack` runs `yarn build` automatically, so `npm publish` always packs a fresh `dist`. The plugin version is injected from `package.json` during the build, so you do not need to edit `src/plugin.ts`.
1404
+ ```bash
1405
+ git tag v0.4.0
1406
+ git push origin v0.4.0
1407
+ ```
1307
1408
 
1308
- For an extra check before publishing:
1409
+ The release workflow requires the `NPM_TOKEN` repository secret. Provenance also requires `id-token: write`, which is already configured in `.github/workflows/release.yml`.
1410
+
1411
+ The workflow runs all checks before publishing. If any check fails, the publish job is skipped. Fix the problem, delete the tag and recreate it before pushing again:
1309
1412
 
1310
1413
  ```bash
1311
- yarn verify
1312
- npm pack --dry-run
1414
+ git tag -d v0.4.0
1415
+ git push origin :refs/tags/v0.4.0
1313
1416
  ```
1314
1417
 
1315
- ## Legacy
1418
+ `prepack` runs `yarn build` automatically, so published packages always contain a fresh `dist`. The plugin version is injected from `package.json` during the build, so you do not need to edit `src/plugin.ts`.
1419
+
1420
+ ## Contributing
1421
+
1422
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, testing and rule-authoring guidelines. All participants are expected to follow the [Code of Conduct](CODE_OF_CONDUCT.md).
1423
+
1424
+ ## Security
1425
+
1426
+ See [SECURITY.md](SECURITY.md) for supported versions and private vulnerability reporting.
1427
+
1428
+ ## Articles
1316
1429
 
1317
- `eslint/` keeps the three original rule implementations before packaging. Source of truth is `src/rules/`.
1430
+ - [How I forced AI to follow the project standard with ESLint](docs/tabnews-eslint-plugin-ai-rules.md)
1318
1431
 
1319
1432
  ## License
1320
1433
 
package/dist/index.cjs CHANGED
@@ -49,22 +49,50 @@ var import_eslint_plugin_import_x = require("eslint-plugin-import-x");
49
49
  var import_eslint_plugin = __toESM(require("@stylistic/eslint-plugin"), 1);
50
50
  var import_typescript_eslint = __toESM(require("typescript-eslint"), 1);
51
51
 
52
+ // src/rules/constants.ts
53
+ var RULE_NAMES = {
54
+ filenamePascalCase: "filename-pascal-case",
55
+ noMultilineImports: "no-multiline-imports",
56
+ projectSetup: "project-setup",
57
+ projectStructure: "project-structure",
58
+ sortImports: "sort-imports"
59
+ };
60
+ var RULE_IDS = {
61
+ filenamePascalCase: `ai-rules/${RULE_NAMES.filenamePascalCase}`,
62
+ noMultilineImports: `ai-rules/${RULE_NAMES.noMultilineImports}`,
63
+ projectSetup: `ai-rules/${RULE_NAMES.projectSetup}`,
64
+ projectStructure: `ai-rules/${RULE_NAMES.projectStructure}`,
65
+ sortImports: `ai-rules/${RULE_NAMES.sortImports}`
66
+ };
67
+
52
68
  // src/rules/FilenamePascalCase.ts
53
69
  var import_node_path = __toESM(require("path"), 1);
54
70
  var filenamePascalCase = {
55
71
  meta: {
56
72
  type: "suggestion",
57
- docs: { description: "Enforce PascalCase for file names" },
73
+ docs: {
74
+ description: "Enforce PascalCase for file names",
75
+ recommended: true,
76
+ url: "https://github.com/lvsouza/eslint-ai-guard/blob/main/README.md#ai-rulesfilename-pascal-case"
77
+ },
58
78
  schema: [
59
79
  {
60
80
  type: "object",
61
81
  properties: {
62
- ignore: { type: "array", items: { type: "string" } },
63
- ignoreMiddleExtensions: { type: "boolean" }
82
+ ignore: {
83
+ type: "array",
84
+ items: { type: "string" },
85
+ description: "Regex strings matched against the file name and relative path."
86
+ },
87
+ ignoreMiddleExtensions: {
88
+ type: "boolean",
89
+ description: "Allow middle extensions such as .test in file names."
90
+ }
64
91
  },
65
92
  additionalProperties: false
66
93
  }
67
94
  ],
95
+ defaultOptions: [{ ignore: [], ignoreMiddleExtensions: true }],
68
96
  messages: {
69
97
  invalid: 'File name "{{basename}}" must be in PascalCase. Rename to "{{expected}}".'
70
98
  }
@@ -122,10 +150,12 @@ var filenamePascalCase = {
122
150
  var noMultilineImports = {
123
151
  meta: {
124
152
  type: "layout",
125
- fixable: "code",
126
153
  docs: {
127
- description: "Disallow multiline imports"
154
+ description: "Disallow multiline imports",
155
+ recommended: true,
156
+ url: "https://github.com/lvsouza/eslint-ai-guard/blob/main/README.md#ai-rulesno-multiline-imports"
128
157
  },
158
+ fixable: "code",
129
159
  schema: [],
130
160
  messages: {
131
161
  multilineImport: "Imports must be written on a single line."
@@ -387,7 +417,9 @@ var projectStructure = {
387
417
  meta: {
388
418
  type: "problem",
389
419
  docs: {
390
- description: "Enforce the configured project folder and file structure"
420
+ description: "Enforce the configured project folder and file structure",
421
+ recommended: false,
422
+ url: "https://github.com/lvsouza/eslint-ai-guard/blob/main/README.md#ai-rulesproject-structure"
391
423
  },
392
424
  schema: [],
393
425
  messages: {
@@ -461,7 +493,7 @@ function hasStructureRules(structure) {
461
493
  }
462
494
 
463
495
  // src/rules/ProjectSetup.ts
464
- var hasWarned = false;
496
+ var hasReported = false;
465
497
  function isConfiguredProject(project) {
466
498
  if (project.relations) return true;
467
499
  if (project.preset === "frontend" || project.preset === "backend" || project.preset === "other") {
@@ -469,36 +501,38 @@ function isConfiguredProject(project) {
469
501
  }
470
502
  return Boolean(project.structure && hasStructureRules(project.structure));
471
503
  }
472
- function warnOnce() {
473
- if (hasWarned) return;
504
+ function shouldReportOnce() {
505
+ if (hasReported) return false;
474
506
  if (process.env.AI_RULES_SILENT === "1" || process.env.AI_RULES_SILENT === "true") {
475
- return;
507
+ return false;
476
508
  }
477
- hasWarned = true;
478
- console.warn(
479
- [
480
- "[eslint-plugin-ai-rules] Project structure validation is not configured.",
481
- "Configure it with aiRules.configs.projects([{ rootFolder: '.', preset: 'frontend' | 'backend' }]).",
482
- "If this project is not a frontend/backend, use preset: 'other' to disable this warning."
483
- ].join("\n")
484
- );
509
+ hasReported = true;
510
+ return true;
485
511
  }
486
512
  var projectSetup = {
487
513
  meta: {
488
514
  type: "suggestion",
489
515
  docs: {
490
- description: "Warn when the project structure validation is not configured"
516
+ description: "Require project structure validation to be configured",
517
+ recommended: true,
518
+ url: "https://github.com/lvsouza/eslint-ai-guard/blob/main/README.md#ai-rulesproject-setup"
491
519
  },
492
520
  schema: [],
493
- messages: {}
521
+ messages: {
522
+ notConfigured: 'Project structure validation is not configured. Configure it with aiRules.configs.projects([{ rootFolder: ".", preset: "frontend" | "backend" }]). If this project is not a frontend/backend, use preset: "other" to disable this warning.'
523
+ }
494
524
  },
495
525
  create(context) {
496
526
  return {
497
- Program() {
527
+ Program(node) {
498
528
  const settings = context.settings["ai-rules"];
499
529
  const projects2 = settings?.projects ?? (settings?.project ? [settings.project] : []);
500
530
  if (projects2.some(isConfiguredProject)) return;
501
- warnOnce();
531
+ if (!shouldReportOnce()) return;
532
+ context.report({
533
+ node,
534
+ messageId: "notConfigured"
535
+ });
502
536
  }
503
537
  };
504
538
  }
@@ -509,12 +543,14 @@ var sortImports = {
509
543
  meta: {
510
544
  type: "layout",
511
545
  docs: {
512
- description: "Sort imports by group and line length descending, collapsing multiline imports"
546
+ description: "Enforce sorted imports by group and line length descending, collapsing multiline imports",
547
+ recommended: true,
548
+ url: "https://github.com/lvsouza/eslint-ai-guard/blob/main/README.md#ai-rulessort-imports"
513
549
  },
514
550
  fixable: "code",
515
551
  schema: [],
516
552
  messages: {
517
- sortRequired: "As importa\xE7\xF5es devem estar ordenadas por grupo e tamanho da linha, ocupando uma \xFAnica linha."
553
+ sortRequired: "Imports must be sorted by group and line length, each on a single line."
518
554
  }
519
555
  },
520
556
  create(context) {
@@ -632,14 +668,14 @@ function getSortedContent(content) {
632
668
  var plugin = {
633
669
  meta: {
634
670
  name: "eslint-plugin-ai-rules",
635
- version: "0.3.1"
671
+ version: "0.4.0"
636
672
  },
637
673
  rules: {
638
- "filename-pascal-case": filenamePascalCase,
639
- "no-multiline-imports": noMultilineImports,
640
- "project-setup": projectSetup,
641
- "project-structure": projectStructure,
642
- "sort-imports": sortImports
674
+ [RULE_NAMES.filenamePascalCase]: filenamePascalCase,
675
+ [RULE_NAMES.noMultilineImports]: noMultilineImports,
676
+ [RULE_NAMES.projectSetup]: projectSetup,
677
+ [RULE_NAMES.projectStructure]: projectStructure,
678
+ [RULE_NAMES.sortImports]: sortImports
643
679
  }
644
680
  };
645
681
 
@@ -660,10 +696,10 @@ var recommended = [
660
696
  ]
661
697
  },
662
698
  rules: {
663
- "ai-rules/sort-imports": "error",
664
- "ai-rules/no-multiline-imports": "error",
665
- "ai-rules/filename-pascal-case": "error",
666
- "ai-rules/project-setup": "warn",
699
+ [RULE_IDS.sortImports]: "error",
700
+ [RULE_IDS.noMultilineImports]: "error",
701
+ [RULE_IDS.filenamePascalCase]: "error",
702
+ [RULE_IDS.projectSetup]: "warn",
667
703
  "max-len": "off",
668
704
  "import-x/no-duplicates": "error",
669
705
  "import-x/no-default-export": "off",
@@ -1880,6 +1916,11 @@ function validateDefinition(definition, index) {
1880
1916
  });
1881
1917
  }
1882
1918
  }
1919
+ if (definition.rules !== void 0 && (typeof definition.rules !== "object" || definition.rules === null || Array.isArray(definition.rules))) {
1920
+ throw new Error(
1921
+ `Invalid project at index ${index}: rules must be an object.`
1922
+ );
1923
+ }
1883
1924
  }
1884
1925
  function resolveStructure(definition, preset) {
1885
1926
  return mergeStructure(preset?.structure, definition.structure);
@@ -1934,15 +1975,16 @@ function projects(definitions) {
1934
1975
  ]));
1935
1976
  const rules = {
1936
1977
  ...baseConfig.rules,
1937
- ...preset?.rules ?? {},
1938
- "ai-rules/project-structure": structureEnabled ? "error" : "off",
1939
- "ai-rules/filename-pascal-case": structureEnabled ? "off" : baseConfig.rules?.["ai-rules/filename-pascal-case"] ?? "error",
1978
+ [RULE_IDS.projectStructure]: structureEnabled ? "error" : "off",
1979
+ [RULE_IDS.filenamePascalCase]: structureEnabled ? "off" : baseConfig.rules?.[RULE_IDS.filenamePascalCase] ?? "error",
1940
1980
  ...relations ? {
1941
1981
  "boundaries/dependencies": [
1942
1982
  "error",
1943
1983
  buildRelationsRuleOptions(relations)
1944
1984
  ]
1945
- } : {}
1985
+ } : {},
1986
+ ...preset?.rules ?? {},
1987
+ ...definition.rules ?? {}
1946
1988
  };
1947
1989
  return {
1948
1990
  ...baseConfig,