@futdevpro/dynamo-eslint 1.15.20 → 1.15.22

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.
@@ -52,7 +52,7 @@ After code changes:
52
52
  1. Request specification from user
53
53
  2. If specification not provided:
54
54
  - Read [documentation rules](documentation_writing_rules.md)
55
- - Create specification in /documentations/specifications
55
+ - Create specification in /fdp-documentations/specifications
56
56
  - Get approval before continuing
57
57
  3. If specification provided:
58
58
  - Review and ensure it's complete
@@ -83,7 +83,7 @@ After code changes:
83
83
  - No sensitive information in commits
84
84
 
85
85
  ## Project Guidelines
86
- - Read and use [FDP Packages](../../documentations/specifications/packages.md)
86
+ - Read and use [FDP Packages](../../fdp-documentations/specifications/packages.md)
87
87
  - Maintain consistent structure
88
88
  - Follow project documentation
89
89
 
@@ -14,7 +14,7 @@
14
14
  - repository url: https://github.com/futdevpro/documentations.git
15
15
  - stack: markdown
16
16
  - in documentations, you should find ALL informations about the development, the company, and the projects
17
- - you MUST follow the rules in the [ai-directives](../../documentations/guidelines/ai-agent/ai_directives.md)
17
+ - you MUST follow the rules in the [ai-directives](../../fdp-documentations/guidelines/ai-agent/ai_directives.md)
18
18
 
19
19
  - FDP Auth Service
20
20
  - short name: auth
@@ -82,7 +82,7 @@
82
82
  - import: '@futdevpro/ngx-dynamo-models';
83
83
  - documentation language: English
84
84
 
85
- - [Dynamo NGX](../../documentations/specifications/dynamo-packages/dynamo-ngx/dynamo-ngx.md)
85
+ - [Dynamo NGX](../../fdp-documentations/specifications/dynamo-packages/dynamo-ngx/dynamo-ngx.md)
86
86
  - short name: ngx
87
87
  - route: NPM-packages/dynamo-ngx
88
88
  - repository url: https://github.com/futdevpro/dynamo-ngx.git
@@ -102,7 +102,7 @@
102
102
  - import: '@futdevpro/fsm-dynamo';
103
103
  - documentation language: English
104
104
 
105
- - [Dynamo CLI](../../documentations/specifications/dynamo-packages/dynamo-cli/dynamo-cli.md)
105
+ - [Dynamo CLI](../../fdp-documentations/specifications/dynamo-packages/dynamo-cli/dynamo-cli.md)
106
106
  - short name: cli
107
107
  - route: NPM-packages/dynamo-cli
108
108
  - repository url: https://github.com/futdevpro/dynamo-cli.git
@@ -157,4 +157,4 @@
157
157
 
158
158
  ATTENTION AI AGENT: This is the primary rule-set you must follow. Additional critical operational guidelines and contextual information are available in the following documentation:
159
159
 
160
- [AI Directives](../../documentations/guidelines/ai-agent/ai_directives.md)
160
+ [AI Directives](../../fdp-documentations/guidelines/ai-agent/ai_directives.md)
@@ -151,7 +151,7 @@
151
151
  },
152
152
  {
153
153
  "label": "pipeline-report",
154
- "command": "fdp pipeline-report --report ./logs/cicd-pipeline/cicd-report.json --overseer-url $OVERSEER_URL --overseer-secret $OVERSEER_SECRET_KEY --branch $GITHUB_REF_NAME",
154
+ "command": "fdp pipeline-report --report ./logs/cicd-pipeline/cicd-report.json --overseer-secret $OVERSEER_SECRET_KEY --branch $GITHUB_REF_NAME",
155
155
  "fatal": false,
156
156
  "always": true,
157
157
  "discord": {
@@ -160,13 +160,13 @@
160
160
  },
161
161
  "condition": {
162
162
  "envSet": [
163
- "OVERSEER_URL"
163
+ "OVERSEER_SECRET_KEY"
164
164
  ]
165
165
  }
166
166
  },
167
167
  {
168
168
  "label": "discord-result",
169
- "command": "fdp pipeline-notify --report ./logs/cicd-pipeline/cicd-report.json --config ./pipeline.cicd.config.json --app-name Dynamo-ESLint --app-emoji 🔧 --webhook-id $DISCORD_WEBHOOK_ID --webhook-token $DISCORD_WEBHOOK_TOKEN --overseer-url $OVERSEER_DASHBOARD_URL",
169
+ "command": "fdp pipeline-notify --report ./logs/cicd-pipeline/cicd-report.json --config ./pipeline.cicd.config.json --app-name Dynamo-ESLint --app-emoji 🔧 --webhook-id $DISCORD_WEBHOOK_ID --webhook-token $DISCORD_WEBHOOK_TOKEN",
170
170
  "fatal": false,
171
171
  "retryOnFail": 2,
172
172
  "retryDelaySec": 5,
@@ -1 +1 @@
1
- {"version":3,"file":"prefer-interface-over-duplicate-types.d.ts","sourceRoot":"","sources":["../../../src/plugin/rules/prefer-interface-over-duplicate-types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAY9B,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA8QhB,CAAC;AAEF,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"prefer-interface-over-duplicate-types.d.ts","sourceRoot":"","sources":["../../../src/plugin/rules/prefer-interface-over-duplicate-types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAY9B,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,UA2ShB,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -22,13 +22,12 @@ const rule = {
22
22
  ],
23
23
  messages: {
24
24
  preferInterface: 'Object type used {{count}} times. Consider creating interface "{{interfaceName}}"}}',
25
- extractInterface: 'Extract to interface "{{interfaceName}}" (⚠️ review the generated types — complex/union/qualified types may need manual correction).',
26
25
  },
27
- // BFR-ADVENTOR-009: az auto-fixer a LOSSY normalizált signature-stringből rekonstruálja az interface-törzset
28
- // (`reference`/`complex`/`union` literálok kerülnek a generált kódba → érvénytelen TS, build-törés `--fix`-re).
29
- // Amíg a fixer forrás-szöveg-megőrzőre nincs átírva, SUGGESTION-ként fut (nem `fixable:'code'`) → a bulk
30
- // `eslint --fix` NEM futtatja automatikusan; csak explicit apply-ra, a fenti figyelmeztetéssel.
31
- hasSuggestions: true,
26
+ // BFR-ADVENTOR-009 (2. lépcső): a fixer forrás-szöveg-megőrzőre átírva (`sourceCode.getText` per property)
27
+ // → a komplex/union/qualified/function típusok EXAKT megőrződnek, a generált interface ÉRVÉNYES TS. Ezért
28
+ // az auto-fix (`fixable:'code'`) VISSZA — a bulk `eslint --fix` biztonságosan futtathatja (nem generál
29
+ // többé `reference`/`complex` literál-hibát). (1. lépcső: suggestion-degrade, most feloldva.)
30
+ fixable: 'code',
32
31
  },
33
32
  create(context) {
34
33
  const options = context.options[0] || {};
@@ -144,6 +143,40 @@ const rule = {
144
143
  }
145
144
  return name;
146
145
  }
146
+ /**
147
+ * BFR-ADVENTOR-009 (2. lépcső): az interface-törzs a FORRÁS-SZÖVEGBŐL épül (sourceCode.getText per
148
+ * member), NEM a lossy normalizált signature-ből → a komplex/union/qualified/function típusok EXAKT
149
+ * megőrződnek (a korábbi `reference`/`complex`/`union` literál-hibák megszűnnek). A `getText` az eredeti
150
+ * property-szöveget adja (pl. `onError: (e: Error) => void`); a záró `;`/`,`-t normalizáljuk.
151
+ */
152
+ function buildInterfaceBody(node) {
153
+ const members = Array.isArray(node?.members) ? node.members : [];
154
+ return members
155
+ .map((member) => {
156
+ const text = sourceCode.getText(member).trim().replace(/[;,]\s*$/, '');
157
+ return ` ${text};`;
158
+ })
159
+ .join('\n');
160
+ }
161
+ /**
162
+ * Beszédes interface-név a property-kulcsokból (BFR-ADVENTOR-009): a nem-beszédes, ütköző
163
+ * `GeneratedInterfaceN` helyett az első 1-3 kulcsból PascalCase + `Params_Interface` (a projekt-konvenció).
164
+ */
165
+ function deriveInterfaceName(node) {
166
+ const members = Array.isArray(node?.members) ? node.members : [];
167
+ const keys = members
168
+ .filter((m) => m.type === 'TSPropertySignature')
169
+ .map((m) => String(m.key?.name ?? m.key?.value ?? ''))
170
+ .filter((k) => !!k)
171
+ .slice(0, 3);
172
+ if (!keys.length) {
173
+ return 'Generated_Interface';
174
+ }
175
+ const pascal = keys
176
+ .map((k) => k.charAt(0).toUpperCase() + k.slice(1))
177
+ .join('');
178
+ return `${pascal}_Interface`;
179
+ }
147
180
  return {
148
181
  TSTypeLiteral(node, _context, _sourceCode) {
149
182
  try {
@@ -169,7 +202,10 @@ const rule = {
169
202
  // Process all collected type usages
170
203
  for (const [signature, usages] of typeUsages) {
171
204
  if (usages.length >= threshold) {
172
- const interfaceName = generateUniqueInterfaceName(generateInterfaceName(signature, usages.length));
205
+ // beszédes név a property-kulcsokból (ütközés-mentesre pontosítva)
206
+ const interfaceName = generateUniqueInterfaceName(deriveInterfaceName(usages[0].node));
207
+ // a törzs a FORRÁS-SZÖVEGBŐL (getText) — a komplex/union/qualified típusok EXAKT megőrződnek
208
+ const interfaceBody = buildInterfaceBody(usages[0].node);
173
209
  // Report on each usage
174
210
  for (const usage of usages) {
175
211
  context.report({
@@ -179,51 +215,40 @@ const rule = {
179
215
  count: usages.length.toString(),
180
216
  interfaceName,
181
217
  },
182
- suggest: [{
183
- messageId: 'extractInterface',
184
- data: { interfaceName },
185
- fix(fixer) {
186
- try {
187
- // Generate interface declaration
188
- const properties = signature.split(';').map(prop => {
189
- const [key, type] = prop.split(':');
190
- return ` ${key}: ${type};`;
191
- }).join('\n');
192
- const interfaceDeclaration = `interface ${interfaceName} {\n${properties}\n}`;
193
- // Find insertion point (after imports, before other code)
194
- const firstNode = sourceCode.ast.body[0];
195
- let insertPosition = 0;
196
- if (firstNode && firstNode.type === 'ImportDeclaration') {
197
- // Find last import
198
- let lastImport = firstNode;
199
- for (const node of sourceCode.ast.body) {
200
- if (node.type === 'ImportDeclaration') {
201
- lastImport = node;
202
- }
203
- else {
204
- break;
205
- }
206
- }
207
- insertPosition = lastImport.range[1];
218
+ fix(fixer) {
219
+ try {
220
+ const interfaceDeclaration = `interface ${interfaceName} {\n${interfaceBody}\n}`;
221
+ // Find insertion point (after imports, before other code)
222
+ const firstNode = sourceCode.ast.body[0];
223
+ let insertPosition = 0;
224
+ if (firstNode && firstNode.type === 'ImportDeclaration') {
225
+ // Find last import
226
+ let lastImport = firstNode;
227
+ for (const node of sourceCode.ast.body) {
228
+ if (node.type === 'ImportDeclaration') {
229
+ lastImport = node;
208
230
  }
209
- // Add interface declaration
210
- const fixes = [
211
- fixer.insertTextAfterRange([insertPosition, insertPosition], `\n\n${interfaceDeclaration}\n`),
212
- ];
213
- // Replace all usages with interface reference
214
- for (const usage of usages) {
215
- const nodeText = sourceCode.getText(usage.node);
216
- const replacement = interfaceName;
217
- fixes.push(fixer.replaceText(usage.node, replacement));
231
+ else {
232
+ break;
218
233
  }
219
- return fixes;
220
234
  }
221
- catch (fixError) {
222
- console.error('[prefer-interface-over-duplicate-types] Error in fix function:', fixError);
223
- return null;
224
- }
225
- },
226
- }],
235
+ insertPosition = lastImport.range[1];
236
+ }
237
+ // Add interface declaration
238
+ const fixes = [
239
+ fixer.insertTextAfterRange([insertPosition, insertPosition], `\n\n${interfaceDeclaration}\n`),
240
+ ];
241
+ // Replace all usages with interface reference
242
+ for (const usage of usages) {
243
+ fixes.push(fixer.replaceText(usage.node, interfaceName));
244
+ }
245
+ return fixes;
246
+ }
247
+ catch (fixError) {
248
+ console.error('[prefer-interface-over-duplicate-types] Error in fix function:', fixError);
249
+ return null;
250
+ }
251
+ },
227
252
  });
228
253
  }
229
254
  }
@@ -1 +1 @@
1
- {"version":3,"file":"prefer-interface-over-duplicate-types.js","sourceRoot":"","sources":["../../../src/plugin/rules/prefer-interface-over-duplicate-types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"prefer-interface-over-duplicate-types.js","sourceRoot":"","sources":["../../../src/plugin/rules/prefer-interface-over-duplicate-types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@futdevpro/dynamo-eslint",
3
- "version": "1.15.20",
3
+ "version": "1.15.22",
4
4
  "description": "Shared ESLint configs, Dynamo-powered plugin and validators for FutDevPro stacks",
5
5
  "author": "Future Development Program Ltd.",
6
6
  "license": "ISC",
@@ -4,10 +4,8 @@ describe('| prefer-interface-over-duplicate-types', () => {
4
4
  it('| should be a valid ESLint rule', () => {
5
5
  expect(preferInterfaceRule.meta?.type).toBe('suggestion');
6
6
  expect(preferInterfaceRule.meta?.docs?.description).toContain('Suggest creating interfaces');
7
- // BFR-ADVENTOR-009: a lossy-signature fixer degradálva suggestion-né (nem auto-`--fix`) → hasSuggestions,
8
- // hogy a bulk `eslint --fix` ne generálhasson érvénytelen kódot (a teljes forrás-megőrző rewrite külön slice).
9
- expect(preferInterfaceRule.meta?.fixable).toBeUndefined();
10
- expect(preferInterfaceRule.meta?.hasSuggestions).toBe(true);
7
+ // BFR-ADVENTOR-009 (2. lépcső): a forrás-megőrző fixer VISSZAKAPCSOLVA auto-fix-re (érvényes kódot ad).
8
+ expect(preferInterfaceRule.meta?.fixable).toBe('code');
11
9
  });
12
10
 
13
11
  it('| should have create function that returns visitor object', () => {
@@ -241,17 +239,35 @@ describe('| prefer-interface-over-duplicate-types', () => {
241
239
  expect(reportCalled).toBe(true);
242
240
  });
243
241
 
244
- it('| should provide suggestion-based fix functionality (BFR-ADVENTOR-009: degraded from auto-fix)', () => {
242
+ it('| auto-fix a FORRÁS-SZÖVEGBŐL épít (BFR-ADVENTOR-009 2. lépcső: komplex típus megőrizve, nem `reference`)', () => {
243
+ // egy komplex property-t szimulálunk: a member getText-je egy function-type — a régi lossy fixer
244
+ // ezt `reference`/`complex`-re redukálta (érvénytelen TS); az új fixer EXAKT megőrzi.
245
+ const complexMember: any = {
246
+ type: 'TSPropertySignature', key: { name: 'onError' },
247
+ };
248
+ const numberMember: any = {
249
+ type: 'TSPropertySignature', key: { name: 'count' },
250
+ };
251
+ const memberTexts: Map<any, string> = new Map([
252
+ [ complexMember, 'onError: (e: Error) => void' ],
253
+ [ numberMember, 'count: number' ],
254
+ ]);
255
+
256
+ let insertedText: string = '';
257
+ const mockFixer: any = {
258
+ insertTextAfterRange: (_range: unknown, text: string): unknown => { insertedText = text; return {}; },
259
+ replaceText: (): unknown => ({}),
260
+ };
261
+
245
262
  const mockContext = {
246
263
  report: (options: any) => {
247
- // a fixer mostantól suggestion (nem auto-`--fix`), így a bulk `--fix` nem generálhat érvénytelen kódot
248
- expect(options.fix).toBeUndefined();
249
- expect(Array.isArray(options.suggest)).toBe(true);
250
- expect(typeof options.suggest[0].fix).toBe('function');
264
+ expect(typeof options.fix).toBe('function'); // auto-fix VISSZA (nem suggestion)
265
+ options.fix(mockFixer);
251
266
  },
252
267
  options: [{ threshold: 2 }],
253
268
  sourceCode: {
254
- getText: () => '{ name: string; age: number }',
269
+ // a body-generátor a member-node getText-jét használja; a normalizáló getTypeString nem fut a fixerben
270
+ getText: (n: any): string => memberTexts.get(n) ?? '{ onError: fn; count: number }',
255
271
  getScope: () => ({ variables: [] }),
256
272
  ast: { body: [] },
257
273
  },
@@ -262,14 +278,23 @@ describe('| prefer-interface-over-duplicate-types', () => {
262
278
  const mockNode = {
263
279
  type: 'TSTypeLiteral',
264
280
  members: [
265
- { type: 'TSPropertySignature', key: { name: 'name' }, typeAnnotation: { typeAnnotation: { type: 'TSStringKeyword' } } },
266
- { type: 'TSPropertySignature', key: { name: 'age' }, typeAnnotation: { typeAnnotation: { type: 'TSNumberKeyword' } } },
281
+ { ...complexMember, typeAnnotation: { typeAnnotation: { type: 'TSFunctionType' } } },
282
+ { ...numberMember, typeAnnotation: { typeAnnotation: { type: 'TSNumberKeyword' } } },
267
283
  ],
268
284
  } as any;
285
+ // a getText a fenti two member-referenciákat kapja — a mockNode.members MÁSOK, ezért a getText-map
286
+ // kulcsait használjuk a mockNode.members-ként:
287
+ mockNode.members = [ complexMember, numberMember ];
269
288
 
270
289
  rule.TSTypeLiteral(mockNode);
271
290
  rule.TSTypeLiteral(mockNode);
272
291
  rule['Program:exit']({} as any);
292
+
293
+ // a generált interface a MEGŐRZÖTT function-type-ot tartalmazza, NEM `reference`/`complex`-et
294
+ expect(insertedText).toContain('onError: (e: Error) => void;');
295
+ expect(insertedText).toContain('count: number;');
296
+ expect(insertedText).not.toContain('reference');
297
+ expect(insertedText).not.toContain('complex');
273
298
  });
274
299
 
275
300
  it('| should handle default threshold when no options provided', () => {
@@ -32,13 +32,12 @@ const rule: Rule.RuleModule = {
32
32
  ],
33
33
  messages: {
34
34
  preferInterface: 'Object type used {{count}} times. Consider creating interface "{{interfaceName}}"}}',
35
- extractInterface: 'Extract to interface "{{interfaceName}}" (⚠️ review the generated types — complex/union/qualified types may need manual correction).',
36
35
  },
37
- // BFR-ADVENTOR-009: az auto-fixer a LOSSY normalizált signature-stringből rekonstruálja az interface-törzset
38
- // (`reference`/`complex`/`union` literálok kerülnek a generált kódba → érvénytelen TS, build-törés `--fix`-re).
39
- // Amíg a fixer forrás-szöveg-megőrzőre nincs átírva, SUGGESTION-ként fut (nem `fixable:'code'`) → a bulk
40
- // `eslint --fix` NEM futtatja automatikusan; csak explicit apply-ra, a fenti figyelmeztetéssel.
41
- hasSuggestions: true,
36
+ // BFR-ADVENTOR-009 (2. lépcső): a fixer forrás-szöveg-megőrzőre átírva (`sourceCode.getText` per property)
37
+ // → a komplex/union/qualified/function típusok EXAKT megőrződnek, a generált interface ÉRVÉNYES TS. Ezért
38
+ // az auto-fix (`fixable:'code'`) VISSZA — a bulk `eslint --fix` biztonságosan futtathatja (nem generál
39
+ // többé `reference`/`complex` literál-hibát). (1. lépcső: suggestion-degrade, most feloldva.)
40
+ fixable: 'code',
42
41
  },
43
42
  create(context) {
44
43
  const options: RuleOptions = context.options[0] || {};
@@ -164,15 +163,55 @@ const rule: Rule.RuleModule = {
164
163
  function generateUniqueInterfaceName(baseName: string): string {
165
164
  let name = baseName;
166
165
  let counter = 1;
167
-
166
+
168
167
  while (isNameConflict(name)) {
169
168
  name = `${baseName}${counter}`;
170
169
  counter++;
171
170
  }
172
-
171
+
173
172
  return name;
174
173
  }
175
174
 
175
+ /**
176
+ * BFR-ADVENTOR-009 (2. lépcső): az interface-törzs a FORRÁS-SZÖVEGBŐL épül (sourceCode.getText per
177
+ * member), NEM a lossy normalizált signature-ből → a komplex/union/qualified/function típusok EXAKT
178
+ * megőrződnek (a korábbi `reference`/`complex`/`union` literál-hibák megszűnnek). A `getText` az eredeti
179
+ * property-szöveget adja (pl. `onError: (e: Error) => void`); a záró `;`/`,`-t normalizáljuk.
180
+ */
181
+ function buildInterfaceBody(node: any): string {
182
+ const members: any[] = Array.isArray(node?.members) ? node.members : [];
183
+
184
+ return members
185
+ .map((member: any): string => {
186
+ const text: string = sourceCode.getText(member).trim().replace(/[;,]\s*$/, '');
187
+ return ` ${text};`;
188
+ })
189
+ .join('\n');
190
+ }
191
+
192
+ /**
193
+ * Beszédes interface-név a property-kulcsokból (BFR-ADVENTOR-009): a nem-beszédes, ütköző
194
+ * `GeneratedInterfaceN` helyett az első 1-3 kulcsból PascalCase + `Params_Interface` (a projekt-konvenció).
195
+ */
196
+ function deriveInterfaceName(node: any): string {
197
+ const members: any[] = Array.isArray(node?.members) ? node.members : [];
198
+ const keys: string[] = members
199
+ .filter((m: any): boolean => m.type === 'TSPropertySignature')
200
+ .map((m: any): string => String(m.key?.name ?? m.key?.value ?? ''))
201
+ .filter((k: string): boolean => !!k)
202
+ .slice(0, 3);
203
+
204
+ if (!keys.length) {
205
+ return 'Generated_Interface';
206
+ }
207
+
208
+ const pascal: string = keys
209
+ .map((k: string): string => k.charAt(0).toUpperCase() + k.slice(1))
210
+ .join('');
211
+
212
+ return `${pascal}_Interface`;
213
+ }
214
+
176
215
  return {
177
216
  TSTypeLiteral(node: any, _context?: any, _sourceCode?: any): void {
178
217
  try {
@@ -202,10 +241,14 @@ const rule: Rule.RuleModule = {
202
241
  // Process all collected type usages
203
242
  for (const [ signature, usages ] of typeUsages) {
204
243
  if (usages.length >= threshold) {
244
+ // beszédes név a property-kulcsokból (ütközés-mentesre pontosítva)
205
245
  const interfaceName = generateUniqueInterfaceName(
206
- generateInterfaceName(signature, usages.length)
246
+ deriveInterfaceName(usages[0].node)
207
247
  );
208
248
 
249
+ // a törzs a FORRÁS-SZÖVEGBŐL (getText) — a komplex/union/qualified típusok EXAKT megőrződnek
250
+ const interfaceBody: string = buildInterfaceBody(usages[0].node);
251
+
209
252
  // Report on each usage
210
253
  for (const usage of usages) {
211
254
  context.report({
@@ -215,19 +258,9 @@ const rule: Rule.RuleModule = {
215
258
  count: usages.length.toString(),
216
259
  interfaceName,
217
260
  },
218
- suggest: [{
219
- messageId: 'extractInterface',
220
- data: { interfaceName },
221
- fix(fixer) {
261
+ fix(fixer) {
222
262
  try {
223
- // Generate interface declaration
224
- const properties = signature.split(';').map(prop => {
225
- const [ key, type ] = prop.split(':');
226
-
227
- return ` ${key}: ${type};`;
228
- }).join('\n');
229
-
230
- const interfaceDeclaration = `interface ${interfaceName} {\n${properties}\n}`;
263
+ const interfaceDeclaration = `interface ${interfaceName} {\n${interfaceBody}\n}`;
231
264
 
232
265
  // Find insertion point (after imports, before other code)
233
266
  const firstNode = sourceCode.ast.body[0];
@@ -254,11 +287,8 @@ const rule: Rule.RuleModule = {
254
287
 
255
288
  // Replace all usages with interface reference
256
289
  for (const usage of usages) {
257
- const nodeText = sourceCode.getText(usage.node);
258
- const replacement = interfaceName;
259
-
260
290
  fixes.push(
261
- fixer.replaceText(usage.node, replacement)
291
+ fixer.replaceText(usage.node, interfaceName)
262
292
  );
263
293
  }
264
294
 
@@ -268,8 +298,7 @@ const rule: Rule.RuleModule = {
268
298
 
269
299
  return null;
270
300
  }
271
- },
272
- }],
301
+ },
273
302
  });
274
303
  }
275
304
  }