@visulima/error 4.4.18 → 4.5.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/CHANGELOG.md +15 -0
- package/LICENSE.md +125 -0
- package/README.md +118 -0
- package/dist/index.cjs +11 -0
- package/dist/index.d.cts +5 -1
- package/dist/index.d.mts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.mjs +5 -0
- package/dist/packem_shared/ai-solution-response-BuaDQAEU.d.cts +3 -0
- package/dist/packem_shared/ai-solution-response-BuaDQAEU.d.mts +3 -0
- package/dist/packem_shared/ai-solution-response-BuaDQAEU.d.ts +3 -0
- package/dist/packem_shared/aiFinder-BGfwKKxE.cjs +263 -0
- package/dist/packem_shared/aiFinder-Bk1vt0_x.mjs +261 -0
- package/dist/packem_shared/aiSolutionResponse-BPckbL56.cjs +37 -0
- package/dist/packem_shared/aiSolutionResponse-bDi4ad8f.mjs +35 -0
- package/dist/packem_shared/errorHintFinder-CQy_qIK3.mjs +23 -0
- package/dist/packem_shared/errorHintFinder-DZugFHq0.cjs +25 -0
- package/dist/packem_shared/formatStackFrameLine-DcXSX--m.cjs +31 -0
- package/dist/packem_shared/formatStackFrameLine-DqkmKWH3.mjs +26 -0
- package/dist/packem_shared/ruleBasedFinder-BYrndubA.mjs +227 -0
- package/dist/packem_shared/ruleBasedFinder-y_-5kbeT.cjs +229 -0
- package/dist/packem_shared/types-BtQS7FHG.d.cts +20 -0
- package/dist/packem_shared/types-BtQS7FHG.d.mts +20 -0
- package/dist/packem_shared/types-BtQS7FHG.d.ts +20 -0
- package/dist/solution/ai/ai-prompt.cjs +42 -0
- package/dist/solution/ai/ai-prompt.d.cts +9 -0
- package/dist/solution/ai/ai-prompt.d.mts +9 -0
- package/dist/solution/ai/ai-prompt.d.ts +9 -0
- package/dist/solution/ai/ai-prompt.mjs +40 -0
- package/dist/solution/ai/index.cjs +13 -0
- package/dist/solution/ai/index.d.cts +16 -0
- package/dist/solution/ai/index.d.mts +16 -0
- package/dist/solution/ai/index.d.ts +16 -0
- package/dist/solution/ai/index.mjs +3 -0
- package/dist/solution/index.cjs +11 -0
- package/dist/solution/index.d.cts +8 -0
- package/dist/solution/index.d.mts +8 -0
- package/dist/solution/index.d.ts +8 -0
- package/dist/solution/index.mjs +2 -0
- package/dist/stacktrace/index.cjs +3 -0
- package/dist/stacktrace/index.d.cts +9 -1
- package/dist/stacktrace/index.d.mts +9 -1
- package/dist/stacktrace/index.d.ts +9 -1
- package/dist/stacktrace/index.mjs +1 -0
- package/package.json +63 -16
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { generateText } from 'ai';
|
|
5
|
+
import aiPrompt from '../solution/ai/ai-prompt.mjs';
|
|
6
|
+
import aiSolutionResponse from './aiSolutionResponse-bDi4ad8f.mjs';
|
|
7
|
+
|
|
8
|
+
var __defProp$1 = Object.defineProperty;
|
|
9
|
+
var __name$1 = (target, value) => __defProp$1(target, "name", { value, configurable: true });
|
|
10
|
+
var __defProp$1$1 = Object.defineProperty;
|
|
11
|
+
var __name$1$1 = /* @__PURE__ */ __name$1((target, value) => __defProp$1$1(target, "name", { value, configurable: true }), "__name$1");
|
|
12
|
+
const DRIVE_LETTER_START_RE = /^[A-Z]:\//i;
|
|
13
|
+
const normalizeWindowsPath = /* @__PURE__ */ __name$1$1((input = "") => {
|
|
14
|
+
if (!input) {
|
|
15
|
+
return input;
|
|
16
|
+
}
|
|
17
|
+
return input.replaceAll("\\", "/").replace(DRIVE_LETTER_START_RE, (r) => r.toUpperCase());
|
|
18
|
+
}, "normalizeWindowsPath");
|
|
19
|
+
var __defProp2 = Object.defineProperty;
|
|
20
|
+
var __name2 = /* @__PURE__ */ __name$1((target, value) => __defProp2(target, "name", { value, configurable: true }), "__name");
|
|
21
|
+
const UNC_REGEX = /^[/\\]{2}/;
|
|
22
|
+
const IS_ABSOLUTE_RE = /^[/\\](?![/\\])|^[/\\]{2}(?!\.)|^[A-Z]:[/\\]/i;
|
|
23
|
+
const DRIVE_LETTER_RE = /^[A-Z]:$/i;
|
|
24
|
+
const normalizeString = /* @__PURE__ */ __name2((path2, allowAboveRoot) => {
|
|
25
|
+
let result = "";
|
|
26
|
+
let lastSegmentLength = 0;
|
|
27
|
+
let lastSlash = -1;
|
|
28
|
+
let dots = 0;
|
|
29
|
+
let char = null;
|
|
30
|
+
for (let index = 0; index <= path2.length; ++index) {
|
|
31
|
+
if (index < path2.length) {
|
|
32
|
+
char = path2[index];
|
|
33
|
+
} else if (char === "/") {
|
|
34
|
+
break;
|
|
35
|
+
} else {
|
|
36
|
+
char = "/";
|
|
37
|
+
}
|
|
38
|
+
if (char === "/") {
|
|
39
|
+
if (lastSlash === index - 1 || dots === 1) ;
|
|
40
|
+
else if (dots === 2) {
|
|
41
|
+
if (result.length < 2 || lastSegmentLength !== 2 || !result.endsWith(".") || result.at(-2) !== ".") {
|
|
42
|
+
if (result.length > 2) {
|
|
43
|
+
const lastSlashIndex = result.lastIndexOf("/");
|
|
44
|
+
if (lastSlashIndex === -1) {
|
|
45
|
+
result = "";
|
|
46
|
+
lastSegmentLength = 0;
|
|
47
|
+
} else {
|
|
48
|
+
result = result.slice(0, lastSlashIndex);
|
|
49
|
+
lastSegmentLength = result.length - 1 - result.lastIndexOf("/");
|
|
50
|
+
}
|
|
51
|
+
lastSlash = index;
|
|
52
|
+
dots = 0;
|
|
53
|
+
continue;
|
|
54
|
+
} else if (result.length > 0) {
|
|
55
|
+
result = "";
|
|
56
|
+
lastSegmentLength = 0;
|
|
57
|
+
lastSlash = index;
|
|
58
|
+
dots = 0;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (allowAboveRoot) {
|
|
63
|
+
result += result.length > 0 ? "/.." : "..";
|
|
64
|
+
lastSegmentLength = 2;
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
if (result.length > 0) {
|
|
68
|
+
result += `/${path2.slice(lastSlash + 1, index)}`;
|
|
69
|
+
} else {
|
|
70
|
+
result = path2.slice(lastSlash + 1, index);
|
|
71
|
+
}
|
|
72
|
+
lastSegmentLength = index - lastSlash - 1;
|
|
73
|
+
}
|
|
74
|
+
lastSlash = index;
|
|
75
|
+
dots = 0;
|
|
76
|
+
} else if (char === "." && dots !== -1) {
|
|
77
|
+
++dots;
|
|
78
|
+
} else {
|
|
79
|
+
dots = -1;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return result;
|
|
83
|
+
}, "normalizeString");
|
|
84
|
+
const isAbsolute = /* @__PURE__ */ __name2((path2) => IS_ABSOLUTE_RE.test(path2), "isAbsolute");
|
|
85
|
+
const normalize = /* @__PURE__ */ __name2(function(path2) {
|
|
86
|
+
if (path2.length === 0) {
|
|
87
|
+
return ".";
|
|
88
|
+
}
|
|
89
|
+
path2 = normalizeWindowsPath(path2);
|
|
90
|
+
const isUNCPath = UNC_REGEX.exec(path2);
|
|
91
|
+
const isPathAbsolute = isAbsolute(path2);
|
|
92
|
+
const trailingSeparator = path2.at(-1) === "/";
|
|
93
|
+
path2 = normalizeString(path2, !isPathAbsolute);
|
|
94
|
+
if (path2.length === 0) {
|
|
95
|
+
if (isPathAbsolute) {
|
|
96
|
+
return "/";
|
|
97
|
+
}
|
|
98
|
+
return trailingSeparator ? "./" : ".";
|
|
99
|
+
}
|
|
100
|
+
if (trailingSeparator) {
|
|
101
|
+
path2 += "/";
|
|
102
|
+
}
|
|
103
|
+
if (DRIVE_LETTER_RE.test(path2)) {
|
|
104
|
+
path2 += "/";
|
|
105
|
+
}
|
|
106
|
+
if (isUNCPath) {
|
|
107
|
+
if (!isPathAbsolute) {
|
|
108
|
+
return `//./${path2}`;
|
|
109
|
+
}
|
|
110
|
+
return `//${path2}`;
|
|
111
|
+
}
|
|
112
|
+
return isPathAbsolute && !isAbsolute(path2) ? `/${path2}` : path2;
|
|
113
|
+
}, "normalize");
|
|
114
|
+
const join = /* @__PURE__ */ __name2((...segments) => {
|
|
115
|
+
let path2 = "";
|
|
116
|
+
for (const seg of segments) {
|
|
117
|
+
if (!seg) {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (path2.length > 0) {
|
|
121
|
+
const pathTrailing = path2[path2.length - 1] === "/";
|
|
122
|
+
const segLeading = seg[0] === "/";
|
|
123
|
+
const both = pathTrailing && segLeading;
|
|
124
|
+
if (both) {
|
|
125
|
+
path2 += seg.slice(1);
|
|
126
|
+
} else {
|
|
127
|
+
path2 += pathTrailing || segLeading ? seg : `/${seg}`;
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
path2 += seg;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return normalize(path2);
|
|
134
|
+
}, "join");
|
|
135
|
+
|
|
136
|
+
var __defProp = Object.defineProperty;
|
|
137
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
138
|
+
const DEFAULT_HEADER = "## Ai Generated Solution";
|
|
139
|
+
const DEFAULT_ERROR_MESSAGE = "Creation of a AI solution failed.";
|
|
140
|
+
const generateCacheKey = /* @__PURE__ */ __name((error, file, temperature) => {
|
|
141
|
+
const keyData = {
|
|
142
|
+
error: {
|
|
143
|
+
name: error.name,
|
|
144
|
+
message: error.message,
|
|
145
|
+
stack: error.stack
|
|
146
|
+
},
|
|
147
|
+
file: {
|
|
148
|
+
file: file.file,
|
|
149
|
+
language: file.language,
|
|
150
|
+
line: file.line,
|
|
151
|
+
snippet: file.snippet
|
|
152
|
+
},
|
|
153
|
+
temperature
|
|
154
|
+
};
|
|
155
|
+
return createHash("sha256").update(JSON.stringify(keyData)).digest("hex");
|
|
156
|
+
}, "generateCacheKey");
|
|
157
|
+
const getCacheDirectory = /* @__PURE__ */ __name((directory) => {
|
|
158
|
+
if (directory) {
|
|
159
|
+
return directory;
|
|
160
|
+
}
|
|
161
|
+
return join(tmpdir(), "visulima-error-cache");
|
|
162
|
+
}, "getCacheDirectory");
|
|
163
|
+
const ensureCacheDirectory = /* @__PURE__ */ __name((cacheDir) => {
|
|
164
|
+
if (!existsSync(cacheDir)) {
|
|
165
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
166
|
+
}
|
|
167
|
+
}, "ensureCacheDirectory");
|
|
168
|
+
const getCacheFilePath = /* @__PURE__ */ __name((cacheDir, key) => {
|
|
169
|
+
return join(cacheDir, `${key}.json`);
|
|
170
|
+
}, "getCacheFilePath");
|
|
171
|
+
const readFromCache = /* @__PURE__ */ __name((cacheFilePath, ttl) => {
|
|
172
|
+
try {
|
|
173
|
+
if (!existsSync(cacheFilePath)) {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
const cacheContent = readFileSync(cacheFilePath, "utf-8");
|
|
177
|
+
const cacheEntry = JSON.parse(cacheContent);
|
|
178
|
+
const now = Date.now();
|
|
179
|
+
if (now - cacheEntry.timestamp > ttl) {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
return cacheEntry.solution;
|
|
183
|
+
} catch {
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
}, "readFromCache");
|
|
187
|
+
const writeToCache = /* @__PURE__ */ __name((cacheFilePath, solution, ttl) => {
|
|
188
|
+
try {
|
|
189
|
+
const cacheEntry = {
|
|
190
|
+
solution,
|
|
191
|
+
timestamp: Date.now(),
|
|
192
|
+
ttl
|
|
193
|
+
};
|
|
194
|
+
writeFileSync(cacheFilePath, JSON.stringify(cacheEntry, null, 2), "utf-8");
|
|
195
|
+
} catch {
|
|
196
|
+
}
|
|
197
|
+
}, "writeToCache");
|
|
198
|
+
const aiFinder = /* @__PURE__ */ __name((model, options) => {
|
|
199
|
+
return {
|
|
200
|
+
handle: /* @__PURE__ */ __name(async (error, file) => {
|
|
201
|
+
const cacheOptions = options?.cache;
|
|
202
|
+
const temperature = options?.temperature ?? 0;
|
|
203
|
+
const ttl = cacheOptions?.ttl ?? 24 * 60 * 60 * 1e3;
|
|
204
|
+
if (cacheOptions?.enabled !== false) {
|
|
205
|
+
const cacheKey = generateCacheKey(error, file, temperature);
|
|
206
|
+
const cacheDir = getCacheDirectory(cacheOptions?.directory);
|
|
207
|
+
const cacheFilePath = getCacheFilePath(cacheDir, cacheKey);
|
|
208
|
+
const cachedSolution = readFromCache(cacheFilePath, ttl);
|
|
209
|
+
if (cachedSolution) {
|
|
210
|
+
return cachedSolution;
|
|
211
|
+
}
|
|
212
|
+
ensureCacheDirectory(cacheDir);
|
|
213
|
+
}
|
|
214
|
+
const content = aiPrompt({ applicationType: void 0, error, file });
|
|
215
|
+
try {
|
|
216
|
+
const result = await generateText({
|
|
217
|
+
model,
|
|
218
|
+
prompt: content,
|
|
219
|
+
temperature
|
|
220
|
+
});
|
|
221
|
+
const messageContent = result.text;
|
|
222
|
+
let solution;
|
|
223
|
+
if (!messageContent) {
|
|
224
|
+
solution = {
|
|
225
|
+
body: aiSolutionResponse(DEFAULT_ERROR_MESSAGE),
|
|
226
|
+
header: DEFAULT_HEADER
|
|
227
|
+
};
|
|
228
|
+
} else {
|
|
229
|
+
solution = {
|
|
230
|
+
body: aiSolutionResponse(messageContent),
|
|
231
|
+
header: DEFAULT_HEADER
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
if (cacheOptions?.enabled !== false) {
|
|
235
|
+
const cacheKey = generateCacheKey(error, file, temperature);
|
|
236
|
+
const cacheDir = getCacheDirectory(cacheOptions?.directory);
|
|
237
|
+
const cacheFilePath = getCacheFilePath(cacheDir, cacheKey);
|
|
238
|
+
writeToCache(cacheFilePath, solution, ttl);
|
|
239
|
+
}
|
|
240
|
+
return solution;
|
|
241
|
+
} catch (error_) {
|
|
242
|
+
console.error(error_);
|
|
243
|
+
const solution = {
|
|
244
|
+
body: aiSolutionResponse(DEFAULT_ERROR_MESSAGE),
|
|
245
|
+
header: DEFAULT_HEADER
|
|
246
|
+
};
|
|
247
|
+
if (cacheOptions?.enabled !== false) {
|
|
248
|
+
const cacheKey = generateCacheKey(error, file, temperature);
|
|
249
|
+
const cacheDir = getCacheDirectory(cacheOptions?.directory);
|
|
250
|
+
const cacheFilePath = getCacheFilePath(cacheDir, cacheKey);
|
|
251
|
+
writeToCache(cacheFilePath, solution, ttl);
|
|
252
|
+
}
|
|
253
|
+
return solution;
|
|
254
|
+
}
|
|
255
|
+
}, "handle"),
|
|
256
|
+
name: "AI SDK",
|
|
257
|
+
priority: 99
|
|
258
|
+
};
|
|
259
|
+
}, "aiFinder");
|
|
260
|
+
|
|
261
|
+
export { aiFinder as default };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
|
+
const between = /* @__PURE__ */ __name((start, end, text) => {
|
|
6
|
+
const startPosition = text.indexOf(start);
|
|
7
|
+
if (startPosition === -1) {
|
|
8
|
+
return "";
|
|
9
|
+
}
|
|
10
|
+
const adjustedStartPosition = startPosition + start.length;
|
|
11
|
+
const endPosition = text.indexOf(end, adjustedStartPosition);
|
|
12
|
+
if (endPosition === -1) {
|
|
13
|
+
return "";
|
|
14
|
+
}
|
|
15
|
+
return text.substring(adjustedStartPosition, endPosition).trim();
|
|
16
|
+
}, "between");
|
|
17
|
+
const aiSolutionResponse = /* @__PURE__ */ __name((rawText) => {
|
|
18
|
+
const description = between("FIX", "ENDFIX", rawText);
|
|
19
|
+
if (!description) {
|
|
20
|
+
return [
|
|
21
|
+
"No solution found.",
|
|
22
|
+
'Provide this response to the Maintainer of <a href="https://github.com/visulima/visulima/issues/new?assignees=&labels=s%3A+pending+triage%2Cc%3A+bug&projects=&template=bug_report.yml" target="_blank" rel="noopener noreferrer" class="text-blue-500 hover:underline inline-flex items-center text-sm">@visulima/error</a>.',
|
|
23
|
+
`"${rawText}"`
|
|
24
|
+
].join("</br></br>");
|
|
25
|
+
}
|
|
26
|
+
const links = between("LINKS", "ENDLINKS", rawText).split("\n").map((link) => JSON.parse(link));
|
|
27
|
+
return `${description.replaceAll(/"([^"]*)"(\s|\.)/g, "<code>$1</code> ")}
|
|
28
|
+
|
|
29
|
+
## Links
|
|
30
|
+
|
|
31
|
+
${links.map((link) => `- <a href="${link.url}" target="_blank" rel="noopener noreferrer">${link.title}</a>`).join("\n")}
|
|
32
|
+
|
|
33
|
+
--------------------
|
|
34
|
+
This solution was generated with the <a href="https://sdk.vercel.ai/" target="_blank" rel="noopener noreferrer">AI SDK</a> and may not be 100% accurate.`;
|
|
35
|
+
}, "aiSolutionResponse");
|
|
36
|
+
|
|
37
|
+
module.exports = aiSolutionResponse;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
const between = /* @__PURE__ */ __name((start, end, text) => {
|
|
4
|
+
const startPosition = text.indexOf(start);
|
|
5
|
+
if (startPosition === -1) {
|
|
6
|
+
return "";
|
|
7
|
+
}
|
|
8
|
+
const adjustedStartPosition = startPosition + start.length;
|
|
9
|
+
const endPosition = text.indexOf(end, adjustedStartPosition);
|
|
10
|
+
if (endPosition === -1) {
|
|
11
|
+
return "";
|
|
12
|
+
}
|
|
13
|
+
return text.substring(adjustedStartPosition, endPosition).trim();
|
|
14
|
+
}, "between");
|
|
15
|
+
const aiSolutionResponse = /* @__PURE__ */ __name((rawText) => {
|
|
16
|
+
const description = between("FIX", "ENDFIX", rawText);
|
|
17
|
+
if (!description) {
|
|
18
|
+
return [
|
|
19
|
+
"No solution found.",
|
|
20
|
+
'Provide this response to the Maintainer of <a href="https://github.com/visulima/visulima/issues/new?assignees=&labels=s%3A+pending+triage%2Cc%3A+bug&projects=&template=bug_report.yml" target="_blank" rel="noopener noreferrer" class="text-blue-500 hover:underline inline-flex items-center text-sm">@visulima/error</a>.',
|
|
21
|
+
`"${rawText}"`
|
|
22
|
+
].join("</br></br>");
|
|
23
|
+
}
|
|
24
|
+
const links = between("LINKS", "ENDLINKS", rawText).split("\n").map((link) => JSON.parse(link));
|
|
25
|
+
return `${description.replaceAll(/"([^"]*)"(\s|\.)/g, "<code>$1</code> ")}
|
|
26
|
+
|
|
27
|
+
## Links
|
|
28
|
+
|
|
29
|
+
${links.map((link) => `- <a href="${link.url}" target="_blank" rel="noopener noreferrer">${link.title}</a>`).join("\n")}
|
|
30
|
+
|
|
31
|
+
--------------------
|
|
32
|
+
This solution was generated with the <a href="https://sdk.vercel.ai/" target="_blank" rel="noopener noreferrer">AI SDK</a> and may not be 100% accurate.`;
|
|
33
|
+
}, "aiSolutionResponse");
|
|
34
|
+
|
|
35
|
+
export { aiSolutionResponse as default };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
const errorHintFinder = {
|
|
4
|
+
handle: /* @__PURE__ */ __name(async (error) => {
|
|
5
|
+
if (error.hint === void 0) {
|
|
6
|
+
return void 0;
|
|
7
|
+
}
|
|
8
|
+
if (typeof error.hint === "string") {
|
|
9
|
+
return { body: error.hint };
|
|
10
|
+
}
|
|
11
|
+
if (typeof error.hint === "object" && typeof error.hint.body === "string") {
|
|
12
|
+
return error.hint;
|
|
13
|
+
}
|
|
14
|
+
if (Array.isArray(error.hint)) {
|
|
15
|
+
return { body: error.hint.join("\n") };
|
|
16
|
+
}
|
|
17
|
+
return void 0;
|
|
18
|
+
}, "handle"),
|
|
19
|
+
name: "errorHint",
|
|
20
|
+
priority: 1
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export { errorHintFinder as default };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
|
+
const errorHintFinder = {
|
|
6
|
+
handle: /* @__PURE__ */ __name(async (error) => {
|
|
7
|
+
if (error.hint === void 0) {
|
|
8
|
+
return void 0;
|
|
9
|
+
}
|
|
10
|
+
if (typeof error.hint === "string") {
|
|
11
|
+
return { body: error.hint };
|
|
12
|
+
}
|
|
13
|
+
if (typeof error.hint === "object" && typeof error.hint.body === "string") {
|
|
14
|
+
return error.hint;
|
|
15
|
+
}
|
|
16
|
+
if (Array.isArray(error.hint)) {
|
|
17
|
+
return { body: error.hint.join("\n") };
|
|
18
|
+
}
|
|
19
|
+
return void 0;
|
|
20
|
+
}, "handle"),
|
|
21
|
+
name: "errorHint",
|
|
22
|
+
priority: 1
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
module.exports = errorHintFinder;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
|
|
4
|
+
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
7
|
+
const formatStackFrameLine = /* @__PURE__ */ __name((frame) => {
|
|
8
|
+
const method = frame.methodName && frame.methodName !== "<unknown>" ? `${frame.methodName} ` : "";
|
|
9
|
+
const file = frame.file ?? "<unknown>";
|
|
10
|
+
const line = frame.line ?? 0;
|
|
11
|
+
const column = frame.column ?? 0;
|
|
12
|
+
if (method.trim()) {
|
|
13
|
+
return ` at ${method}(${file}:${line}:${column})`;
|
|
14
|
+
}
|
|
15
|
+
return ` at ${file}:${line}:${column}`;
|
|
16
|
+
}, "formatStackFrameLine");
|
|
17
|
+
const formatStacktrace = /* @__PURE__ */ __name((frames, options) => {
|
|
18
|
+
const lines = [];
|
|
19
|
+
if (options?.header && (options.header.name || options.header.message)) {
|
|
20
|
+
const headerName = String(options.header.name || "Error");
|
|
21
|
+
const headerMessage = String(options.header.message || "");
|
|
22
|
+
lines.push(`${headerName}${headerMessage ? ": " : ""}${headerMessage}`);
|
|
23
|
+
}
|
|
24
|
+
for (const frame of frames) {
|
|
25
|
+
lines.push(formatStackFrameLine(frame));
|
|
26
|
+
}
|
|
27
|
+
return lines.join("\n");
|
|
28
|
+
}, "formatStacktrace");
|
|
29
|
+
|
|
30
|
+
exports.formatStackFrameLine = formatStackFrameLine;
|
|
31
|
+
exports.formatStacktrace = formatStacktrace;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
const formatStackFrameLine = /* @__PURE__ */ __name((frame) => {
|
|
4
|
+
const method = frame.methodName && frame.methodName !== "<unknown>" ? `${frame.methodName} ` : "";
|
|
5
|
+
const file = frame.file ?? "<unknown>";
|
|
6
|
+
const line = frame.line ?? 0;
|
|
7
|
+
const column = frame.column ?? 0;
|
|
8
|
+
if (method.trim()) {
|
|
9
|
+
return ` at ${method}(${file}:${line}:${column})`;
|
|
10
|
+
}
|
|
11
|
+
return ` at ${file}:${line}:${column}`;
|
|
12
|
+
}, "formatStackFrameLine");
|
|
13
|
+
const formatStacktrace = /* @__PURE__ */ __name((frames, options) => {
|
|
14
|
+
const lines = [];
|
|
15
|
+
if (options?.header && (options.header.name || options.header.message)) {
|
|
16
|
+
const headerName = String(options.header.name || "Error");
|
|
17
|
+
const headerMessage = String(options.header.message || "");
|
|
18
|
+
lines.push(`${headerName}${headerMessage ? ": " : ""}${headerMessage}`);
|
|
19
|
+
}
|
|
20
|
+
for (const frame of frames) {
|
|
21
|
+
lines.push(formatStackFrameLine(frame));
|
|
22
|
+
}
|
|
23
|
+
return lines.join("\n");
|
|
24
|
+
}, "formatStacktrace");
|
|
25
|
+
|
|
26
|
+
export { formatStackFrameLine, formatStacktrace };
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
const code = /* @__PURE__ */ __name((s) => `\`\`\`
|
|
4
|
+
${s.trim()}
|
|
5
|
+
\`\`\``, "code");
|
|
6
|
+
const bash = /* @__PURE__ */ __name((s) => `\`\`\`bash
|
|
7
|
+
${s.trim()}
|
|
8
|
+
\`\`\``, "bash");
|
|
9
|
+
const ts = /* @__PURE__ */ __name((s) => `\`\`\`ts
|
|
10
|
+
${s.trim()}
|
|
11
|
+
\`\`\``, "ts");
|
|
12
|
+
const js = /* @__PURE__ */ __name((s) => `\`\`\`js
|
|
13
|
+
${s.trim()}
|
|
14
|
+
\`\`\``, "js");
|
|
15
|
+
const has = /* @__PURE__ */ __name((message, ...needles) => {
|
|
16
|
+
const lower = message.toLowerCase();
|
|
17
|
+
return needles.some((n) => lower.includes(n.toLowerCase()));
|
|
18
|
+
}, "has");
|
|
19
|
+
const rules = [
|
|
20
|
+
{
|
|
21
|
+
name: "esm-cjs-interop",
|
|
22
|
+
test: /* @__PURE__ */ __name((error) => {
|
|
23
|
+
const message = (error?.message || String(error || "")).toString();
|
|
24
|
+
if (has(
|
|
25
|
+
message,
|
|
26
|
+
"err_require_esm",
|
|
27
|
+
"cannot use import statement outside a module",
|
|
28
|
+
"must use import to load es module",
|
|
29
|
+
"require() of es module",
|
|
30
|
+
"does not provide an export named"
|
|
31
|
+
)) {
|
|
32
|
+
return {
|
|
33
|
+
md: [
|
|
34
|
+
"Your project or a dependency may be mixing CommonJS and ES Modules.",
|
|
35
|
+
"",
|
|
36
|
+
"Try:",
|
|
37
|
+
"- Ensure package.json has the correct `type` (either `module` or `commonjs`).",
|
|
38
|
+
"- Use dynamic `import()` when requiring ESM from CJS.",
|
|
39
|
+
"- Prefer ESM-compatible entrypoints from dependencies.",
|
|
40
|
+
"- In Node, align `module` resolution with your bundler config.",
|
|
41
|
+
"",
|
|
42
|
+
"Check Node resolution:",
|
|
43
|
+
bash("node -v\ncat package.json | jq .type"),
|
|
44
|
+
"",
|
|
45
|
+
"Example dynamic import in CJS:",
|
|
46
|
+
js("(async () => { const mod = await import('some-esm'); mod.default(); })();")
|
|
47
|
+
].join("\n"),
|
|
48
|
+
title: "ESM/CJS interop"
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return void 0;
|
|
52
|
+
}, "test")
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: "missing-default-export",
|
|
56
|
+
test: /* @__PURE__ */ __name((error) => {
|
|
57
|
+
const message = (error?.message || String(error || "")).toString();
|
|
58
|
+
if (has(message, "default export not found", "has no default export", "does not provide an export named 'default'", "is not exported from")) {
|
|
59
|
+
return {
|
|
60
|
+
md: [
|
|
61
|
+
"Verify your import/export shapes.",
|
|
62
|
+
"",
|
|
63
|
+
"Default export example:",
|
|
64
|
+
ts("export default function Component() {}\n// import Component from './file'"),
|
|
65
|
+
"",
|
|
66
|
+
"Named export example:",
|
|
67
|
+
ts("export function Component() {}\n// import { Component } from './file'")
|
|
68
|
+
].join("\n"),
|
|
69
|
+
title: "Export mismatch (default vs named)"
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return void 0;
|
|
73
|
+
}, "test")
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: "port-in-use",
|
|
77
|
+
test: /* @__PURE__ */ __name((error) => {
|
|
78
|
+
const message = (error?.message || String(error || "")).toString();
|
|
79
|
+
if (has(message, "eaddrinuse", "address already in use", "listen eaddrinuse")) {
|
|
80
|
+
return {
|
|
81
|
+
md: [
|
|
82
|
+
"Another process is using the port.",
|
|
83
|
+
"",
|
|
84
|
+
"Change the port or stop the other process.",
|
|
85
|
+
"",
|
|
86
|
+
"On macOS/Linux:",
|
|
87
|
+
bash("lsof -i :3000\nkill -9 <PID>"),
|
|
88
|
+
"",
|
|
89
|
+
"On Windows (PowerShell):",
|
|
90
|
+
bash("netstat -ano | findstr :3000\ntaskkill /PID <PID> /F")
|
|
91
|
+
].join("\n"),
|
|
92
|
+
title: "Port already in use"
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return void 0;
|
|
96
|
+
}, "test")
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: "file-not-found-or-case",
|
|
100
|
+
test: /* @__PURE__ */ __name((error, file) => {
|
|
101
|
+
const message = (error?.message || String(error || "")).toString();
|
|
102
|
+
if (has(message, "enoent", "module not found", "cannot find module")) {
|
|
103
|
+
return {
|
|
104
|
+
md: [
|
|
105
|
+
"Check the import path and filename case (Linux/macOS are case-sensitive).",
|
|
106
|
+
"If using TS path aliases, verify `tsconfig.paths` and bundler aliases.",
|
|
107
|
+
"",
|
|
108
|
+
"Current file:",
|
|
109
|
+
code(`${file.file}:${file.line}`)
|
|
110
|
+
].join("\n"),
|
|
111
|
+
title: "Missing file or path case mismatch"
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return void 0;
|
|
115
|
+
}, "test")
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
name: "ts-path-mapping",
|
|
119
|
+
test: /* @__PURE__ */ __name((error) => {
|
|
120
|
+
const message = (error?.message || String(error || "")).toString();
|
|
121
|
+
if (has(message, "ts2307", "cannot find module") || message.includes("TS2307")) {
|
|
122
|
+
return {
|
|
123
|
+
md: [
|
|
124
|
+
"If you use path aliases, align TS `paths` with Vite/Webpack resolve aliases.",
|
|
125
|
+
"Ensure file extensions are correct and included in resolver.",
|
|
126
|
+
"",
|
|
127
|
+
"tsconfig.json excerpt:",
|
|
128
|
+
ts(`{
|
|
129
|
+
"compilerOptions": {
|
|
130
|
+
"baseUrl": ".",
|
|
131
|
+
"paths": { "@/*": ["src/*"] }
|
|
132
|
+
}
|
|
133
|
+
}`)
|
|
134
|
+
].join("\n"),
|
|
135
|
+
title: "TypeScript path mapping / resolution"
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
return void 0;
|
|
139
|
+
}, "test")
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: "network-dns-enotfound",
|
|
143
|
+
test: /* @__PURE__ */ __name((error) => {
|
|
144
|
+
const message = (error?.message || String(error || "")).toString();
|
|
145
|
+
if (has(message, "enotfound", "getaddrinfo enotfound", "dns", "fetch failed", "ecconnrefused", "econnrefused")) {
|
|
146
|
+
return {
|
|
147
|
+
md: [
|
|
148
|
+
"The host may be unreachable or misconfigured.",
|
|
149
|
+
"",
|
|
150
|
+
"Try:",
|
|
151
|
+
"- Verify the hostname and protocol (http/https).",
|
|
152
|
+
"- Check VPN/proxy and firewall.",
|
|
153
|
+
"- Confirm the service is running and listening on the expected port.",
|
|
154
|
+
"",
|
|
155
|
+
bash("ping <host>\nnslookup <host>\ncurl -v http://<host>:<port>")
|
|
156
|
+
].join("\n"),
|
|
157
|
+
title: "Network/DNS connection issue"
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return void 0;
|
|
161
|
+
}, "test")
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
name: "react-hydration-mismatch",
|
|
165
|
+
test: /* @__PURE__ */ __name((error) => {
|
|
166
|
+
const message = (error?.message || String(error || "")).toString();
|
|
167
|
+
if (has(message, "hydration failed", "did not match", "expected server html", "text content does not match")) {
|
|
168
|
+
return {
|
|
169
|
+
md: [
|
|
170
|
+
"Client and server rendered markup differ.",
|
|
171
|
+
"",
|
|
172
|
+
"Checklist:",
|
|
173
|
+
"- Avoid non-deterministic rendering during SSR (dates, random, locale).",
|
|
174
|
+
"- Ensure feature flags / env checks are consistent between server and client.",
|
|
175
|
+
"- Wrap browser-only code with guards (e.g., check `typeof window !== 'undefined'`).",
|
|
176
|
+
"- Ensure data used on server matches client rehydration data."
|
|
177
|
+
].join("\n"),
|
|
178
|
+
title: "React hydration mismatch"
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return void 0;
|
|
182
|
+
}, "test")
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
name: "undefined-property",
|
|
186
|
+
test: /* @__PURE__ */ __name((error) => {
|
|
187
|
+
const message = (error?.message || String(error || "")).toString();
|
|
188
|
+
if (has(message, "cannot read properties of undefined", "reading '")) {
|
|
189
|
+
return {
|
|
190
|
+
md: [
|
|
191
|
+
"A variable or function returned `undefined`.",
|
|
192
|
+
"",
|
|
193
|
+
"Mitigations:",
|
|
194
|
+
"- Add nullish checks before property access.",
|
|
195
|
+
"- Validate function return values and input props/state.",
|
|
196
|
+
"",
|
|
197
|
+
ts("const value = maybe?.prop; // or: if (maybe) { use(maybe.prop) }")
|
|
198
|
+
].join("\n"),
|
|
199
|
+
title: "Accessing property of undefined"
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
return void 0;
|
|
203
|
+
}, "test")
|
|
204
|
+
}
|
|
205
|
+
];
|
|
206
|
+
const ruleBasedFinder = {
|
|
207
|
+
handle: /* @__PURE__ */ __name(async (error, file) => {
|
|
208
|
+
try {
|
|
209
|
+
const matches = rules.map((r) => {
|
|
210
|
+
return { match: r.test(error, file), rule: r };
|
|
211
|
+
}).filter((x) => Boolean(x.match));
|
|
212
|
+
if (matches.length === 0) {
|
|
213
|
+
return void 0;
|
|
214
|
+
}
|
|
215
|
+
const sections = matches.sort((a, b) => (a.match.priority || 0) - (b.match.priority || 0)).map((m) => `#### ${m.match.title}
|
|
216
|
+
|
|
217
|
+
${m.match.md}`).join("\n\n---\n\n");
|
|
218
|
+
return { body: sections, header: "### Potential fixes detected" };
|
|
219
|
+
} catch {
|
|
220
|
+
return void 0;
|
|
221
|
+
}
|
|
222
|
+
}, "handle"),
|
|
223
|
+
name: "ruleBasedHints",
|
|
224
|
+
priority: 0
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
export { ruleBasedFinder as default };
|