cmp-standards 2.0.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 (238) hide show
  1. package/README.md +541 -0
  2. package/dist/analytics/index.d.ts +5 -0
  3. package/dist/analytics/index.d.ts.map +1 -0
  4. package/dist/analytics/index.js +5 -0
  5. package/dist/analytics/index.js.map +1 -0
  6. package/dist/analytics/tracker.d.ts +107 -0
  7. package/dist/analytics/tracker.d.ts.map +1 -0
  8. package/dist/analytics/tracker.js +333 -0
  9. package/dist/analytics/tracker.js.map +1 -0
  10. package/dist/auto-improve/eslint-generator.d.ts +36 -0
  11. package/dist/auto-improve/eslint-generator.d.ts.map +1 -0
  12. package/dist/auto-improve/eslint-generator.js +280 -0
  13. package/dist/auto-improve/eslint-generator.js.map +1 -0
  14. package/dist/auto-improve/index.d.ts +6 -0
  15. package/dist/auto-improve/index.d.ts.map +1 -0
  16. package/dist/auto-improve/index.js +6 -0
  17. package/dist/auto-improve/index.js.map +1 -0
  18. package/dist/auto-improve/pattern-detector.d.ts +92 -0
  19. package/dist/auto-improve/pattern-detector.d.ts.map +1 -0
  20. package/dist/auto-improve/pattern-detector.js +231 -0
  21. package/dist/auto-improve/pattern-detector.js.map +1 -0
  22. package/dist/cli/index.d.ts +18 -0
  23. package/dist/cli/index.d.ts.map +1 -0
  24. package/dist/cli/index.js +769 -0
  25. package/dist/cli/index.js.map +1 -0
  26. package/dist/dashboard/index.d.ts +6 -0
  27. package/dist/dashboard/index.d.ts.map +1 -0
  28. package/dist/dashboard/index.js +6 -0
  29. package/dist/dashboard/index.js.map +1 -0
  30. package/dist/dashboard/server.d.ts +15 -0
  31. package/dist/dashboard/server.d.ts.map +1 -0
  32. package/dist/dashboard/server.js +373 -0
  33. package/dist/dashboard/server.js.map +1 -0
  34. package/dist/dashboard/ui.d.ts +9 -0
  35. package/dist/dashboard/ui.d.ts.map +1 -0
  36. package/dist/dashboard/ui.js +530 -0
  37. package/dist/dashboard/ui.js.map +1 -0
  38. package/dist/db/client.d.ts +66 -0
  39. package/dist/db/client.d.ts.map +1 -0
  40. package/dist/db/client.js +159 -0
  41. package/dist/db/client.js.map +1 -0
  42. package/dist/db/drizzle-client.d.ts +302 -0
  43. package/dist/db/drizzle-client.d.ts.map +1 -0
  44. package/dist/db/drizzle-client.js +404 -0
  45. package/dist/db/drizzle-client.js.map +1 -0
  46. package/dist/db/index.d.ts +5 -0
  47. package/dist/db/index.d.ts.map +1 -0
  48. package/dist/db/index.js +5 -0
  49. package/dist/db/index.js.map +1 -0
  50. package/dist/eslint/config-builder.d.ts +45 -0
  51. package/dist/eslint/config-builder.d.ts.map +1 -0
  52. package/dist/eslint/config-builder.js +128 -0
  53. package/dist/eslint/config-builder.js.map +1 -0
  54. package/dist/eslint/index.d.ts +161 -0
  55. package/dist/eslint/index.d.ts.map +1 -0
  56. package/dist/eslint/index.js +106 -0
  57. package/dist/eslint/index.js.map +1 -0
  58. package/dist/eslint/rules/consistent-error-handling.d.ts +9 -0
  59. package/dist/eslint/rules/consistent-error-handling.d.ts.map +1 -0
  60. package/dist/eslint/rules/consistent-error-handling.js +52 -0
  61. package/dist/eslint/rules/consistent-error-handling.js.map +1 -0
  62. package/dist/eslint/rules/finance-ledger-sync.d.ts +12 -0
  63. package/dist/eslint/rules/finance-ledger-sync.d.ts.map +1 -0
  64. package/dist/eslint/rules/finance-ledger-sync.js +72 -0
  65. package/dist/eslint/rules/finance-ledger-sync.js.map +1 -0
  66. package/dist/eslint/rules/no-async-useeffect.d.ts +10 -0
  67. package/dist/eslint/rules/no-async-useeffect.d.ts.map +1 -0
  68. package/dist/eslint/rules/no-async-useeffect.js +49 -0
  69. package/dist/eslint/rules/no-async-useeffect.js.map +1 -0
  70. package/dist/eslint/rules/no-await-in-loop.d.ts +10 -0
  71. package/dist/eslint/rules/no-await-in-loop.d.ts.map +1 -0
  72. package/dist/eslint/rules/no-await-in-loop.js +51 -0
  73. package/dist/eslint/rules/no-await-in-loop.js.map +1 -0
  74. package/dist/eslint/rules/no-inline-functions-in-jsx.d.ts +10 -0
  75. package/dist/eslint/rules/no-inline-functions-in-jsx.d.ts.map +1 -0
  76. package/dist/eslint/rules/no-inline-functions-in-jsx.js +45 -0
  77. package/dist/eslint/rules/no-inline-functions-in-jsx.js.map +1 -0
  78. package/dist/eslint/rules/no-raw-sql.d.ts +19 -0
  79. package/dist/eslint/rules/no-raw-sql.d.ts.map +1 -0
  80. package/dist/eslint/rules/no-raw-sql.js +136 -0
  81. package/dist/eslint/rules/no-raw-sql.js.map +1 -0
  82. package/dist/eslint/rules/no-sequential-api-calls.d.ts +10 -0
  83. package/dist/eslint/rules/no-sequential-api-calls.d.ts.map +1 -0
  84. package/dist/eslint/rules/no-sequential-api-calls.js +72 -0
  85. package/dist/eslint/rules/no-sequential-api-calls.js.map +1 -0
  86. package/dist/eslint/rules/prefer-server-components.d.ts +10 -0
  87. package/dist/eslint/rules/prefer-server-components.d.ts.map +1 -0
  88. package/dist/eslint/rules/prefer-server-components.js +76 -0
  89. package/dist/eslint/rules/prefer-server-components.js.map +1 -0
  90. package/dist/eslint/rules/require-loading-states.d.ts +9 -0
  91. package/dist/eslint/rules/require-loading-states.d.ts.map +1 -0
  92. package/dist/eslint/rules/require-loading-states.js +85 -0
  93. package/dist/eslint/rules/require-loading-states.js.map +1 -0
  94. package/dist/eslint/rules/require-zod-validation.d.ts +10 -0
  95. package/dist/eslint/rules/require-zod-validation.d.ts.map +1 -0
  96. package/dist/eslint/rules/require-zod-validation.js +70 -0
  97. package/dist/eslint/rules/require-zod-validation.js.map +1 -0
  98. package/dist/eslint/rules/semantic-tokens-only.d.ts +10 -0
  99. package/dist/eslint/rules/semantic-tokens-only.d.ts.map +1 -0
  100. package/dist/eslint/rules/semantic-tokens-only.js +62 -0
  101. package/dist/eslint/rules/semantic-tokens-only.js.map +1 -0
  102. package/dist/feedback/collector.d.ts +74 -0
  103. package/dist/feedback/collector.d.ts.map +1 -0
  104. package/dist/feedback/collector.js +231 -0
  105. package/dist/feedback/collector.js.map +1 -0
  106. package/dist/feedback/index.d.ts +5 -0
  107. package/dist/feedback/index.d.ts.map +1 -0
  108. package/dist/feedback/index.js +5 -0
  109. package/dist/feedback/index.js.map +1 -0
  110. package/dist/hooks/index.d.ts +8 -0
  111. package/dist/hooks/index.d.ts.map +1 -0
  112. package/dist/hooks/index.js +8 -0
  113. package/dist/hooks/index.js.map +1 -0
  114. package/dist/hooks/memory-checkpoint.d.ts +43 -0
  115. package/dist/hooks/memory-checkpoint.d.ts.map +1 -0
  116. package/dist/hooks/memory-checkpoint.js +257 -0
  117. package/dist/hooks/memory-checkpoint.js.map +1 -0
  118. package/dist/hooks/post-tool-use.d.ts +61 -0
  119. package/dist/hooks/post-tool-use.d.ts.map +1 -0
  120. package/dist/hooks/post-tool-use.js +262 -0
  121. package/dist/hooks/post-tool-use.js.map +1 -0
  122. package/dist/hooks/pre-tool-use.d.ts +34 -0
  123. package/dist/hooks/pre-tool-use.d.ts.map +1 -0
  124. package/dist/hooks/pre-tool-use.js +358 -0
  125. package/dist/hooks/pre-tool-use.js.map +1 -0
  126. package/dist/hooks/session-start.d.ts +38 -0
  127. package/dist/hooks/session-start.d.ts.map +1 -0
  128. package/dist/hooks/session-start.js +274 -0
  129. package/dist/hooks/session-start.js.map +1 -0
  130. package/dist/index.d.ts +29 -0
  131. package/dist/index.d.ts.map +1 -0
  132. package/dist/index.js +39 -0
  133. package/dist/index.js.map +1 -0
  134. package/dist/mcp/index.d.ts +5 -0
  135. package/dist/mcp/index.d.ts.map +1 -0
  136. package/dist/mcp/index.js +5 -0
  137. package/dist/mcp/index.js.map +1 -0
  138. package/dist/mcp/server.d.ts +42 -0
  139. package/dist/mcp/server.d.ts.map +1 -0
  140. package/dist/mcp/server.js +599 -0
  141. package/dist/mcp/server.js.map +1 -0
  142. package/dist/registry/embeddings.d.ts +38 -0
  143. package/dist/registry/embeddings.d.ts.map +1 -0
  144. package/dist/registry/embeddings.js +110 -0
  145. package/dist/registry/embeddings.js.map +1 -0
  146. package/dist/registry/generator.d.ts +41 -0
  147. package/dist/registry/generator.d.ts.map +1 -0
  148. package/dist/registry/generator.js +323 -0
  149. package/dist/registry/generator.js.map +1 -0
  150. package/dist/registry/index.d.ts +6 -0
  151. package/dist/registry/index.d.ts.map +1 -0
  152. package/dist/registry/index.js +6 -0
  153. package/dist/registry/index.js.map +1 -0
  154. package/dist/services/IdeaCollector.d.ts +103 -0
  155. package/dist/services/IdeaCollector.d.ts.map +1 -0
  156. package/dist/services/IdeaCollector.js +371 -0
  157. package/dist/services/IdeaCollector.js.map +1 -0
  158. package/dist/services/ProjectScaffold.d.ts +76 -0
  159. package/dist/services/ProjectScaffold.d.ts.map +1 -0
  160. package/dist/services/ProjectScaffold.js +479 -0
  161. package/dist/services/ProjectScaffold.js.map +1 -0
  162. package/dist/services/ProjectScanner.d.ts +81 -0
  163. package/dist/services/ProjectScanner.d.ts.map +1 -0
  164. package/dist/services/ProjectScanner.js +349 -0
  165. package/dist/services/ProjectScanner.js.map +1 -0
  166. package/dist/services/TaskTracker.d.ts +89 -0
  167. package/dist/services/TaskTracker.d.ts.map +1 -0
  168. package/dist/services/TaskTracker.js +324 -0
  169. package/dist/services/TaskTracker.js.map +1 -0
  170. package/dist/services/WorkPlanManager.d.ts +107 -0
  171. package/dist/services/WorkPlanManager.d.ts.map +1 -0
  172. package/dist/services/WorkPlanManager.js +440 -0
  173. package/dist/services/WorkPlanManager.js.map +1 -0
  174. package/dist/services/auto-inject.d.ts +77 -0
  175. package/dist/services/auto-inject.d.ts.map +1 -0
  176. package/dist/services/auto-inject.js +289 -0
  177. package/dist/services/auto-inject.js.map +1 -0
  178. package/dist/services/auto-tag.d.ts +61 -0
  179. package/dist/services/auto-tag.d.ts.map +1 -0
  180. package/dist/services/auto-tag.js +203 -0
  181. package/dist/services/auto-tag.js.map +1 -0
  182. package/dist/services/cross-project-sync.d.ts +76 -0
  183. package/dist/services/cross-project-sync.d.ts.map +1 -0
  184. package/dist/services/cross-project-sync.js +235 -0
  185. package/dist/services/cross-project-sync.js.map +1 -0
  186. package/dist/services/index.d.ts +17 -0
  187. package/dist/services/index.d.ts.map +1 -0
  188. package/dist/services/index.js +23 -0
  189. package/dist/services/index.js.map +1 -0
  190. package/dist/services/memory-consolidation.d.ts +77 -0
  191. package/dist/services/memory-consolidation.d.ts.map +1 -0
  192. package/dist/services/memory-consolidation.js +298 -0
  193. package/dist/services/memory-consolidation.js.map +1 -0
  194. package/dist/services/semantic-search.d.ts +93 -0
  195. package/dist/services/semantic-search.d.ts.map +1 -0
  196. package/dist/services/semantic-search.js +278 -0
  197. package/dist/services/semantic-search.js.map +1 -0
  198. package/dist/services/weekly-digest.d.ts +105 -0
  199. package/dist/services/weekly-digest.d.ts.map +1 -0
  200. package/dist/services/weekly-digest.js +292 -0
  201. package/dist/services/weekly-digest.js.map +1 -0
  202. package/dist/types/index.d.ts +274 -0
  203. package/dist/types/index.d.ts.map +1 -0
  204. package/dist/types/index.js +84 -0
  205. package/dist/types/index.js.map +1 -0
  206. package/dist/utils/config.d.ts +21 -0
  207. package/dist/utils/config.d.ts.map +1 -0
  208. package/dist/utils/config.js +89 -0
  209. package/dist/utils/config.js.map +1 -0
  210. package/dist/utils/index.d.ts +6 -0
  211. package/dist/utils/index.d.ts.map +1 -0
  212. package/dist/utils/index.js +6 -0
  213. package/dist/utils/index.js.map +1 -0
  214. package/dist/utils/paths.d.ts +28 -0
  215. package/dist/utils/paths.d.ts.map +1 -0
  216. package/dist/utils/paths.js +80 -0
  217. package/dist/utils/paths.js.map +1 -0
  218. package/package.json +95 -0
  219. package/templates/agents/architecture-expert.md +61 -0
  220. package/templates/agents/database-expert.md +62 -0
  221. package/templates/agents/documentation-expert.md +57 -0
  222. package/templates/agents/memory-expert.md +88 -0
  223. package/templates/agents/performance-expert.md +61 -0
  224. package/templates/agents/security-expert.md +59 -0
  225. package/templates/agents/ux-expert.md +63 -0
  226. package/templates/agents/worker.md +75 -0
  227. package/templates/ai-skills/SKILL_TEMPLATE.md +55 -0
  228. package/templates/commands/experts.md +138 -0
  229. package/templates/hooks/README.md +158 -0
  230. package/templates/hooks/project.config.json.template +77 -0
  231. package/templates/hooks/settings.local.json.template +57 -0
  232. package/templates/memory-config.json +82 -0
  233. package/templates/memory-config.schema.json +212 -0
  234. package/templates/settings.json +58 -0
  235. package/templates/workflows/business-improvement.md +264 -0
  236. package/templates/workflows/expert-review.md +153 -0
  237. package/templates/workflows/internal-app.md +245 -0
  238. package/templates/workflows/sync-docs.md +187 -0
@@ -0,0 +1,19 @@
1
+ /**
2
+ * ESLint Rule: cmp/no-raw-sql
3
+ *
4
+ * Prevents raw SQL execution that could lead to SQL injection.
5
+ *
6
+ * DANGEROUS:
7
+ * - db.execute() with template strings
8
+ * - String concatenation in SQL queries
9
+ * - mysql.query() with unparameterized strings
10
+ *
11
+ * SAFE:
12
+ * - Drizzle query builder (always safe)
13
+ * - db.execute() with proper parameter placeholders
14
+ * - Drizzle sql`...` tagged template literals
15
+ */
16
+ import type { Rule } from 'eslint';
17
+ declare const rule: Rule.RuleModule;
18
+ export default rule;
19
+ //# sourceMappingURL=no-raw-sql.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-raw-sql.d.ts","sourceRoot":"","sources":["../../../src/eslint/rules/no-raw-sql.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAElC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA2IhB,CAAA;AAED,eAAe,IAAI,CAAA"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * ESLint Rule: cmp/no-raw-sql
3
+ *
4
+ * Prevents raw SQL execution that could lead to SQL injection.
5
+ *
6
+ * DANGEROUS:
7
+ * - db.execute() with template strings
8
+ * - String concatenation in SQL queries
9
+ * - mysql.query() with unparameterized strings
10
+ *
11
+ * SAFE:
12
+ * - Drizzle query builder (always safe)
13
+ * - db.execute() with proper parameter placeholders
14
+ * - Drizzle sql`...` tagged template literals
15
+ */
16
+ const rule = {
17
+ meta: {
18
+ type: 'problem',
19
+ docs: {
20
+ description: 'Prevent raw SQL execution (SQL injection)',
21
+ category: 'Security',
22
+ recommended: true,
23
+ },
24
+ messages: {
25
+ rawSqlTemplateLiteral: 'Raw SQL with template literals is dangerous. Use Drizzle query builder or parameterized queries.',
26
+ rawSqlConcatenation: 'SQL string concatenation detected. Use Drizzle query builder or parameterized queries.',
27
+ useQueryBuilder: 'Use Drizzle query builder instead: db.select().from(table).where(eq(field, value))',
28
+ },
29
+ schema: [],
30
+ },
31
+ create(context) {
32
+ function isSqlExecution(node) {
33
+ if (node.type !== 'CallExpression')
34
+ return false;
35
+ const callee = node.callee;
36
+ if (callee.type === 'MemberExpression' &&
37
+ callee.property.type === 'Identifier' &&
38
+ ['execute', 'query', 'run'].includes(callee.property.name)) {
39
+ return true;
40
+ }
41
+ return false;
42
+ }
43
+ function usesTemplateLiteral(node) {
44
+ const firstArg = node.arguments[0];
45
+ return firstArg && firstArg.type === 'TemplateLiteral';
46
+ }
47
+ function usesStringConcatenation(node) {
48
+ const firstArg = node.arguments[0];
49
+ if (!firstArg)
50
+ return false;
51
+ if (firstArg.type === 'BinaryExpression' && firstArg.operator === '+') {
52
+ return true;
53
+ }
54
+ return false;
55
+ }
56
+ function isParameterized(node) {
57
+ const secondArg = node.arguments[1];
58
+ return secondArg && secondArg.type === 'ArrayExpression';
59
+ }
60
+ function isDrizzleSqlTemplate(node) {
61
+ if (node.type === 'TaggedTemplateExpression') {
62
+ const tag = node.tag;
63
+ if (tag.type === 'Identifier' && tag.name === 'sql') {
64
+ return true;
65
+ }
66
+ if (tag.type === 'MemberExpression' &&
67
+ tag.property.type === 'Identifier' &&
68
+ tag.property.name === 'sql') {
69
+ return true;
70
+ }
71
+ }
72
+ return false;
73
+ }
74
+ function isSqlTemplateLiteral(node) {
75
+ if (node.type !== 'TemplateLiteral')
76
+ return false;
77
+ const sqlText = node.quasis.map((q) => q.value.raw).join(' ').toUpperCase();
78
+ const sqlKeywords = ['SELECT', 'UPDATE', 'DELETE', 'INSERT', 'FROM', 'WHERE', 'SET', 'JOIN'];
79
+ return sqlKeywords.some(keyword => sqlText.includes(keyword));
80
+ }
81
+ return {
82
+ TaggedTemplateExpression(node) {
83
+ if (isDrizzleSqlTemplate(node)) {
84
+ return;
85
+ }
86
+ },
87
+ VariableDeclarator(node) {
88
+ if (node.init && isDrizzleSqlTemplate(node.init)) {
89
+ return;
90
+ }
91
+ if (node.init && isSqlTemplateLiteral(node.init)) {
92
+ context.report({
93
+ node: node.init,
94
+ messageId: 'rawSqlTemplateLiteral',
95
+ });
96
+ }
97
+ },
98
+ CallExpression(node) {
99
+ if (!isSqlExecution(node)) {
100
+ return;
101
+ }
102
+ if (usesTemplateLiteral(node)) {
103
+ context.report({
104
+ node,
105
+ messageId: 'rawSqlTemplateLiteral',
106
+ });
107
+ return;
108
+ }
109
+ if (usesStringConcatenation(node)) {
110
+ context.report({
111
+ node,
112
+ messageId: 'rawSqlConcatenation',
113
+ });
114
+ return;
115
+ }
116
+ const firstArg = node.arguments[0];
117
+ if (firstArg &&
118
+ firstArg.type === 'Literal' &&
119
+ typeof firstArg.value === 'string' &&
120
+ !isParameterized(node)) {
121
+ const sql = firstArg.value.toUpperCase();
122
+ if (sql.includes('WHERE') ||
123
+ sql.includes('SET') ||
124
+ sql.includes('VALUES')) {
125
+ context.report({
126
+ node,
127
+ messageId: 'useQueryBuilder',
128
+ });
129
+ }
130
+ }
131
+ },
132
+ };
133
+ },
134
+ };
135
+ export default rule;
136
+ //# sourceMappingURL=no-raw-sql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-raw-sql.js","sourceRoot":"","sources":["../../../src/eslint/rules/no-raw-sql.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * ESLint Rule: cmp/no-sequential-api-calls
3
+ *
4
+ * Detects sequential API calls that could be parallelized.
5
+ * Use Promise.all() for independent requests.
6
+ */
7
+ import type { Rule } from 'eslint';
8
+ declare const rule: Rule.RuleModule;
9
+ export default rule;
10
+ //# sourceMappingURL=no-sequential-api-calls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-sequential-api-calls.d.ts","sourceRoot":"","sources":["../../../src/eslint/rules/no-sequential-api-calls.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAElC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAiEhB,CAAA;AAED,eAAe,IAAI,CAAA"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * ESLint Rule: cmp/no-sequential-api-calls
3
+ *
4
+ * Detects sequential API calls that could be parallelized.
5
+ * Use Promise.all() for independent requests.
6
+ */
7
+ const rule = {
8
+ meta: {
9
+ type: 'suggestion',
10
+ docs: {
11
+ description: 'Detect sequential API calls that could be parallelized',
12
+ category: 'Performance',
13
+ recommended: true,
14
+ },
15
+ messages: {
16
+ sequentialCalls: 'Multiple sequential await calls detected. Consider using Promise.all() for parallel execution.',
17
+ },
18
+ schema: [],
19
+ },
20
+ create(context) {
21
+ return {
22
+ BlockStatement(node) {
23
+ let consecutiveAwaits = 0;
24
+ let lastAwaitLine = -1;
25
+ for (const statement of node.body) {
26
+ if (statement.type === 'VariableDeclaration' ||
27
+ statement.type === 'ExpressionStatement') {
28
+ const hasAwait = containsAwait(statement);
29
+ if (hasAwait) {
30
+ const currentLine = statement.loc?.start.line || 0;
31
+ if (lastAwaitLine >= 0 && currentLine - lastAwaitLine <= 2) {
32
+ consecutiveAwaits++;
33
+ }
34
+ else {
35
+ consecutiveAwaits = 1;
36
+ }
37
+ lastAwaitLine = currentLine;
38
+ }
39
+ }
40
+ if (consecutiveAwaits >= 3) {
41
+ context.report({
42
+ node: statement,
43
+ messageId: 'sequentialCalls',
44
+ });
45
+ consecutiveAwaits = 0;
46
+ }
47
+ }
48
+ },
49
+ };
50
+ function containsAwait(node) {
51
+ if (!node)
52
+ return false;
53
+ if (node.type === 'AwaitExpression')
54
+ return true;
55
+ for (const key of Object.keys(node)) {
56
+ const child = node[key];
57
+ if (child && typeof child === 'object') {
58
+ if (Array.isArray(child)) {
59
+ if (child.some(c => containsAwait(c)))
60
+ return true;
61
+ }
62
+ else if (containsAwait(child)) {
63
+ return true;
64
+ }
65
+ }
66
+ }
67
+ return false;
68
+ }
69
+ },
70
+ };
71
+ export default rule;
72
+ //# sourceMappingURL=no-sequential-api-calls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-sequential-api-calls.js","sourceRoot":"","sources":["../../../src/eslint/rules/no-sequential-api-calls.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,IAAI,GAAoB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EAAE,wDAAwD;YACrE,QAAQ,EAAE,aAAa;YACvB,WAAW,EAAE,IAAI;SAClB;QACD,QAAQ,EAAE;YACR,eAAe,EAAE,gGAAgG;SAClH;QACD,MAAM,EAAE,EAAE;KACX;IAED,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,cAAc,CAAC,IAAS;gBACtB,IAAI,iBAAiB,GAAG,CAAC,CAAA;gBACzB,IAAI,aAAa,GAAG,CAAC,CAAC,CAAA;gBAEtB,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;oBAClC,IACE,SAAS,CAAC,IAAI,KAAK,qBAAqB;wBACxC,SAAS,CAAC,IAAI,KAAK,qBAAqB,EACxC,CAAC;wBACD,MAAM,QAAQ,GAAG,aAAa,CAAC,SAAS,CAAC,CAAA;wBACzC,IAAI,QAAQ,EAAE,CAAC;4BACb,MAAM,WAAW,GAAG,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,CAAA;4BAClD,IAAI,aAAa,IAAI,CAAC,IAAI,WAAW,GAAG,aAAa,IAAI,CAAC,EAAE,CAAC;gCAC3D,iBAAiB,EAAE,CAAA;4BACrB,CAAC;iCAAM,CAAC;gCACN,iBAAiB,GAAG,CAAC,CAAA;4BACvB,CAAC;4BACD,aAAa,GAAG,WAAW,CAAA;wBAC7B,CAAC;oBACH,CAAC;oBAED,IAAI,iBAAiB,IAAI,CAAC,EAAE,CAAC;wBAC3B,OAAO,CAAC,MAAM,CAAC;4BACb,IAAI,EAAE,SAAS;4BACf,SAAS,EAAE,iBAAiB;yBAC7B,CAAC,CAAA;wBACF,iBAAiB,GAAG,CAAC,CAAA;oBACvB,CAAC;gBACH,CAAC;YACH,CAAC;SACF,CAAA;QAED,SAAS,aAAa,CAAC,IAAS;YAC9B,IAAI,CAAC,IAAI;gBAAE,OAAO,KAAK,CAAA;YACvB,IAAI,IAAI,CAAC,IAAI,KAAK,iBAAiB;gBAAE,OAAO,IAAI,CAAA;YAEhD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAA;gBACvB,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oBACvC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;wBACzB,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;4BAAE,OAAO,IAAI,CAAA;oBACpD,CAAC;yBAAM,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;wBAChC,OAAO,IAAI,CAAA;oBACb,CAAC;gBACH,CAAC;YACH,CAAC;YACD,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;CACF,CAAA;AAED,eAAe,IAAI,CAAA"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * ESLint Rule: cmp/prefer-server-components
3
+ *
4
+ * For Next.js App Router projects - prefer Server Components.
5
+ * Only add 'use client' when actually needed.
6
+ */
7
+ import type { Rule } from 'eslint';
8
+ declare const rule: Rule.RuleModule;
9
+ export default rule;
10
+ //# sourceMappingURL=prefer-server-components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefer-server-components.d.ts","sourceRoot":"","sources":["../../../src/eslint/rules/prefer-server-components.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAalC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAmEhB,CAAA;AAED,eAAe,IAAI,CAAA"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * ESLint Rule: cmp/prefer-server-components
3
+ *
4
+ * For Next.js App Router projects - prefer Server Components.
5
+ * Only add 'use client' when actually needed.
6
+ */
7
+ const CLIENT_ONLY_HOOKS = [
8
+ 'useState',
9
+ 'useEffect',
10
+ 'useRef',
11
+ 'useContext',
12
+ 'useReducer',
13
+ 'useCallback',
14
+ 'useMemo',
15
+ 'useLayoutEffect',
16
+ ];
17
+ const rule = {
18
+ meta: {
19
+ type: 'suggestion',
20
+ docs: {
21
+ description: 'Prefer Server Components in Next.js App Router',
22
+ category: 'Next.js',
23
+ recommended: false, // Only for Next.js projects
24
+ },
25
+ messages: {
26
+ unnecessaryUseClient: "'use client' may not be needed. Only add it for client-side features.",
27
+ missingUseClient: "This file uses client hooks but doesn't have 'use client' directive.",
28
+ },
29
+ schema: [],
30
+ },
31
+ create(context) {
32
+ let hasUseClientDirective = false;
33
+ let hasClientHooks = false;
34
+ let hasEventHandlers = false;
35
+ return {
36
+ Program(node) {
37
+ // Check for 'use client' directive
38
+ const firstStatement = node.body[0];
39
+ if (firstStatement?.type === 'ExpressionStatement' &&
40
+ firstStatement.expression?.type === 'Literal' &&
41
+ firstStatement.expression.value === 'use client') {
42
+ hasUseClientDirective = true;
43
+ }
44
+ },
45
+ 'Program:exit'(node) {
46
+ // If has 'use client' but no client features
47
+ if (hasUseClientDirective && !hasClientHooks && !hasEventHandlers) {
48
+ context.report({
49
+ node: node.body[0],
50
+ messageId: 'unnecessaryUseClient',
51
+ });
52
+ }
53
+ // Reset
54
+ hasUseClientDirective = false;
55
+ hasClientHooks = false;
56
+ hasEventHandlers = false;
57
+ },
58
+ CallExpression(node) {
59
+ if (node.callee.type === 'Identifier') {
60
+ if (CLIENT_ONLY_HOOKS.includes(node.callee.name)) {
61
+ hasClientHooks = true;
62
+ }
63
+ }
64
+ },
65
+ JSXAttribute(node) {
66
+ const name = node.name?.name;
67
+ if (typeof name === 'string' &&
68
+ (name.startsWith('on') && name[2]?.toUpperCase() === name[2])) {
69
+ hasEventHandlers = true;
70
+ }
71
+ },
72
+ };
73
+ },
74
+ };
75
+ export default rule;
76
+ //# sourceMappingURL=prefer-server-components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefer-server-components.js","sourceRoot":"","sources":["../../../src/eslint/rules/prefer-server-components.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,iBAAiB,GAAG;IACxB,UAAU;IACV,WAAW;IACX,QAAQ;IACR,YAAY;IACZ,YAAY;IACZ,aAAa;IACb,SAAS;IACT,iBAAiB;CAClB,CAAA;AAED,MAAM,IAAI,GAAoB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EAAE,gDAAgD;YAC7D,QAAQ,EAAE,SAAS;YACnB,WAAW,EAAE,KAAK,EAAE,4BAA4B;SACjD;QACD,QAAQ,EAAE;YACR,oBAAoB,EAAE,uEAAuE;YAC7F,gBAAgB,EAAE,sEAAsE;SACzF;QACD,MAAM,EAAE,EAAE;KACX;IAED,MAAM,CAAC,OAAO;QACZ,IAAI,qBAAqB,GAAG,KAAK,CAAA;QACjC,IAAI,cAAc,GAAG,KAAK,CAAA;QAC1B,IAAI,gBAAgB,GAAG,KAAK,CAAA;QAE5B,OAAO;YACL,OAAO,CAAC,IAAS;gBACf,mCAAmC;gBACnC,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;gBACnC,IACE,cAAc,EAAE,IAAI,KAAK,qBAAqB;oBAC9C,cAAc,CAAC,UAAU,EAAE,IAAI,KAAK,SAAS;oBAC7C,cAAc,CAAC,UAAU,CAAC,KAAK,KAAK,YAAY,EAChD,CAAC;oBACD,qBAAqB,GAAG,IAAI,CAAA;gBAC9B,CAAC;YACH,CAAC;YAED,cAAc,CAAC,IAAS;gBACtB,6CAA6C;gBAC7C,IAAI,qBAAqB,IAAI,CAAC,cAAc,IAAI,CAAC,gBAAgB,EAAE,CAAC;oBAClE,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;wBAClB,SAAS,EAAE,sBAAsB;qBAClC,CAAC,CAAA;gBACJ,CAAC;gBAED,QAAQ;gBACR,qBAAqB,GAAG,KAAK,CAAA;gBAC7B,cAAc,GAAG,KAAK,CAAA;gBACtB,gBAAgB,GAAG,KAAK,CAAA;YAC1B,CAAC;YAED,cAAc,CAAC,IAAS;gBACtB,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBACtC,IAAI,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;wBACjD,cAAc,GAAG,IAAI,CAAA;oBACvB,CAAC;gBACH,CAAC;YACH,CAAC;YAED,YAAY,CAAC,IAAS;gBACpB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,IAAI,CAAA;gBAC5B,IACE,OAAO,IAAI,KAAK,QAAQ;oBACxB,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,EAC7D,CAAC;oBACD,gBAAgB,GAAG,IAAI,CAAA;gBACzB,CAAC;YACH,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAA;AAED,eAAe,IAAI,CAAA"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * ESLint Rule: cmp/require-loading-states
3
+ *
4
+ * Ensures components using data fetching hooks handle loading states.
5
+ */
6
+ import type { Rule } from 'eslint';
7
+ declare const rule: Rule.RuleModule;
8
+ export default rule;
9
+ //# sourceMappingURL=require-loading-states.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-loading-states.d.ts","sourceRoot":"","sources":["../../../src/eslint/rules/require-loading-states.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAElC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA2FhB,CAAA;AAED,eAAe,IAAI,CAAA"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * ESLint Rule: cmp/require-loading-states
3
+ *
4
+ * Ensures components using data fetching hooks handle loading states.
5
+ */
6
+ const rule = {
7
+ meta: {
8
+ type: 'suggestion',
9
+ docs: {
10
+ description: 'Require handling of loading states in data fetching',
11
+ category: 'UX',
12
+ recommended: true,
13
+ },
14
+ messages: {
15
+ missingLoadingState: 'Data fetching detected but no loading state handling. Check for isLoading/isPending.',
16
+ },
17
+ schema: [],
18
+ },
19
+ create(context) {
20
+ let hasQueryHook = false;
21
+ let hasLoadingCheck = false;
22
+ return {
23
+ 'Program:exit'() {
24
+ // Reset for next file
25
+ hasQueryHook = false;
26
+ hasLoadingCheck = false;
27
+ },
28
+ CallExpression(node) {
29
+ const callee = node.callee;
30
+ // Detect query hooks
31
+ if (callee.type === 'MemberExpression') {
32
+ const property = callee.property?.name;
33
+ if (property === 'useQuery' ||
34
+ property === 'useMutation' ||
35
+ property === 'useSuspenseQuery') {
36
+ hasQueryHook = true;
37
+ }
38
+ }
39
+ // Check for trpc query calls
40
+ if (callee.type === 'Identifier' && callee.name.startsWith('use')) {
41
+ const name = callee.name;
42
+ if (name.includes('Query') || name.includes('Mutation')) {
43
+ hasQueryHook = true;
44
+ }
45
+ }
46
+ },
47
+ MemberExpression(node) {
48
+ // Check for isLoading or isPending access
49
+ if (node.property?.name === 'isLoading' ||
50
+ node.property?.name === 'isPending' ||
51
+ node.property?.name === 'isFetching') {
52
+ hasLoadingCheck = true;
53
+ }
54
+ },
55
+ // Check at function level
56
+ 'FunctionDeclaration:exit'(node) {
57
+ if (hasQueryHook && !hasLoadingCheck) {
58
+ context.report({
59
+ node,
60
+ messageId: 'missingLoadingState',
61
+ });
62
+ }
63
+ hasQueryHook = false;
64
+ hasLoadingCheck = false;
65
+ },
66
+ 'ArrowFunctionExpression:exit'(node) {
67
+ if (hasQueryHook && !hasLoadingCheck) {
68
+ // Only report for component-like arrow functions
69
+ const parent = node.parent;
70
+ if (parent?.type === 'VariableDeclarator' &&
71
+ parent.id?.name?.[0]?.toUpperCase() === parent.id?.name?.[0]) {
72
+ context.report({
73
+ node,
74
+ messageId: 'missingLoadingState',
75
+ });
76
+ }
77
+ }
78
+ hasQueryHook = false;
79
+ hasLoadingCheck = false;
80
+ },
81
+ };
82
+ },
83
+ };
84
+ export default rule;
85
+ //# sourceMappingURL=require-loading-states.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-loading-states.js","sourceRoot":"","sources":["../../../src/eslint/rules/require-loading-states.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,IAAI,GAAoB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EAAE,qDAAqD;YAClE,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,IAAI;SAClB;QACD,QAAQ,EAAE;YACR,mBAAmB,EAAE,sFAAsF;SAC5G;QACD,MAAM,EAAE,EAAE;KACX;IAED,MAAM,CAAC,OAAO;QACZ,IAAI,YAAY,GAAG,KAAK,CAAA;QACxB,IAAI,eAAe,GAAG,KAAK,CAAA;QAE3B,OAAO;YACL,cAAc;gBACZ,sBAAsB;gBACtB,YAAY,GAAG,KAAK,CAAA;gBACpB,eAAe,GAAG,KAAK,CAAA;YACzB,CAAC;YAED,cAAc,CAAC,IAAS;gBACtB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;gBAE1B,qBAAqB;gBACrB,IAAI,MAAM,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;oBACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAA;oBACtC,IACE,QAAQ,KAAK,UAAU;wBACvB,QAAQ,KAAK,aAAa;wBAC1B,QAAQ,KAAK,kBAAkB,EAC/B,CAAC;wBACD,YAAY,GAAG,IAAI,CAAA;oBACrB,CAAC;gBACH,CAAC;gBAED,6BAA6B;gBAC7B,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,IAAI,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;oBAClE,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAA;oBACxB,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;wBACxD,YAAY,GAAG,IAAI,CAAA;oBACrB,CAAC;gBACH,CAAC;YACH,CAAC;YAED,gBAAgB,CAAC,IAAS;gBACxB,0CAA0C;gBAC1C,IACE,IAAI,CAAC,QAAQ,EAAE,IAAI,KAAK,WAAW;oBACnC,IAAI,CAAC,QAAQ,EAAE,IAAI,KAAK,WAAW;oBACnC,IAAI,CAAC,QAAQ,EAAE,IAAI,KAAK,YAAY,EACpC,CAAC;oBACD,eAAe,GAAG,IAAI,CAAA;gBACxB,CAAC;YACH,CAAC;YAED,0BAA0B;YAC1B,0BAA0B,CAAC,IAAS;gBAClC,IAAI,YAAY,IAAI,CAAC,eAAe,EAAE,CAAC;oBACrC,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;wBACJ,SAAS,EAAE,qBAAqB;qBACjC,CAAC,CAAA;gBACJ,CAAC;gBACD,YAAY,GAAG,KAAK,CAAA;gBACpB,eAAe,GAAG,KAAK,CAAA;YACzB,CAAC;YAED,8BAA8B,CAAC,IAAS;gBACtC,IAAI,YAAY,IAAI,CAAC,eAAe,EAAE,CAAC;oBACrC,iDAAiD;oBACjD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;oBAC1B,IACE,MAAM,EAAE,IAAI,KAAK,oBAAoB;wBACrC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAC5D,CAAC;wBACD,OAAO,CAAC,MAAM,CAAC;4BACb,IAAI;4BACJ,SAAS,EAAE,qBAAqB;yBACjC,CAAC,CAAA;oBACJ,CAAC;gBACH,CAAC;gBACD,YAAY,GAAG,KAAK,CAAA;gBACpB,eAAe,GAAG,KAAK,CAAA;YACzB,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAA;AAED,eAAe,IAAI,CAAA"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * ESLint Rule: cmp/require-zod-validation
3
+ *
4
+ * Ensures that TRPC procedures have proper Zod input validation.
5
+ * Unvalidated inputs are a security risk.
6
+ */
7
+ import type { Rule } from 'eslint';
8
+ declare const rule: Rule.RuleModule;
9
+ export default rule;
10
+ //# sourceMappingURL=require-zod-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-zod-validation.d.ts","sourceRoot":"","sources":["../../../src/eslint/rules/require-zod-validation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAElC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAiEhB,CAAA;AAED,eAAe,IAAI,CAAA"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * ESLint Rule: cmp/require-zod-validation
3
+ *
4
+ * Ensures that TRPC procedures have proper Zod input validation.
5
+ * Unvalidated inputs are a security risk.
6
+ */
7
+ const rule = {
8
+ meta: {
9
+ type: 'problem',
10
+ docs: {
11
+ description: 'Require Zod validation on TRPC procedures',
12
+ category: 'Security',
13
+ recommended: true,
14
+ },
15
+ messages: {
16
+ missingInput: 'TRPC mutation/query should have .input() validation with Zod schema',
17
+ emptyInput: 'Input validation should not be empty - define a Zod schema',
18
+ },
19
+ schema: [],
20
+ },
21
+ create(context) {
22
+ return {
23
+ CallExpression(node) {
24
+ // Look for .mutation() or .query() calls
25
+ if (node.callee.type !== 'MemberExpression')
26
+ return;
27
+ const propertyName = node.callee.property?.name;
28
+ if (!['mutation', 'query'].includes(propertyName))
29
+ return;
30
+ // Check the call chain for .input()
31
+ let current = node.callee.object;
32
+ let hasInput = false;
33
+ while (current) {
34
+ if (current.type === 'CallExpression') {
35
+ const callee = current.callee;
36
+ if (callee.type === 'MemberExpression' &&
37
+ callee.property?.name === 'input') {
38
+ hasInput = true;
39
+ // Check if input is empty or just z.object({})
40
+ const inputArg = current.arguments[0];
41
+ if (!inputArg) {
42
+ context.report({
43
+ node: current,
44
+ messageId: 'emptyInput',
45
+ });
46
+ }
47
+ break;
48
+ }
49
+ current = callee.object;
50
+ }
51
+ else if (current.type === 'MemberExpression') {
52
+ current = current.object;
53
+ }
54
+ else {
55
+ break;
56
+ }
57
+ }
58
+ // Only warn for mutations without input (queries might not need input)
59
+ if (!hasInput && propertyName === 'mutation') {
60
+ context.report({
61
+ node,
62
+ messageId: 'missingInput',
63
+ });
64
+ }
65
+ },
66
+ };
67
+ },
68
+ };
69
+ export default rule;
70
+ //# sourceMappingURL=require-zod-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"require-zod-validation.js","sourceRoot":"","sources":["../../../src/eslint/rules/require-zod-validation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,IAAI,GAAoB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EAAE,2CAA2C;YACxD,QAAQ,EAAE,UAAU;YACpB,WAAW,EAAE,IAAI;SAClB;QACD,QAAQ,EAAE;YACR,YAAY,EAAE,qEAAqE;YACnF,UAAU,EAAE,4DAA4D;SACzE;QACD,MAAM,EAAE,EAAE;KACX;IAED,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,cAAc,CAAC,IAAS;gBACtB,yCAAyC;gBACzC,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB;oBAAE,OAAM;gBAEnD,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAA;gBAC/C,IAAI,CAAC,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC;oBAAE,OAAM;gBAEzD,oCAAoC;gBACpC,IAAI,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAA;gBAChC,IAAI,QAAQ,GAAG,KAAK,CAAA;gBAEpB,OAAO,OAAO,EAAE,CAAC;oBACf,IAAI,OAAO,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;wBACtC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAA;wBAC7B,IACE,MAAM,CAAC,IAAI,KAAK,kBAAkB;4BAClC,MAAM,CAAC,QAAQ,EAAE,IAAI,KAAK,OAAO,EACjC,CAAC;4BACD,QAAQ,GAAG,IAAI,CAAA;4BAEf,+CAA+C;4BAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;4BACrC,IAAI,CAAC,QAAQ,EAAE,CAAC;gCACd,OAAO,CAAC,MAAM,CAAC;oCACb,IAAI,EAAE,OAAO;oCACb,SAAS,EAAE,YAAY;iCACxB,CAAC,CAAA;4BACJ,CAAC;4BACD,MAAK;wBACP,CAAC;wBACD,OAAO,GAAG,MAAM,CAAC,MAAM,CAAA;oBACzB,CAAC;yBAAM,IAAI,OAAO,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;wBAC/C,OAAO,GAAG,OAAO,CAAC,MAAM,CAAA;oBAC1B,CAAC;yBAAM,CAAC;wBACN,MAAK;oBACP,CAAC;gBACH,CAAC;gBAED,uEAAuE;gBACvE,IAAI,CAAC,QAAQ,IAAI,YAAY,KAAK,UAAU,EAAE,CAAC;oBAC7C,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;wBACJ,SAAS,EAAE,cAAc;qBAC1B,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAA;AAED,eAAe,IAAI,CAAA"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * ESLint Rule: cmp/semantic-tokens-only
3
+ *
4
+ * Prevents hardcoded colors in Tailwind classes.
5
+ * Use semantic tokens (bg-container, text-content) instead of raw colors (bg-gray-100).
6
+ */
7
+ import type { Rule } from 'eslint';
8
+ declare const rule: Rule.RuleModule;
9
+ export default rule;
10
+ //# sourceMappingURL=semantic-tokens-only.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-tokens-only.d.ts","sourceRoot":"","sources":["../../../src/eslint/rules/semantic-tokens-only.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AASlC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UAqDhB,CAAA;AAED,eAAe,IAAI,CAAA"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * ESLint Rule: cmp/semantic-tokens-only
3
+ *
4
+ * Prevents hardcoded colors in Tailwind classes.
5
+ * Use semantic tokens (bg-container, text-content) instead of raw colors (bg-gray-100).
6
+ */
7
+ const FORBIDDEN_PATTERNS = [
8
+ // Raw colors
9
+ /\b(bg|text|border|ring|outline|shadow|from|to|via)-(red|blue|green|yellow|purple|pink|gray|slate|zinc|neutral|stone|orange|amber|lime|emerald|teal|cyan|sky|indigo|violet|fuchsia|rose)-\d+/,
10
+ // Hardcoded hex colors
11
+ /\[(#[0-9a-fA-F]{3,8})\]/,
12
+ ];
13
+ const rule = {
14
+ meta: {
15
+ type: 'suggestion',
16
+ docs: {
17
+ description: 'Use semantic design tokens instead of hardcoded colors',
18
+ category: 'Best Practices',
19
+ recommended: true,
20
+ },
21
+ messages: {
22
+ useSemanticToken: 'Use semantic token (e.g., bg-container, text-content) instead of hardcoded color: {{value}}',
23
+ },
24
+ schema: [],
25
+ },
26
+ create(context) {
27
+ function checkString(node, value) {
28
+ for (const pattern of FORBIDDEN_PATTERNS) {
29
+ const match = value.match(pattern);
30
+ if (match) {
31
+ context.report({
32
+ node,
33
+ messageId: 'useSemanticToken',
34
+ data: { value: match[0] },
35
+ });
36
+ return;
37
+ }
38
+ }
39
+ }
40
+ return {
41
+ Literal(node) {
42
+ if (typeof node.value === 'string') {
43
+ checkString(node, node.value);
44
+ }
45
+ },
46
+ TemplateElement(node) {
47
+ if (node.value?.raw) {
48
+ checkString(node, node.value.raw);
49
+ }
50
+ },
51
+ JSXAttribute(node) {
52
+ if (node.name?.name === 'className' &&
53
+ node.value?.type === 'Literal' &&
54
+ typeof node.value.value === 'string') {
55
+ checkString(node.value, node.value.value);
56
+ }
57
+ },
58
+ };
59
+ },
60
+ };
61
+ export default rule;
62
+ //# sourceMappingURL=semantic-tokens-only.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-tokens-only.js","sourceRoot":"","sources":["../../../src/eslint/rules/semantic-tokens-only.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,kBAAkB,GAAG;IACzB,aAAa;IACb,6LAA6L;IAC7L,uBAAuB;IACvB,yBAAyB;CAC1B,CAAA;AAED,MAAM,IAAI,GAAoB;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EAAE,wDAAwD;YACrE,QAAQ,EAAE,gBAAgB;YAC1B,WAAW,EAAE,IAAI;SAClB;QACD,QAAQ,EAAE;YACR,gBAAgB,EAAE,6FAA6F;SAChH;QACD,MAAM,EAAE,EAAE;KACX;IAED,MAAM,CAAC,OAAO;QACZ,SAAS,WAAW,CAAC,IAAS,EAAE,KAAa;YAC3C,KAAK,MAAM,OAAO,IAAI,kBAAkB,EAAE,CAAC;gBACzC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;gBAClC,IAAI,KAAK,EAAE,CAAC;oBACV,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;wBACJ,SAAS,EAAE,kBAAkB;wBAC7B,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE;qBAC1B,CAAC,CAAA;oBACF,OAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO;YACL,OAAO,CAAC,IAAS;gBACf,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;oBACnC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC/B,CAAC;YACH,CAAC;YAED,eAAe,CAAC,IAAS;gBACvB,IAAI,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC;oBACpB,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;gBACnC,CAAC;YACH,CAAC;YAED,YAAY,CAAC,IAAS;gBACpB,IACE,IAAI,CAAC,IAAI,EAAE,IAAI,KAAK,WAAW;oBAC/B,IAAI,CAAC,KAAK,EAAE,IAAI,KAAK,SAAS;oBAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,KAAK,QAAQ,EACpC,CAAC;oBACD,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;gBAC3C,CAAC;YACH,CAAC;SACF,CAAA;IACH,CAAC;CACF,CAAA;AAED,eAAe,IAAI,CAAA"}