@mui/internal-babel-plugin-minify-errors 1.0.13 → 2.0.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.
@@ -8,5 +8,8 @@ module.exports = {
8
8
  // Babel import helpers do not add one.
9
9
  // Since this is auto generated code we don't care about code style.
10
10
  'import/newline-after-import': 'off',
11
+ 'import/no-unresolved': 'off',
12
+ '@typescript-eslint/no-unused-vars': 'off',
13
+ 'no-undef': 'off',
11
14
  },
12
15
  };
@@ -0,0 +1,3 @@
1
+ {
2
+ "42": "MUI: This is a test error message.\nWith a second line."
3
+ }
@@ -0,0 +1 @@
1
+ throw /* minify-error */ new Error('MUI: This is a test error message.\n' + 'With a second line.');
@@ -0,0 +1,6 @@
1
+ import _formatErrorMessage from '@custom/error-formatter';
2
+ throw new Error(
3
+ process.env.NODE_ENV !== 'production'
4
+ ? 'MUI: This is a test error message.\n' + 'With a second line.'
5
+ : _formatErrorMessage(42),
6
+ );
@@ -0,0 +1,3 @@
1
+ {
2
+ "42": "MUI: This is a test error message.\nWith a second line."
3
+ }
@@ -0,0 +1 @@
1
+ throw /* minify-error */ new Error('MUI: This is a test error message.\n' + 'With a second line.');
@@ -0,0 +1,6 @@
1
+ import _formatErrorMessage from '@custom/error-formatter';
2
+ throw new Error(
3
+ process.env.NODE_ENV !== 'production'
4
+ ? 'MUI: This is a test error message.\n' + 'With a second line.'
5
+ : _formatErrorMessage(42),
6
+ );
@@ -0,0 +1,5 @@
1
+ {
2
+ "imports": {
3
+ "#error-formatter": "@custom/error-formatter"
4
+ }
5
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "42": "MUI: This is a test error message.\nWith a second line."
3
+ }
@@ -0,0 +1 @@
1
+ throw /* minify-error */ new Error('MUI: This is a test error message.\n' + 'With a second line.');
@@ -0,0 +1,6 @@
1
+ import _formatErrorMessage from '@custom/error-formatter';
2
+ throw new Error(
3
+ process.env.NODE_ENV !== 'production'
4
+ ? 'MUI: This is a test error message.\n' + 'With a second line.'
5
+ : _formatErrorMessage(42),
6
+ );
@@ -0,0 +1,7 @@
1
+ {
2
+ "imports": {
3
+ "#error-formatter": "#error-formatter-2",
4
+ "#error-formatter-2": "#error-formatter-3",
5
+ "#error-formatter-3": "@custom/error-formatter"
6
+ }
7
+ }
@@ -0,0 +1,3 @@
1
+ export default function formatter() {
2
+ return 'Hello world';
3
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "42": "MUI: This is a test error message.\nWith a second line."
3
+ }
@@ -0,0 +1 @@
1
+ throw /* minify-error */ new Error('MUI: This is a test error message.\n' + 'With a second line.');
@@ -0,0 +1,6 @@
1
+ import _formatErrorMessage from './error/formatter.js';
2
+ throw new Error(
3
+ process.env.NODE_ENV !== 'production'
4
+ ? 'MUI: This is a test error message.\n' + 'With a second line.'
5
+ : _formatErrorMessage(42),
6
+ );
@@ -0,0 +1,5 @@
1
+ {
2
+ "imports": {
3
+ "#error-formatter": "./error/formatter.ts"
4
+ }
5
+ }
@@ -1,5 +1,3 @@
1
- import _formatMuiErrorMessage from '@mui/utils/formatMuiErrorMessage';
2
- throw new Error(process.env.NODE_ENV !== 'production' ? 'exists' : _formatMuiErrorMessage(1));
3
- throw new Error(
4
- process.env.NODE_ENV !== 'production' ? 'will be created' : _formatMuiErrorMessage(2),
5
- );
1
+ import _formatErrorMessage from '@mui/utils/formatMuiErrorMessage';
2
+ throw new Error(process.env.NODE_ENV !== 'production' ? 'exists' : _formatErrorMessage(1));
3
+ throw new Error(process.env.NODE_ENV !== 'production' ? 'will be created' : _formatErrorMessage(2));
@@ -1,18 +1,16 @@
1
- import _formatMuiErrorMessage from '@mui/utils/formatMuiErrorMessage';
1
+ import _formatErrorMessage from '@mui/utils/formatMuiErrorMessage';
2
2
  const foo = 'foo';
3
3
  const bar = 'bar';
4
4
  throw new Error(
5
- process.env.NODE_ENV !== 'production'
6
- ? `MUI: ${foo}, ${bar}`
7
- : _formatMuiErrorMessage(1, foo, bar),
5
+ process.env.NODE_ENV !== 'production' ? `MUI: ${foo}, ${bar}` : _formatErrorMessage(1, foo, bar),
8
6
  );
9
7
  throw new Error(
10
8
  process.env.NODE_ENV !== 'production'
11
9
  ? `MUI: ${foo}` + `, ${bar}`
12
- : _formatMuiErrorMessage(1, foo, bar),
10
+ : _formatErrorMessage(1, foo, bar),
13
11
  );
14
12
  throw new Error(
15
13
  process.env.NODE_ENV !== 'production'
16
14
  ? 'MUI: ' + `${foo}, ${bar}`
17
- : _formatMuiErrorMessage(1, foo, bar),
15
+ : _formatErrorMessage(1, foo, bar),
18
16
  );
@@ -1,11 +1,11 @@
1
- import _formatMuiErrorMessage from '@mui/utils/formatMuiErrorMessage';
1
+ import _formatErrorMessage from '@mui/utils/formatMuiErrorMessage';
2
2
  throw new Error(
3
3
  process.env.NODE_ENV !== 'production'
4
4
  ? 'MUI: Expected valid input target.\n' + 'Did you use `inputComponent`'
5
- : _formatMuiErrorMessage(1),
5
+ : _formatErrorMessage(1),
6
6
  );
7
7
  throw new Error(
8
8
  process.env.NODE_ENV !== 'production'
9
9
  ? `MUI: Expected valid input target.\n` + `Did you use \`inputComponent\``
10
- : _formatMuiErrorMessage(1),
10
+ : _formatErrorMessage(1),
11
11
  );
package/index.js CHANGED
@@ -2,26 +2,54 @@
2
2
 
3
3
  const helperModuleImports = require('@babel/helper-module-imports');
4
4
  const fs = require('fs');
5
+ const nodePath = require('path');
6
+ const finder = require('find-package-json');
5
7
 
6
- const COMMENT_MARKER = 'minify-error';
8
+ /**
9
+ * Normalize a file path to POSIX in order for it to be platform-agnostic.
10
+ * @param {string} importPath
11
+ * @returns {string}
12
+ */
13
+ function toPosixPath(importPath) {
14
+ return nodePath.normalize(importPath).split(nodePath.sep).join(nodePath.posix.sep);
15
+ }
16
+
17
+ /**
18
+ * Converts a file path to a node import specifier.
19
+ * @param {string} importPath
20
+ * @returns {string}
21
+ */
22
+ function pathToNodeImportSpecifier(importPath) {
23
+ const normalized = toPosixPath(importPath);
24
+ return normalized.startsWith('/') || normalized.startsWith('.') ? normalized : `./${normalized}`;
25
+ }
26
+
27
+ const COMMENT_OPT_IN_MARKER = 'minify-error';
28
+ const COMMENT_OPT_OUT_MARKER = 'minify-error-disabled';
7
29
 
8
30
  /**
9
31
  * @typedef {import('@babel/core')} babel
10
32
  */
11
33
 
12
34
  /**
13
- * @typedef {{updatedErrorCodes?: boolean, formatMuiErrorMessageIdentifier?: babel.types.Identifier}} PluginState
35
+ * @typedef {babel.PluginPass & {updatedErrorCodes?: boolean, formatErrorMessageIdentifier?: babel.types.Identifier}} PluginState
14
36
  * @typedef {'annotate' | 'throw' | 'write'} MissingError
15
- * @typedef {{ errorCodesPath: string, missingError: MissingError }} Options
37
+ * @typedef {{
38
+ * errorCodesPath: string,
39
+ * missingError: MissingError,
40
+ * runtimeModule?: string,
41
+ * detection?: 'opt-in' | 'opt-out',
42
+ * outExtension?: string
43
+ * }} Options
16
44
  */
17
45
 
18
46
  /**
19
- *
47
+ * Extracts the message and expressions from a node.
20
48
  * @param {babel.types} t
21
49
  * @param {babel.types.Node} node
22
50
  * @returns {{ message: string, expressions: babel.types.Expression[] } | null}
23
51
  */
24
- function extractMessageFromExpression(t, node) {
52
+ function extractMessage(t, node) {
25
53
  if (t.isTemplateLiteral(node)) {
26
54
  return {
27
55
  message: node.quasis.map((quasi) => quasi.value.cooked).join('%s'),
@@ -37,12 +65,8 @@ function extractMessageFromExpression(t, node) {
37
65
  return { message: node.value, expressions: [] };
38
66
  }
39
67
  if (t.isBinaryExpression(node) && node.operator === '+') {
40
- if (t.isPrivateName(node.left)) {
41
- // This is only psossible with `in` expressions, e.g. `#foo in {}`
42
- throw new Error('Unreachable');
43
- }
44
- const left = extractMessageFromExpression(t, node.left);
45
- const right = extractMessageFromExpression(t, node.right);
68
+ const left = extractMessage(t, node.left);
69
+ const right = extractMessage(t, node.right);
46
70
  if (!left || !right) {
47
71
  return null;
48
72
  }
@@ -55,35 +79,156 @@ function extractMessageFromExpression(t, node) {
55
79
  }
56
80
 
57
81
  /**
58
- *
82
+ * Handles unminifyable errors based on the missingError option.
59
83
  * @param {MissingError} missingError
60
84
  * @param {babel.NodePath} path
61
- * @returns
62
85
  */
63
- function handleUnminifyable(missingError, path) {
86
+ function handleUnminifyableError(missingError, path) {
64
87
  switch (missingError) {
65
- case 'annotate': {
66
- // Outputs:
67
- // /* FIXME (minify-errors-in-prod): Unminified error message in production build! */
68
- // throw new Error(foo)
88
+ case 'annotate':
69
89
  path.addComment(
70
90
  'leading',
71
91
  ' FIXME (minify-errors-in-prod): Unminifyable error in production! ',
72
92
  );
73
- return;
74
- }
75
- case 'throw': {
93
+ break;
94
+ case 'throw':
76
95
  throw new Error(
77
- `Unminifyable error. You can only use literal strings and template strings as error messages.`,
96
+ 'Unminifyable error. You can only use literal strings and template strings as error messages.',
78
97
  );
79
- }
80
- case 'write': {
81
- return;
82
- }
83
- default: {
98
+ case 'write':
99
+ break;
100
+ default:
84
101
  throw new Error(`Unknown missingError option: ${missingError}`);
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Transforms the error message node.
107
+ * @param {babel.types} t
108
+ * @param {babel.NodePath} path
109
+ * @param {babel.types.Expression} messageNode
110
+ * @param {PluginState} state
111
+ * @param {Map<string, number>} errorCodesLookup
112
+ * @param {MissingError} missingError
113
+ * @param {string} runtimeModule
114
+ * @param {string} outExtension
115
+ * @returns {babel.types.Expression | null}
116
+ */
117
+ function transformMessage(
118
+ t,
119
+ path,
120
+ messageNode,
121
+ state,
122
+ errorCodesLookup,
123
+ missingError,
124
+ runtimeModule,
125
+ outExtension,
126
+ ) {
127
+ const message = extractMessage(t, messageNode);
128
+ if (!message) {
129
+ handleUnminifyableError(missingError, path);
130
+ return null;
131
+ }
132
+
133
+ let errorCode = errorCodesLookup.get(message.message);
134
+ if (errorCode === undefined) {
135
+ switch (missingError) {
136
+ case 'annotate':
137
+ path.addComment(
138
+ 'leading',
139
+ ' FIXME (minify-errors-in-prod): Unminified error message in production build! ',
140
+ );
141
+ return null;
142
+ case 'throw':
143
+ throw new Error(
144
+ `Missing error code for message '${message.message}'. Did you forget to run \`pnpm extract-error-codes\` first?`,
145
+ );
146
+ case 'write':
147
+ errorCode = errorCodesLookup.size + 1;
148
+ errorCodesLookup.set(message.message, errorCode);
149
+ state.updatedErrorCodes = true;
150
+ break;
151
+ default:
152
+ throw new Error(`Unknown missingError option: ${missingError}`);
85
153
  }
86
154
  }
155
+
156
+ if (!state.formatErrorMessageIdentifier) {
157
+ state.formatErrorMessageIdentifier = helperModuleImports.addDefault(
158
+ path,
159
+ transformExtension(resolveRuntimeModule(runtimeModule, state), outExtension),
160
+ { nameHint: '_formatErrorMessage' },
161
+ );
162
+ }
163
+
164
+ return t.conditionalExpression(
165
+ t.binaryExpression(
166
+ '!==',
167
+ t.memberExpression(
168
+ t.memberExpression(t.identifier('process'), t.identifier('env')),
169
+ t.identifier('NODE_ENV'),
170
+ ),
171
+ t.stringLiteral('production'),
172
+ ),
173
+ messageNode,
174
+ t.callExpression(t.cloneNode(state.formatErrorMessageIdentifier, true), [
175
+ t.numericLiteral(errorCode),
176
+ ...message.expressions,
177
+ ]),
178
+ );
179
+ }
180
+
181
+ /**
182
+ * Resolves the runtime module path recursively.
183
+ * @param {string} runtimeModule
184
+ * @param {PluginState} state
185
+ * @param {Set<string>} [visitedModules]
186
+ * @returns {string}
187
+ */
188
+ function resolveRuntimeModule(runtimeModule, state, visitedModules = new Set()) {
189
+ if (!runtimeModule.startsWith('#')) {
190
+ return runtimeModule;
191
+ }
192
+
193
+ const currentFile = state.filename;
194
+ if (!currentFile) {
195
+ throw new Error('filename is not defined');
196
+ }
197
+
198
+ const result = finder(currentFile).next();
199
+ if (result.done) {
200
+ throw new Error('Could not find package.json');
201
+ }
202
+
203
+ const pkg = result.value;
204
+ const pkgPath = result.filename;
205
+ const runtimeModulePath = pkg?.imports?.[runtimeModule];
206
+ if (typeof runtimeModulePath !== 'string') {
207
+ throw new Error(`Invalid runtime module path for ${runtimeModule}`);
208
+ }
209
+
210
+ if (visitedModules.has(runtimeModule)) {
211
+ throw new Error(`Circular import detected for ${runtimeModule}`);
212
+ }
213
+ visitedModules.add(runtimeModule);
214
+
215
+ if (runtimeModulePath.startsWith('.')) {
216
+ const resolvedPath = nodePath.resolve(nodePath.dirname(pkgPath), runtimeModulePath);
217
+ const relativePath = nodePath.relative(nodePath.dirname(currentFile), resolvedPath);
218
+ return pathToNodeImportSpecifier(relativePath);
219
+ }
220
+
221
+ return resolveRuntimeModule(runtimeModulePath, state, visitedModules);
222
+ }
223
+
224
+ /**
225
+ *
226
+ * @param {string} importSpecifier
227
+ * @param {string} outExtension
228
+ * @returns
229
+ */
230
+ function transformExtension(importSpecifier, outExtension = '.js') {
231
+ return importSpecifier.replace(/\.[a-zA-Z0-9]+$/, outExtension);
87
232
  }
88
233
 
89
234
  /**
@@ -91,7 +236,16 @@ function handleUnminifyable(missingError, path) {
91
236
  * @param {Options} options
92
237
  * @returns {babel.PluginObj<PluginState>}
93
238
  */
94
- module.exports = function plugin({ types: t }, { errorCodesPath, missingError = 'annotate' }) {
239
+ module.exports = function plugin(
240
+ { types: t },
241
+ {
242
+ errorCodesPath,
243
+ missingError = 'annotate',
244
+ runtimeModule = '#formatErrorMessage',
245
+ detection = 'opt-in',
246
+ outExtension = '.js',
247
+ },
248
+ ) {
95
249
  if (!errorCodesPath) {
96
250
  throw new Error('errorCodesPath is required.');
97
251
  }
@@ -104,23 +258,46 @@ module.exports = function plugin({ types: t }, { errorCodesPath, missingError =
104
258
  );
105
259
 
106
260
  return {
261
+ name: '@mui/internal-babel-plugin-minify-errors',
107
262
  visitor: {
108
263
  NewExpression(newExpressionPath, state) {
109
264
  if (!newExpressionPath.get('callee').isIdentifier({ name: 'Error' })) {
110
265
  return;
111
266
  }
112
267
 
113
- if (
114
- !newExpressionPath.node.leadingComments?.some((comment) =>
115
- comment.value.includes(COMMENT_MARKER),
116
- )
117
- ) {
118
- return;
119
- }
268
+ switch (detection) {
269
+ case 'opt-in': {
270
+ if (
271
+ !newExpressionPath.node.leadingComments?.some((comment) =>
272
+ comment.value.includes(COMMENT_OPT_IN_MARKER),
273
+ )
274
+ ) {
275
+ return;
276
+ }
277
+ newExpressionPath.node.leadingComments = newExpressionPath.node.leadingComments.filter(
278
+ (comment) => !comment.value.includes(COMMENT_OPT_IN_MARKER),
279
+ );
280
+ break;
281
+ }
282
+ case 'opt-out': {
283
+ if (
284
+ newExpressionPath.node.leadingComments?.some((comment) =>
285
+ comment.value.includes(COMMENT_OPT_OUT_MARKER),
286
+ )
287
+ ) {
288
+ newExpressionPath.node.leadingComments =
289
+ newExpressionPath.node.leadingComments.filter(
290
+ (comment) => !comment.value.includes(COMMENT_OPT_OUT_MARKER),
291
+ );
292
+ return;
293
+ }
120
294
 
121
- newExpressionPath.node.leadingComments = newExpressionPath.node.leadingComments.filter(
122
- (comment) => !comment.value.includes(COMMENT_MARKER),
123
- );
295
+ break;
296
+ }
297
+ default: {
298
+ throw new Error(`Unknown detection option: ${detection}`);
299
+ }
300
+ }
124
301
 
125
302
  const messagePath = newExpressionPath.get('arguments')[0];
126
303
  if (!messagePath) {
@@ -129,88 +306,24 @@ module.exports = function plugin({ types: t }, { errorCodesPath, missingError =
129
306
 
130
307
  const messageNode = messagePath.node;
131
308
  if (t.isSpreadElement(messageNode) || t.isArgumentPlaceholder(messageNode)) {
132
- handleUnminifyable(missingError, newExpressionPath);
133
- return;
134
- }
135
-
136
- const message = extractMessageFromExpression(t, messageNode);
137
-
138
- if (!message) {
139
- handleUnminifyable(missingError, newExpressionPath);
309
+ handleUnminifyableError(missingError, newExpressionPath);
140
310
  return;
141
311
  }
142
312
 
143
- let errorCode = errorCodesLookup.get(message.message);
144
- if (errorCode === undefined) {
145
- switch (missingError) {
146
- case 'annotate': {
147
- // Outputs:
148
- // /* FIXME (minify-errors-in-prod): Unminified error message in production build! */
149
- // throw new Error(`A message with ${interpolation}`)
150
- newExpressionPath.addComment(
151
- 'leading',
152
- ' FIXME (minify-errors-in-prod): Unminified error message in production build! ',
153
- );
154
- return;
155
- }
156
- case 'throw': {
157
- throw new Error(
158
- `Missing error code for message '${message.message}'. Did you forget to run \`pnpm extract-error-codes\` first?`,
159
- );
160
- }
161
- case 'write': {
162
- errorCode = errorCodesLookup.size + 1;
163
- errorCodesLookup.set(message.message, errorCode);
164
- state.updatedErrorCodes = true;
165
- break;
166
- }
167
- default: {
168
- throw new Error(`Unknown missingError option: ${missingError}`);
169
- }
170
- }
171
- }
172
-
173
- if (!state.formatMuiErrorMessageIdentifier) {
174
- // Outputs:
175
- // import { formatMuiErrorMessage } from '@mui/utils';
176
- state.formatMuiErrorMessageIdentifier = helperModuleImports.addDefault(
177
- newExpressionPath,
178
- '@mui/utils/formatMuiErrorMessage',
179
- { nameHint: '_formatMuiErrorMessage' },
180
- );
181
- }
182
-
183
- // Outputs:
184
- // `A ${adj} message that contains ${noun}`;
185
- const devMessage = messageNode;
186
-
187
- // Outputs:
188
- // formatMuiErrorMessage(ERROR_CODE, adj, noun)
189
- const prodMessage = t.callExpression(
190
- t.cloneNode(state.formatMuiErrorMessageIdentifier, true),
191
- [t.numericLiteral(errorCode), ...message.expressions],
313
+ const transformedMessage = transformMessage(
314
+ t,
315
+ newExpressionPath,
316
+ messageNode,
317
+ state,
318
+ errorCodesLookup,
319
+ missingError,
320
+ runtimeModule,
321
+ outExtension,
192
322
  );
193
323
 
194
- // Outputs:
195
- // new Error(
196
- // process.env.NODE_ENV !== "production"
197
- // ? `A message with ${interpolation}`
198
- // : formatProdError('A message with %s', interpolation)
199
- // )
200
- messagePath.replaceWith(
201
- t.conditionalExpression(
202
- t.binaryExpression(
203
- '!==',
204
- t.memberExpression(
205
- t.memberExpression(t.identifier('process'), t.identifier('env')),
206
- t.identifier('NODE_ENV'),
207
- ),
208
- t.stringLiteral('production'),
209
- ),
210
- devMessage,
211
- prodMessage,
212
- ),
213
- );
324
+ if (transformedMessage) {
325
+ messagePath.replaceWith(transformedMessage);
326
+ }
214
327
  },
215
328
  },
216
329
  post() {
package/index.test.js CHANGED
@@ -23,6 +23,7 @@ pluginTester({
23
23
  title: 'literal',
24
24
  pluginOptions: {
25
25
  errorCodesPath: path.join(fixturePath, 'literal', 'error-codes.json'),
26
+ runtimeModule: '@mui/utils/formatMuiErrorMessage',
26
27
  },
27
28
  fixture: path.join(fixturePath, 'literal', 'input.js'),
28
29
  output: readOutputFixtureSync('literal', 'output.js'),
@@ -31,6 +32,7 @@ pluginTester({
31
32
  title: 'interpolation',
32
33
  pluginOptions: {
33
34
  errorCodesPath: path.join(fixturePath, 'interpolation', 'error-codes.json'),
35
+ runtimeModule: '@mui/utils/formatMuiErrorMessage',
34
36
  },
35
37
  fixture: path.join(fixturePath, 'interpolation', 'input.js'),
36
38
  output: readOutputFixtureSync('interpolation', 'output.js'),
@@ -39,6 +41,7 @@ pluginTester({
39
41
  title: 'annotates missing error codes',
40
42
  pluginOptions: {
41
43
  errorCodesPath: path.join(fixturePath, 'no-error-code-annotation', 'error-codes.json'),
44
+ runtimeModule: '@mui/utils/formatMuiErrorMessage',
42
45
  },
43
46
  fixture: path.join(fixturePath, 'no-error-code-annotation', 'input.js'),
44
47
  output: readOutputFixtureSync('no-error-code-annotation', 'output.js'),
@@ -48,17 +51,19 @@ pluginTester({
48
51
  // babel prefixes with filename.
49
52
  // We're only interested in the message.
50
53
  error:
51
- /: Missing error code for message 'missing'. Did you forget to run `pnpm extract-error-codes` first?/,
54
+ /: Missing error code for message 'missing'. Did you forget to run `pnpm extract-error-codes` first\?/,
52
55
  fixture: path.join(fixturePath, 'no-error-code-throw', 'input.js'),
53
56
  pluginOptions: {
54
57
  errorCodesPath: path.join(fixturePath, 'no-error-code-throw', 'error-codes.json'),
55
58
  missingError: 'throw',
59
+ runtimeModule: '@mui/utils/formatMuiErrorMessage',
56
60
  },
57
61
  },
58
62
  {
59
63
  title: 'annotates unminifyable errors',
60
64
  pluginOptions: {
61
65
  errorCodesPath: path.join(fixturePath, 'unminifyable-annotation', 'error-codes.json'),
66
+ runtimeModule: '@mui/utils/formatMuiErrorMessage',
62
67
  },
63
68
  fixture: path.join(fixturePath, 'unminifyable-annotation', 'input.js'),
64
69
  output: readOutputFixtureSync('unminifyable-annotation', 'output.js'),
@@ -68,20 +73,21 @@ pluginTester({
68
73
  // babel prefixes with filename.
69
74
  // We're only interested in the message.
70
75
  error:
71
- /: Unminifyable error. You can only use literal strings and template strings as error messages.?/,
76
+ /: Unminifyable error. You can only use literal strings and template strings as error messages./,
72
77
  fixture: path.join(fixturePath, 'unminifyable-throw', 'input.js'),
73
78
  pluginOptions: {
74
79
  errorCodesPath: path.join(fixturePath, 'unminifyable-throw', 'error-codes.json'),
75
80
  missingError: 'throw',
81
+ runtimeModule: '@mui/utils/formatMuiErrorMessage',
76
82
  },
77
83
  },
78
84
  {
79
85
  title: 'can extract errors',
80
-
81
86
  fixture: path.join(fixturePath, 'error-code-extraction', 'input.js'),
82
87
  pluginOptions: {
83
88
  errorCodesPath: temporaryErrorCodesPath,
84
89
  missingError: 'write',
90
+ runtimeModule: '@mui/utils/formatMuiErrorMessage',
85
91
  },
86
92
  output: readOutputFixtureSync('error-code-extraction', 'output.js'),
87
93
  setup() {
@@ -108,5 +114,49 @@ pluginTester({
108
114
  };
109
115
  },
110
116
  },
117
+ {
118
+ title: 'uses custom runtime module',
119
+ pluginOptions: {
120
+ errorCodesPath: path.join(fixturePath, 'custom-runtime', 'error-codes.json'),
121
+ runtimeModule: '@custom/error-formatter',
122
+ },
123
+ fixture: path.join(fixturePath, 'custom-runtime', 'input.js'),
124
+ output: readOutputFixtureSync('custom-runtime', 'output.js'),
125
+ },
126
+ {
127
+ title: 'uses custom runtime module with imports',
128
+ pluginOptions: {
129
+ errorCodesPath: path.join(fixturePath, 'custom-runtime-imports', 'error-codes.json'),
130
+ runtimeModule: '#error-formatter',
131
+ },
132
+ fixture: path.join(fixturePath, 'custom-runtime-imports', 'input.js'),
133
+ output: readOutputFixtureSync('custom-runtime-imports', 'output.js'),
134
+ },
135
+ {
136
+ title: 'uses custom runtime module with relative path',
137
+ pluginOptions: {
138
+ errorCodesPath: path.join(
139
+ fixturePath,
140
+ 'custom-runtime-imports-relative',
141
+ 'error-codes.json',
142
+ ),
143
+ runtimeModule: '#error-formatter',
144
+ },
145
+ fixture: path.join(fixturePath, 'custom-runtime-imports-relative', 'input.js'),
146
+ output: readOutputFixtureSync('custom-runtime-imports-relative', 'output.js'),
147
+ },
148
+ {
149
+ title: 'uses custom runtime module with recursive imports',
150
+ pluginOptions: {
151
+ errorCodesPath: path.join(
152
+ fixturePath,
153
+ 'custom-runtime-imports-recursive',
154
+ 'error-codes.json',
155
+ ),
156
+ runtimeModule: '#error-formatter',
157
+ },
158
+ fixture: path.join(fixturePath, 'custom-runtime-imports-recursive', 'input.js'),
159
+ output: readOutputFixtureSync('custom-runtime-imports-recursive', 'output.js'),
160
+ },
111
161
  ],
112
162
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/internal-babel-plugin-minify-errors",
3
- "version": "1.0.13",
3
+ "version": "2.0.1",
4
4
  "author": "MUI Team",
5
5
  "description": "This is an internal package not meant for general use.",
6
6
  "repository": {
@@ -17,10 +17,12 @@
17
17
  "url": "https://opencollective.com/mui-org"
18
18
  },
19
19
  "dependencies": {
20
- "@babel/helper-module-imports": "^7.25.9"
20
+ "@babel/helper-module-imports": "^7.25.9",
21
+ "find-package-json": "^1.2.0"
21
22
  },
22
23
  "devDependencies": {
23
24
  "@types/babel__helper-module-imports": "^7.18.3",
25
+ "@types/find-package-json": "^1.2.6",
24
26
  "babel-plugin-tester": "^11.0.4",
25
27
  "chai": "^4.5.0"
26
28
  },