@dyyz1993/create-agent 2.0.0 → 2.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.
Files changed (165) hide show
  1. package/package.json +1 -1
  2. package/src/commands/create.ts +31 -31
  3. package/src/commands/workspace.ts +112 -105
  4. package/src/lib/copy.ts +24 -1
  5. package/templates/agent/electron/main.js +46 -0
  6. package/templates/agent/electron/preload.js +5 -0
  7. package/templates/agent/electron-builder.json +40 -0
  8. package/templates/agent/eslint.config.mjs +17 -2
  9. package/templates/agent/package.json +69 -3
  10. package/templates/agent/src/__tests__/hybrid-mode.test.ts +126 -0
  11. package/templates/agent/src/__tests__/server-config-security.test.ts +55 -0
  12. package/templates/agent/src/bun/index.ts +96 -41
  13. package/templates/agent/src/bun/three.d.ts +1 -0
  14. package/templates/agent/src/gateway/__tests__/ws-handler-token.test.ts +118 -0
  15. package/templates/agent/src/gateway/http-routes.ts +1 -1
  16. package/templates/agent/src/gateway/ws-handler.ts +84 -56
  17. package/templates/agent/src/mainview/App.tsx +29 -26
  18. package/templates/agent/src/mainview/__tests__/i18n/i18n.test.ts +1 -0
  19. package/templates/agent/src/mainview/__tests__/setup.ts +32 -29
  20. package/templates/agent/src/mainview/__tests__/theme-variables.test.ts +36 -0
  21. package/templates/agent/src/mainview/components/chat/ChatPanel.tsx +88 -88
  22. package/templates/agent/src/mainview/components/common/ErrorBoundary.tsx +1 -58
  23. package/templates/agent/src/mainview/components/common/LanguageSwitcher.tsx +1 -0
  24. package/templates/agent/src/mainview/components/common/ThemeToggle.tsx +1 -0
  25. package/templates/agent/src/mainview/components/feed/FeedPanel.tsx +232 -210
  26. package/templates/agent/src/mainview/components/file-preview/VirtualizedCodeView.tsx +105 -81
  27. package/templates/agent/src/mainview/components/search/SearchPanel.tsx +427 -378
  28. package/templates/agent/src/mainview/components/todo/TodoPanel.tsx +149 -122
  29. package/templates/agent/src/mainview/hooks/use-input-history.ts +70 -61
  30. package/templates/agent/src/mainview/lib/api-client.ts +179 -172
  31. package/templates/agent/src/mainview/main.tsx +4 -10
  32. package/templates/agent/src/mainview/stores/use-feed-store.ts +107 -107
  33. package/templates/agent/src/mainview/utils/drop-handler.ts +114 -115
  34. package/templates/agent/src/server-config.ts +34 -32
  35. package/templates/agent/src/server.ts +42 -54
  36. package/templates/agent/src/shared/handlers/__tests__/chat-concurrency.test.ts +127 -0
  37. package/templates/agent/src/shared/handlers/__tests__/handler-isolation.test.ts +244 -0
  38. package/templates/agent/src/shared/handlers/bash.ts +65 -65
  39. package/templates/agent/src/shared/handlers/chat.ts +189 -155
  40. package/templates/agent/src/shared/handlers/debug.ts +12 -0
  41. package/templates/agent/src/shared/handlers/feed.ts +31 -32
  42. package/templates/agent/src/shared/handlers/git.ts +286 -243
  43. package/templates/agent/src/shared/handlers/index.ts +1 -0
  44. package/templates/agent/src/shared/handlers/rules.ts +31 -31
  45. package/templates/agent/src/shared/handlers/todo.ts +31 -31
  46. package/templates/agent/src/shared/http-routes.ts +250 -0
  47. package/templates/agent/src/shared/lib/__tests__/web-server.test.ts +190 -0
  48. package/templates/agent/src/shared/lib/bash-security.ts +43 -43
  49. package/templates/agent/src/shared/lib/logger.ts +117 -95
  50. package/templates/agent/src/shared/lib/web-server.ts +128 -0
  51. package/templates/agent/src/shared/modules/debug.ts +8 -0
  52. package/templates/agent/src/shared/rpc-schema.ts +16 -3
  53. package/templates/agent/test-upload.txt +0 -0
  54. package/templates/agent/tsconfig.ipc.json +14 -0
  55. package/templates/agent/tsconfig.json +13 -3
  56. package/templates/chat/eslint.config.mjs +15 -2
  57. package/templates/chat/package.json +13 -2
  58. package/templates/chat/src/__tests__/hybrid-mode.test.ts +125 -0
  59. package/templates/chat/src/__tests__/server-config-security.test.ts +55 -0
  60. package/templates/chat/src/__tests__/server-config.test.ts +46 -44
  61. package/templates/chat/src/bun/index.ts +94 -44
  62. package/templates/chat/src/bun/three.d.ts +1 -0
  63. package/templates/chat/src/gateway/http-routes.ts +1 -1
  64. package/templates/chat/src/gateway/ws-handler.ts +84 -56
  65. package/templates/chat/src/mainview/App.tsx +6 -0
  66. package/templates/chat/src/mainview/__tests__/i18n/i18n.test.ts +1 -0
  67. package/templates/chat/src/mainview/__tests__/theme-variables.test.ts +36 -0
  68. package/templates/chat/src/mainview/components/common/LanguageSwitcher.tsx +1 -0
  69. package/templates/chat/src/mainview/components/common/ThemeToggle.tsx +1 -0
  70. package/templates/chat/src/mainview/hooks/use-input-history.ts +70 -61
  71. package/templates/chat/src/mainview/lib/api-client.ts +180 -156
  72. package/templates/chat/src/mainview/lib/rpc-cache.ts +84 -0
  73. package/templates/chat/src/mainview/main.tsx +10 -6
  74. package/templates/chat/src/server-config.ts +33 -31
  75. package/templates/chat/src/server.ts +42 -60
  76. package/templates/chat/src/shared/handlers/chat.ts +196 -162
  77. package/templates/chat/src/shared/handlers/debug.ts +12 -0
  78. package/templates/chat/src/shared/handlers/index.ts +1 -0
  79. package/templates/chat/src/shared/http-routes.ts +250 -0
  80. package/templates/chat/src/shared/lib/__tests__/logger.test.ts +92 -0
  81. package/templates/chat/src/shared/lib/logger.ts +108 -95
  82. package/templates/chat/src/shared/lib/web-server.ts +128 -0
  83. package/templates/chat/src/shared/modules/debug.ts +8 -0
  84. package/templates/chat/src/shared/rpc-schema.ts +3 -2
  85. package/templates/chat/test-upload.txt +0 -0
  86. package/templates/chat/tsconfig.ipc.json +14 -0
  87. package/templates/chat/tsconfig.json +12 -2
  88. package/templates/general/eslint.config.mjs +15 -2
  89. package/templates/general/package.json +13 -2
  90. package/templates/general/src/__tests__/hybrid-mode.test.ts +125 -0
  91. package/templates/general/src/__tests__/server-config-security.test.ts +55 -0
  92. package/templates/general/src/__tests__/server-config.test.ts +46 -44
  93. package/templates/general/src/bun/index.ts +94 -44
  94. package/templates/general/src/bun/three.d.ts +1 -0
  95. package/templates/general/src/gateway/http-routes.ts +1 -1
  96. package/templates/general/src/gateway/ws-handler.ts +84 -56
  97. package/templates/general/src/mainview/__tests__/i18n/i18n.test.ts +1 -0
  98. package/templates/general/src/mainview/__tests__/theme-variables.test.ts +36 -0
  99. package/templates/general/src/mainview/components/common/LanguageSwitcher.tsx +1 -0
  100. package/templates/general/src/mainview/components/common/ThemeToggle.tsx +1 -0
  101. package/templates/general/src/mainview/components/feed/FeedPanel.tsx +241 -219
  102. package/templates/general/src/mainview/components/file-preview/VirtualizedCodeView.tsx +101 -81
  103. package/templates/general/src/mainview/components/layout/AppLayout.tsx +6 -0
  104. package/templates/general/src/mainview/components/search/SearchPanel.tsx +429 -378
  105. package/templates/general/src/mainview/hooks/use-input-history.ts +70 -61
  106. package/templates/general/src/mainview/lib/api-client.ts +180 -156
  107. package/templates/general/src/mainview/lib/rpc-cache.ts +84 -0
  108. package/templates/general/src/mainview/main.tsx +10 -6
  109. package/templates/general/src/mainview/stores/use-feed-store.ts +107 -107
  110. package/templates/general/src/mainview/utils/drop-handler.ts +114 -115
  111. package/templates/general/src/server-config.ts +33 -31
  112. package/templates/general/src/server.ts +42 -60
  113. package/templates/general/src/shared/handlers/__tests__/chat.test.ts +165 -160
  114. package/templates/general/src/shared/handlers/chat.ts +189 -155
  115. package/templates/general/src/shared/handlers/debug.ts +12 -0
  116. package/templates/general/src/shared/handlers/feed.ts +38 -40
  117. package/templates/general/src/shared/handlers/git.ts +286 -243
  118. package/templates/general/src/shared/handlers/index.ts +1 -0
  119. package/templates/general/src/shared/http-routes.ts +250 -0
  120. package/templates/general/src/shared/lib/__tests__/logger.test.ts +92 -0
  121. package/templates/general/src/shared/lib/logger.ts +117 -95
  122. package/templates/general/src/shared/lib/web-server.ts +128 -0
  123. package/templates/general/src/shared/modules/debug.ts +8 -0
  124. package/templates/general/src/shared/rpc-schema.ts +12 -2
  125. package/templates/general/test-upload.txt +0 -0
  126. package/templates/general/tsconfig.ipc.json +14 -0
  127. package/templates/general/tsconfig.json +12 -2
  128. package/templates/shared/__tests__/cors-security.test.ts +165 -0
  129. package/templates/shared/__tests__/file-path-security.test.ts +260 -0
  130. package/templates/shared/__tests__/http-routes.test.ts +174 -0
  131. package/templates/shared/__tests__/logger.test.ts +186 -0
  132. package/templates/shared/components/ErrorBoundary.tsx +59 -0
  133. package/templates/shared/env.d.ts +11 -0
  134. package/templates/shared/http-routes.ts +250 -0
  135. package/templates/shared/logger.ts +129 -0
  136. package/templates/shared/test-upload.txt +0 -0
  137. package/templates/shared/vite-base.config.ts +92 -0
  138. package/templates/shared/vitest-base.config.ts +42 -0
  139. package/templates/agent/eslint-plugin-rpc/index.js +0 -50
  140. package/templates/agent/eslint-plugin-rpc/package.json +0 -6
  141. package/templates/agent/eslint-plugin-rpc/rules/module-file-naming.js +0 -99
  142. package/templates/agent/eslint-plugin-rpc/rules/no-bare-method.js +0 -78
  143. package/templates/agent/eslint-plugin-rpc/rules/no-direct-register.js +0 -65
  144. package/templates/agent/eslint-plugin-rpc/rules/no-hardcoded-strings.js +0 -69
  145. package/templates/agent/eslint-plugin-rpc/rules/require-api-client.js +0 -58
  146. package/templates/agent/eslint-plugin-rpc/rules/require-typed-register.js +0 -78
  147. package/templates/agent/eslint-plugin-rpc/rules/schema-merge-only.js +0 -55
  148. package/templates/chat/eslint-plugin-rpc/index.js +0 -50
  149. package/templates/chat/eslint-plugin-rpc/package.json +0 -6
  150. package/templates/chat/eslint-plugin-rpc/rules/module-file-naming.js +0 -99
  151. package/templates/chat/eslint-plugin-rpc/rules/no-bare-method.js +0 -78
  152. package/templates/chat/eslint-plugin-rpc/rules/no-direct-register.js +0 -65
  153. package/templates/chat/eslint-plugin-rpc/rules/no-hardcoded-strings.js +0 -69
  154. package/templates/chat/eslint-plugin-rpc/rules/require-api-client.js +0 -58
  155. package/templates/chat/eslint-plugin-rpc/rules/require-typed-register.js +0 -78
  156. package/templates/chat/eslint-plugin-rpc/rules/schema-merge-only.js +0 -55
  157. package/templates/general/eslint-plugin-rpc/index.js +0 -50
  158. package/templates/general/eslint-plugin-rpc/package.json +0 -6
  159. package/templates/general/eslint-plugin-rpc/rules/module-file-naming.js +0 -99
  160. package/templates/general/eslint-plugin-rpc/rules/no-bare-method.js +0 -78
  161. package/templates/general/eslint-plugin-rpc/rules/no-direct-register.js +0 -65
  162. package/templates/general/eslint-plugin-rpc/rules/no-hardcoded-strings.js +0 -69
  163. package/templates/general/eslint-plugin-rpc/rules/require-api-client.js +0 -58
  164. package/templates/general/eslint-plugin-rpc/rules/require-typed-register.js +0 -78
  165. package/templates/general/eslint-plugin-rpc/rules/schema-merge-only.js +0 -55
@@ -1,50 +0,0 @@
1
- /**
2
- * eslint-plugin-rpc — RPC 模块化规范 ESLint 插件(单注册架构)
3
- *
4
- * 规则列表:
5
- * - rpc/no-bare-method : 方法名必须使用 module.action 格式
6
- * - rpc/no-direct-register : server.register() 只允许在 handlers/ 目录内使用
7
- * - rpc/schema-merge-only : rpc-schema.ts 禁止直接定义方法
8
- * - rpc/module-file-naming : 模块文件命名、导出、方法前缀强制规范
9
- * - rpc/require-typed-register : 入口文件必须导入 registerAllHandlers
10
- * - rpc/require-api-client : 前端必须通过 apiClient 调用 RPC
11
- */
12
- "use strict";
13
-
14
- const noBareMethod = require("./rules/no-bare-method");
15
- const noDirectRegister = require("./rules/no-direct-register");
16
- const schemaMergeOnly = require("./rules/schema-merge-only");
17
- const moduleFileNaming = require("./rules/module-file-naming");
18
- const requireTypedRegister = require("./rules/require-typed-register");
19
- const requireApiClient = require("./rules/require-api-client");
20
- const noHardcodedStrings = require("./rules/no-hardcoded-strings");
21
-
22
- module.exports = {
23
- meta: {
24
- name: "eslint-plugin-rpc",
25
- version: "1.0.0",
26
- },
27
- rules: {
28
- "no-bare-method": noBareMethod,
29
- "no-direct-register": noDirectRegister,
30
- "schema-merge-only": schemaMergeOnly,
31
- "module-file-naming": moduleFileNaming,
32
- "require-typed-register": requireTypedRegister,
33
- "require-api-client": requireApiClient,
34
- "no-hardcoded-strings": noHardcodedStrings,
35
- },
36
- configs: {
37
- recommended: {
38
- plugins: ["rpc"],
39
- rules: {
40
- "rpc/no-bare-method": "error",
41
- "rpc/no-direct-register": "error",
42
- "rpc/schema-merge-only": "error",
43
- "rpc/module-file-naming": "error",
44
- "rpc/require-typed-register": "error",
45
- "rpc/require-api-client": "error",
46
- "rpc/no-hardcoded-strings": "warn",
47
- },
48
- },
49
- },
50
- };
@@ -1,6 +0,0 @@
1
- {
2
- "name": "@dyyz1993/eslint-plugin-rpc",
3
- "version": "1.0.0",
4
- "private": true,
5
- "main": "index.js"
6
- }
@@ -1,99 +0,0 @@
1
- /**
2
- * @fileoverview 强制 RPC 模块文件的命名和导出规范
3
- */
4
- "use strict";
5
-
6
- function getModuleName(filename) {
7
- const match = filename.match(/\/modules\/([^/]+)\.[jt]sx?$/);
8
- return match ? match[1] : null;
9
- }
10
-
11
- module.exports = {
12
- meta: {
13
- type: "problem",
14
- docs: {
15
- description: "RPC 模块文件必须遵循命名和导出规范",
16
- category: "RPC Conventions",
17
- recommended: "error",
18
- },
19
- messages: {
20
- missingMethodsExport:
21
- '模块文件 "{{file}}" 必须导出 "{{ModuleName}}Methods" 接口。',
22
- methodPrefixMismatch:
23
- '方法 "{{method}}" 的前缀不匹配模块 "{{module}}"。必须以 "{{module}}." 开头。',
24
- eventPrefixMismatch:
25
- '事件 "{{event}}" 的前缀不匹配模块 "{{module}}"。必须以 "{{module}}." 开头。',
26
- },
27
- schema: [],
28
- },
29
-
30
- create(context) {
31
- const filename = context.getFilename();
32
- const moduleName = getModuleName(filename);
33
- if (!moduleName) return {};
34
-
35
- const moduleNamePascal = moduleName
36
- .split(/[-_]/)
37
- .map((s) => s.charAt(0).toUpperCase() + s.slice(1))
38
- .join("");
39
-
40
- let hasMethodsExport = false;
41
-
42
- return {
43
- TSInterfaceDeclaration(node) {
44
- const name = node.id.name;
45
-
46
- if (name === `${moduleNamePascal}Methods`) {
47
- hasMethodsExport = true;
48
-
49
- if (node.body && node.body.body) {
50
- for (const member of node.body.body) {
51
- if (member.type === "TSPropertySignature" && member.key) {
52
- const key =
53
- member.key.type === "Literal" ? String(member.key.value) : null;
54
- if (key && !key.startsWith(`${moduleName}.`)) {
55
- context.report({
56
- node: member,
57
- messageId: "methodPrefixMismatch",
58
- data: { method: key, module: moduleName },
59
- });
60
- }
61
- }
62
- }
63
- }
64
- }
65
-
66
- if (name === `${moduleNamePascal}Events`) {
67
- if (node.body && node.body.body) {
68
- for (const member of node.body.body) {
69
- if (member.type === "TSPropertySignature" && member.key) {
70
- const key =
71
- member.key.type === "Literal" ? String(member.key.value) : null;
72
- if (key && !key.startsWith(`${moduleName}.`)) {
73
- context.report({
74
- node: member,
75
- messageId: "eventPrefixMismatch",
76
- data: { event: key, module: moduleName },
77
- });
78
- }
79
- }
80
- }
81
- }
82
- }
83
- },
84
-
85
- "Program:exit"() {
86
- if (!hasMethodsExport) {
87
- context.report({
88
- loc: { line: 1, column: 0 },
89
- messageId: "missingMethodsExport",
90
- data: {
91
- file: filename.split("/").pop(),
92
- ModuleName: moduleNamePascal,
93
- },
94
- });
95
- }
96
- },
97
- };
98
- },
99
- };
@@ -1,78 +0,0 @@
1
- /**
2
- * @fileoverview 禁止使用裸方法名(无模块前缀)
3
- */
4
- "use strict";
5
-
6
- const METHOD_CALL_PATTERNS = [
7
- { calleePattern: /^register$/, argIndex: 0 },
8
- { calleePattern: /\.call$/, argIndex: 0 },
9
- { calleePattern: /\.subscribe$/, argIndex: 0 },
10
- { calleePattern: /\.emitEvent$/, argIndex: 0 },
11
- ];
12
-
13
- function isModuleMethodName(name) {
14
- const parts = name.split(".");
15
- return parts.length === 2 && parts[0].length > 0 && parts[1].length > 0;
16
- }
17
-
18
- module.exports = {
19
- meta: {
20
- type: "problem",
21
- docs: {
22
- description: "RPC 方法名必须使用 module.action 格式(禁止裸方法名)",
23
- category: "RPC Conventions",
24
- recommended: "error",
25
- },
26
- messages: {
27
- bareMethod:
28
- 'RPC 方法名 "{{name}}" 缺少模块前缀。必须使用 "module.action" 格式,如 "{{suggestion}}"。',
29
- invalidFormat:
30
- 'RPC 方法名 "{{name}}" 格式错误。必须使用 "module.action" 格式(单一 "." 分隔)。',
31
- },
32
- schema: [],
33
- },
34
-
35
- create(context) {
36
- const filename = context.getFilename();
37
-
38
- if (!/\.[jt]sx?$/.test(filename)) return {};
39
-
40
- return {
41
- CallExpression(node) {
42
- const { callee, arguments: args } = node;
43
-
44
- let calleeText = "";
45
- if (callee.type === "Identifier") {
46
- calleeText = callee.name;
47
- } else if (callee.type === "MemberExpression" && callee.property.type === "Identifier") {
48
- calleeText = `.${callee.property.name}`;
49
- }
50
-
51
- for (const pattern of METHOD_CALL_PATTERNS) {
52
- if (!pattern.calleePattern.test(calleeText)) continue;
53
- if (args.length <= pattern.argIndex) continue;
54
-
55
- const arg = args[pattern.argIndex];
56
- if (arg.type !== "Literal" || typeof arg.value !== "string") continue;
57
-
58
- const methodName = arg.value;
59
-
60
- if (!methodName.includes(".")) {
61
- const suggestion = `module.${methodName}`;
62
- context.report({
63
- node: arg,
64
- messageId: "bareMethod",
65
- data: { name: methodName, suggestion },
66
- });
67
- } else if (!isModuleMethodName(methodName)) {
68
- context.report({
69
- node: arg,
70
- messageId: "invalidFormat",
71
- data: { name: methodName },
72
- });
73
- }
74
- }
75
- },
76
- };
77
- },
78
- };
@@ -1,65 +0,0 @@
1
- /**
2
- * @fileoverview server.register() 只允许在 shared/handlers/ 目录内使用
3
- */
4
- "use strict";
5
-
6
- module.exports = {
7
- meta: {
8
- type: "problem",
9
- docs: {
10
- description:
11
- "server.register() 只允许在 shared/handlers/ 目录内使用,入口文件和其他文件禁止直接调用",
12
- category: "RPC Conventions",
13
- recommended: "error",
14
- },
15
- messages: {
16
- noDirectRegisterInEntry:
17
- "入口文件禁止直接调用 server.register()。请导入并使用 registerAllHandlers() 统一注册 handler。",
18
- noDirectRegisterGeneral:
19
- "禁止直接调用 server.register()。Handler 注册只能在 shared/handlers/ 目录内的文件中进行。",
20
- },
21
- schema: [],
22
- },
23
-
24
- create(context) {
25
- const filename = context.getFilename();
26
-
27
- if (!/src\/.*\.[jt]sx?$/.test(filename)) return {};
28
-
29
- if (filename.includes("shared/handlers/")) return {};
30
-
31
- const isEntryPoint =
32
- filename.endsWith("bun/index.ts") || filename.endsWith("server.ts");
33
-
34
- return {
35
- CallExpression(node) {
36
- const { callee } = node;
37
-
38
- if (
39
- callee.type === "MemberExpression" &&
40
- callee.property.type === "Identifier" &&
41
- callee.property.name === "register" &&
42
- callee.object.type === "Identifier"
43
- ) {
44
- const objectName = callee.object.name;
45
-
46
- const serverVarNames = [
47
- "server",
48
- "rpcServer",
49
- "rpc",
50
- "rpc_server",
51
- ];
52
-
53
- if (serverVarNames.includes(objectName)) {
54
- context.report({
55
- node,
56
- messageId: isEntryPoint
57
- ? "noDirectRegisterInEntry"
58
- : "noDirectRegisterGeneral",
59
- });
60
- }
61
- }
62
- },
63
- };
64
- },
65
- };
@@ -1,69 +0,0 @@
1
- "use strict";
2
-
3
- module.exports = {
4
- meta: {
5
- type: "suggestion",
6
- docs: {
7
- description: "disallow hardcoded strings in JSX (use i18n t() instead)",
8
- category: "Best Practices",
9
- recommended: false,
10
- },
11
- fixable: null,
12
- schema: [
13
- {
14
- type: "object",
15
- properties: {
16
- ignoreAttributes: {
17
- type: "array",
18
- items: { type: "string" },
19
- },
20
- ignoreComponents: {
21
- type: "array",
22
- items: { type: "string" },
23
- },
24
- },
25
- additionalProperties: false,
26
- },
27
- ],
28
- messages: {
29
- hardcodedString:
30
- 'Hardcoded string "{{text}}" should use i18n translation (t()).',
31
- },
32
- },
33
-
34
- create(context) {
35
- const options = context.options[0] || {};
36
- const ignoreAttributes = new Set(options.ignoreAttributes || ["className", "style", "id", "key", "ref", "type", "name", "data-testid", "viewBox", "d", "points", "x1", "x2", "y1", "y2", "strokeWidth", "strokeLinecap", "strokeLinejoin", "fill", "stroke", "xmlns"]);
37
- new Set(options.ignoreComponents || []);
38
-
39
- return {
40
- JSXText(node) {
41
- const text = node.value.trim();
42
- if (text.length > 1 && /[a-zA-Z]{2,}/.test(text)) {
43
- context.report({
44
- node,
45
- messageId: "hardcodedString",
46
- data: { text },
47
- });
48
- }
49
- },
50
- JSXAttribute(node) {
51
- if (ignoreAttributes.has(node.name.name)) return;
52
- if (
53
- node.value &&
54
- node.value.type === "Literal" &&
55
- typeof node.value.value === "string"
56
- ) {
57
- const text = node.value.value.trim();
58
- if (text.length > 3 && /[a-zA-Z]{3,}/.test(text) && !text.startsWith("var(") && !text.startsWith("bg-") && !text.startsWith("text-") && !text.startsWith("border-")) {
59
- context.report({
60
- node,
61
- messageId: "hardcodedString",
62
- data: { text },
63
- });
64
- }
65
- }
66
- },
67
- };
68
- },
69
- };
@@ -1,58 +0,0 @@
1
- /**
2
- * @fileoverview 强制前端使用 apiClient 进行 RPC 调用
3
- */
4
- "use strict";
5
-
6
- module.exports = {
7
- meta: {
8
- type: "problem",
9
- docs: {
10
- description: "前端 RPC 调用必须通过 apiClient",
11
- category: "RPC Conventions",
12
- recommended: "error",
13
- },
14
- messages: {
15
- useApiClient:
16
- "前端 RPC 调用必须通过 apiClient.call() / apiClient.subscribe()。禁止直接操作 WebSocket 或其他传输层。",
17
- },
18
- schema: [],
19
- },
20
-
21
- create(context) {
22
- const filename = context.getFilename();
23
-
24
- if (!/mainview\/.*\.[jt]sx?$/.test(filename)) return {};
25
-
26
- return {
27
- NewExpression(node) {
28
- if (
29
- node.callee.type === "Identifier" &&
30
- node.callee.name === "WebSocket"
31
- ) {
32
- context.report({
33
- node,
34
- messageId: "useApiClient",
35
- });
36
- }
37
- },
38
-
39
- CallExpression(node) {
40
- if (
41
- node.callee.type === "MemberExpression" &&
42
- node.callee.property.type === "Identifier" &&
43
- node.callee.property.name === "send"
44
- ) {
45
- if (node.callee.object.type === "Identifier") {
46
- const objName = node.callee.object.name.toLowerCase();
47
- if (objName.includes("websocket") || objName.includes("ws")) {
48
- context.report({
49
- node,
50
- messageId: "useApiClient",
51
- });
52
- }
53
- }
54
- }
55
- },
56
- };
57
- },
58
- };
@@ -1,78 +0,0 @@
1
- /**
2
- * @fileoverview 入口文件必须导入 registerAllHandlers
3
- */
4
- "use strict";
5
-
6
- module.exports = {
7
- meta: {
8
- type: "problem",
9
- docs: {
10
- description: "入口文件必须导入并调用 registerAllHandlers",
11
- category: "RPC Conventions",
12
- recommended: "error",
13
- },
14
- messages: {
15
- missingRegisterAllHandlersImport:
16
- '入口文件必须导入 registerAllHandlers。请添加:import { registerAllHandlers } from "./shared/handlers/register-all-handlers";',
17
- missingRegisterAllHandlersCall:
18
- "已导入 registerAllHandlers 但未调用。请在创建 server 后调用 registerAllHandlers(server)。",
19
- },
20
- schema: [],
21
- },
22
-
23
- create(context) {
24
- const filename = context.getFilename();
25
-
26
- const isEntryPoint =
27
- filename.endsWith("bun/index.ts") || filename.endsWith("gateway/ws-handler.ts");
28
-
29
- if (!isEntryPoint) return {};
30
-
31
- let hasRegisterAllHandlersImport = false;
32
- let hasRegisterAllHandlersCall = false;
33
- let importNode = null;
34
-
35
- return {
36
- ImportDeclaration(node) {
37
- if (
38
- node.source.type === "Literal" &&
39
- typeof node.source.value === "string" &&
40
- node.source.value.includes("register-all-handlers")
41
- ) {
42
- for (const specifier of node.specifiers) {
43
- if (
44
- specifier.type === "ImportSpecifier" &&
45
- specifier.imported.name === "registerAllHandlers"
46
- ) {
47
- hasRegisterAllHandlersImport = true;
48
- importNode = node;
49
- }
50
- }
51
- }
52
- },
53
-
54
- CallExpression(node) {
55
- if (
56
- node.callee.type === "Identifier" &&
57
- node.callee.name === "registerAllHandlers"
58
- ) {
59
- hasRegisterAllHandlersCall = true;
60
- }
61
- },
62
-
63
- "Program:exit"() {
64
- if (!hasRegisterAllHandlersImport) {
65
- context.report({
66
- loc: { line: 1, column: 0 },
67
- messageId: "missingRegisterAllHandlersImport",
68
- });
69
- } else if (!hasRegisterAllHandlersCall) {
70
- context.report({
71
- node: importNode,
72
- messageId: "missingRegisterAllHandlersCall",
73
- });
74
- }
75
- },
76
- };
77
- },
78
- };
@@ -1,55 +0,0 @@
1
- /**
2
- * @fileoverview rpc-schema.ts 只允许合并,禁止直接定义方法
3
- */
4
- "use strict";
5
-
6
- module.exports = {
7
- meta: {
8
- type: "problem",
9
- docs: {
10
- description: "rpc-schema.ts 禁止直接定义方法,只允许 extends 合并",
11
- category: "RPC Conventions",
12
- recommended: "error",
13
- },
14
- messages: {
15
- noDirectDefinition:
16
- 'rpc-schema.ts 中禁止直接定义方法 "{{key}}"。请在 src/shared/modules/ 下对应模块文件中定义,然后在此处 extends 合并。',
17
- },
18
- schema: [],
19
- },
20
-
21
- create(context) {
22
- const filename = context.getFilename();
23
-
24
- if (!filename.endsWith("rpc-schema.ts") && !filename.endsWith("rpc-schema.tsx")) return {};
25
-
26
- const schemaInterfaces = new Set(["RPCMethods", "RPCEvents"]);
27
-
28
- return {
29
- TSInterfaceDeclaration(node) {
30
- if (!schemaInterfaces.has(node.id.name)) return;
31
-
32
- if (node.body && node.body.body) {
33
- for (const member of node.body.body) {
34
- if (member.type === "TSPropertySignature" && member.key) {
35
- const keyName =
36
- member.key.type === "Identifier"
37
- ? member.key.name
38
- : member.key.type === "Literal"
39
- ? String(member.key.value)
40
- : null;
41
-
42
- if (keyName) {
43
- context.report({
44
- node: member,
45
- messageId: "noDirectDefinition",
46
- data: { key: keyName },
47
- });
48
- }
49
- }
50
- }
51
- }
52
- },
53
- };
54
- },
55
- };