@wrongstack/plugins 0.281.1 → 0.282.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.
- package/README.md +29 -3
- package/dist/accessibility-auditor.d.ts +40 -0
- package/dist/accessibility-auditor.js +411 -0
- package/dist/agent-handoff.d.ts +37 -0
- package/dist/agent-handoff.js +298 -0
- package/dist/api-compatibility-gate.d.ts +38 -0
- package/dist/api-compatibility-gate.js +357 -0
- package/dist/auto-i18n-extractor.d.ts +36 -0
- package/dist/auto-i18n-extractor.js +335 -0
- package/dist/checkpoint.js +18 -0
- package/dist/code-metrics.d.ts +31 -0
- package/dist/code-metrics.js +338 -0
- package/dist/commit-validator.js +67 -12
- package/dist/cost-tracker.js +58 -16
- package/dist/dead-code-detector.d.ts +34 -0
- package/dist/dead-code-detector.js +354 -0
- package/dist/dep-guard.js +47 -6
- package/dist/dependency-vulnerability-gate.d.ts +35 -0
- package/dist/dependency-vulnerability-gate.js +308 -0
- package/dist/diff-summary.js +97 -10
- package/dist/doc-sync-guard.d.ts +33 -0
- package/dist/doc-sync-guard.js +223 -0
- package/dist/duplicate-code-detector.d.ts +33 -0
- package/dist/duplicate-code-detector.js +384 -0
- package/dist/feature-flag-tracker.d.ts +38 -0
- package/dist/feature-flag-tracker.js +316 -0
- package/dist/file-watcher.js +85 -36
- package/dist/format-on-save.js +76 -10
- package/dist/import-organizer.js +73 -14
- package/dist/index.d.ts +27 -0
- package/dist/index.js +14067 -5054
- package/dist/interface-contract-guard.d.ts +37 -0
- package/dist/interface-contract-guard.js +302 -0
- package/dist/knowledge-graph.d.ts +45 -0
- package/dist/knowledge-graph.js +325 -0
- package/dist/license-audit-gate.d.ts +34 -0
- package/dist/license-audit-gate.js +260 -0
- package/dist/llm-cache.js +5 -0
- package/dist/loop-breaker.d.ts +0 -38
- package/dist/loop-breaker.js +209 -8
- package/dist/migration-planner.d.ts +30 -0
- package/dist/migration-planner.js +349 -0
- package/dist/model-router.js +5 -0
- package/dist/performance-regression-gate.d.ts +33 -0
- package/dist/performance-regression-gate.js +315 -0
- package/dist/plugin-stack-observer.d.ts +35 -0
- package/dist/plugin-stack-observer.js +125 -0
- package/dist/pr-drafter.d.ts +35 -0
- package/dist/pr-drafter.js +334 -0
- package/dist/prompt-firewall.js +5 -0
- package/dist/refactor-suggester.d.ts +38 -0
- package/dist/refactor-suggester.js +382 -0
- package/dist/release-notes-generator.d.ts +27 -0
- package/dist/release-notes-generator.js +209 -0
- package/dist/schema-evolution-guard.d.ts +42 -0
- package/dist/schema-evolution-guard.js +319 -0
- package/dist/security-hotspot-scanner.d.ts +30 -0
- package/dist/security-hotspot-scanner.js +402 -0
- package/dist/semantic-search-indexer.d.ts +38 -0
- package/dist/semantic-search-indexer.js +436 -0
- package/dist/shell-check.js +38 -3
- package/dist/smart-rename.d.ts +26 -0
- package/dist/smart-rename.js +170 -0
- package/dist/spec-linker.js +273 -133
- package/dist/test-coverage-gate.d.ts +37 -0
- package/dist/test-coverage-gate.js +263 -0
- package/dist/test-flake-detector.d.ts +27 -0
- package/dist/test-flake-detector.js +274 -0
- package/dist/test-generator.d.ts +32 -0
- package/dist/test-generator.js +243 -0
- package/dist/test-runner-gate.js +154 -22
- package/dist/todo-listener.d.ts +2 -2
- package/dist/todo-listener.js +5 -5
- package/dist/token-throttle.js +5 -0
- package/dist/type-gate.d.ts +37 -0
- package/dist/type-gate.js +311 -0
- package/package.json +112 -4
- package/LICENSE +0 -21
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { execFileSync } from 'child_process';
|
|
2
|
+
import { mkdirSync, writeFileSync } from 'fs';
|
|
3
|
+
import { dirname, resolve, isAbsolute, relative } from 'path';
|
|
4
|
+
|
|
5
|
+
// src/pr-drafter/index.ts
|
|
6
|
+
var API_VERSION = "^0.1.10";
|
|
7
|
+
var state = {
|
|
8
|
+
commits: [],
|
|
9
|
+
files: /* @__PURE__ */ new Set(),
|
|
10
|
+
models: /* @__PURE__ */ new Set(),
|
|
11
|
+
totalInputTokens: 0,
|
|
12
|
+
totalOutputTokens: 0,
|
|
13
|
+
toolCalls: 0,
|
|
14
|
+
draftsWritten: 0,
|
|
15
|
+
draftErrors: 0,
|
|
16
|
+
stopInvocations: 0,
|
|
17
|
+
stopHookUnregister: null,
|
|
18
|
+
eventUnsubscribers: []
|
|
19
|
+
};
|
|
20
|
+
var DEFAULTS = {
|
|
21
|
+
enabled: true,
|
|
22
|
+
outputPath: ".wrongstack/PR_DRAFT.md",
|
|
23
|
+
writeOnStop: true,
|
|
24
|
+
includeDiff: true,
|
|
25
|
+
includeCommits: true,
|
|
26
|
+
includeFiles: true,
|
|
27
|
+
aiSummary: false
|
|
28
|
+
};
|
|
29
|
+
function readConfig(raw) {
|
|
30
|
+
if (!raw || typeof raw !== "object") return { ...DEFAULTS };
|
|
31
|
+
const r = raw;
|
|
32
|
+
return {
|
|
33
|
+
enabled: r["enabled"] !== false,
|
|
34
|
+
outputPath: typeof r["outputPath"] === "string" ? r["outputPath"] : DEFAULTS.outputPath,
|
|
35
|
+
writeOnStop: r["writeOnStop"] !== false,
|
|
36
|
+
includeDiff: r["includeDiff"] !== false,
|
|
37
|
+
includeCommits: r["includeCommits"] !== false,
|
|
38
|
+
includeFiles: r["includeFiles"] !== false,
|
|
39
|
+
aiSummary: r["aiSummary"] === true
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function resolveProjectPath(rawPath, cwd = process.cwd()) {
|
|
43
|
+
if (typeof rawPath !== "string" || rawPath.length === 0) return null;
|
|
44
|
+
const root = resolve(cwd);
|
|
45
|
+
const resolved = isAbsolute(rawPath) ? resolve(rawPath) : resolve(root, rawPath);
|
|
46
|
+
const rel = relative(root, resolved);
|
|
47
|
+
if (rel === "" || !rel.startsWith("..") && !isAbsolute(rel)) return resolved;
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
function gitBranch() {
|
|
51
|
+
try {
|
|
52
|
+
const out = execFileSync("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
53
|
+
encoding: "utf-8",
|
|
54
|
+
cwd: process.cwd(),
|
|
55
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
56
|
+
timeout: 5e3
|
|
57
|
+
});
|
|
58
|
+
return out.trim();
|
|
59
|
+
} catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function gitDiff() {
|
|
64
|
+
try {
|
|
65
|
+
return execFileSync("git", ["diff", "--stat"], {
|
|
66
|
+
encoding: "utf-8",
|
|
67
|
+
cwd: process.cwd(),
|
|
68
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
69
|
+
timeout: 1e4
|
|
70
|
+
}).trim();
|
|
71
|
+
} catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async function buildDraft(cfg, llm) {
|
|
76
|
+
const branch = gitBranch();
|
|
77
|
+
const diffStat = cfg.includeDiff ? gitDiff() : null;
|
|
78
|
+
const lines = [];
|
|
79
|
+
lines.push("# PR Draft");
|
|
80
|
+
if (branch) lines.push(`**Branch:** \`${branch}\``);
|
|
81
|
+
lines.push(`**Generated:** ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
82
|
+
lines.push("");
|
|
83
|
+
if (cfg.aiSummary && llm) {
|
|
84
|
+
try {
|
|
85
|
+
const context = `Files changed: ${[...state.files].join(", ") || "none"}
|
|
86
|
+
Commits: ${state.commits.join("; ") || "none"}
|
|
87
|
+
Tool calls: ${state.toolCalls}
|
|
88
|
+
Tokens: ${state.totalInputTokens} in / ${state.totalOutputTokens} out`;
|
|
89
|
+
const result = await llm.complete(
|
|
90
|
+
"Write a concise PR title and one-paragraph summary for the changes below. Format exactly as:\nTITLE: <title>\nSUMMARY: <summary>\n\n" + context,
|
|
91
|
+
{ system: "You write terse engineering PR descriptions.", maxTokens: 250 }
|
|
92
|
+
);
|
|
93
|
+
const text = result.text.trim();
|
|
94
|
+
const titleMatch = /TITLE:\s*(.+)/i.exec(text);
|
|
95
|
+
const summaryMatch = /SUMMARY:\s*(.+)/is.exec(text);
|
|
96
|
+
if (titleMatch?.[1]) lines.push(`## ${titleMatch[1].trim()}`);
|
|
97
|
+
if (summaryMatch?.[1]) lines.push(summaryMatch[1].trim(), "");
|
|
98
|
+
} catch {
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (cfg.includeCommits && state.commits.length > 0) {
|
|
102
|
+
lines.push("## Commits");
|
|
103
|
+
for (const c of state.commits) lines.push(`- ${c}`);
|
|
104
|
+
lines.push("");
|
|
105
|
+
}
|
|
106
|
+
if (cfg.includeFiles && state.files.size > 0) {
|
|
107
|
+
lines.push("## Files changed");
|
|
108
|
+
for (const f of [...state.files].sort()) lines.push(`- \`${f}\``);
|
|
109
|
+
lines.push("");
|
|
110
|
+
}
|
|
111
|
+
if (diffStat) {
|
|
112
|
+
lines.push("## Diff summary");
|
|
113
|
+
lines.push("```");
|
|
114
|
+
lines.push(diffStat);
|
|
115
|
+
lines.push("```");
|
|
116
|
+
lines.push("");
|
|
117
|
+
}
|
|
118
|
+
lines.push("## Session metrics");
|
|
119
|
+
lines.push(`- Tool calls: ${state.toolCalls}`);
|
|
120
|
+
lines.push(`- Models used: ${[...state.models].join(", ") || "unknown"}`);
|
|
121
|
+
lines.push(`- Tokens: ${state.totalInputTokens} in / ${state.totalOutputTokens} out`);
|
|
122
|
+
lines.push("");
|
|
123
|
+
const title = state.commits[0] ?? `Changes on ${branch ?? "current branch"}`;
|
|
124
|
+
return { title, body: lines.join("\n") };
|
|
125
|
+
}
|
|
126
|
+
async function writeDraft(cfg, llm) {
|
|
127
|
+
const resolved = resolveProjectPath(cfg.outputPath);
|
|
128
|
+
if (!resolved) {
|
|
129
|
+
state.draftErrors += 1;
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const draft = await buildDraft(cfg, llm);
|
|
133
|
+
try {
|
|
134
|
+
mkdirSync(dirname(resolved), { recursive: true });
|
|
135
|
+
writeFileSync(resolved, draft.body);
|
|
136
|
+
state.draftsWritten += 1;
|
|
137
|
+
} catch {
|
|
138
|
+
state.draftErrors += 1;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
var plugin = {
|
|
142
|
+
name: "pr-drafter",
|
|
143
|
+
version: "0.1.0",
|
|
144
|
+
description: "Collects session work (commits, edited files, diff) and drafts a pull-request description",
|
|
145
|
+
apiVersion: API_VERSION,
|
|
146
|
+
capabilities: { tools: true, hooks: true },
|
|
147
|
+
defaultConfig: { ...DEFAULTS },
|
|
148
|
+
configSchema: {
|
|
149
|
+
type: "object",
|
|
150
|
+
properties: {
|
|
151
|
+
enabled: { type: "boolean", default: true, description: "Master switch." },
|
|
152
|
+
outputPath: {
|
|
153
|
+
type: "string",
|
|
154
|
+
default: ".wrongstack/PR_DRAFT.md",
|
|
155
|
+
description: "Path where the markdown PR draft is written."
|
|
156
|
+
},
|
|
157
|
+
writeOnStop: {
|
|
158
|
+
type: "boolean",
|
|
159
|
+
default: true,
|
|
160
|
+
description: "Automatically write the draft when the session stops."
|
|
161
|
+
},
|
|
162
|
+
includeDiff: {
|
|
163
|
+
type: "boolean",
|
|
164
|
+
default: true,
|
|
165
|
+
description: "Include git diff --stat in the draft."
|
|
166
|
+
},
|
|
167
|
+
includeCommits: {
|
|
168
|
+
type: "boolean",
|
|
169
|
+
default: true,
|
|
170
|
+
description: "Include recorded commit messages."
|
|
171
|
+
},
|
|
172
|
+
includeFiles: {
|
|
173
|
+
type: "boolean",
|
|
174
|
+
default: true,
|
|
175
|
+
description: "Include files touched by write/edit tools."
|
|
176
|
+
},
|
|
177
|
+
aiSummary: {
|
|
178
|
+
type: "boolean",
|
|
179
|
+
default: false,
|
|
180
|
+
description: "Use api.llm to generate a PR title and summary."
|
|
181
|
+
},
|
|
182
|
+
llm: {
|
|
183
|
+
type: "object",
|
|
184
|
+
description: "Optional { provider, model } override for the AI summary."
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
},
|
|
188
|
+
setup(api) {
|
|
189
|
+
state.commits = [];
|
|
190
|
+
state.files = /* @__PURE__ */ new Set();
|
|
191
|
+
state.models = /* @__PURE__ */ new Set();
|
|
192
|
+
state.totalInputTokens = 0;
|
|
193
|
+
state.totalOutputTokens = 0;
|
|
194
|
+
state.toolCalls = 0;
|
|
195
|
+
state.draftsWritten = 0;
|
|
196
|
+
state.draftErrors = 0;
|
|
197
|
+
state.stopInvocations = 0;
|
|
198
|
+
state.stopHookUnregister = null;
|
|
199
|
+
for (const off of state.eventUnsubscribers) {
|
|
200
|
+
try {
|
|
201
|
+
off();
|
|
202
|
+
} catch {
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
state.eventUnsubscribers = [];
|
|
206
|
+
const cfg = readConfig(api.config.extensions?.["pr-drafter"]);
|
|
207
|
+
if (api.onPattern) {
|
|
208
|
+
const offTool = api.onPattern("tool.completed", (_event, payload) => {
|
|
209
|
+
const p = payload;
|
|
210
|
+
const toolName = p?.tool;
|
|
211
|
+
state.toolCalls += 1;
|
|
212
|
+
if (toolName === "git_autocommit" && p?.result?.committed) {
|
|
213
|
+
const msg = p.result.commitMessage ?? p.input?.message ?? "commit";
|
|
214
|
+
state.commits.push(msg);
|
|
215
|
+
}
|
|
216
|
+
if ((toolName === "write" || toolName === "edit") && p?.input?.path) {
|
|
217
|
+
state.files.add(p.input.path);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
state.eventUnsubscribers.push(offTool);
|
|
221
|
+
}
|
|
222
|
+
if (api.onEvent) {
|
|
223
|
+
const offUsage = api.onEvent("provider.response", (payload) => {
|
|
224
|
+
const p = payload;
|
|
225
|
+
if (p?.model) state.models.add(p.model);
|
|
226
|
+
state.totalInputTokens += p?.usage?.input ?? 0;
|
|
227
|
+
state.totalOutputTokens += p?.usage?.output ?? 0;
|
|
228
|
+
});
|
|
229
|
+
state.eventUnsubscribers.push(offUsage);
|
|
230
|
+
}
|
|
231
|
+
const stopHook = async () => {
|
|
232
|
+
if (!cfg.enabled || !cfg.writeOnStop) return;
|
|
233
|
+
state.stopInvocations += 1;
|
|
234
|
+
await writeDraft(cfg, api.llm);
|
|
235
|
+
};
|
|
236
|
+
state.stopHookUnregister = api.registerHook("Stop", void 0, stopHook);
|
|
237
|
+
api.tools.register({
|
|
238
|
+
name: "pr_draft",
|
|
239
|
+
description: "Generate or refresh the pull-request draft for the current session. Writes the markdown file and returns its path + title.",
|
|
240
|
+
inputSchema: {
|
|
241
|
+
type: "object",
|
|
242
|
+
properties: {
|
|
243
|
+
preview: {
|
|
244
|
+
type: "boolean",
|
|
245
|
+
description: "When true, return the draft body without writing to disk."
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
permission: "auto",
|
|
250
|
+
category: "Workflow",
|
|
251
|
+
mutating: false,
|
|
252
|
+
async execute(input) {
|
|
253
|
+
if (!cfg.enabled) return { ok: false, error: "pr-drafter is disabled" };
|
|
254
|
+
const draft = await buildDraft(cfg, api.llm);
|
|
255
|
+
if (input.preview) {
|
|
256
|
+
return { ok: true, preview: true, title: draft.title, body: draft.body };
|
|
257
|
+
}
|
|
258
|
+
const resolved = resolveProjectPath(cfg.outputPath);
|
|
259
|
+
if (!resolved) return { ok: false, error: "outputPath resolves outside project" };
|
|
260
|
+
try {
|
|
261
|
+
mkdirSync(dirname(resolved), { recursive: true });
|
|
262
|
+
writeFileSync(resolved, draft.body);
|
|
263
|
+
state.draftsWritten += 1;
|
|
264
|
+
return {
|
|
265
|
+
ok: true,
|
|
266
|
+
path: cfg.outputPath,
|
|
267
|
+
resolvedPath: resolved,
|
|
268
|
+
title: draft.title
|
|
269
|
+
};
|
|
270
|
+
} catch (err) {
|
|
271
|
+
state.draftErrors += 1;
|
|
272
|
+
return {
|
|
273
|
+
ok: false,
|
|
274
|
+
error: err instanceof Error ? err.message : String(err)
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
api.log.info("pr-drafter plugin loaded", {
|
|
280
|
+
version: "0.1.0",
|
|
281
|
+
outputPath: cfg.outputPath,
|
|
282
|
+
writeOnStop: cfg.writeOnStop
|
|
283
|
+
});
|
|
284
|
+
},
|
|
285
|
+
teardown(api) {
|
|
286
|
+
if (state.stopHookUnregister) {
|
|
287
|
+
try {
|
|
288
|
+
state.stopHookUnregister();
|
|
289
|
+
} catch {
|
|
290
|
+
}
|
|
291
|
+
state.stopHookUnregister = null;
|
|
292
|
+
}
|
|
293
|
+
for (const off of state.eventUnsubscribers) {
|
|
294
|
+
try {
|
|
295
|
+
off();
|
|
296
|
+
} catch {
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
state.eventUnsubscribers = [];
|
|
300
|
+
const final = {
|
|
301
|
+
commits: state.commits.length,
|
|
302
|
+
files: state.files.size,
|
|
303
|
+
toolCalls: state.toolCalls,
|
|
304
|
+
draftsWritten: state.draftsWritten,
|
|
305
|
+
draftErrors: state.draftErrors
|
|
306
|
+
};
|
|
307
|
+
state.commits = [];
|
|
308
|
+
state.files = /* @__PURE__ */ new Set();
|
|
309
|
+
state.models = /* @__PURE__ */ new Set();
|
|
310
|
+
state.totalInputTokens = 0;
|
|
311
|
+
state.totalOutputTokens = 0;
|
|
312
|
+
state.toolCalls = 0;
|
|
313
|
+
state.draftsWritten = 0;
|
|
314
|
+
state.draftErrors = 0;
|
|
315
|
+
state.stopInvocations = 0;
|
|
316
|
+
api.log.info("pr-drafter: teardown complete", { final });
|
|
317
|
+
},
|
|
318
|
+
async health() {
|
|
319
|
+
return {
|
|
320
|
+
ok: state.draftErrors === 0,
|
|
321
|
+
message: `pr-drafter: ${state.commits.length} commit(s), ${state.files.size} file(s), ${state.draftsWritten} draft(s) written, ${state.draftErrors} error(s)`,
|
|
322
|
+
counters: {
|
|
323
|
+
commits: state.commits.length,
|
|
324
|
+
files: state.files.size,
|
|
325
|
+
toolCalls: state.toolCalls,
|
|
326
|
+
draftsWritten: state.draftsWritten,
|
|
327
|
+
draftErrors: state.draftErrors
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
var pr_drafter_default = plugin;
|
|
333
|
+
|
|
334
|
+
export { pr_drafter_default as default };
|
package/dist/prompt-firewall.js
CHANGED
|
@@ -157,6 +157,11 @@ var plugin = {
|
|
|
157
157
|
}
|
|
158
158
|
const cfg = readConfig(api.config.extensions?.["prompt-firewall"]);
|
|
159
159
|
if (cfg.enabled) {
|
|
160
|
+
api.emitCustom?.("provider.wrap:loaded", {
|
|
161
|
+
plugin: "prompt-firewall",
|
|
162
|
+
kind: "security",
|
|
163
|
+
wraps: ["request", "response"]
|
|
164
|
+
});
|
|
160
165
|
state.extensionUnregister = api.extensions.register({
|
|
161
166
|
name: "prompt-firewall",
|
|
162
167
|
owner: "prompt-firewall",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Plugin } from '@wrongstack/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* refactor-suggester plugin — regex-based smell detector that suggests
|
|
5
|
+
* refactoring opportunities in source files.
|
|
6
|
+
*
|
|
7
|
+
* Tools registered:
|
|
8
|
+
* - suggest_refactors : Scan a file or directory for smells.
|
|
9
|
+
* - refactor_status : Report config + counters.
|
|
10
|
+
*
|
|
11
|
+
* Hooks registered:
|
|
12
|
+
* - PostToolUse with matcher `write|edit` to source files, injecting
|
|
13
|
+
* suggestions for the changed file.
|
|
14
|
+
*
|
|
15
|
+
* Config (`config.extensions['refactor-suggester']`):
|
|
16
|
+
*
|
|
17
|
+
* ```jsonc
|
|
18
|
+
* {
|
|
19
|
+
* "enabled": true,
|
|
20
|
+
* "extensions": [".ts", ".tsx", ".js", ".jsx"],
|
|
21
|
+
* "maxSuggestions": 20,
|
|
22
|
+
* "rules": { "longFunctionLines": 50, "maxParams": 5, "maxNesting": 3 }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
type SmellType = 'long-function' | 'deep-nesting' | 'many-parameters' | 'magic-number' | 'console-log';
|
|
30
|
+
interface RefactorSuggestion {
|
|
31
|
+
file: string;
|
|
32
|
+
line: number;
|
|
33
|
+
type: SmellType;
|
|
34
|
+
message: string;
|
|
35
|
+
}
|
|
36
|
+
declare const plugin: Plugin;
|
|
37
|
+
|
|
38
|
+
export { type RefactorSuggestion, type SmellType, plugin as default };
|