@lark-apaas/fullstack-presets 1.1.1 → 1.1.2-alpha.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.
|
@@ -9,8 +9,19 @@ const eslint_server_1 = __importDefault(require("./eslint-server"));
|
|
|
9
9
|
const js_1 = __importDefault(require("@eslint/js"));
|
|
10
10
|
const typescript_eslint_1 = __importDefault(require("typescript-eslint"));
|
|
11
11
|
const eslint_plugin_nestjs_typed_1 = __importDefault(require("@darraghor/eslint-plugin-nestjs-typed"));
|
|
12
|
-
const
|
|
13
|
-
|
|
12
|
+
const testFileIgnorePatterns = [
|
|
13
|
+
'**/__tests__/**',
|
|
14
|
+
'**/*.test.js',
|
|
15
|
+
'**/*.test.jsx',
|
|
16
|
+
'**/*.test.ts',
|
|
17
|
+
'**/*.test.tsx',
|
|
18
|
+
'**/*.spec.js',
|
|
19
|
+
'**/*.spec.jsx',
|
|
20
|
+
'**/*.spec.ts',
|
|
21
|
+
'**/*.spec.tsx',
|
|
22
|
+
];
|
|
23
|
+
const globalIgnoreServerPatterns = ['server/database/.introspect/**', ...testFileIgnorePatterns]; // 全局 eslint server ignore
|
|
24
|
+
const globalIgnoreClientPatterns = ['dist', 'node_modules', 'client/src/api/gen', ...testFileIgnorePatterns]; // 全局 eslint client Ignore
|
|
14
25
|
// 只导出纯净的规则配置,不包含基础配置
|
|
15
26
|
// 用户需要在项目配置中自己添加基础配置(eslintJs, tseslint, nestjs 等)
|
|
16
27
|
exports.eslintPresets = {
|
|
@@ -4,6 +4,88 @@ const globals = require('globals');
|
|
|
4
4
|
const reactHooks = require('eslint-plugin-react-hooks');
|
|
5
5
|
const tseslint = require('typescript-eslint');
|
|
6
6
|
const importPlugin = require('eslint-plugin-import');
|
|
7
|
+
// 检查是否启用宽松 lint 模式
|
|
8
|
+
const isLooseMode = process.env.FORCE_FRAMEWORK_LINT_LOOSE_MODE === 'true';
|
|
9
|
+
// 基础语法规则:所有模式都启用(包括 loose 模式)
|
|
10
|
+
const baseSyntaxRules = [
|
|
11
|
+
// SelectItem组件的value属性值不能为空字符串
|
|
12
|
+
{
|
|
13
|
+
message: 'The `value` attribute of the `SelectItem` component cannot be an empty string.',
|
|
14
|
+
selector: 'JSXOpeningElement[name.name="SelectItem"]:has(JSXAttribute[name.name="value"][value.value=""]), JSXOpeningElement[name.name="SelectItem"]:has(JSXAttribute[name.name="value"][value.expression.value=""])',
|
|
15
|
+
},
|
|
16
|
+
// 禁用`window.location.href`赋值使用,可以读取
|
|
17
|
+
{
|
|
18
|
+
selector: 'AssignmentExpression[left.object.object.name="window"][left.object.property.name="location"][left.property.name="href"]',
|
|
19
|
+
message: "Please don't use `window.location.href` to navigate. Use `useNavigate` hook from 'react-router-dom' instead.",
|
|
20
|
+
},
|
|
21
|
+
// 禁止`location.href`赋值使用,可以读取
|
|
22
|
+
{
|
|
23
|
+
selector: 'AssignmentExpression[left.object.name="location"][left.property.name="href"]',
|
|
24
|
+
message: "Please don't use `location.href` to navigate. Use `useNavigate` hook from 'react-router-dom' instead.",
|
|
25
|
+
},
|
|
26
|
+
// 禁止a标签href使用相对路径
|
|
27
|
+
{
|
|
28
|
+
selector: "JSXOpeningElement[name.name='a']:has(JSXAttribute[name.name='href'][value.value=/^(?!https?:|\\u002F\\u002F|mailto:|tel:|#).+/])",
|
|
29
|
+
message: "Please don't use relative paths in <a> tags. Use NavLink from 'react-router-dom' instead.",
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
// 严格语法规则:仅正常模式启用,loose 模式下不启用
|
|
33
|
+
const strictSyntaxRules = [
|
|
34
|
+
// 限制使用 fetch(推荐使用生成的 API Client)
|
|
35
|
+
{
|
|
36
|
+
message: "Please don't use fetch, use Generated API Client instead",
|
|
37
|
+
selector: "CallExpression[callee.name='fetch'][arguments.0.type='Literal'][arguments.0.value=/^\\u002F/]",
|
|
38
|
+
},
|
|
39
|
+
// 避免使用 console.log,推荐使用 logger 库
|
|
40
|
+
{
|
|
41
|
+
selector: "CallExpression[callee.object.name='console'][callee.property.name=/^(log|warn|info|debug|trace)$/]",
|
|
42
|
+
message: 'Avoid using console.log, console.warn, etc. Use `@lark-apaas/client-toolkit/logger` instead.',
|
|
43
|
+
},
|
|
44
|
+
// 禁用BOM方法alert和confirm,及不推荐使用同名方法
|
|
45
|
+
{
|
|
46
|
+
message: "Please don't use window.alert, use `Dialog` component instead for better user experience and consistency",
|
|
47
|
+
selector: "MemberExpression[object.name='window'][property.name='alert']",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
message: "Please don't use window.confirm, use `Dialog` component instead for better user experience and consistency",
|
|
51
|
+
selector: "MemberExpression[object.name='window'][property.name='confirm']",
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
message: "Please don't use alert. It may conflict with window.alert BOM method, use `Dialog` component instead for better user experience and consistency",
|
|
55
|
+
selector: "CallExpression[callee.name='alert']",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
message: "Please don't use confirm. It may conflict with window.confirm BOM method, use `Dialog` component instead for better user experience and consistency",
|
|
59
|
+
selector: "CallExpression[callee.name='confirm']",
|
|
60
|
+
},
|
|
61
|
+
// 禁止 variant 为 outline|link|ghost 的 Button 使用 text-white
|
|
62
|
+
{
|
|
63
|
+
selector: 'JSXElement[openingElement.name.name="Button"]' +
|
|
64
|
+
':has(JSXAttribute[name.name="variant"][value.value=/^(outline|link|ghost)$/])' +
|
|
65
|
+
':has(JSXAttribute[name.name="className"][value.value=/text-white/])',
|
|
66
|
+
message: 'Button with variant="outline|link|ghost" should not use "text-white" className. This causes visibility issues. Consider using proper semantic color tokens from `client/src/tailwind-theme.css`',
|
|
67
|
+
},
|
|
68
|
+
// 禁止在 Button 上组合 text-primary-foreground 与 bg-background 并用的情况
|
|
69
|
+
{
|
|
70
|
+
selector: 'JSXElement[openingElement.name.name="Button"]' +
|
|
71
|
+
':has(JSXAttribute[name.name="className"][value.value=/text-primary-foreground/])' +
|
|
72
|
+
':has(JSXAttribute[name.name="className"][value.value=/bg-background/])',
|
|
73
|
+
message: 'Button should not use "text-primary-foreground" and "bg-background" className. This causes visibility issues. Consider using proper semantic color tokens from `client/src/tailwind-theme.css`',
|
|
74
|
+
},
|
|
75
|
+
// 禁止使用 text-accent
|
|
76
|
+
{
|
|
77
|
+
selector: 'JSXAttribute[name.name="className"][value.value=/(^|\\s)text-accent(\\s|$)/]',
|
|
78
|
+
message: 'Classname "text-accent" would cause visibility issues. Consider using proper semantic color tokens from `client/src/tailwind-theme.css`',
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
// 宽松模式下覆盖的规则(关闭非关键规则)
|
|
82
|
+
const looseOverrideRules = isLooseMode
|
|
83
|
+
? {
|
|
84
|
+
'@typescript-eslint/no-unsafe-function-type': 'off',
|
|
85
|
+
'@typescript-eslint/no-unused-expressions': 'off',
|
|
86
|
+
'no-useless-escape': 'off', // 允许不必要的转义字符
|
|
87
|
+
}
|
|
88
|
+
: {};
|
|
7
89
|
exports.default = {
|
|
8
90
|
name: 'fullstack-presets/client-recommend',
|
|
9
91
|
languageOptions: {
|
|
@@ -67,74 +149,8 @@ exports.default = {
|
|
|
67
149
|
],
|
|
68
150
|
},
|
|
69
151
|
],
|
|
70
|
-
'no-restricted-syntax': [
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
{
|
|
74
|
-
message: "Please don't use fetch, use Generated API Client instead",
|
|
75
|
-
selector: "CallExpression[callee.name='fetch'][arguments.0.type='Literal'][arguments.0.value=/^\\u002F/]",
|
|
76
|
-
},
|
|
77
|
-
// 避免使用 console.log,推荐使用 logger 库
|
|
78
|
-
{
|
|
79
|
-
selector: "CallExpression[callee.object.name='console'][callee.property.name=/^(log|warn|info|debug|trace)$/]",
|
|
80
|
-
message: 'Avoid using console.log, console.warn, etc. Use `@lark-apaas/client-toolkit/logger` instead.',
|
|
81
|
-
},
|
|
82
|
-
// 禁用BOM方法alert和confirm,及不推荐使用同名方法
|
|
83
|
-
{
|
|
84
|
-
message: "Please don't use window.alert, use `Dialog` component instead for better user experience and consistency",
|
|
85
|
-
selector: "MemberExpression[object.name='window'][property.name='alert']",
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
message: "Please don't use window.confirm, use `Dialog` component instead for better user experience and consistency",
|
|
89
|
-
selector: "MemberExpression[object.name='window'][property.name='confirm']",
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
message: "Please don't use alert. It may conflict with window.alert BOM method, use `Dialog` component instead for better user experience and consistency",
|
|
93
|
-
selector: "CallExpression[callee.name='alert']",
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
message: "Please don't use confirm. It may conflict with window.confirm BOM method, use `Dialog` component instead for better user experience and consistency",
|
|
97
|
-
selector: "CallExpression[callee.name='confirm']",
|
|
98
|
-
},
|
|
99
|
-
// 禁用`window.location.href`赋值使用,可以读取
|
|
100
|
-
{
|
|
101
|
-
selector: 'AssignmentExpression[left.object.object.name="window"][left.object.property.name="location"][left.property.name="href"]',
|
|
102
|
-
message: "Please don't use `window.location.href` to navigate. Use `useNavigate` hook from 'react-router-dom' instead.",
|
|
103
|
-
},
|
|
104
|
-
// 禁止`location.href`赋值使用,可以读取
|
|
105
|
-
{
|
|
106
|
-
selector: 'AssignmentExpression[left.object.name="location"][left.property.name="href"]',
|
|
107
|
-
message: "Please don't use `location.href` to navigate. Use `useNavigate` hook from 'react-router-dom' instead.",
|
|
108
|
-
},
|
|
109
|
-
// SelectItem组件的value属性值不能为空字符串
|
|
110
|
-
{
|
|
111
|
-
message: 'The `value` attribute of the `SelectItem` component cannot be an empty string.',
|
|
112
|
-
selector: 'JSXOpeningElement[name.name="SelectItem"]:has(JSXAttribute[name.name="value"][value.value=""]), JSXOpeningElement[name.name="SelectItem"]:has(JSXAttribute[name.name="value"][value.expression.value=""])',
|
|
113
|
-
},
|
|
114
|
-
// 禁止a标签href使用相对路径
|
|
115
|
-
{
|
|
116
|
-
selector: "JSXOpeningElement[name.name='a']:has(JSXAttribute[name.name='href'][value.value=/^(?!https?:|\\u002F\\u002F|mailto:|tel:|#).+/])",
|
|
117
|
-
message: "Please don't use relative paths in <a> tags. Use NavLink from 'react-router-dom' instead.",
|
|
118
|
-
},
|
|
119
|
-
// 禁止 variant 为 outline|link|ghost 的 Button 使用 text-white
|
|
120
|
-
{
|
|
121
|
-
selector: 'JSXElement[openingElement.name.name="Button"]' +
|
|
122
|
-
':has(JSXAttribute[name.name="variant"][value.value=/^(outline|link|ghost)$/])' +
|
|
123
|
-
':has(JSXAttribute[name.name="className"][value.value=/text-white/])',
|
|
124
|
-
message: 'Button with variant="outline|link|ghost" should not use "text-white" className. This causes visibility issues. Consider using proper semantic color tokens from `client/src/tailwind-theme.css`',
|
|
125
|
-
},
|
|
126
|
-
// 禁止在 Button 上组合 text-primary-foreground 与 bg-background 并用的情况
|
|
127
|
-
{
|
|
128
|
-
selector: 'JSXElement[openingElement.name.name="Button"]' +
|
|
129
|
-
':has(JSXAttribute[name.name="className"][value.value=/text-primary-foreground/])' +
|
|
130
|
-
':has(JSXAttribute[name.name="className"][value.value=/bg-background/])',
|
|
131
|
-
message: 'Button should not use "text-primary-foreground" and "bg-background" className. This causes visibility issues. Consider using proper semantic color tokens from `client/src/tailwind-theme.css`',
|
|
132
|
-
},
|
|
133
|
-
// 禁止使用 text-accent
|
|
134
|
-
{
|
|
135
|
-
selector: 'JSXAttribute[name.name="className"][value.value=/(^|\\s)text-accent(\\s|$)/]',
|
|
136
|
-
message: 'Classname "text-accent" would cause visibility issues. Consider using proper semantic color tokens from `client/src/tailwind-theme.css`',
|
|
137
|
-
},
|
|
138
|
-
],
|
|
152
|
+
'no-restricted-syntax': ['error', ...baseSyntaxRules, ...(isLooseMode ? [] : strictSyntaxRules)],
|
|
153
|
+
// 宽松模式下覆盖上述规则
|
|
154
|
+
...looseOverrideRules,
|
|
139
155
|
},
|
|
140
156
|
};
|
|
@@ -9,8 +9,19 @@ const eslint_server_1 = __importDefault(require("./eslint-server"));
|
|
|
9
9
|
const js_1 = __importDefault(require("@eslint/js"));
|
|
10
10
|
const typescript_eslint_1 = __importDefault(require("typescript-eslint"));
|
|
11
11
|
const eslint_plugin_nestjs_typed_1 = __importDefault(require("@darraghor/eslint-plugin-nestjs-typed"));
|
|
12
|
-
const
|
|
13
|
-
|
|
12
|
+
const testFileIgnorePatterns = [
|
|
13
|
+
'**/__tests__/**',
|
|
14
|
+
'**/*.test.js',
|
|
15
|
+
'**/*.test.jsx',
|
|
16
|
+
'**/*.test.ts',
|
|
17
|
+
'**/*.test.tsx',
|
|
18
|
+
'**/*.spec.js',
|
|
19
|
+
'**/*.spec.jsx',
|
|
20
|
+
'**/*.spec.ts',
|
|
21
|
+
'**/*.spec.tsx',
|
|
22
|
+
];
|
|
23
|
+
const globalIgnoreServerPatterns = ['server/database/.introspect/**', ...testFileIgnorePatterns]; // 全局 eslint server ignore
|
|
24
|
+
const globalIgnoreClientPatterns = ['dist', 'node_modules', 'client/src/api/gen', ...testFileIgnorePatterns]; // 全局 eslint client Ignore
|
|
14
25
|
// 只导出纯净的规则配置,不包含基础配置
|
|
15
26
|
// 用户需要在项目配置中自己添加基础配置(eslintJs, tseslint, nestjs 等)
|
|
16
27
|
exports.eslintPresets = {
|