@griddo/ax 12.5.0 → 12.5.1

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.
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Guards the fix for webpack 5 dropping the file name from module warnings.
3
+ *
4
+ * webpack 4 gave CRA warnings as strings carrying their own `./src/Foo.tsx` header;
5
+ * webpack 5 moves it to a `moduleName` field that `formatWebpackMessages` ignores,
6
+ * which left "Attempted import error: 'x' is not exported from './styles.module.css'"
7
+ * pointing at no file in particular.
8
+ */
9
+ const formatWebpackMessages = require("react-dev-utils/formatWebpackMessages");
10
+
11
+ const ModulePathInMessagesPlugin = require("../webpack/ModulePathInMessagesPlugin");
12
+
13
+ /** Minimal stand-in for the two tapable hooks the plugin uses. */
14
+ const runPlugin = ({ warnings = [], errors = [] } = {}) => {
15
+ const compilation = {
16
+ warnings,
17
+ errors,
18
+ requestShortener: {},
19
+ hooks: { afterSeal: { tap: (_name, fn) => fn() } },
20
+ };
21
+ const compiler = { hooks: { compilation: { tap: (_name, fn) => fn(compilation) } } };
22
+
23
+ new ModulePathInMessagesPlugin().apply(compiler);
24
+
25
+ return compilation;
26
+ };
27
+
28
+ const makeWarning = (message, { module = true, loc = { start: { line: 2, column: 12 } } } = {}) => ({
29
+ message,
30
+ loc,
31
+ module: module ? { readableIdentifier: () => "./src/ui/modules/Wysiwyg/index.tsx" } : undefined,
32
+ });
33
+
34
+ describe("ModulePathInMessagesPlugin", () => {
35
+ test("prefixes the warning with the module path and location", () => {
36
+ const warning = makeWarning("export 'intro' was not found in './styles.module.css'");
37
+
38
+ runPlugin({ warnings: [warning] });
39
+
40
+ expect(warning.message).toBe(
41
+ "./src/ui/modules/Wysiwyg/index.tsx:2:12\nexport 'intro' was not found in './styles.module.css'",
42
+ );
43
+ });
44
+
45
+ test("decorates errors too", () => {
46
+ const error = makeWarning("Module not found");
47
+
48
+ runPlugin({ errors: [error] });
49
+
50
+ expect(error.message).toBe("./src/ui/modules/Wysiwyg/index.tsx:2:12\nModule not found");
51
+ });
52
+
53
+ test("omits the location when the warning has none", () => {
54
+ const warning = makeWarning("boom", { loc: null });
55
+
56
+ runPlugin({ warnings: [warning] });
57
+
58
+ expect(warning.message).toBe("./src/ui/modules/Wysiwyg/index.tsx\nboom");
59
+ });
60
+
61
+ test("leaves warnings that are not attached to a module alone", () => {
62
+ const warning = makeWarning("something global", { module: false });
63
+
64
+ runPlugin({ warnings: [warning] });
65
+
66
+ expect(warning.message).toBe("something global");
67
+ });
68
+
69
+ test("does not prefix twice across watch-mode rebuilds", () => {
70
+ const warning = makeWarning("export 'intro' was not found in './styles.module.css'");
71
+
72
+ runPlugin({ warnings: [warning] });
73
+ const afterFirstBuild = warning.message;
74
+ runPlugin({ warnings: [warning] });
75
+
76
+ expect(warning.message).toBe(afterFirstBuild);
77
+ });
78
+
79
+ // The contract that makes the whole thing worthwhile: formatWebpackMessages
80
+ // rewrites the export line wholesale and strips a trailing `2:12-24` off line 0,
81
+ // so the header has to survive both to reach the terminal.
82
+ test("the path survives formatWebpackMessages", () => {
83
+ const warning = makeWarning("export 'intro' (imported as 'styles') was not found in './styles.module.css'");
84
+
85
+ runPlugin({ warnings: [warning] });
86
+ const [formatted] = formatWebpackMessages({ errors: [], warnings: [{ message: warning.message }] }).warnings;
87
+
88
+ expect(formatted).toBe(
89
+ "./src/ui/modules/Wysiwyg/index.tsx:2:12\n" +
90
+ "Attempted import error: 'intro' is not exported from './styles.module.css' (imported as 'styles').",
91
+ );
92
+ });
93
+ });
@@ -0,0 +1,47 @@
1
+ const NAME = "GriddoModulePathInMessages";
2
+
3
+ /**
4
+ * Prefixes every module-attached warning/error with the file that caused it.
5
+ *
6
+ * webpack 4 handed CRA its warnings as plain strings that already carried the
7
+ * `./src/Foo.tsx 2:12-24` header. webpack 5 hands them over as objects
8
+ * (`{ message, moduleName, loc }`), and `react-dev-utils`'s `formatWebpackMessages`
9
+ * only reads `.message` — so the file and location are dropped on the floor.
10
+ * That leaves messages like "Attempted import error: 'intro' is not exported
11
+ * from './styles.module.css'" with no way to tell which of the many
12
+ * `styles.module.css` files is at fault.
13
+ *
14
+ * Folding the location back into `.message` restores the webpack 4 shape that
15
+ * `formatWebpackMessages` expects (line 0 = file, line 1 = message), and it fixes
16
+ * both paths at once: `griddo build` (which calls the formatter directly) and
17
+ * `griddo start` (where `createCompiler` calls it internally, out of our reach).
18
+ */
19
+ class ModulePathInMessagesPlugin {
20
+ apply(compiler) {
21
+ compiler.hooks.compilation.tap(NAME, (compilation) => {
22
+ // `afterSeal` runs once dependency warnings have been collected and before
23
+ // anything can call `stats.toJson()`.
24
+ compilation.hooks.afterSeal.tap(NAME, () => {
25
+ const decorate = (err) => {
26
+ const module = err.module;
27
+ if (!module || typeof module.readableIdentifier !== "function") {
28
+ return;
29
+ }
30
+ const name = module.readableIdentifier(compilation.requestShortener);
31
+ const loc = err.loc?.start ? `:${err.loc.start.line}:${err.loc.start.column}` : "";
32
+ const header = `${name}${loc}`;
33
+ // Guard against double-prefixing on watch-mode rebuilds that reuse errors.
34
+ if (typeof err.message !== "string" || err.message.startsWith(header)) {
35
+ return;
36
+ }
37
+ err.message = `${header}\n${err.message}`;
38
+ };
39
+
40
+ compilation.warnings.forEach(decorate);
41
+ compilation.errors.forEach(decorate);
42
+ });
43
+ });
44
+ }
45
+ }
46
+
47
+ module.exports = ModulePathInMessagesPlugin;
@@ -18,6 +18,7 @@ const ModuleNotFoundPlugin = require("react-dev-utils/ModuleNotFoundPlugin");
18
18
  const ForkTsCheckerWebpackPlugin = require("react-dev-utils/ForkTsCheckerWebpackPlugin");
19
19
  const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
20
20
  const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");
21
+ const ModulePathInMessagesPlugin = require("./webpack/ModulePathInMessagesPlugin");
21
22
  const createEnvironmentHash = require("./webpack/persistentCache/createEnvironmentHash");
22
23
 
23
24
  const postcssNormalize = require("postcss-normalize");
@@ -548,6 +549,10 @@ module.exports = function (webpackEnv) {
548
549
  ],
549
550
  },
550
551
  plugins: [
552
+ // webpack 5 moves the offending file out of the warning text and into a
553
+ // separate `moduleName` field that react-dev-utils' formatter ignores. This
554
+ // folds it back in so messages point at a file again.
555
+ new ModulePathInMessagesPlugin(),
551
556
  // Restore webpack 4's Node core-module handling for browser bundles. Clients run
552
557
  // `griddo build` (this config) against their own instance, so this guards legacy
553
558
  // instances against "Module not found" for Node builtins that webpack 5 no longer
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@griddo/ax",
3
3
  "description": "Griddo Author Experience",
4
- "version": "12.5.0",
4
+ "version": "12.5.1",
5
5
  "authors": [
6
6
  "Álvaro Sánchez' <alvaro.sanches@secuoyas.com>",
7
7
  "Diego M. Béjar <diego.bejar@secuoyas.com>",
@@ -199,5 +199,5 @@
199
199
  "publishConfig": {
200
200
  "access": "public"
201
201
  },
202
- "gitHead": "02d4a5b3c3d3f4a4339db6746b6d6572139e51e5"
202
+ "gitHead": "0341f4c939ce5e316e37effdaca2ef26dee8b8af"
203
203
  }