Skip to content

Commit 0841721

Browse files
authored
Report transformation errors during cross file resolve (#480)
1 parent bc1f82e commit 0841721

File tree

4 files changed

+76
-3
lines changed

4 files changed

+76
-3
lines changed

.changeset/rich-laws-camp.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"next-yak": patch
3+
---
4+
5+
Report transformation errors during cross file resolve

packages/next-yak/cross-file-resolver/__tests__/parseModule.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,48 @@ test("parse .yak module extensions", async () => {
470470
assert.strictEqual(parsedModule5.type, "regular");
471471
});
472472

473+
test("wraps errors from extractExports with file path", async () => {
474+
const path = "/path/to/module.js";
475+
476+
await expect(
477+
parseModule(
478+
{
479+
extractExports() {
480+
throw new Error("The loaded module contains errors");
481+
},
482+
getTransformed() {
483+
return { code: "" };
484+
},
485+
},
486+
path,
487+
),
488+
).rejects.toThrow(
489+
`Error parsing file "${path}"\n Caused by: The loaded module contains errors`,
490+
);
491+
});
492+
493+
test("wraps errors from getTransformed with file path", async () => {
494+
const path = "/path/to/module.js";
495+
496+
await expect(
497+
parseModule(
498+
{
499+
extractExports() {
500+
return { importYak: true, named: {}, all: [] };
501+
},
502+
getTransformed() {
503+
throw new Error(
504+
'The shorthand access to the variable "$foo" is not allowed',
505+
);
506+
},
507+
},
508+
path,
509+
),
510+
).rejects.toThrow(
511+
`Error parsing file "${path}"\n Caused by: The shorthand access to the variable "$foo" is not allowed`,
512+
);
513+
});
514+
473515
test("parse .yak module with cache multiple times extract/transform/evaluate each time", async () => {
474516
const path = "/path/to/module.yak.js";
475517

packages/next-yak/cross-file-resolver/parseModule.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export async function parseModule(
2626
}
2727

2828
if (context.cache?.parse === undefined) {
29-
return uncachedParseModule(context, modulePath);
29+
return await uncachedParseModule(context, modulePath);
3030
}
3131

3232
const cached = context.cache.parse.get(modulePath);
@@ -45,8 +45,9 @@ export async function parseModule(
4545

4646
return cached;
4747
} catch (error) {
48+
const causeMessage = error instanceof Error ? error.message : String(error);
4849
throw new Error(
49-
`Error parsing file ${modulePath}: ${(error as Error).message}`,
50+
`Error parsing file "${modulePath}"\n Caused by: ${causeMessage}`,
5051
);
5152
}
5253
}

packages/next-yak/loaders/lib/resolveCrossFileSelectors.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,32 @@ function getParseContext(
6666
async getTransformed(modulePath) {
6767
const transformedSource = new Promise<string>((resolve, reject) => {
6868
loader.loadModule(modulePath, (err, source) => {
69-
if (err) return reject(err);
69+
if (err) {
70+
// When webpack reports "The loaded module contains errors",
71+
// the actual errors are stored on the module in the compilation.
72+
// Extract and report the real errors for better debugging.
73+
const compilation = loader._compilation;
74+
if (compilation) {
75+
try {
76+
for (const mod of compilation.modules) {
77+
if ("resource" in mod && mod.resource === modulePath) {
78+
const errors = mod.getErrors();
79+
if (errors) {
80+
const messages = Array.from(errors)
81+
.map((e) => e.message)
82+
.filter(Boolean);
83+
if (messages.length > 0) {
84+
return reject(new Error(messages.join("\n")));
85+
}
86+
}
87+
}
88+
}
89+
} catch {
90+
// Ignore errors while trying to extract module errors
91+
}
92+
}
93+
return reject(err);
94+
}
7095
let sourceString: string;
7196
if (typeof source === "string") {
7297
sourceString = source;

0 commit comments

Comments
 (0)