@agilebot/eslint-config 0.6.1 → 0.7.0-beta.1

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/dist/index.mjs ADDED
@@ -0,0 +1,1093 @@
1
+ /**
2
+ * @license @agilebot/eslint-config v0.7.0-beta.1
3
+ *
4
+ * Copyright (c) Agilebot, Inc. and its affiliates.
5
+ *
6
+ * This source code is licensed under the MIT license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+
10
+ import {
11
+ DEFAULT_GLOBS,
12
+ DTS_GLOBS,
13
+ IGNORE_GLOBS,
14
+ JS_GLOBS,
15
+ TS_GLOBS,
16
+ VUE_GLOBS,
17
+ __dirname,
18
+ define_STANDARD_RULES_default
19
+ } from "./chunk-XQZGZMJY.mjs";
20
+
21
+ // src/factory/index.ts
22
+ import assert from "node:assert";
23
+ import { findTsconfigFiles } from "@agilebot/eslint-utils";
24
+ import * as parserTs from "@typescript-eslint/parser";
25
+ import * as parserVue from "vue-eslint-parser";
26
+
27
+ // src/configs/env.ts
28
+ import globals from "globals";
29
+ function env() {
30
+ return {
31
+ name: "agilebot/env",
32
+ files: DEFAULT_GLOBS,
33
+ languageOptions: {
34
+ globals: {
35
+ ...globals.browser,
36
+ ...globals.node,
37
+ ...globals.es2015,
38
+ ...globals.mocha,
39
+ ...globals.jest,
40
+ ...globals.jasmine
41
+ }
42
+ }
43
+ };
44
+ }
45
+
46
+ // src/configs/standard.ts
47
+ import pluginImport from "eslint-plugin-import-x";
48
+ import pluginNode from "eslint-plugin-n";
49
+ import pluginPromise from "eslint-plugin-promise";
50
+ import pluginTs from "@typescript-eslint/eslint-plugin";
51
+ function standard() {
52
+ const standardRules = {};
53
+ const originalStdRules = (
54
+ // @ts-expect-error -- extracted rules from eslint-config-love
55
+ typeof define_STANDARD_RULES_default === "undefined" ? {} : (
56
+ // @ts-expect-error -- extracted rules from eslint-config-love
57
+ define_STANDARD_RULES_default
58
+ )
59
+ );
60
+ const disabledRules = new Set(Object.values(standardDisabled()).flat());
61
+ Object.entries(originalStdRules).forEach(([key, value]) => {
62
+ if (disabledRules.has(key)) {
63
+ return;
64
+ }
65
+ if (key.startsWith("import/")) {
66
+ standardRules[`import-x/${key.slice(7)}`] = value;
67
+ } else {
68
+ standardRules[key] = value;
69
+ }
70
+ });
71
+ return {
72
+ name: "agilebot/standard",
73
+ files: DEFAULT_GLOBS,
74
+ plugins: {
75
+ n: pluginNode,
76
+ "@typescript-eslint": pluginTs,
77
+ promise: pluginPromise,
78
+ "import-x": pluginImport
79
+ },
80
+ rules: {
81
+ ...standardRules,
82
+ "no-alert": "error",
83
+ // 找出TODO注释,以便后期修复
84
+ "no-warning-comments": [
85
+ "warn",
86
+ {
87
+ terms: ["todo", "fixme"]
88
+ }
89
+ ],
90
+ // 避免使用同步方法
91
+ "n/no-sync": "error",
92
+ // 尽量使用fs.promises而不是fs
93
+ "n/prefer-promises/fs": "error",
94
+ "n/prefer-promises/dns": "error",
95
+ // 路径拼接使用path.join,而不是直接使用加号
96
+ "n/no-path-concat": "error",
97
+ "promise/no-return-wrap": "error",
98
+ "promise/no-nesting": "error",
99
+ "promise/no-promise-in-callback": "error",
100
+ "promise/no-callback-in-promise": "error",
101
+ "promise/param-names": "error",
102
+ "promise/valid-params": "error",
103
+ "promise/no-multiple-resolved": "error",
104
+ "promise/no-return-in-finally": "error",
105
+ "promise/prefer-await-to-then": "warn",
106
+ // 自定义standard规则
107
+ "@typescript-eslint/max-params": ["error", { max: 5 }],
108
+ "@typescript-eslint/only-throw-error": [
109
+ "error",
110
+ {
111
+ allowThrowingAny: true,
112
+ allowThrowingUnknown: true
113
+ }
114
+ ],
115
+ "@typescript-eslint/no-loop-func": "warn"
116
+ }
117
+ };
118
+ }
119
+ function standardDisabled() {
120
+ return {
121
+ uncategoized: [
122
+ "@typescript-eslint/no-extraneous-class",
123
+ "@typescript-eslint/consistent-type-assertions",
124
+ "@typescript-eslint/no-non-null-assertion"
125
+ ],
126
+ "v9.0.0": ["@typescript-eslint/strict-boolean-expressions"],
127
+ "v10.0.0": ["@typescript-eslint/explicit-function-return-type"],
128
+ "v12.0.0": [
129
+ "@typescript-eslint/restrict-template-expressions",
130
+ "@typescript-eslint/space-before-function-paren"
131
+ ],
132
+ "v17.0.0": [
133
+ "@typescript-eslint/no-invalid-void-type",
134
+ "@typescript-eslint/method-signature-style"
135
+ ],
136
+ "v26.0.0": ["@typescript-eslint/no-confusing-void-expression"],
137
+ "v40.0.0": ["@typescript-eslint/unbound-method"],
138
+ "v42.0.0": ["@typescript-eslint/no-unsafe-argument"],
139
+ "v55.0.0": ["@typescript-eslint/class-methods-use-this"],
140
+ "v57.0.0": [
141
+ "@typescript-eslint/init-declarations",
142
+ "@typescript-eslint/no-empty-function"
143
+ ],
144
+ "v58.0.0": ["@typescript-eslint/no-explicit-any"],
145
+ "v64.0.0": ["@typescript-eslint/no-deprecated"],
146
+ "v65.0.0": ["@typescript-eslint/no-magic-numbers"],
147
+ "v70.0.0": ["@typescript-eslint/no-unnecessary-condition"],
148
+ "v75.0.0": ["@typescript-eslint/no-unnecessary-type-parameters"],
149
+ "v76.0.0": ["@typescript-eslint/no-unsafe-assignment"],
150
+ "v77.0.0": ["@typescript-eslint/no-unsafe-call"],
151
+ "v79.0.0": ["@typescript-eslint/no-unsafe-enum-comparison"],
152
+ "v80.0.0": ["@typescript-eslint/no-unsafe-member-access"],
153
+ "v81.0.0": ["@typescript-eslint/no-unsafe-return"],
154
+ "v82.0.0": ["@typescript-eslint/no-unsafe-unary-minus"],
155
+ "v89.0.0": ["@typescript-eslint/prefer-destructuring"]
156
+ };
157
+ }
158
+
159
+ // src/configs/ts.ts
160
+ import { isInEditor } from "@agilebot/eslint-utils";
161
+ import * as pluginTs2 from "@typescript-eslint/eslint-plugin";
162
+ import pluginStylistic from "@stylistic/eslint-plugin";
163
+ import pluginPreferArrowFunctions from "eslint-plugin-prefer-arrow-functions";
164
+ import pluginUnusedImports from "eslint-plugin-unused-imports";
165
+ function ts() {
166
+ return {
167
+ name: "agilebot/ts",
168
+ files: DEFAULT_GLOBS,
169
+ plugins: {
170
+ "@typescript-eslint": pluginTs2,
171
+ "@stylistic": pluginStylistic,
172
+ "prefer-arrow-functions": pluginPreferArrowFunctions,
173
+ "unused-imports": pluginUnusedImports
174
+ },
175
+ rules: {
176
+ // 如果没用模板字符串,避免使用反引号
177
+ "@stylistic/quotes": ["error", "single", { avoidEscape: true }],
178
+ "prefer-arrow-functions/prefer-arrow-functions": [
179
+ "warn",
180
+ {
181
+ allowNamedFunctions: true,
182
+ classPropertiesAllowed: false,
183
+ disallowPrototype: false,
184
+ returnStyle: "unchanged",
185
+ singleReturnOnly: false
186
+ }
187
+ ],
188
+ "@typescript-eslint/no-unused-vars": "off",
189
+ "unused-imports/no-unused-imports": isInEditor() ? "off" : "error",
190
+ "unused-imports/no-unused-vars": [
191
+ "warn",
192
+ {
193
+ args: "after-used",
194
+ argsIgnorePattern: "^_",
195
+ vars: "all",
196
+ varsIgnorePattern: "^_",
197
+ caughtErrors: "none",
198
+ caughtErrorsIgnorePattern: "^_",
199
+ destructuredArrayIgnorePattern: "^_",
200
+ ignoreRestSiblings: true
201
+ }
202
+ ],
203
+ // 优先使用interface而不是type
204
+ "@typescript-eslint/consistent-type-definitions": "error",
205
+ "@typescript-eslint/naming-convention": [
206
+ "error",
207
+ // variable规则在@agilebot/var-naming中定义
208
+ {
209
+ selector: "function",
210
+ format: ["camelCase", "PascalCase"]
211
+ },
212
+ {
213
+ selector: "variable",
214
+ types: ["function"],
215
+ format: ["camelCase", "PascalCase"]
216
+ },
217
+ {
218
+ selector: "typeLike",
219
+ format: ["PascalCase"]
220
+ },
221
+ {
222
+ selector: "parameter",
223
+ format: ["camelCase"],
224
+ leadingUnderscore: "allow"
225
+ },
226
+ {
227
+ selector: "method",
228
+ format: ["camelCase"]
229
+ },
230
+ {
231
+ selector: "classProperty",
232
+ format: ["camelCase", "UPPER_CASE", "PascalCase"],
233
+ leadingUnderscore: "allow"
234
+ },
235
+ {
236
+ selector: "typeProperty",
237
+ format: ["camelCase"]
238
+ },
239
+ {
240
+ selector: "enum",
241
+ format: ["PascalCase"]
242
+ },
243
+ {
244
+ selector: "enumMember",
245
+ format: ["PascalCase", "UPPER_CASE"]
246
+ }
247
+ ],
248
+ // 禁止没有必要的初始化
249
+ "@typescript-eslint/no-inferrable-types": "error",
250
+ // 函数中未使用await,函数签名不要加async
251
+ "@typescript-eslint/require-await": "error",
252
+ // 没有必要的类型as
253
+ "@typescript-eslint/no-unnecessary-type-assertion": "error",
254
+ // 数组用T[]而不是Array<T>
255
+ "@typescript-eslint/array-type": ["error", { default: "array" }],
256
+ // Promise必须加await或void
257
+ "@typescript-eslint/no-misused-promises": [
258
+ "error",
259
+ {
260
+ checksVoidReturn: false
261
+ }
262
+ ],
263
+ "@typescript-eslint/no-deprecated": "error"
264
+ }
265
+ };
266
+ }
267
+ function tsOnly() {
268
+ return {
269
+ name: "agilebot/ts-only",
270
+ files: TS_GLOBS,
271
+ rules: {
272
+ "prefer-object-has-own": "error",
273
+ "@typescript-eslint/explicit-member-accessibility": "error"
274
+ }
275
+ };
276
+ }
277
+ function jsOnly() {
278
+ return {
279
+ name: "agilebot/js-only",
280
+ files: JS_GLOBS,
281
+ rules: {
282
+ "@typescript-eslint/no-require-imports": "off"
283
+ }
284
+ };
285
+ }
286
+ function dts() {
287
+ return {
288
+ name: "agilebot/dts",
289
+ files: DTS_GLOBS,
290
+ rules: {
291
+ // .d.ts中支持导入ts文件中的类型
292
+ "@typescript-eslint/consistent-type-imports": "off",
293
+ // .d.ts中忽略属性命名规则
294
+ "@typescript-eslint/naming-convention": "off",
295
+ // .d.ts中忽略三斜线引用
296
+ "@typescript-eslint/triple-slash-reference": "off"
297
+ }
298
+ };
299
+ }
300
+
301
+ // src/configs/imports.ts
302
+ import path from "node:path";
303
+ import fs from "node:fs";
304
+ import { findCacheDir, findRootDir, isInEditor as isInEditor2 } from "@agilebot/eslint-utils";
305
+ import pluginImport2 from "eslint-plugin-import-x";
306
+ import pluginNoRelativeImportPaths from "eslint-plugin-no-relative-import-paths";
307
+ function imports(opts) {
308
+ const rootDir = findRootDir(__dirname);
309
+ const pkgPath = path.join(opts.packageDir, "package.json");
310
+ if (!fs.existsSync(pkgPath)) {
311
+ throw new Error(`package.json not found in ${opts.packageDir}`);
312
+ }
313
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
314
+ const tmpPkg = {
315
+ name: `${pkg.name}/tmp`,
316
+ dependencies: {
317
+ [pkg.name]: "*"
318
+ }
319
+ };
320
+ const tmpPkgSafeName = tmpPkg.name.replace(/\//g, "__");
321
+ const cacheDir = findCacheDir(rootDir);
322
+ const tmpPkgDir = path.join(cacheDir, "tmp-pkg", tmpPkgSafeName);
323
+ if (!fs.existsSync(tmpPkgDir)) {
324
+ fs.mkdirSync(tmpPkgDir, { recursive: true });
325
+ }
326
+ const tmpPkgJson = JSON.stringify(tmpPkg, null, 2);
327
+ fs.writeFileSync(path.join(tmpPkgDir, "package.json"), tmpPkgJson);
328
+ return {
329
+ name: "agilebot/imports",
330
+ files: DEFAULT_GLOBS,
331
+ plugins: {
332
+ "import-x": pluginImport2,
333
+ "no-relative-import-paths": pluginNoRelativeImportPaths
334
+ },
335
+ rules: {
336
+ ...pluginImport2.configs.recommended.rules,
337
+ ...pluginImport2.configs.typescript.rules,
338
+ "import-x/no-unresolved": [
339
+ "error",
340
+ {
341
+ ignore: [
342
+ String.raw`\?(react|raw|url|inline|worker|worker&inline|worker&url|sharedworker|sharedworker&inline|sharedworker&url)$`
343
+ ]
344
+ }
345
+ ],
346
+ "import-x/no-named-as-default-member": "off",
347
+ "import-x/no-named-as-default": "off",
348
+ "import-x/no-useless-path-segments": [
349
+ "error",
350
+ {
351
+ noUselessIndex: true
352
+ }
353
+ ],
354
+ "import-x/no-cycle": isInEditor2() ? "off" : "error",
355
+ "import-x/newline-after-import": "error",
356
+ "import-x/first": "error",
357
+ "import-x/no-import-module-exports": "error",
358
+ "import-x/no-anonymous-default-export": [
359
+ "error",
360
+ {
361
+ allowArray: true,
362
+ allowObject: true
363
+ }
364
+ ],
365
+ "import-x/no-extraneous-dependencies": [
366
+ "error",
367
+ {
368
+ packageDir: [opts.packageDir, tmpPkgDir, rootDir],
369
+ devDependencies: [
370
+ "test/**/*",
371
+ "tests/**/*",
372
+ "**/__tests__/**",
373
+ "**/*.test.{ts,tsx,js,jsx,cjs,mjs,mts,cts}",
374
+ "**/*.config.{ts,js,cjs,mjs,mts,cts}",
375
+ "**/.storybook/**",
376
+ "**/*.stories.{ts,tsx}",
377
+ "**/scripts/*.{ts,mts}",
378
+ ...opts.devDependencies ?? []
379
+ ],
380
+ includeInternal: true
381
+ }
382
+ ],
383
+ "import-x/order": [
384
+ "error",
385
+ {
386
+ groups: [
387
+ "builtin",
388
+ "external",
389
+ "internal",
390
+ "parent",
391
+ "sibling",
392
+ "index",
393
+ "object"
394
+ ],
395
+ pathGroups: [
396
+ {
397
+ pattern: `${pkg.name}/**`,
398
+ group: "parent",
399
+ position: "after"
400
+ }
401
+ ],
402
+ "newlines-between": "never",
403
+ distinctGroup: false
404
+ }
405
+ ],
406
+ "no-relative-import-paths/no-relative-import-paths": [
407
+ "warn",
408
+ { allowSameFolder: true }
409
+ ]
410
+ },
411
+ settings: {
412
+ "import-x/parsers": {
413
+ "@typescript-eslint/parser": [".ts", ".tsx"]
414
+ },
415
+ "import-x/resolver": opts.resolver === "oxc" ? {
416
+ oxc: true
417
+ } : {
418
+ typescript: {
419
+ alwaysTryTypes: true
420
+ }
421
+ },
422
+ "import-x/internal-regex": opts.monorepoScope ? `^${opts.monorepoScope.replace(/\//g, "")}/` : void 0,
423
+ "import-x/core-modules": opts.coreModules ?? void 0
424
+ }
425
+ };
426
+ }
427
+
428
+ // src/configs/unicorn.ts
429
+ import pluginUnicorn from "eslint-plugin-unicorn";
430
+ function unicorn(opts) {
431
+ return {
432
+ name: "agilebot/unicorn",
433
+ files: DEFAULT_GLOBS,
434
+ plugins: {
435
+ unicorn: pluginUnicorn
436
+ },
437
+ rules: {
438
+ ...pluginUnicorn.configs["flat/recommended"].rules,
439
+ "unicorn/prefer-module": opts.module ? "error" : "off",
440
+ "unicorn/prefer-top-level-await": "off",
441
+ "unicorn/filename-case": "off",
442
+ "unicorn/import-style": "off",
443
+ "unicorn/prefer-at": "off",
444
+ "unicorn/prevent-abbreviations": "off",
445
+ "unicorn/prefer-date-now": "off",
446
+ "unicorn/no-process-exit": "off",
447
+ "unicorn/no-null": "off",
448
+ "unicorn/consistent-function-scoping": "off",
449
+ "unicorn/numeric-separators-style": "off",
450
+ "unicorn/prefer-optional-catch-binding": "off",
451
+ "unicorn/no-negated-condition": "off",
452
+ "unicorn/switch-case-braces": "off",
453
+ "unicorn/no-array-for-each": "off",
454
+ "unicorn/prefer-ternary": "off",
455
+ "unicorn/better-regex": "off",
456
+ "unicorn/error-message": "off",
457
+ "unicorn/no-object-as-default-parameter": "off",
458
+ "unicorn/no-array-push-push": "off",
459
+ "unicorn/no-useless-undefined": "off",
460
+ "unicorn/prefer-blob-reading-methods": "off",
461
+ "unicorn/catch-error-name": [
462
+ "error",
463
+ {
464
+ name: "err"
465
+ }
466
+ ],
467
+ "unicorn/prefer-global-this": "off"
468
+ }
469
+ };
470
+ }
471
+
472
+ // src/configs/react.ts
473
+ import pluginReact from "eslint-plugin-react";
474
+ import pluginReactX from "@eslint-react/eslint-plugin";
475
+ import pluginReactHooks from "eslint-plugin-react-hooks";
476
+ import pluginJsxA11y from "eslint-plugin-jsx-a11y";
477
+ import pluginStylistic2 from "@stylistic/eslint-plugin";
478
+ import pluginAgilebot from "@agilebot/eslint-plugin";
479
+ function react(opts) {
480
+ return {
481
+ name: "agilebot/react",
482
+ files: DEFAULT_GLOBS,
483
+ plugins: {
484
+ react: pluginReact,
485
+ "react-hooks": pluginReactHooks,
486
+ "jsx-a11y": pluginJsxA11y,
487
+ ...pluginReactX.configs.recommended.plugins,
488
+ "@stylistic": pluginStylistic2,
489
+ "@agilebot": pluginAgilebot
490
+ },
491
+ rules: {
492
+ ...pluginJsxA11y.flatConfigs.recommended.rules,
493
+ // recommended rules from eslint-plugin-react
494
+ "react/no-is-mounted": "error",
495
+ // recommended rules from @eslint-react
496
+ "@eslint-react/no-direct-mutation-state": "error",
497
+ // Children API
498
+ // '@eslint-react/no-children-count': 'warn',
499
+ // '@eslint-react/no-children-for-each': 'warn',
500
+ // '@eslint-react/no-children-map': 'warn',
501
+ // '@eslint-react/no-children-only': 'warn',
502
+ "@eslint-react/no-children-prop": "error",
503
+ "@eslint-react/no-children-to-array": "warn",
504
+ "@eslint-react/no-clone-element": "warn",
505
+ "@eslint-react/no-class-component": "error",
506
+ "@eslint-react/no-string-refs": "error",
507
+ "@eslint-react/no-missing-key": "error",
508
+ "@eslint-react/no-array-index-key": "warn",
509
+ "@eslint-react/no-duplicate-key": "error",
510
+ "@eslint-react/no-comment-textnodes": "error",
511
+ "@eslint-react/no-component-will-mount": "error",
512
+ "@eslint-react/no-component-will-receive-props": "error",
513
+ "@eslint-react/no-component-will-update": "error",
514
+ "@eslint-react/no-unsafe-component-will-mount": "warn",
515
+ "@eslint-react/no-unsafe-component-will-receive-props": "warn",
516
+ "@eslint-react/no-unsafe-component-will-update": "warn",
517
+ // '@eslint-react/no-unstable-context-value': 'error',
518
+ // '@eslint-react/no-unstable-default-props': 'error',
519
+ "@eslint-react/ensure-forward-ref-using-ref": "warn",
520
+ "@eslint-react/no-create-ref": "error",
521
+ "@eslint-react/no-nested-components": "warn",
522
+ "@eslint-react/no-redundant-should-component-update": "error",
523
+ "@eslint-react/no-set-state-in-component-did-mount": "warn",
524
+ "@eslint-react/no-set-state-in-component-did-update": "warn",
525
+ "@eslint-react/no-set-state-in-component-will-update": "warn",
526
+ "@eslint-react/prefer-shorthand-boolean": "error",
527
+ "@eslint-react/no-access-state-in-setstate": "error",
528
+ "@eslint-react/prefer-shorthand-fragment": "error",
529
+ "@eslint-react/no-missing-component-display-name": "error",
530
+ "@eslint-react/no-prop-types": "error",
531
+ "@eslint-react/no-useless-fragment": [
532
+ "error",
533
+ { allowExpressions: true }
534
+ ],
535
+ "@eslint-react/jsx-uses-vars": "error",
536
+ "@eslint-react/jsx-no-duplicate-props": "error",
537
+ // recommended rules from @eslint-react/dom
538
+ "@eslint-react/dom/no-children-in-void-dom-elements": "error",
539
+ "@eslint-react/dom/no-unsafe-target-blank": "error",
540
+ "@eslint-react/dom/no-dangerously-set-innerhtml": "error",
541
+ "@eslint-react/dom/no-dangerously-set-innerhtml-with-children": "error",
542
+ "@eslint-react/dom/no-find-dom-node": "error",
543
+ "@eslint-react/dom/no-render-return-value": "error",
544
+ // recommended rules from @eslint-react/hooks-extra
545
+ "@eslint-react/hooks-extra/prefer-use-state-lazy-initialization": "warn",
546
+ // recommended rules react-hooks
547
+ "react-hooks/rules-of-hooks": "error",
548
+ // recommended rules from @eslint-react/naming-convention
549
+ "@eslint-react/naming-convention/component-name": "error",
550
+ "@eslint-react/naming-convention/use-state": "error",
551
+ // recommended rules from @eslint-react/web-api
552
+ "@eslint-react/web-api/no-leaked-interval": "warn",
553
+ "@eslint-react/web-api/no-leaked-timeout": "warn",
554
+ "@eslint-react/web-api/no-leaked-event-listener": "warn",
555
+ "@eslint-react/web-api/no-leaked-resize-observer": "warn",
556
+ // 以下是自定义规则
557
+ "react/jsx-handler-names": [
558
+ "error",
559
+ {
560
+ eventHandlerPrefix: "handle",
561
+ eventHandlerPropPrefix: "on",
562
+ checkLocalVariables: true
563
+ }
564
+ ],
565
+ "react/no-unused-prop-types": "error",
566
+ // Stylistic rules are not supported by @eslint-react. Use dprint or @stylistic instead.
567
+ "@stylistic/jsx-self-closing-comp": "error",
568
+ // <App prop={'Hello'} />没必要,使用<App prop="Hello" />
569
+ "@stylistic/jsx-curly-brace-presence": [
570
+ "error",
571
+ {
572
+ props: "never",
573
+ children: "never",
574
+ propElementValues: "always"
575
+ }
576
+ ],
577
+ "jsx-a11y/click-events-have-key-events": "off",
578
+ "jsx-a11y/no-static-element-interactions": "off",
579
+ "jsx-a11y/alt-text": "off"
580
+ },
581
+ settings: {
582
+ react: {
583
+ version: typeof opts.version === "string" ? opts.version : "detect"
584
+ }
585
+ }
586
+ };
587
+ }
588
+ function reactJsOnly() {
589
+ return {
590
+ name: "agilebot/react-js-only",
591
+ files: JS_GLOBS,
592
+ rules: {
593
+ // The following can be enforced by TypeScript, no need to implement them
594
+ "react/jsx-no-duplicate-props": "error",
595
+ "react/jsx-no-undef": "error",
596
+ "react/jsx-uses-react": "error",
597
+ "react/no-unescaped-entities": "error",
598
+ "react/no-unknown-property": "error",
599
+ "react/react-in-jsx-scope": "error",
600
+ "react/require-render-return": "error"
601
+ }
602
+ };
603
+ }
604
+
605
+ // src/configs/vue.ts
606
+ import pluginVue from "eslint-plugin-vue";
607
+ function vue(opts) {
608
+ return {
609
+ name: "agilebot/vue",
610
+ files: VUE_GLOBS,
611
+ plugins: {
612
+ vue: pluginVue
613
+ },
614
+ rules: {
615
+ ...opts.version === 3 ? pluginVue.configs["vue3-strongly-recommended"].rules : pluginVue.configs["strongly-recommended"].rules
616
+ }
617
+ };
618
+ }
619
+
620
+ // src/configs/jsdoc.ts
621
+ import pluginJsdoc from "eslint-plugin-jsdoc";
622
+ function jsdoc(opt) {
623
+ return {
624
+ name: "agilebot/jsdoc",
625
+ files: DEFAULT_GLOBS,
626
+ plugins: {
627
+ jsdoc: pluginJsdoc
628
+ },
629
+ rules: {
630
+ ...opt.ts ? pluginJsdoc.configs["flat/recommended-typescript-error"].rules : pluginJsdoc.configs["flat/recommended-error"].rules,
631
+ // 禁止有空行
632
+ "jsdoc/no-blank-block-descriptions": "error",
633
+ "jsdoc/no-blank-blocks": "error",
634
+ // 每行注释都有星号
635
+ "jsdoc/require-asterisk-prefix": "error",
636
+ "jsdoc/check-tag-names": [
637
+ "error",
638
+ {
639
+ typed: opt.ts
640
+ }
641
+ ],
642
+ "jsdoc/require-returns": "off",
643
+ // @return注释不是很有必要
644
+ "jsdoc/require-returns-type": "off"
645
+ }
646
+ };
647
+ }
648
+
649
+ // src/configs/lodash.ts
650
+ import pluginLodash from "eslint-plugin-you-dont-need-lodash-underscore";
651
+
652
+ // ../../node_modules/.pnpm/@eslint+compat@1.2.3_eslint@9.15.0_jiti@2.3.3_/node_modules/@eslint/compat/dist/esm/index.js
653
+ var removedMethodNames = /* @__PURE__ */ new Map([
654
+ ["getSource", "getText"],
655
+ ["getSourceLines", "getLines"],
656
+ ["getAllComments", "getAllComments"],
657
+ ["getDeclaredVariables", "getDeclaredVariables"],
658
+ ["getNodeByRangeIndex", "getNodeByRangeIndex"],
659
+ ["getCommentsBefore", "getCommentsBefore"],
660
+ ["getCommentsAfter", "getCommentsAfter"],
661
+ ["getCommentsInside", "getCommentsInside"],
662
+ ["getJSDocComment", "getJSDocComment"],
663
+ ["getFirstToken", "getFirstToken"],
664
+ ["getFirstTokens", "getFirstTokens"],
665
+ ["getLastToken", "getLastToken"],
666
+ ["getLastTokens", "getLastTokens"],
667
+ ["getTokenAfter", "getTokenAfter"],
668
+ ["getTokenBefore", "getTokenBefore"],
669
+ ["getTokenByRangeStart", "getTokenByRangeStart"],
670
+ ["getTokens", "getTokens"],
671
+ ["getTokensAfter", "getTokensAfter"],
672
+ ["getTokensBefore", "getTokensBefore"],
673
+ ["getTokensBetween", "getTokensBetween"]
674
+ ]);
675
+ var fixedUpRuleReplacements = /* @__PURE__ */ new WeakMap();
676
+ var fixedUpRules = /* @__PURE__ */ new WeakSet();
677
+ var fixedUpPluginReplacements = /* @__PURE__ */ new WeakMap();
678
+ var fixedUpPlugins = /* @__PURE__ */ new WeakSet();
679
+ function fixupRule(ruleDefinition) {
680
+ if (fixedUpRuleReplacements.has(ruleDefinition)) {
681
+ return fixedUpRuleReplacements.get(ruleDefinition);
682
+ }
683
+ const isLegacyRule = typeof ruleDefinition === "function";
684
+ if (!isLegacyRule && fixedUpRules.has(ruleDefinition)) {
685
+ return ruleDefinition;
686
+ }
687
+ const originalCreate = isLegacyRule ? ruleDefinition : ruleDefinition.create.bind(ruleDefinition);
688
+ function ruleCreate(context) {
689
+ if ("getScope" in context) {
690
+ return originalCreate(context);
691
+ }
692
+ const sourceCode = context.sourceCode;
693
+ let currentNode = sourceCode.ast;
694
+ const newContext = Object.assign(Object.create(context), {
695
+ parserServices: sourceCode.parserServices,
696
+ /*
697
+ * The following methods rely on the current node in the traversal,
698
+ * so we need to add them manually.
699
+ */
700
+ getScope() {
701
+ return sourceCode.getScope(currentNode);
702
+ },
703
+ getAncestors() {
704
+ return sourceCode.getAncestors(currentNode);
705
+ },
706
+ markVariableAsUsed(variable) {
707
+ sourceCode.markVariableAsUsed(variable, currentNode);
708
+ }
709
+ });
710
+ for (const [
711
+ contextMethodName,
712
+ sourceCodeMethodName
713
+ ] of removedMethodNames) {
714
+ newContext[contextMethodName] = sourceCode[sourceCodeMethodName].bind(sourceCode);
715
+ }
716
+ Object.freeze(newContext);
717
+ const visitor = originalCreate(newContext);
718
+ for (const [methodName, method] of Object.entries(visitor)) {
719
+ if (methodName.startsWith("on")) {
720
+ visitor[methodName] = (...args) => {
721
+ currentNode = args[methodName === "onCodePathSegmentLoop" ? 2 : 1];
722
+ return method.call(visitor, ...args);
723
+ };
724
+ continue;
725
+ }
726
+ visitor[methodName] = (...args) => {
727
+ currentNode = args[0];
728
+ return method.call(visitor, ...args);
729
+ };
730
+ }
731
+ return visitor;
732
+ }
733
+ const newRuleDefinition = {
734
+ ...isLegacyRule ? void 0 : ruleDefinition,
735
+ create: ruleCreate
736
+ };
737
+ const { schema } = ruleDefinition;
738
+ if (schema) {
739
+ if (!newRuleDefinition.meta) {
740
+ newRuleDefinition.meta = { schema };
741
+ } else {
742
+ newRuleDefinition.meta = {
743
+ ...newRuleDefinition.meta,
744
+ // top-level `schema` had precedence over `meta.schema` so it's okay to overwrite `meta.schema` if it exists
745
+ schema
746
+ };
747
+ }
748
+ }
749
+ fixedUpRuleReplacements.set(ruleDefinition, newRuleDefinition);
750
+ fixedUpRules.add(newRuleDefinition);
751
+ return newRuleDefinition;
752
+ }
753
+ function fixupPluginRules(plugin) {
754
+ if (fixedUpPluginReplacements.has(plugin)) {
755
+ return fixedUpPluginReplacements.get(plugin);
756
+ }
757
+ if (fixedUpPlugins.has(plugin) || !plugin.rules) {
758
+ return plugin;
759
+ }
760
+ const newPlugin = {
761
+ ...plugin,
762
+ rules: Object.fromEntries(
763
+ Object.entries(plugin.rules).map(([ruleId, ruleDefinition]) => [
764
+ ruleId,
765
+ fixupRule(ruleDefinition)
766
+ ])
767
+ )
768
+ };
769
+ fixedUpPluginReplacements.set(plugin, newPlugin);
770
+ fixedUpPlugins.add(newPlugin);
771
+ return newPlugin;
772
+ }
773
+
774
+ // src/configs/lodash.ts
775
+ function lodash() {
776
+ return {
777
+ // lodash一些方法可能影响性能,如forEach等,优先使用js的原生方法
778
+ name: "agilebot/lodash",
779
+ files: DEFAULT_GLOBS,
780
+ plugins: {
781
+ "you-dont-need-lodash-underscore": fixupPluginRules(pluginLodash)
782
+ },
783
+ rules: {
784
+ ...pluginLodash.configs["all-warn"].rules,
785
+ "you-dont-need-lodash-underscore/throttle": "off"
786
+ }
787
+ };
788
+ }
789
+
790
+ // src/configs/comments.ts
791
+ import pluginComments from "@eslint-community/eslint-plugin-eslint-comments";
792
+ function comments() {
793
+ return {
794
+ name: "agilebot/comments",
795
+ files: DEFAULT_GLOBS,
796
+ plugins: {
797
+ "@eslint-community/eslint-comments": pluginComments
798
+ },
799
+ rules: {
800
+ // 禁止未使用的eslint-disable注释
801
+ "@eslint-community/eslint-comments/no-unused-disable": "error",
802
+ // 禁止无限制的eslint-disable注释
803
+ "@eslint-community/eslint-comments/no-unlimited-disable": "error",
804
+ // 禁止重复的eslint-disable注释
805
+ "@eslint-community/eslint-comments/no-duplicate-disable": "error",
806
+ // 禁止聚合的eslint-enable注释
807
+ "@eslint-community/eslint-comments/no-aggregating-enable": "error",
808
+ // 须说明原因eslint-disable
809
+ "@eslint-community/eslint-comments/require-description": [
810
+ "error",
811
+ {
812
+ ignore: ["eslint-env", "exported", "global", "globals"]
813
+ }
814
+ ]
815
+ }
816
+ };
817
+ }
818
+
819
+ // src/configs/cspell.ts
820
+ import pluginCSpell from "@cspell/eslint-plugin";
821
+ function cspell(opts) {
822
+ return {
823
+ name: "agilebot/cspell",
824
+ files: DEFAULT_GLOBS,
825
+ plugins: {
826
+ "@cspell": pluginCSpell
827
+ },
828
+ rules: {
829
+ "@cspell/spellchecker": [
830
+ "warn",
831
+ {
832
+ checkComments: false,
833
+ autoFix: false,
834
+ cspell: opts
835
+ }
836
+ ]
837
+ }
838
+ };
839
+ }
840
+
841
+ // src/configs/agilebot.ts
842
+ import pluginAgilebot2 from "@agilebot/eslint-plugin";
843
+ import pluginReactHooks2 from "eslint-plugin-react-hooks";
844
+ function agilebot(opts) {
845
+ return {
846
+ name: "agilebot/agilebot",
847
+ files: DEFAULT_GLOBS,
848
+ plugins: {
849
+ "@agilebot": pluginAgilebot2,
850
+ "react-hooks": pluginReactHooks2
851
+ },
852
+ rules: {
853
+ ...pluginAgilebot2.configs.recommended.rules,
854
+ "react-hooks/exhaustive-deps": "off",
855
+ "@agilebot/react-better-exhaustive-deps": "warn"
856
+ },
857
+ settings: {
858
+ "agilebot/project-root": opts.root,
859
+ "agilebot/monorepo-scope": opts.monorepoScope ? opts.monorepoScope.replace(/\//g, "") : void 0
860
+ }
861
+ };
862
+ }
863
+
864
+ // src/configs/prettier.ts
865
+ import prettierRecommended from "eslint-plugin-prettier/recommended";
866
+ import pluginPrettier from "eslint-plugin-prettier";
867
+ function prettier() {
868
+ return {
869
+ name: "agilebot/prettier",
870
+ files: DEFAULT_GLOBS,
871
+ plugins: {
872
+ prettier: pluginPrettier
873
+ },
874
+ // Do not extends
875
+ // extends: ['plugin:prettier/recommended'],
876
+ rules: {
877
+ ...prettierRecommended.rules,
878
+ curly: "error",
879
+ "arrow-body-style": "off",
880
+ "prettier/prettier": [
881
+ "error",
882
+ {
883
+ endOfLine: "auto"
884
+ }
885
+ ]
886
+ }
887
+ };
888
+ }
889
+
890
+ // src/configs/godaddy.ts
891
+ import configGodaddy from "eslint-config-godaddy";
892
+ import js from "@eslint/js";
893
+ import pluginMocha from "eslint-plugin-mocha";
894
+ function godaddy() {
895
+ return {
896
+ name: "agilebot/godaddy",
897
+ files: DEFAULT_GLOBS,
898
+ languageOptions: {
899
+ parserOptions: {
900
+ ecmaVersion: 2022,
901
+ sourceType: "module"
902
+ }
903
+ },
904
+ plugins: {
905
+ mocha: pluginMocha
906
+ },
907
+ rules: {
908
+ ...js.configs.recommended.rules,
909
+ ...configGodaddy.rules,
910
+ "quote-props": "off",
911
+ "linebreak-style": "off",
912
+ complexity: "off",
913
+ "max-statements": "off",
914
+ "id-length": "off",
915
+ "default-case": "off",
916
+ "valid-jsdoc": "off",
917
+ "generator-star-spacing": "off",
918
+ "max-params": "off",
919
+ "max-depth": "off",
920
+ "max-len": "off",
921
+ indent: "off",
922
+ "no-undefined": "off",
923
+ "no-process-env": "off",
924
+ "no-sync": "off",
925
+ "no-continue": "off",
926
+ "no-case-declarations": "off",
927
+ "callback-return": "off",
928
+ "unicorn/prefer-string-slice": "off",
929
+ "unicorn/prefer-string-replace-all": "off",
930
+ "new-cap": "off"
931
+ }
932
+ };
933
+ }
934
+
935
+ // src/factory/index.ts
936
+ function factory(root, options) {
937
+ assert.ok(root, "root option is required");
938
+ const tsconfigFiles = findTsconfigFiles(root, {
939
+ absolute: true
940
+ });
941
+ const defaultOptions = {
942
+ jsdoc: true,
943
+ prettier: true,
944
+ lodash: true,
945
+ cspell: {},
946
+ import: true,
947
+ importResolver: "typescript"
948
+ };
949
+ options = {
950
+ ...defaultOptions,
951
+ ...options
952
+ };
953
+ if (options?.config) {
954
+ assert.ok(
955
+ Object.keys(options.config).every(
956
+ (key) => key === "rules" || key === "settings"
957
+ ),
958
+ "config option must only contain rules and settings"
959
+ );
960
+ }
961
+ const commonConfigs = [
962
+ unicorn({
963
+ module: options?.module ?? false
964
+ }),
965
+ comments()
966
+ ];
967
+ if (options.import) {
968
+ commonConfigs.push(
969
+ imports({
970
+ packageDir: root,
971
+ devDependencies: options?.devDependencies,
972
+ monorepoScope: options?.monorepoScope,
973
+ coreModules: options?.coreModules,
974
+ resolver: options?.importResolver
975
+ })
976
+ );
977
+ }
978
+ if (options.prettier) {
979
+ commonConfigs.push(prettier());
980
+ }
981
+ const config = [];
982
+ if (options.godaddy) {
983
+ config.push({
984
+ name: "agilebot/parser",
985
+ files: DEFAULT_GLOBS,
986
+ languageOptions: {
987
+ parser: options.godaddy === "typescript" ? parserTs : void 0,
988
+ parserOptions: {
989
+ project: tsconfigFiles.length > 0 ? tsconfigFiles : true
990
+ }
991
+ }
992
+ });
993
+ config.push(env());
994
+ if (options.jsdoc) {
995
+ config.push(
996
+ jsdoc({
997
+ ts: false
998
+ })
999
+ );
1000
+ }
1001
+ config.push(...commonConfigs);
1002
+ config.push(godaddy());
1003
+ if (options.config) {
1004
+ config.push(options.config);
1005
+ }
1006
+ } else {
1007
+ config.push({
1008
+ name: "agilebot/parser",
1009
+ files: DEFAULT_GLOBS,
1010
+ languageOptions: {
1011
+ parser: !options.vue ? parserTs : parserVue,
1012
+ parserOptions: {
1013
+ parser: parserTs,
1014
+ tsconfigRootDir: root,
1015
+ projectService: true,
1016
+ project: tsconfigFiles.length > 0 ? tsconfigFiles : true,
1017
+ ecmaFeatures: {
1018
+ jsx: true
1019
+ },
1020
+ sourceType: options.module ? "module" : void 0,
1021
+ extraFileExtensions: !options?.vue ? void 0 : [".vue"]
1022
+ }
1023
+ }
1024
+ });
1025
+ config.push(env());
1026
+ config.push(standard());
1027
+ config.push(ts());
1028
+ config.push(jsOnly());
1029
+ config.push(dts());
1030
+ config.push(tsOnly());
1031
+ if (options.react) {
1032
+ config.push(react({ version: options.react }));
1033
+ config.push(reactJsOnly());
1034
+ }
1035
+ if (options.vue) {
1036
+ config.push(
1037
+ vue({
1038
+ version: options.vue
1039
+ })
1040
+ );
1041
+ }
1042
+ if (options.lodash) {
1043
+ config.push(lodash());
1044
+ }
1045
+ if (options.cspell) {
1046
+ config.push(cspell(options.cspell));
1047
+ }
1048
+ if (options.jsdoc) {
1049
+ config.push({
1050
+ ...jsdoc({
1051
+ ts: true
1052
+ }),
1053
+ files: TS_GLOBS
1054
+ });
1055
+ config.push({
1056
+ ...jsdoc({
1057
+ ts: false
1058
+ }),
1059
+ files: JS_GLOBS
1060
+ });
1061
+ }
1062
+ config.push(...commonConfigs);
1063
+ config.push(
1064
+ agilebot({
1065
+ root,
1066
+ monorepoScope: options?.monorepoScope
1067
+ })
1068
+ );
1069
+ if (options.config) {
1070
+ config.push(options.config);
1071
+ }
1072
+ }
1073
+ config.push({
1074
+ name: "agilebot/ignores",
1075
+ ignores: [...IGNORE_GLOBS, ...options.ignores ?? []]
1076
+ });
1077
+ const includedPlugins = /* @__PURE__ */ new Set();
1078
+ config.forEach((configItem) => {
1079
+ if (configItem.plugins) {
1080
+ Object.keys(configItem.plugins).forEach((pluginName) => {
1081
+ if (includedPlugins.has(pluginName)) {
1082
+ delete configItem.plugins[pluginName];
1083
+ } else {
1084
+ includedPlugins.add(pluginName);
1085
+ }
1086
+ });
1087
+ }
1088
+ });
1089
+ return config;
1090
+ }
1091
+ export {
1092
+ factory as agilebot
1093
+ };