@webpieces/dev-config 0.2.95 → 0.2.98

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 (181) hide show
  1. package/config/eslint/base.mjs +1 -1
  2. package/executors.json +6 -91
  3. package/package.json +6 -19
  4. package/{executors → src/executors}/help/executor.d.ts +4 -2
  5. package/src/executors/help/executor.js.map +1 -0
  6. package/src/executors/validate-eslint-sync/executor.js.map +1 -0
  7. package/{executors → src/executors}/validate-versions-locked/executor.js +2 -1
  8. package/src/executors/validate-versions-locked/executor.js.map +1 -0
  9. package/src/index.d.ts +1 -1
  10. package/src/index.js +1 -1
  11. package/src/index.js.map +1 -1
  12. package/src/plugin.d.ts +86 -0
  13. package/{plugin.js → src/plugin.js} +31 -15
  14. package/src/plugin.js.map +1 -0
  15. package/src/toError.d.ts +5 -0
  16. package/src/toError.js +37 -0
  17. package/src/toError.js.map +1 -0
  18. package/templates/eslint.webpieces.config.mjs +1 -1
  19. package/architecture/executors/diff-utils.d.ts +0 -24
  20. package/architecture/executors/diff-utils.js +0 -119
  21. package/architecture/executors/diff-utils.js.map +0 -1
  22. package/architecture/executors/diff-utils.ts +0 -127
  23. package/architecture/executors/generate/executor.d.ts +0 -16
  24. package/architecture/executors/generate/executor.js +0 -44
  25. package/architecture/executors/generate/executor.js.map +0 -1
  26. package/architecture/executors/generate/executor.ts +0 -59
  27. package/architecture/executors/generate/schema.json +0 -14
  28. package/architecture/executors/validate-architecture-unchanged/executor.d.ts +0 -17
  29. package/architecture/executors/validate-architecture-unchanged/executor.js +0 -229
  30. package/architecture/executors/validate-architecture-unchanged/executor.js.map +0 -1
  31. package/architecture/executors/validate-architecture-unchanged/executor.ts +0 -251
  32. package/architecture/executors/validate-architecture-unchanged/schema.json +0 -14
  33. package/architecture/executors/validate-code/executor.d.ts +0 -78
  34. package/architecture/executors/validate-code/executor.js +0 -243
  35. package/architecture/executors/validate-code/executor.js.map +0 -1
  36. package/architecture/executors/validate-code/executor.ts +0 -406
  37. package/architecture/executors/validate-code/schema.json +0 -227
  38. package/architecture/executors/validate-dtos/executor.d.ts +0 -42
  39. package/architecture/executors/validate-dtos/executor.js +0 -561
  40. package/architecture/executors/validate-dtos/executor.js.map +0 -1
  41. package/architecture/executors/validate-dtos/executor.ts +0 -689
  42. package/architecture/executors/validate-dtos/schema.json +0 -33
  43. package/architecture/executors/validate-modified-files/executor.d.ts +0 -25
  44. package/architecture/executors/validate-modified-files/executor.js +0 -501
  45. package/architecture/executors/validate-modified-files/executor.js.map +0 -1
  46. package/architecture/executors/validate-modified-files/executor.ts +0 -571
  47. package/architecture/executors/validate-modified-files/schema.json +0 -25
  48. package/architecture/executors/validate-modified-methods/executor.d.ts +0 -31
  49. package/architecture/executors/validate-modified-methods/executor.js +0 -694
  50. package/architecture/executors/validate-modified-methods/executor.js.map +0 -1
  51. package/architecture/executors/validate-modified-methods/executor.ts +0 -797
  52. package/architecture/executors/validate-modified-methods/schema.json +0 -25
  53. package/architecture/executors/validate-new-methods/executor.d.ts +0 -28
  54. package/architecture/executors/validate-new-methods/executor.js +0 -513
  55. package/architecture/executors/validate-new-methods/executor.js.map +0 -1
  56. package/architecture/executors/validate-new-methods/executor.ts +0 -584
  57. package/architecture/executors/validate-new-methods/schema.json +0 -25
  58. package/architecture/executors/validate-no-any-unknown/executor.d.ts +0 -42
  59. package/architecture/executors/validate-no-any-unknown/executor.js +0 -462
  60. package/architecture/executors/validate-no-any-unknown/executor.js.map +0 -1
  61. package/architecture/executors/validate-no-any-unknown/executor.ts +0 -540
  62. package/architecture/executors/validate-no-any-unknown/schema.json +0 -24
  63. package/architecture/executors/validate-no-architecture-cycles/executor.d.ts +0 -16
  64. package/architecture/executors/validate-no-architecture-cycles/executor.js +0 -48
  65. package/architecture/executors/validate-no-architecture-cycles/executor.js.map +0 -1
  66. package/architecture/executors/validate-no-architecture-cycles/executor.ts +0 -60
  67. package/architecture/executors/validate-no-architecture-cycles/schema.json +0 -8
  68. package/architecture/executors/validate-no-destructure/executor.d.ts +0 -52
  69. package/architecture/executors/validate-no-destructure/executor.js +0 -491
  70. package/architecture/executors/validate-no-destructure/executor.js.map +0 -1
  71. package/architecture/executors/validate-no-destructure/executor.ts +0 -578
  72. package/architecture/executors/validate-no-destructure/schema.json +0 -24
  73. package/architecture/executors/validate-no-direct-api-resolver/executor.d.ts +0 -47
  74. package/architecture/executors/validate-no-direct-api-resolver/executor.js +0 -566
  75. package/architecture/executors/validate-no-direct-api-resolver/executor.js.map +0 -1
  76. package/architecture/executors/validate-no-direct-api-resolver/executor.ts +0 -666
  77. package/architecture/executors/validate-no-direct-api-resolver/schema.json +0 -29
  78. package/architecture/executors/validate-no-inline-types/executor.d.ts +0 -91
  79. package/architecture/executors/validate-no-inline-types/executor.js +0 -669
  80. package/architecture/executors/validate-no-inline-types/executor.js.map +0 -1
  81. package/architecture/executors/validate-no-inline-types/executor.ts +0 -775
  82. package/architecture/executors/validate-no-inline-types/schema.json +0 -24
  83. package/architecture/executors/validate-no-skiplevel-deps/executor.d.ts +0 -19
  84. package/architecture/executors/validate-no-skiplevel-deps/executor.js +0 -227
  85. package/architecture/executors/validate-no-skiplevel-deps/executor.js.map +0 -1
  86. package/architecture/executors/validate-no-skiplevel-deps/executor.ts +0 -267
  87. package/architecture/executors/validate-no-skiplevel-deps/schema.json +0 -8
  88. package/architecture/executors/validate-packagejson/executor.d.ts +0 -16
  89. package/architecture/executors/validate-packagejson/executor.js +0 -57
  90. package/architecture/executors/validate-packagejson/executor.js.map +0 -1
  91. package/architecture/executors/validate-packagejson/executor.ts +0 -74
  92. package/architecture/executors/validate-packagejson/schema.json +0 -8
  93. package/architecture/executors/validate-prisma-converters/executor.d.ts +0 -60
  94. package/architecture/executors/validate-prisma-converters/executor.js +0 -634
  95. package/architecture/executors/validate-prisma-converters/executor.js.map +0 -1
  96. package/architecture/executors/validate-prisma-converters/executor.ts +0 -822
  97. package/architecture/executors/validate-prisma-converters/schema.json +0 -38
  98. package/architecture/executors/validate-return-types/executor.d.ts +0 -29
  99. package/architecture/executors/validate-return-types/executor.js +0 -439
  100. package/architecture/executors/validate-return-types/executor.js.map +0 -1
  101. package/architecture/executors/validate-return-types/executor.ts +0 -524
  102. package/architecture/executors/validate-return-types/schema.json +0 -24
  103. package/architecture/executors/visualize/executor.d.ts +0 -17
  104. package/architecture/executors/visualize/executor.js +0 -49
  105. package/architecture/executors/visualize/executor.js.map +0 -1
  106. package/architecture/executors/visualize/executor.ts +0 -63
  107. package/architecture/executors/visualize/schema.json +0 -14
  108. package/architecture/index.d.ts +0 -19
  109. package/architecture/index.js +0 -23
  110. package/architecture/index.js.map +0 -1
  111. package/architecture/index.ts +0 -20
  112. package/architecture/lib/graph-comparator.d.ts +0 -39
  113. package/architecture/lib/graph-comparator.js +0 -100
  114. package/architecture/lib/graph-comparator.js.map +0 -1
  115. package/architecture/lib/graph-comparator.ts +0 -141
  116. package/architecture/lib/graph-generator.d.ts +0 -19
  117. package/architecture/lib/graph-generator.js +0 -84
  118. package/architecture/lib/graph-generator.js.map +0 -1
  119. package/architecture/lib/graph-generator.ts +0 -97
  120. package/architecture/lib/graph-loader.d.ts +0 -31
  121. package/architecture/lib/graph-loader.js +0 -98
  122. package/architecture/lib/graph-loader.js.map +0 -1
  123. package/architecture/lib/graph-loader.ts +0 -116
  124. package/architecture/lib/graph-sorter.d.ts +0 -37
  125. package/architecture/lib/graph-sorter.js +0 -110
  126. package/architecture/lib/graph-sorter.js.map +0 -1
  127. package/architecture/lib/graph-sorter.ts +0 -137
  128. package/architecture/lib/graph-visualizer.d.ts +0 -29
  129. package/architecture/lib/graph-visualizer.js +0 -217
  130. package/architecture/lib/graph-visualizer.js.map +0 -1
  131. package/architecture/lib/graph-visualizer.ts +0 -231
  132. package/architecture/lib/package-validator.d.ts +0 -38
  133. package/architecture/lib/package-validator.js +0 -126
  134. package/architecture/lib/package-validator.js.map +0 -1
  135. package/architecture/lib/package-validator.ts +0 -170
  136. package/eslint-plugin/__tests__/catch-error-pattern.test.ts +0 -374
  137. package/eslint-plugin/__tests__/max-file-lines.test.ts +0 -207
  138. package/eslint-plugin/__tests__/max-method-lines.test.ts +0 -258
  139. package/eslint-plugin/__tests__/no-unmanaged-exceptions.test.ts +0 -359
  140. package/eslint-plugin/index.d.ts +0 -23
  141. package/eslint-plugin/index.js +0 -30
  142. package/eslint-plugin/index.js.map +0 -1
  143. package/eslint-plugin/index.ts +0 -29
  144. package/eslint-plugin/rules/catch-error-pattern.d.ts +0 -11
  145. package/eslint-plugin/rules/catch-error-pattern.js +0 -143
  146. package/eslint-plugin/rules/catch-error-pattern.js.map +0 -1
  147. package/eslint-plugin/rules/catch-error-pattern.ts +0 -246
  148. package/eslint-plugin/rules/enforce-architecture.d.ts +0 -15
  149. package/eslint-plugin/rules/enforce-architecture.js +0 -476
  150. package/eslint-plugin/rules/enforce-architecture.js.map +0 -1
  151. package/eslint-plugin/rules/enforce-architecture.ts +0 -543
  152. package/eslint-plugin/rules/max-file-lines.d.ts +0 -12
  153. package/eslint-plugin/rules/max-file-lines.js +0 -257
  154. package/eslint-plugin/rules/max-file-lines.js.map +0 -1
  155. package/eslint-plugin/rules/max-file-lines.ts +0 -272
  156. package/eslint-plugin/rules/max-method-lines.d.ts +0 -12
  157. package/eslint-plugin/rules/max-method-lines.js +0 -240
  158. package/eslint-plugin/rules/max-method-lines.js.map +0 -1
  159. package/eslint-plugin/rules/max-method-lines.ts +0 -287
  160. package/eslint-plugin/rules/no-unmanaged-exceptions.d.ts +0 -22
  161. package/eslint-plugin/rules/no-unmanaged-exceptions.js +0 -160
  162. package/eslint-plugin/rules/no-unmanaged-exceptions.js.map +0 -1
  163. package/eslint-plugin/rules/no-unmanaged-exceptions.ts +0 -179
  164. package/executors/help/executor.js.map +0 -1
  165. package/executors/help/executor.ts +0 -61
  166. package/executors/validate-eslint-sync/executor.js.map +0 -1
  167. package/executors/validate-eslint-sync/executor.ts +0 -87
  168. package/executors/validate-versions-locked/executor.js.map +0 -1
  169. package/executors/validate-versions-locked/executor.ts +0 -368
  170. package/plugin/README.md +0 -243
  171. package/plugin/index.d.ts +0 -4
  172. package/plugin/index.js +0 -8
  173. package/plugin/index.js.map +0 -1
  174. package/plugin/index.ts +0 -4
  175. /package/{executors → src/executors}/help/executor.js +0 -0
  176. /package/{executors → src/executors}/help/schema.json +0 -0
  177. /package/{executors → src/executors}/validate-eslint-sync/executor.d.ts +0 -0
  178. /package/{executors → src/executors}/validate-eslint-sync/executor.js +0 -0
  179. /package/{executors → src/executors}/validate-eslint-sync/schema.json +0 -0
  180. /package/{executors → src/executors}/validate-versions-locked/executor.d.ts +0 -0
  181. /package/{executors → src/executors}/validate-versions-locked/schema.json +0 -0
@@ -1,240 +0,0 @@
1
- "use strict";
2
- /**
3
- * ESLint rule to enforce maximum method length
4
- *
5
- * Enforces a configurable maximum line count for methods, functions, and arrow functions.
6
- * Default: 70 lines
7
- *
8
- * Configuration:
9
- * '@webpieces/max-method-lines': ['error', { max: 70 }]
10
- */
11
- const tslib_1 = require("tslib");
12
- const fs = tslib_1.__importStar(require("fs"));
13
- const path = tslib_1.__importStar(require("path"));
14
- const toError_1 = require("../../toError");
15
- const METHOD_DOC_CONTENT = `# AI Agent Instructions: Method Too Long
16
-
17
- **READ THIS FILE to fix methods that are too long**
18
-
19
- ## Core Principle
20
- Every method should read like a TABLE OF CONTENTS of a book.
21
- - Each method call is a "chapter"
22
- - When you dive into a method, you find another table of contents
23
- - Keeping methods under 70 lines is achievable with proper extraction
24
-
25
- ## Command: Extract Code into Named Methods
26
-
27
- ### Pattern 1: Extract Loop Bodies
28
- \`\`\`typescript
29
- // BAD: 50 lines embedded in loop
30
- for (const order of orders) {
31
- // 20 lines of validation logic
32
- // 15 lines of processing logic
33
- // 10 lines of notification logic
34
- }
35
-
36
- // GOOD: Extracted to named methods
37
- for (const order of orders) {
38
- validateOrder(order);
39
- processOrderItems(order);
40
- sendNotifications(order);
41
- }
42
- \`\`\`
43
-
44
- ### Pattern 2: Try-Catch Wrapper for Exception Handling
45
- \`\`\`typescript
46
- // GOOD: Separates success path from error handling
47
- async function handleRequest(req: Request): Promise<Response> {
48
- try {
49
- return await executeRequest(req);
50
- } catch (err: unknown) {
51
- const error = toError(err);
52
- return createErrorResponse(error);
53
- }
54
- }
55
- \`\`\`
56
-
57
- ### Pattern 3: Sequential Method Calls (Table of Contents)
58
- \`\`\`typescript
59
- // GOOD: Self-documenting steps
60
- function processOrder(order: Order): void {
61
- validateOrderData(order);
62
- calculateTotals(order);
63
- applyDiscounts(order);
64
- processPayment(order);
65
- updateInventory(order);
66
- sendConfirmation(order);
67
- }
68
- \`\`\`
69
-
70
- ### Pattern 4: Separate Data Object Creation
71
- \`\`\`typescript
72
- // BAD: 15 lines of inline object creation
73
- doSomething({ field1: ..., field2: ..., field3: ..., /* 15 more fields */ });
74
-
75
- // GOOD: Extract to factory method
76
- const request = createRequestObject(data);
77
- doSomething(request);
78
- \`\`\`
79
-
80
- ### Pattern 5: Extract Inline Logic to Named Functions
81
- \`\`\`typescript
82
- // BAD: Complex inline logic
83
- if (user.role === 'admin' && user.permissions.includes('write') && !user.suspended) {
84
- // 30 lines of admin logic
85
- }
86
-
87
- // GOOD: Extract to named methods
88
- if (isAdminWithWriteAccess(user)) {
89
- performAdminOperation(user);
90
- }
91
- \`\`\`
92
-
93
- ## AI Agent Action Steps
94
-
95
- 1. **IDENTIFY** the long method in the error message
96
- 2. **READ** the method to understand its logical sections
97
- 3. **EXTRACT** logical units into separate methods with descriptive names
98
- 4. **REPLACE** inline code with method calls
99
- 5. **VERIFY** each extracted method is <70 lines
100
- 6. **TEST** that functionality remains unchanged
101
-
102
- ## Examples of "Logical Units" to Extract
103
- - Validation logic -> \`validateX()\`
104
- - Data transformation -> \`transformXToY()\`
105
- - API calls -> \`fetchXFromApi()\`
106
- - Object creation -> \`createX()\`
107
- - Loop bodies -> \`processItem()\`
108
- - Error handling -> \`handleXError()\`
109
-
110
- Remember: Methods should read like a table of contents. Each line should be a "chapter title" (method call) that describes what happens, not how it happens.
111
- `;
112
- // Module-level flag to prevent redundant file creation
113
- let methodDocCreated = false;
114
- function getWorkspaceRoot(context) {
115
- const filename = context.filename || context.getFilename();
116
- let dir = path.dirname(filename);
117
- while (dir !== path.dirname(dir)) {
118
- const pkgPath = path.join(dir, 'package.json');
119
- if (fs.existsSync(pkgPath)) {
120
- try {
121
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
122
- if (pkg.workspaces || pkg.name === 'webpieces-ts') {
123
- return dir;
124
- }
125
- }
126
- catch (err) {
127
- //const error = toError(err);
128
- void err;
129
- }
130
- }
131
- dir = path.dirname(dir);
132
- }
133
- return process.cwd();
134
- }
135
- function ensureDocFile(docPath, content) {
136
- try {
137
- fs.mkdirSync(path.dirname(docPath), { recursive: true });
138
- fs.writeFileSync(docPath, content, 'utf-8');
139
- return true;
140
- }
141
- catch (err) {
142
- const error = (0, toError_1.toError)(err);
143
- console.warn(`[webpieces] Could not create doc file: ${docPath}`, error);
144
- return false;
145
- }
146
- }
147
- function ensureMethodDoc(context) {
148
- const workspaceRoot = getWorkspaceRoot(context);
149
- const docPath = path.join(workspaceRoot, 'tmp', 'webpieces', 'webpieces.methods.md');
150
- // Check if file exists AND flag is true - if both, skip
151
- if (methodDocCreated && fs.existsSync(docPath))
152
- return;
153
- if (ensureDocFile(docPath, METHOD_DOC_CONTENT)) {
154
- methodDocCreated = true;
155
- }
156
- }
157
- function getFunctionName(funcNode) {
158
- if (funcNode.type === 'FunctionDeclaration' && funcNode.id?.name) {
159
- return funcNode.id.name;
160
- }
161
- if (funcNode.type === 'FunctionExpression' && funcNode.id?.name) {
162
- return funcNode.id.name;
163
- }
164
- return 'anonymous';
165
- }
166
- function reportTooLong(ctx, node, name, lineCount) {
167
- ctx.context.report({
168
- node,
169
- messageId: 'tooLong',
170
- data: {
171
- name,
172
- actual: String(lineCount),
173
- max: String(ctx.maxLines),
174
- },
175
- });
176
- }
177
- function checkFunctionNode(ctx, node) {
178
- ensureMethodDoc(ctx.context);
179
- const funcNode = node;
180
- // Skip function expressions inside method definitions
181
- if (funcNode.type === 'FunctionExpression' && funcNode['parent']?.type === 'MethodDefinition') {
182
- return;
183
- }
184
- if (!funcNode.loc || !funcNode.body)
185
- return;
186
- const name = getFunctionName(funcNode);
187
- const lineCount = funcNode.loc.end.line - funcNode.loc.start.line + 1;
188
- if (lineCount > ctx.maxLines) {
189
- reportTooLong(ctx, funcNode, name, lineCount);
190
- }
191
- }
192
- function checkMethodNode(ctx, node) {
193
- ensureMethodDoc(ctx.context);
194
- if (!node.loc || !node.value)
195
- return;
196
- const name = node.key?.name || 'anonymous';
197
- const lineCount = node.loc.end.line - node.loc.start.line + 1;
198
- if (lineCount > ctx.maxLines) {
199
- reportTooLong(ctx, node, name, lineCount);
200
- }
201
- }
202
- const rule = {
203
- meta: {
204
- type: 'suggestion',
205
- docs: {
206
- description: 'Enforce maximum method length',
207
- category: 'Best Practices',
208
- recommended: false,
209
- url: 'https://github.com/deanhiller/webpieces-ts',
210
- },
211
- messages: {
212
- tooLong: 'AI Agent: READ tmp/webpieces/webpieces.methods.md for fix instructions. Method "{{name}}" has {{actual}} lines (max: {{max}})',
213
- },
214
- fixable: undefined,
215
- schema: [
216
- {
217
- type: 'object',
218
- properties: {
219
- max: {
220
- type: 'integer',
221
- minimum: 1,
222
- },
223
- },
224
- additionalProperties: false,
225
- },
226
- ],
227
- },
228
- create(context) {
229
- const options = context.options[0];
230
- const ctx = { context, maxLines: options?.max ?? 70 };
231
- return {
232
- FunctionDeclaration: (node) => checkFunctionNode(ctx, node),
233
- FunctionExpression: (node) => checkFunctionNode(ctx, node),
234
- ArrowFunctionExpression: (node) => checkFunctionNode(ctx, node),
235
- MethodDefinition: (node) => checkMethodNode(ctx, node),
236
- };
237
- },
238
- };
239
- module.exports = rule;
240
- //# sourceMappingURL=max-method-lines.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"max-method-lines.js","sourceRoot":"","sources":["../../../../../../packages/tooling/dev-config/eslint-plugin/rules/max-method-lines.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * ESLint rule to enforce maximum method length\n *\n * Enforces a configurable maximum line count for methods, functions, and arrow functions.\n * Default: 70 lines\n *\n * Configuration:\n * '@webpieces/max-method-lines': ['error', { max: 70 }]\n */\n\nimport type { Rule } from 'eslint';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { toError } from '../../toError';\n\ninterface MethodLinesOptions {\n max: number;\n}\n\ninterface FunctionNode {\n type:\n | 'FunctionDeclaration'\n | 'FunctionExpression'\n | 'ArrowFunctionExpression'\n | 'MethodDefinition';\n body?: any;\n loc?: {\n start: { line: number };\n end: { line: number };\n };\n key?: {\n name?: string;\n };\n id?: {\n name?: string;\n };\n [key: string]: any;\n}\n\ninterface CheckerContext {\n context: Rule.RuleContext;\n maxLines: number;\n}\n\nconst METHOD_DOC_CONTENT = `# AI Agent Instructions: Method Too Long\n\n**READ THIS FILE to fix methods that are too long**\n\n## Core Principle\nEvery method should read like a TABLE OF CONTENTS of a book.\n- Each method call is a \"chapter\"\n- When you dive into a method, you find another table of contents\n- Keeping methods under 70 lines is achievable with proper extraction\n\n## Command: Extract Code into Named Methods\n\n### Pattern 1: Extract Loop Bodies\n\\`\\`\\`typescript\n// BAD: 50 lines embedded in loop\nfor (const order of orders) {\n // 20 lines of validation logic\n // 15 lines of processing logic\n // 10 lines of notification logic\n}\n\n// GOOD: Extracted to named methods\nfor (const order of orders) {\n validateOrder(order);\n processOrderItems(order);\n sendNotifications(order);\n}\n\\`\\`\\`\n\n### Pattern 2: Try-Catch Wrapper for Exception Handling\n\\`\\`\\`typescript\n// GOOD: Separates success path from error handling\nasync function handleRequest(req: Request): Promise<Response> {\n try {\n return await executeRequest(req);\n } catch (err: unknown) {\n const error = toError(err);\n return createErrorResponse(error);\n }\n}\n\\`\\`\\`\n\n### Pattern 3: Sequential Method Calls (Table of Contents)\n\\`\\`\\`typescript\n// GOOD: Self-documenting steps\nfunction processOrder(order: Order): void {\n validateOrderData(order);\n calculateTotals(order);\n applyDiscounts(order);\n processPayment(order);\n updateInventory(order);\n sendConfirmation(order);\n}\n\\`\\`\\`\n\n### Pattern 4: Separate Data Object Creation\n\\`\\`\\`typescript\n// BAD: 15 lines of inline object creation\ndoSomething({ field1: ..., field2: ..., field3: ..., /* 15 more fields */ });\n\n// GOOD: Extract to factory method\nconst request = createRequestObject(data);\ndoSomething(request);\n\\`\\`\\`\n\n### Pattern 5: Extract Inline Logic to Named Functions\n\\`\\`\\`typescript\n// BAD: Complex inline logic\nif (user.role === 'admin' && user.permissions.includes('write') && !user.suspended) {\n // 30 lines of admin logic\n}\n\n// GOOD: Extract to named methods\nif (isAdminWithWriteAccess(user)) {\n performAdminOperation(user);\n}\n\\`\\`\\`\n\n## AI Agent Action Steps\n\n1. **IDENTIFY** the long method in the error message\n2. **READ** the method to understand its logical sections\n3. **EXTRACT** logical units into separate methods with descriptive names\n4. **REPLACE** inline code with method calls\n5. **VERIFY** each extracted method is <70 lines\n6. **TEST** that functionality remains unchanged\n\n## Examples of \"Logical Units\" to Extract\n- Validation logic -> \\`validateX()\\`\n- Data transformation -> \\`transformXToY()\\`\n- API calls -> \\`fetchXFromApi()\\`\n- Object creation -> \\`createX()\\`\n- Loop bodies -> \\`processItem()\\`\n- Error handling -> \\`handleXError()\\`\n\nRemember: Methods should read like a table of contents. Each line should be a \"chapter title\" (method call) that describes what happens, not how it happens.\n`;\n\n// Module-level flag to prevent redundant file creation\nlet methodDocCreated = false;\n\nfunction getWorkspaceRoot(context: Rule.RuleContext): string {\n const filename = context.filename || context.getFilename();\n let dir = path.dirname(filename);\n\n while (dir !== path.dirname(dir)) {\n const pkgPath = path.join(dir, 'package.json');\n if (fs.existsSync(pkgPath)) {\n try {\n const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));\n if (pkg.workspaces || pkg.name === 'webpieces-ts') {\n return dir;\n }\n } catch (err: unknown) {\n //const error = toError(err);\n void err;\n }\n }\n dir = path.dirname(dir);\n }\n return process.cwd();\n}\n\nfunction ensureDocFile(docPath: string, content: string): boolean {\n try {\n fs.mkdirSync(path.dirname(docPath), { recursive: true });\n fs.writeFileSync(docPath, content, 'utf-8');\n return true;\n } catch (err: unknown) {\n const error = toError(err);\n console.warn(`[webpieces] Could not create doc file: ${docPath}`, error);\n return false;\n }\n}\n\nfunction ensureMethodDoc(context: Rule.RuleContext): void {\n const workspaceRoot = getWorkspaceRoot(context);\n const docPath = path.join(workspaceRoot, 'tmp', 'webpieces', 'webpieces.methods.md');\n\n // Check if file exists AND flag is true - if both, skip\n if (methodDocCreated && fs.existsSync(docPath)) return;\n\n if (ensureDocFile(docPath, METHOD_DOC_CONTENT)) {\n methodDocCreated = true;\n }\n}\n\nfunction getFunctionName(funcNode: FunctionNode): string {\n if (funcNode.type === 'FunctionDeclaration' && funcNode.id?.name) {\n return funcNode.id.name;\n }\n if (funcNode.type === 'FunctionExpression' && funcNode.id?.name) {\n return funcNode.id.name;\n }\n return 'anonymous';\n}\n\nfunction reportTooLong(ctx: CheckerContext, node: any, name: string, lineCount: number): void {\n ctx.context.report({\n node,\n messageId: 'tooLong',\n data: {\n name,\n actual: String(lineCount),\n max: String(ctx.maxLines),\n },\n });\n}\n\nfunction checkFunctionNode(ctx: CheckerContext, node: any): void {\n ensureMethodDoc(ctx.context);\n const funcNode = node as FunctionNode;\n\n // Skip function expressions inside method definitions\n if (funcNode.type === 'FunctionExpression' && funcNode['parent']?.type === 'MethodDefinition') {\n return;\n }\n\n if (!funcNode.loc || !funcNode.body) return;\n\n const name = getFunctionName(funcNode);\n const lineCount = funcNode.loc.end.line - funcNode.loc.start.line + 1;\n\n if (lineCount > ctx.maxLines) {\n reportTooLong(ctx, funcNode, name, lineCount);\n }\n}\n\nfunction checkMethodNode(ctx: CheckerContext, node: any): void {\n ensureMethodDoc(ctx.context);\n\n if (!node.loc || !node.value) return;\n\n const name = node.key?.name || 'anonymous';\n const lineCount = node.loc.end.line - node.loc.start.line + 1;\n\n if (lineCount > ctx.maxLines) {\n reportTooLong(ctx, node, name, lineCount);\n }\n}\n\nconst rule: Rule.RuleModule = {\n meta: {\n type: 'suggestion',\n docs: {\n description: 'Enforce maximum method length',\n category: 'Best Practices',\n recommended: false,\n url: 'https://github.com/deanhiller/webpieces-ts',\n },\n messages: {\n tooLong:\n 'AI Agent: READ tmp/webpieces/webpieces.methods.md for fix instructions. Method \"{{name}}\" has {{actual}} lines (max: {{max}})',\n },\n fixable: undefined,\n schema: [\n {\n type: 'object',\n properties: {\n max: {\n type: 'integer',\n minimum: 1,\n },\n },\n additionalProperties: false,\n },\n ],\n },\n\n create(context: Rule.RuleContext): Rule.RuleListener {\n const options = context.options[0] as MethodLinesOptions | undefined;\n const ctx: CheckerContext = { context, maxLines: options?.max ?? 70 };\n\n return {\n FunctionDeclaration: (node) => checkFunctionNode(ctx, node),\n FunctionExpression: (node) => checkFunctionNode(ctx, node),\n ArrowFunctionExpression: (node) => checkFunctionNode(ctx, node),\n MethodDefinition: (node) => checkMethodNode(ctx, node),\n };\n },\n};\n\nexport = rule;\n"]}
@@ -1,287 +0,0 @@
1
- /**
2
- * ESLint rule to enforce maximum method length
3
- *
4
- * Enforces a configurable maximum line count for methods, functions, and arrow functions.
5
- * Default: 70 lines
6
- *
7
- * Configuration:
8
- * '@webpieces/max-method-lines': ['error', { max: 70 }]
9
- */
10
-
11
- import type { Rule } from 'eslint';
12
- import * as fs from 'fs';
13
- import * as path from 'path';
14
- import { toError } from '../../toError';
15
-
16
- interface MethodLinesOptions {
17
- max: number;
18
- }
19
-
20
- interface FunctionNode {
21
- type:
22
- | 'FunctionDeclaration'
23
- | 'FunctionExpression'
24
- | 'ArrowFunctionExpression'
25
- | 'MethodDefinition';
26
- body?: any;
27
- loc?: {
28
- start: { line: number };
29
- end: { line: number };
30
- };
31
- key?: {
32
- name?: string;
33
- };
34
- id?: {
35
- name?: string;
36
- };
37
- [key: string]: any;
38
- }
39
-
40
- interface CheckerContext {
41
- context: Rule.RuleContext;
42
- maxLines: number;
43
- }
44
-
45
- const METHOD_DOC_CONTENT = `# AI Agent Instructions: Method Too Long
46
-
47
- **READ THIS FILE to fix methods that are too long**
48
-
49
- ## Core Principle
50
- Every method should read like a TABLE OF CONTENTS of a book.
51
- - Each method call is a "chapter"
52
- - When you dive into a method, you find another table of contents
53
- - Keeping methods under 70 lines is achievable with proper extraction
54
-
55
- ## Command: Extract Code into Named Methods
56
-
57
- ### Pattern 1: Extract Loop Bodies
58
- \`\`\`typescript
59
- // BAD: 50 lines embedded in loop
60
- for (const order of orders) {
61
- // 20 lines of validation logic
62
- // 15 lines of processing logic
63
- // 10 lines of notification logic
64
- }
65
-
66
- // GOOD: Extracted to named methods
67
- for (const order of orders) {
68
- validateOrder(order);
69
- processOrderItems(order);
70
- sendNotifications(order);
71
- }
72
- \`\`\`
73
-
74
- ### Pattern 2: Try-Catch Wrapper for Exception Handling
75
- \`\`\`typescript
76
- // GOOD: Separates success path from error handling
77
- async function handleRequest(req: Request): Promise<Response> {
78
- try {
79
- return await executeRequest(req);
80
- } catch (err: unknown) {
81
- const error = toError(err);
82
- return createErrorResponse(error);
83
- }
84
- }
85
- \`\`\`
86
-
87
- ### Pattern 3: Sequential Method Calls (Table of Contents)
88
- \`\`\`typescript
89
- // GOOD: Self-documenting steps
90
- function processOrder(order: Order): void {
91
- validateOrderData(order);
92
- calculateTotals(order);
93
- applyDiscounts(order);
94
- processPayment(order);
95
- updateInventory(order);
96
- sendConfirmation(order);
97
- }
98
- \`\`\`
99
-
100
- ### Pattern 4: Separate Data Object Creation
101
- \`\`\`typescript
102
- // BAD: 15 lines of inline object creation
103
- doSomething({ field1: ..., field2: ..., field3: ..., /* 15 more fields */ });
104
-
105
- // GOOD: Extract to factory method
106
- const request = createRequestObject(data);
107
- doSomething(request);
108
- \`\`\`
109
-
110
- ### Pattern 5: Extract Inline Logic to Named Functions
111
- \`\`\`typescript
112
- // BAD: Complex inline logic
113
- if (user.role === 'admin' && user.permissions.includes('write') && !user.suspended) {
114
- // 30 lines of admin logic
115
- }
116
-
117
- // GOOD: Extract to named methods
118
- if (isAdminWithWriteAccess(user)) {
119
- performAdminOperation(user);
120
- }
121
- \`\`\`
122
-
123
- ## AI Agent Action Steps
124
-
125
- 1. **IDENTIFY** the long method in the error message
126
- 2. **READ** the method to understand its logical sections
127
- 3. **EXTRACT** logical units into separate methods with descriptive names
128
- 4. **REPLACE** inline code with method calls
129
- 5. **VERIFY** each extracted method is <70 lines
130
- 6. **TEST** that functionality remains unchanged
131
-
132
- ## Examples of "Logical Units" to Extract
133
- - Validation logic -> \`validateX()\`
134
- - Data transformation -> \`transformXToY()\`
135
- - API calls -> \`fetchXFromApi()\`
136
- - Object creation -> \`createX()\`
137
- - Loop bodies -> \`processItem()\`
138
- - Error handling -> \`handleXError()\`
139
-
140
- Remember: Methods should read like a table of contents. Each line should be a "chapter title" (method call) that describes what happens, not how it happens.
141
- `;
142
-
143
- // Module-level flag to prevent redundant file creation
144
- let methodDocCreated = false;
145
-
146
- function getWorkspaceRoot(context: Rule.RuleContext): string {
147
- const filename = context.filename || context.getFilename();
148
- let dir = path.dirname(filename);
149
-
150
- while (dir !== path.dirname(dir)) {
151
- const pkgPath = path.join(dir, 'package.json');
152
- if (fs.existsSync(pkgPath)) {
153
- try {
154
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
155
- if (pkg.workspaces || pkg.name === 'webpieces-ts') {
156
- return dir;
157
- }
158
- } catch (err: unknown) {
159
- //const error = toError(err);
160
- void err;
161
- }
162
- }
163
- dir = path.dirname(dir);
164
- }
165
- return process.cwd();
166
- }
167
-
168
- function ensureDocFile(docPath: string, content: string): boolean {
169
- try {
170
- fs.mkdirSync(path.dirname(docPath), { recursive: true });
171
- fs.writeFileSync(docPath, content, 'utf-8');
172
- return true;
173
- } catch (err: unknown) {
174
- const error = toError(err);
175
- console.warn(`[webpieces] Could not create doc file: ${docPath}`, error);
176
- return false;
177
- }
178
- }
179
-
180
- function ensureMethodDoc(context: Rule.RuleContext): void {
181
- const workspaceRoot = getWorkspaceRoot(context);
182
- const docPath = path.join(workspaceRoot, 'tmp', 'webpieces', 'webpieces.methods.md');
183
-
184
- // Check if file exists AND flag is true - if both, skip
185
- if (methodDocCreated && fs.existsSync(docPath)) return;
186
-
187
- if (ensureDocFile(docPath, METHOD_DOC_CONTENT)) {
188
- methodDocCreated = true;
189
- }
190
- }
191
-
192
- function getFunctionName(funcNode: FunctionNode): string {
193
- if (funcNode.type === 'FunctionDeclaration' && funcNode.id?.name) {
194
- return funcNode.id.name;
195
- }
196
- if (funcNode.type === 'FunctionExpression' && funcNode.id?.name) {
197
- return funcNode.id.name;
198
- }
199
- return 'anonymous';
200
- }
201
-
202
- function reportTooLong(ctx: CheckerContext, node: any, name: string, lineCount: number): void {
203
- ctx.context.report({
204
- node,
205
- messageId: 'tooLong',
206
- data: {
207
- name,
208
- actual: String(lineCount),
209
- max: String(ctx.maxLines),
210
- },
211
- });
212
- }
213
-
214
- function checkFunctionNode(ctx: CheckerContext, node: any): void {
215
- ensureMethodDoc(ctx.context);
216
- const funcNode = node as FunctionNode;
217
-
218
- // Skip function expressions inside method definitions
219
- if (funcNode.type === 'FunctionExpression' && funcNode['parent']?.type === 'MethodDefinition') {
220
- return;
221
- }
222
-
223
- if (!funcNode.loc || !funcNode.body) return;
224
-
225
- const name = getFunctionName(funcNode);
226
- const lineCount = funcNode.loc.end.line - funcNode.loc.start.line + 1;
227
-
228
- if (lineCount > ctx.maxLines) {
229
- reportTooLong(ctx, funcNode, name, lineCount);
230
- }
231
- }
232
-
233
- function checkMethodNode(ctx: CheckerContext, node: any): void {
234
- ensureMethodDoc(ctx.context);
235
-
236
- if (!node.loc || !node.value) return;
237
-
238
- const name = node.key?.name || 'anonymous';
239
- const lineCount = node.loc.end.line - node.loc.start.line + 1;
240
-
241
- if (lineCount > ctx.maxLines) {
242
- reportTooLong(ctx, node, name, lineCount);
243
- }
244
- }
245
-
246
- const rule: Rule.RuleModule = {
247
- meta: {
248
- type: 'suggestion',
249
- docs: {
250
- description: 'Enforce maximum method length',
251
- category: 'Best Practices',
252
- recommended: false,
253
- url: 'https://github.com/deanhiller/webpieces-ts',
254
- },
255
- messages: {
256
- tooLong:
257
- 'AI Agent: READ tmp/webpieces/webpieces.methods.md for fix instructions. Method "{{name}}" has {{actual}} lines (max: {{max}})',
258
- },
259
- fixable: undefined,
260
- schema: [
261
- {
262
- type: 'object',
263
- properties: {
264
- max: {
265
- type: 'integer',
266
- minimum: 1,
267
- },
268
- },
269
- additionalProperties: false,
270
- },
271
- ],
272
- },
273
-
274
- create(context: Rule.RuleContext): Rule.RuleListener {
275
- const options = context.options[0] as MethodLinesOptions | undefined;
276
- const ctx: CheckerContext = { context, maxLines: options?.max ?? 70 };
277
-
278
- return {
279
- FunctionDeclaration: (node) => checkFunctionNode(ctx, node),
280
- FunctionExpression: (node) => checkFunctionNode(ctx, node),
281
- ArrowFunctionExpression: (node) => checkFunctionNode(ctx, node),
282
- MethodDefinition: (node) => checkMethodNode(ctx, node),
283
- };
284
- },
285
- };
286
-
287
- export = rule;
@@ -1,22 +0,0 @@
1
- /**
2
- * ESLint rule to discourage try-catch blocks outside test files
3
- *
4
- * Works alongside catch-error-pattern rule:
5
- * - catch-error-pattern: Enforces HOW to handle exceptions (with toError())
6
- * - no-unmanaged-exceptions: Enforces WHERE try-catch is allowed (tests only by default)
7
- *
8
- * Philosophy: Exceptions should bubble to global error handlers where they are logged
9
- * with traceId and stored for debugging via /debugLocal and /debugCloud endpoints.
10
- * Local try-catch blocks break this architecture and create blind spots in production.
11
- *
12
- * Auto-allowed in:
13
- * - Test files (.test.ts, .spec.ts, __tests__/)
14
- *
15
- * Requires eslint-disable comment in:
16
- * - Retry loops with exponential backoff
17
- * - Batch processing where partial failure is expected
18
- * - Resource cleanup (with approval)
19
- */
20
- import type { Rule } from 'eslint';
21
- declare const rule: Rule.RuleModule;
22
- export = rule;