@mui/internal-babel-plugin-minify-errors 2.0.8-canary.7 → 2.0.8-canary.8

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/index.js CHANGED
@@ -1,26 +1,14 @@
1
- /**
2
- * @mui/internal-babel-plugin-minify-errors v2.0.8-canary.7
3
- *
4
- * @license MIT
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
- "use strict";
1
+ // @ts-check
2
+
3
+ const helperModuleImports = require('@babel/helper-module-imports');
4
+ const fs = require('fs');
5
+ const nodePath = require('path');
6
+ const finder = require('find-package-json');
9
7
 
10
- var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard")["default"];
11
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault")["default"];
12
- Object.defineProperty(exports, "__esModule", {
13
- value: true
14
- });
15
- exports["default"] = plugin;
16
- var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
17
- var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
18
- var helperModuleImports = _interopRequireWildcard(require("@babel/helper-module-imports"));
19
- var fs = _interopRequireWildcard(require("node:fs"));
20
- var nodePath = _interopRequireWildcard(require("node:path"));
21
- var _findPackageJson = _interopRequireDefault(require("find-package-json"));
22
8
  /**
23
9
  * Normalize a file path to POSIX in order for it to be platform-agnostic.
10
+ * @param {string} importPath
11
+ * @returns {string}
24
12
  */
25
13
  function toPosixPath(importPath) {
26
14
  return nodePath.normalize(importPath).split(nodePath.sep).join(nodePath.posix.sep);
@@ -28,45 +16,63 @@ function toPosixPath(importPath) {
28
16
 
29
17
  /**
30
18
  * Converts a file path to a node import specifier.
19
+ * @param {string} importPath
20
+ * @returns {string}
31
21
  */
32
22
  function pathToNodeImportSpecifier(importPath) {
33
- var normalized = toPosixPath(importPath);
34
- return normalized.startsWith('/') || normalized.startsWith('.') ? normalized : "./".concat(normalized);
23
+ const normalized = toPosixPath(importPath);
24
+ return normalized.startsWith('/') || normalized.startsWith('.') ? normalized : `./${normalized}`;
35
25
  }
36
- var COMMENT_OPT_IN_MARKER = 'minify-error';
37
- var COMMENT_OPT_OUT_MARKER = 'minify-error-disabled';
26
+
27
+ const COMMENT_OPT_IN_MARKER = 'minify-error';
28
+ const COMMENT_OPT_OUT_MARKER = 'minify-error-disabled';
29
+
30
+ /**
31
+ * @typedef {import('@babel/core')} babel
32
+ */
33
+
34
+ /**
35
+ * @typedef {babel.PluginPass & {updatedErrorCodes?: boolean, formatErrorMessageIdentifier?: babel.types.Identifier}} PluginState
36
+ * @typedef {'annotate' | 'throw' | 'write'} MissingError
37
+ * @typedef {{
38
+ * errorCodesPath: string,
39
+ * missingError: MissingError,
40
+ * runtimeModule?: string,
41
+ * detection?: 'opt-in' | 'opt-out',
42
+ * outExtension?: string
43
+ * }} Options
44
+ */
45
+
38
46
  /**
39
47
  * Extracts the message and expressions from a node.
48
+ * @param {babel.types} t
49
+ * @param {babel.types.Node} node
50
+ * @returns {{ message: string, expressions: babel.types.Expression[] } | null}
40
51
  */
41
52
  function extractMessage(t, node) {
42
53
  if (t.isTemplateLiteral(node)) {
43
54
  return {
44
- message: node.quasis.map(function (quasi) {
45
- return quasi.value.cooked;
46
- }).join('%s'),
47
- expressions: node.expressions.map(function (expression) {
55
+ message: node.quasis.map((quasi) => quasi.value.cooked).join('%s'),
56
+ expressions: node.expressions.map((expression) => {
48
57
  if (t.isExpression(expression)) {
49
58
  return expression;
50
59
  }
51
60
  throw new Error('Can only evaluate javascript template literals.');
52
- })
61
+ }),
53
62
  };
54
63
  }
55
64
  if (t.isStringLiteral(node)) {
56
- return {
57
- message: node.value,
58
- expressions: []
59
- };
65
+ return { message: node.value, expressions: [] };
60
66
  }
61
67
  if (t.isBinaryExpression(node) && node.operator === '+') {
62
- var left = extractMessage(t, node.left);
63
- var right = extractMessage(t, node.right);
68
+ const left = extractMessage(t, node.left);
69
+ const right = extractMessage(t, node.right);
64
70
  if (!left || !right) {
65
71
  return null;
66
72
  }
67
73
  return {
68
74
  message: left.message + right.message,
69
- expressions: [].concat((0, _toConsumableArray2["default"])(left.expressions), (0, _toConsumableArray2["default"])(right.expressions))
75
+ expressions: [...left.expressions, ...right.expressions],
70
76
  };
71
77
  }
72
78
  return null;
@@ -74,189 +80,259 @@ function extractMessage(t, node) {
74
80
 
75
81
  /**
76
82
  * Handles unminifyable errors based on the missingError option.
83
+ * @param {MissingError} missingError
84
+ * @param {babel.NodePath} path
77
85
  */
78
86
  function handleUnminifyableError(missingError, path) {
79
87
  switch (missingError) {
80
88
  case 'annotate':
81
- path.addComment('leading', ' FIXME (minify-errors-in-prod): Unminifyable error in production! ');
89
+ path.addComment(
90
+ 'leading',
91
+ ' FIXME (minify-errors-in-prod): Unminifyable error in production! ',
92
+ );
82
93
  break;
83
94
  case 'throw':
84
- throw new Error('Unminifyable error. You can only use literal strings and template strings as error messages.');
95
+ throw new Error(
96
+ 'Unminifyable error. You can only use literal strings and template strings as error messages.',
97
+ );
85
98
  case 'write':
86
99
  break;
87
100
  default:
88
- throw new Error("Unknown missingError option: ".concat(missingError));
101
+ throw new Error(`Unknown missingError option: ${missingError}`);
89
102
  }
90
103
  }
91
104
 
92
105
  /**
93
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}
94
116
  */
95
- function transformMessage(t, path, messageNode, state, errorCodesLookup, missingError, runtimeModule, outExtension) {
96
- var message = extractMessage(t, messageNode);
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);
97
128
  if (!message) {
98
129
  handleUnminifyableError(missingError, path);
99
130
  return null;
100
131
  }
101
- var errorCode = errorCodesLookup.get(message.message);
132
+
133
+ let errorCode = errorCodesLookup.get(message.message);
102
134
  if (errorCode === undefined) {
103
135
  switch (missingError) {
104
136
  case 'annotate':
105
- path.addComment('leading', ' FIXME (minify-errors-in-prod): Unminified error message in production build! ');
137
+ path.addComment(
138
+ 'leading',
139
+ ' FIXME (minify-errors-in-prod): Unminified error message in production build! ',
140
+ );
106
141
  return null;
107
142
  case 'throw':
108
- throw new Error("Missing error code for message '".concat(message.message, "'. Did you forget to run `pnpm extract-error-codes` first?"));
143
+ throw new Error(
144
+ `Missing error code for message '${message.message}'. Did you forget to run \`pnpm extract-error-codes\` first?`,
145
+ );
109
146
  case 'write':
110
147
  errorCode = errorCodesLookup.size + 1;
111
148
  errorCodesLookup.set(message.message, errorCode);
112
149
  state.updatedErrorCodes = true;
113
150
  break;
114
151
  default:
115
- throw new Error("Unknown missingError option: ".concat(missingError));
152
+ throw new Error(`Unknown missingError option: ${missingError}`);
116
153
  }
117
154
  }
155
+
118
156
  if (!state.formatErrorMessageIdentifier) {
119
- state.formatErrorMessageIdentifier = helperModuleImports.addDefault(path, transformExtension(resolveRuntimeModule(runtimeModule, state), outExtension), {
120
- nameHint: '_formatErrorMessage'
121
- });
157
+ state.formatErrorMessageIdentifier = helperModuleImports.addDefault(
158
+ path,
159
+ transformExtension(resolveRuntimeModule(runtimeModule, state), outExtension),
160
+ { nameHint: '_formatErrorMessage' },
161
+ );
122
162
  }
123
- return t.conditionalExpression(t.binaryExpression('!==', t.memberExpression(t.memberExpression(t.identifier('process'), t.identifier('env')), t.identifier('NODE_ENV')), t.stringLiteral('production')), messageNode, t.callExpression(t.cloneNode(state.formatErrorMessageIdentifier, true), [t.numericLiteral(errorCode)].concat((0, _toConsumableArray2["default"])(message.expressions))));
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
+ );
124
179
  }
125
180
 
126
181
  /**
127
182
  * Resolves the runtime module path recursively.
183
+ * @param {string} runtimeModule
184
+ * @param {PluginState} state
185
+ * @param {Set<string>} [visitedModules]
186
+ * @returns {string}
128
187
  */
129
- function resolveRuntimeModule(runtimeModule, state) {
130
- var _pkg$imports;
131
- var visitedModules = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : new Set();
188
+ function resolveRuntimeModule(runtimeModule, state, visitedModules = new Set()) {
132
189
  if (!runtimeModule.startsWith('#')) {
133
190
  return runtimeModule;
134
191
  }
135
- var currentFile = state.filename;
192
+
193
+ const currentFile = state.filename;
136
194
  if (!currentFile) {
137
195
  throw new Error('filename is not defined');
138
196
  }
139
- var result = (0, _findPackageJson["default"])(currentFile).next();
197
+
198
+ const result = finder(currentFile).next();
140
199
  if (result.done) {
141
200
  throw new Error('Could not find package.json');
142
201
  }
143
- var pkg = result.value;
144
- var pkgPath = result.filename;
145
- var runtimeModulePath = pkg == null || (_pkg$imports = pkg.imports) == null ? void 0 : _pkg$imports[runtimeModule];
202
+
203
+ const pkg = result.value;
204
+ const pkgPath = result.filename;
205
+ const runtimeModulePath = pkg?.imports?.[runtimeModule];
146
206
  if (typeof runtimeModulePath !== 'string') {
147
- throw new Error("Invalid runtime module path for ".concat(runtimeModule));
207
+ throw new Error(`Invalid runtime module path for ${runtimeModule}`);
148
208
  }
209
+
149
210
  if (visitedModules.has(runtimeModule)) {
150
- throw new Error("Circular import detected for ".concat(runtimeModule));
211
+ throw new Error(`Circular import detected for ${runtimeModule}`);
151
212
  }
152
213
  visitedModules.add(runtimeModule);
214
+
153
215
  if (runtimeModulePath.startsWith('.')) {
154
- var resolvedPath = nodePath.resolve(nodePath.dirname(pkgPath), runtimeModulePath);
155
- var relativePath = nodePath.relative(nodePath.dirname(currentFile), resolvedPath);
216
+ const resolvedPath = nodePath.resolve(nodePath.dirname(pkgPath), runtimeModulePath);
217
+ const relativePath = nodePath.relative(nodePath.dirname(currentFile), resolvedPath);
156
218
  return pathToNodeImportSpecifier(relativePath);
157
219
  }
220
+
158
221
  return resolveRuntimeModule(runtimeModulePath, state, visitedModules);
159
222
  }
160
223
 
161
224
  /**
162
- * Transform file extension of import specifier.
225
+ *
226
+ * @param {string} importSpecifier
227
+ * @param {string} outExtension
228
+ * @returns
163
229
  */
164
- function transformExtension(importSpecifier) {
165
- var outExtension = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '.js';
230
+ function transformExtension(importSpecifier, outExtension = '.js') {
166
231
  return importSpecifier.replace(/\.[a-zA-Z0-9]+$/, outExtension);
167
232
  }
168
233
 
169
234
  /**
170
- * Babel plugin for minifying error messages.
235
+ * @param {babel} file
236
+ * @param {Options} options
237
+ * @returns {babel.PluginObj<PluginState>}
171
238
  */
172
- function plugin(_ref, _ref2) {
173
- var t = _ref.types;
174
- var errorCodesPath = _ref2.errorCodesPath,
175
- _ref2$missingError = _ref2.missingError,
176
- missingError = _ref2$missingError === void 0 ? 'annotate' : _ref2$missingError,
177
- _ref2$runtimeModule = _ref2.runtimeModule,
178
- runtimeModule = _ref2$runtimeModule === void 0 ? '#formatErrorMessage' : _ref2$runtimeModule,
179
- _ref2$detection = _ref2.detection,
180
- detection = _ref2$detection === void 0 ? 'opt-in' : _ref2$detection,
181
- _ref2$outExtension = _ref2.outExtension,
182
- outExtension = _ref2$outExtension === void 0 ? '.js' : _ref2$outExtension;
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
+ ) {
183
249
  if (!errorCodesPath) {
184
250
  throw new Error('errorCodesPath is required.');
185
251
  }
186
- var errorCodesContent = fs.readFileSync(errorCodesPath, 'utf8');
187
- var errorCodes = JSON.parse(errorCodesContent);
188
- var errorCodesLookup = new Map(Object.entries(errorCodes).map(function (_ref3) {
189
- var _ref4 = (0, _slicedToArray2["default"])(_ref3, 2),
190
- key = _ref4[0],
191
- value = _ref4[1];
192
- return [value, Number(key)];
193
- }));
252
+
253
+ const errorCodesContent = fs.readFileSync(errorCodesPath, 'utf8');
254
+ const errorCodes = JSON.parse(errorCodesContent);
255
+
256
+ const errorCodesLookup = new Map(
257
+ Object.entries(errorCodes).map(([key, value]) => [value, Number(key)]),
258
+ );
259
+
194
260
  return {
195
261
  name: '@mui/internal-babel-plugin-minify-errors',
196
262
  visitor: {
197
- NewExpression: function NewExpression(newExpressionPath, state) {
198
- if (!newExpressionPath.get('callee').isIdentifier({
199
- name: 'Error'
200
- })) {
263
+ NewExpression(newExpressionPath, state) {
264
+ if (!newExpressionPath.get('callee').isIdentifier({ name: 'Error' })) {
201
265
  return;
202
266
  }
267
+
203
268
  switch (detection) {
204
- case 'opt-in':
205
- {
206
- var _newExpressionPath$no;
207
- if (!((_newExpressionPath$no = newExpressionPath.node.leadingComments) != null && _newExpressionPath$no.some(function (comment) {
208
- return comment.value.includes(COMMENT_OPT_IN_MARKER);
209
- }))) {
210
- return;
211
- }
212
- newExpressionPath.node.leadingComments = newExpressionPath.node.leadingComments.filter(function (comment) {
213
- return !comment.value.includes(COMMENT_OPT_IN_MARKER);
214
- });
215
- break;
269
+ case 'opt-in': {
270
+ if (
271
+ !newExpressionPath.node.leadingComments?.some((comment) =>
272
+ comment.value.includes(COMMENT_OPT_IN_MARKER),
273
+ )
274
+ ) {
275
+ return;
216
276
  }
217
- case 'opt-out':
218
- {
219
- var _newExpressionPath$no2;
220
- if ((_newExpressionPath$no2 = newExpressionPath.node.leadingComments) != null && _newExpressionPath$no2.some(function (comment) {
221
- return comment.value.includes(COMMENT_OPT_OUT_MARKER);
222
- })) {
223
- newExpressionPath.node.leadingComments = newExpressionPath.node.leadingComments.filter(function (comment) {
224
- return !comment.value.includes(COMMENT_OPT_OUT_MARKER);
225
- });
226
- return;
227
- }
228
- break;
229
- }
230
- default:
231
- {
232
- throw new Error("Unknown detection option: ".concat(detection));
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;
233
293
  }
294
+
295
+ break;
296
+ }
297
+ default: {
298
+ throw new Error(`Unknown detection option: ${detection}`);
299
+ }
234
300
  }
235
- var messagePath = newExpressionPath.get('arguments')[0];
301
+
302
+ const messagePath = newExpressionPath.get('arguments')[0];
236
303
  if (!messagePath) {
237
304
  return;
238
305
  }
239
- var messageNode = messagePath.node;
306
+
307
+ const messageNode = messagePath.node;
240
308
  if (t.isSpreadElement(messageNode) || t.isArgumentPlaceholder(messageNode)) {
241
309
  handleUnminifyableError(missingError, newExpressionPath);
242
310
  return;
243
311
  }
244
- var transformedMessage = transformMessage(t, newExpressionPath, messageNode, state, errorCodesLookup, missingError, runtimeModule, outExtension);
312
+
313
+ const transformedMessage = transformMessage(
314
+ t,
315
+ newExpressionPath,
316
+ messageNode,
317
+ state,
318
+ errorCodesLookup,
319
+ missingError,
320
+ runtimeModule,
321
+ outExtension,
322
+ );
323
+
245
324
  if (transformedMessage) {
246
325
  messagePath.replaceWith(transformedMessage);
247
326
  }
248
- }
327
+ },
249
328
  },
250
- post: function post() {
329
+ post() {
251
330
  if (missingError === 'write' && this.updatedErrorCodes) {
252
- var invertedErrorCodes = Object.fromEntries(Array.from(errorCodesLookup, function (_ref5) {
253
- var _ref6 = (0, _slicedToArray2["default"])(_ref5, 2),
254
- key = _ref6[0],
255
- value = _ref6[1];
256
- return [value, key];
257
- }));
258
- fs.writeFileSync(errorCodesPath, "".concat(JSON.stringify(invertedErrorCodes, null, 2), "\n"));
331
+ const invertedErrorCodes = Object.fromEntries(
332
+ Array.from(errorCodesLookup, ([key, value]) => [value, key]),
333
+ );
334
+ fs.writeFileSync(errorCodesPath, `${JSON.stringify(invertedErrorCodes, null, 2)}\n`);
259
335
  }
260
- }
336
+ },
261
337
  };
262
- }
338
+ };
package/index.test.js ADDED
@@ -0,0 +1,170 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ import { pluginTester } from 'babel-plugin-tester';
5
+ import { expect } from 'vitest';
6
+ import plugin from './index';
7
+
8
+ const temporaryErrorCodesPath = path.join(os.tmpdir(), 'error-codes.json');
9
+ const fixturePath = path.resolve(__dirname, './__fixtures__');
10
+
11
+ /**
12
+ *
13
+ * @param {string} fixture
14
+ * @param {string} file
15
+ * @returns {string}
16
+ */
17
+ function readOutputFixtureSync(fixture, file) {
18
+ // babel hardcodes the linefeed to \n
19
+ return fs
20
+ .readFileSync(path.join(fixturePath, fixture, file), { encoding: 'utf8' })
21
+ .replace(/\r?\n/g, '\n');
22
+ }
23
+
24
+ pluginTester({
25
+ plugin,
26
+ pluginName: 'minify-errors',
27
+ filepath: __filename,
28
+ tests: [
29
+ {
30
+ title: 'literal',
31
+ pluginOptions: {
32
+ errorCodesPath: path.join(fixturePath, 'literal', 'error-codes.json'),
33
+ runtimeModule: '@mui/utils/formatMuiErrorMessage',
34
+ },
35
+ fixture: path.join(fixturePath, 'literal', 'input.js'),
36
+ output: readOutputFixtureSync('literal', 'output.js'),
37
+ },
38
+ {
39
+ title: 'interpolation',
40
+ pluginOptions: {
41
+ errorCodesPath: path.join(fixturePath, 'interpolation', 'error-codes.json'),
42
+ runtimeModule: '@mui/utils/formatMuiErrorMessage',
43
+ },
44
+ fixture: path.join(fixturePath, 'interpolation', 'input.js'),
45
+ output: readOutputFixtureSync('interpolation', 'output.js'),
46
+ },
47
+ {
48
+ title: 'annotates missing error codes',
49
+ pluginOptions: {
50
+ errorCodesPath: path.join(fixturePath, 'no-error-code-annotation', 'error-codes.json'),
51
+ runtimeModule: '@mui/utils/formatMuiErrorMessage',
52
+ },
53
+ fixture: path.join(fixturePath, 'no-error-code-annotation', 'input.js'),
54
+ output: readOutputFixtureSync('no-error-code-annotation', 'output.js'),
55
+ },
56
+ {
57
+ title: 'can throw on missing error codes',
58
+ // babel prefixes with filename.
59
+ // We're only interested in the message.
60
+ error:
61
+ /: Missing error code for message 'missing'. Did you forget to run `pnpm extract-error-codes` first\?/,
62
+ fixture: path.join(fixturePath, 'no-error-code-throw', 'input.js'),
63
+ pluginOptions: {
64
+ errorCodesPath: path.join(fixturePath, 'no-error-code-throw', 'error-codes.json'),
65
+ missingError: 'throw',
66
+ runtimeModule: '@mui/utils/formatMuiErrorMessage',
67
+ },
68
+ },
69
+ {
70
+ title: 'annotates unminifyable errors',
71
+ pluginOptions: {
72
+ errorCodesPath: path.join(fixturePath, 'unminifyable-annotation', 'error-codes.json'),
73
+ runtimeModule: '@mui/utils/formatMuiErrorMessage',
74
+ },
75
+ fixture: path.join(fixturePath, 'unminifyable-annotation', 'input.js'),
76
+ output: readOutputFixtureSync('unminifyable-annotation', 'output.js'),
77
+ },
78
+ {
79
+ title: 'can throw on unminifyable errors',
80
+ // babel prefixes with filename.
81
+ // We're only interested in the message.
82
+ error:
83
+ /: Unminifyable error. You can only use literal strings and template strings as error messages./,
84
+ fixture: path.join(fixturePath, 'unminifyable-throw', 'input.js'),
85
+ pluginOptions: {
86
+ errorCodesPath: path.join(fixturePath, 'unminifyable-throw', 'error-codes.json'),
87
+ missingError: 'throw',
88
+ runtimeModule: '@mui/utils/formatMuiErrorMessage',
89
+ },
90
+ },
91
+ {
92
+ title: 'can extract errors',
93
+ fixture: path.join(fixturePath, 'error-code-extraction', 'input.js'),
94
+ pluginOptions: {
95
+ errorCodesPath: temporaryErrorCodesPath,
96
+ missingError: 'write',
97
+ runtimeModule: '@mui/utils/formatMuiErrorMessage',
98
+ },
99
+ output: readOutputFixtureSync('error-code-extraction', 'output.js'),
100
+ setup() {
101
+ fs.copyFileSync(
102
+ path.join(fixturePath, 'error-code-extraction', 'error-codes.before.json'),
103
+ temporaryErrorCodesPath,
104
+ );
105
+
106
+ return function teardown() {
107
+ try {
108
+ const actualErrorCodes = JSON.parse(
109
+ fs.readFileSync(temporaryErrorCodesPath, { encoding: 'utf8' }),
110
+ );
111
+ const expectedErrorCodes = JSON.parse(
112
+ fs.readFileSync(
113
+ path.join(fixturePath, 'error-code-extraction', 'error-codes.after.json'),
114
+ 'utf-8',
115
+ ),
116
+ );
117
+
118
+ expect(actualErrorCodes).to.deep.equal(expectedErrorCodes);
119
+ } finally {
120
+ fs.unlinkSync(temporaryErrorCodesPath);
121
+ }
122
+ };
123
+ },
124
+ },
125
+ {
126
+ title: 'uses custom runtime module',
127
+ pluginOptions: {
128
+ errorCodesPath: path.join(fixturePath, 'custom-runtime', 'error-codes.json'),
129
+ runtimeModule: '@custom/error-formatter',
130
+ },
131
+ fixture: path.join(fixturePath, 'custom-runtime', 'input.js'),
132
+ output: readOutputFixtureSync('custom-runtime', 'output.js'),
133
+ },
134
+ {
135
+ title: 'uses custom runtime module with imports',
136
+ pluginOptions: {
137
+ errorCodesPath: path.join(fixturePath, 'custom-runtime-imports', 'error-codes.json'),
138
+ runtimeModule: '#error-formatter',
139
+ },
140
+ fixture: path.join(fixturePath, 'custom-runtime-imports', 'input.js'),
141
+ output: readOutputFixtureSync('custom-runtime-imports', 'output.js'),
142
+ },
143
+ {
144
+ title: 'uses custom runtime module with relative path',
145
+ pluginOptions: {
146
+ errorCodesPath: path.join(
147
+ fixturePath,
148
+ 'custom-runtime-imports-relative',
149
+ 'error-codes.json',
150
+ ),
151
+ runtimeModule: '#error-formatter',
152
+ },
153
+ fixture: path.join(fixturePath, 'custom-runtime-imports-relative', 'input.js'),
154
+ output: readOutputFixtureSync('custom-runtime-imports-relative', 'output.js'),
155
+ },
156
+ {
157
+ title: 'uses custom runtime module with recursive imports',
158
+ pluginOptions: {
159
+ errorCodesPath: path.join(
160
+ fixturePath,
161
+ 'custom-runtime-imports-recursive',
162
+ 'error-codes.json',
163
+ ),
164
+ runtimeModule: '#error-formatter',
165
+ },
166
+ fixture: path.join(fixturePath, 'custom-runtime-imports-recursive', 'input.js'),
167
+ output: readOutputFixtureSync('custom-runtime-imports-recursive', 'output.js'),
168
+ },
169
+ ],
170
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/internal-babel-plugin-minify-errors",
3
- "version": "2.0.8-canary.7",
3
+ "version": "2.0.8-canary.8",
4
4
  "author": "MUI Team",
5
5
  "description": "This is an internal package not meant for general use.",
6
6
  "repository": {
@@ -20,32 +20,28 @@
20
20
  "@babel/helper-module-imports": "^7.27.1",
21
21
  "find-package-json": "^1.2.0"
22
22
  },
23
+ "devDependencies": {
24
+ "@babel/core": "^7.28.3",
25
+ "@types/babel__core": "^7.20.5",
26
+ "@types/babel__helper-module-imports": "^7.18.3",
27
+ "@types/find-package-json": "^1.2.6",
28
+ "babel-plugin-tester": "^12.0.0"
29
+ },
23
30
  "peerDependencies": {
24
31
  "@babel/core": "7"
25
32
  },
26
33
  "sideEffects": false,
27
34
  "type": "commonjs",
35
+ "main": "./index.js",
36
+ "exports": {
37
+ ".": "./index.js"
38
+ },
28
39
  "engines": {
29
40
  "node": ">=14.0.0"
30
41
  },
31
42
  "publishConfig": {
32
43
  "access": "public"
33
44
  },
34
- "gitSha": "ad561386f8eaa51a46c7ce0c17df6ad1ba929d3d",
35
- "main": "./index.js",
36
- "types": "./index.d.ts",
37
- "exports": {
38
- "./package.json": "./package.json",
39
- ".": {
40
- "import": {
41
- "types": "./esm/index.d.ts",
42
- "default": "./esm/index.js"
43
- },
44
- "require": {
45
- "types": "./index.d.ts",
46
- "default": "./index.js"
47
- }
48
- },
49
- "./esm": null
50
- }
45
+ "gitSha": "6a3e097acfa56e9838d2edb7f05755bda41f365d",
46
+ "scripts": {}
51
47
  }
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "node",
6
+ "allowJs": true,
7
+ "checkJs": true,
8
+ "skipLibCheck": true,
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "resolveJsonModule": true,
12
+ "isolatedModules": true,
13
+ "outDir": "./build",
14
+ "noEmit": true,
15
+ "composite": true
16
+ },
17
+ "include": ["."],
18
+ "exclude": ["node_modules", "build", "__fixtures__"]
19
+ }
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ // babel-plugin-tester expects it
6
+ globals: true,
7
+ },
8
+ });
package/CHANGELOG.md DELETED
@@ -1,5 +0,0 @@
1
- # Versions
2
-
3
- ## 2.0.6
4
-
5
- Changelog start
package/README.md DELETED
@@ -1,38 +0,0 @@
1
- # MUI Public
2
-
3
- Mono-repository for the MUI organization with code that can be public.
4
- See https://github.com/mui/mui-private for code that needs to be private.
5
-
6
- ## Applications
7
-
8
- ### [tools-public.mui.com](https://tools-public.mui.com/)
9
-
10
- - Folder: `/apps/tools-public/`
11
- - Hosting: https://dashboard.render.com/web/srv-d08mooq4d50c73fso49g
12
- - [Docs](./apps/tools-public/#readme)
13
-
14
- Internal public Toolpad apps that run the operations of MUI, built using https://github.com/mui/toolpad.
15
-
16
- ### [frontend-public.mui.com](https://frontend-public.mui.com/)
17
-
18
- - Folder: `/apps/code-infra-dashboard/`
19
- - Hosting: https://app.netlify.com/sites/mui-frontend-public/overview
20
- - [Docs](./apps/code-infra-dashboard/#readme)
21
-
22
- ## Versioning
23
-
24
- Steps:
25
-
26
- 1. Checkout latest master
27
- 1. Run `pnpm release:prepare`
28
- 1. Run `pnpm release:version`
29
- 1. Open PR with the changes
30
-
31
- ## Publishing
32
-
33
- Steps:
34
-
35
- 1. Merge versioning PR
36
- 1. Checkout release commit on master
37
- 1. Run `pnpm release:prepare`
38
- 1. Run `pnpm release:publish`
package/esm/index.d.ts DELETED
@@ -1,25 +0,0 @@
1
- import * as babel from '@babel/core';
2
- export interface PluginState extends babel.PluginPass {
3
- updatedErrorCodes?: boolean;
4
- formatErrorMessageIdentifier?: babel.types.Identifier;
5
- }
6
- export type MissingError = 'annotate' | 'throw' | 'write';
7
- export interface Options {
8
- errorCodesPath: string;
9
- missingError?: MissingError;
10
- runtimeModule?: string;
11
- detection?: 'opt-in' | 'opt-out';
12
- outExtension?: string;
13
- }
14
- /**
15
- * Babel plugin for minifying error messages.
16
- */
17
- export default function plugin({
18
- types: t
19
- }: typeof babel, {
20
- errorCodesPath,
21
- missingError,
22
- runtimeModule,
23
- detection,
24
- outExtension
25
- }: Options): babel.PluginObj<PluginState>;
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../home/runner/work/mui-public/mui-public/packages/babel-plugin-minify-errors/src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AAuBrC,MAAM,WAAW,WAAY,SAAQ,KAAK,CAAC,UAAU;IACnD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,4BAA4B,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC;CACvD;AAED,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1D,MAAM,WAAW,OAAO;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAkLD;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAC5B,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,EAC1B,EACE,cAAc,EACd,YAAyB,EACzB,aAAqC,EACrC,SAAoB,EACpB,YAAoB,GACrB,EAAE,OAAO,GACT,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CA6F9B"}
package/esm/index.js DELETED
@@ -1,255 +0,0 @@
1
- /**
2
- * @mui/internal-babel-plugin-minify-errors v2.0.8-canary.7
3
- *
4
- * @license MIT
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
- import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
9
- import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
10
- import * as helperModuleImports from '@babel/helper-module-imports';
11
- import * as fs from 'node:fs';
12
- import * as nodePath from 'node:path';
13
- import finder from 'find-package-json';
14
-
15
- /**
16
- * Normalize a file path to POSIX in order for it to be platform-agnostic.
17
- */
18
- function toPosixPath(importPath) {
19
- return nodePath.normalize(importPath).split(nodePath.sep).join(nodePath.posix.sep);
20
- }
21
-
22
- /**
23
- * Converts a file path to a node import specifier.
24
- */
25
- function pathToNodeImportSpecifier(importPath) {
26
- var normalized = toPosixPath(importPath);
27
- return normalized.startsWith('/') || normalized.startsWith('.') ? normalized : "./".concat(normalized);
28
- }
29
- var COMMENT_OPT_IN_MARKER = 'minify-error';
30
- var COMMENT_OPT_OUT_MARKER = 'minify-error-disabled';
31
- /**
32
- * Extracts the message and expressions from a node.
33
- */
34
- function extractMessage(t, node) {
35
- if (t.isTemplateLiteral(node)) {
36
- return {
37
- message: node.quasis.map(function (quasi) {
38
- return quasi.value.cooked;
39
- }).join('%s'),
40
- expressions: node.expressions.map(function (expression) {
41
- if (t.isExpression(expression)) {
42
- return expression;
43
- }
44
- throw new Error('Can only evaluate javascript template literals.');
45
- })
46
- };
47
- }
48
- if (t.isStringLiteral(node)) {
49
- return {
50
- message: node.value,
51
- expressions: []
52
- };
53
- }
54
- if (t.isBinaryExpression(node) && node.operator === '+') {
55
- var left = extractMessage(t, node.left);
56
- var right = extractMessage(t, node.right);
57
- if (!left || !right) {
58
- return null;
59
- }
60
- return {
61
- message: left.message + right.message,
62
- expressions: [].concat(_toConsumableArray(left.expressions), _toConsumableArray(right.expressions))
63
- };
64
- }
65
- return null;
66
- }
67
-
68
- /**
69
- * Handles unminifyable errors based on the missingError option.
70
- */
71
- function handleUnminifyableError(missingError, path) {
72
- switch (missingError) {
73
- case 'annotate':
74
- path.addComment('leading', ' FIXME (minify-errors-in-prod): Unminifyable error in production! ');
75
- break;
76
- case 'throw':
77
- throw new Error('Unminifyable error. You can only use literal strings and template strings as error messages.');
78
- case 'write':
79
- break;
80
- default:
81
- throw new Error("Unknown missingError option: ".concat(missingError));
82
- }
83
- }
84
-
85
- /**
86
- * Transforms the error message node.
87
- */
88
- function transformMessage(t, path, messageNode, state, errorCodesLookup, missingError, runtimeModule, outExtension) {
89
- var message = extractMessage(t, messageNode);
90
- if (!message) {
91
- handleUnminifyableError(missingError, path);
92
- return null;
93
- }
94
- var errorCode = errorCodesLookup.get(message.message);
95
- if (errorCode === undefined) {
96
- switch (missingError) {
97
- case 'annotate':
98
- path.addComment('leading', ' FIXME (minify-errors-in-prod): Unminified error message in production build! ');
99
- return null;
100
- case 'throw':
101
- throw new Error("Missing error code for message '".concat(message.message, "'. Did you forget to run `pnpm extract-error-codes` first?"));
102
- case 'write':
103
- errorCode = errorCodesLookup.size + 1;
104
- errorCodesLookup.set(message.message, errorCode);
105
- state.updatedErrorCodes = true;
106
- break;
107
- default:
108
- throw new Error("Unknown missingError option: ".concat(missingError));
109
- }
110
- }
111
- if (!state.formatErrorMessageIdentifier) {
112
- state.formatErrorMessageIdentifier = helperModuleImports.addDefault(path, transformExtension(resolveRuntimeModule(runtimeModule, state), outExtension), {
113
- nameHint: '_formatErrorMessage'
114
- });
115
- }
116
- return t.conditionalExpression(t.binaryExpression('!==', t.memberExpression(t.memberExpression(t.identifier('process'), t.identifier('env')), t.identifier('NODE_ENV')), t.stringLiteral('production')), messageNode, t.callExpression(t.cloneNode(state.formatErrorMessageIdentifier, true), [t.numericLiteral(errorCode)].concat(_toConsumableArray(message.expressions))));
117
- }
118
-
119
- /**
120
- * Resolves the runtime module path recursively.
121
- */
122
- function resolveRuntimeModule(runtimeModule, state) {
123
- var _pkg$imports;
124
- var visitedModules = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : new Set();
125
- if (!runtimeModule.startsWith('#')) {
126
- return runtimeModule;
127
- }
128
- var currentFile = state.filename;
129
- if (!currentFile) {
130
- throw new Error('filename is not defined');
131
- }
132
- var result = finder(currentFile).next();
133
- if (result.done) {
134
- throw new Error('Could not find package.json');
135
- }
136
- var pkg = result.value;
137
- var pkgPath = result.filename;
138
- var runtimeModulePath = pkg == null || (_pkg$imports = pkg.imports) == null ? void 0 : _pkg$imports[runtimeModule];
139
- if (typeof runtimeModulePath !== 'string') {
140
- throw new Error("Invalid runtime module path for ".concat(runtimeModule));
141
- }
142
- if (visitedModules.has(runtimeModule)) {
143
- throw new Error("Circular import detected for ".concat(runtimeModule));
144
- }
145
- visitedModules.add(runtimeModule);
146
- if (runtimeModulePath.startsWith('.')) {
147
- var resolvedPath = nodePath.resolve(nodePath.dirname(pkgPath), runtimeModulePath);
148
- var relativePath = nodePath.relative(nodePath.dirname(currentFile), resolvedPath);
149
- return pathToNodeImportSpecifier(relativePath);
150
- }
151
- return resolveRuntimeModule(runtimeModulePath, state, visitedModules);
152
- }
153
-
154
- /**
155
- * Transform file extension of import specifier.
156
- */
157
- function transformExtension(importSpecifier) {
158
- var outExtension = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '.js';
159
- return importSpecifier.replace(/\.[a-zA-Z0-9]+$/, outExtension);
160
- }
161
-
162
- /**
163
- * Babel plugin for minifying error messages.
164
- */
165
- export default function plugin(_ref, _ref2) {
166
- var t = _ref.types;
167
- var errorCodesPath = _ref2.errorCodesPath,
168
- _ref2$missingError = _ref2.missingError,
169
- missingError = _ref2$missingError === void 0 ? 'annotate' : _ref2$missingError,
170
- _ref2$runtimeModule = _ref2.runtimeModule,
171
- runtimeModule = _ref2$runtimeModule === void 0 ? '#formatErrorMessage' : _ref2$runtimeModule,
172
- _ref2$detection = _ref2.detection,
173
- detection = _ref2$detection === void 0 ? 'opt-in' : _ref2$detection,
174
- _ref2$outExtension = _ref2.outExtension,
175
- outExtension = _ref2$outExtension === void 0 ? '.js' : _ref2$outExtension;
176
- if (!errorCodesPath) {
177
- throw new Error('errorCodesPath is required.');
178
- }
179
- var errorCodesContent = fs.readFileSync(errorCodesPath, 'utf8');
180
- var errorCodes = JSON.parse(errorCodesContent);
181
- var errorCodesLookup = new Map(Object.entries(errorCodes).map(function (_ref3) {
182
- var _ref4 = _slicedToArray(_ref3, 2),
183
- key = _ref4[0],
184
- value = _ref4[1];
185
- return [value, Number(key)];
186
- }));
187
- return {
188
- name: '@mui/internal-babel-plugin-minify-errors',
189
- visitor: {
190
- NewExpression: function NewExpression(newExpressionPath, state) {
191
- if (!newExpressionPath.get('callee').isIdentifier({
192
- name: 'Error'
193
- })) {
194
- return;
195
- }
196
- switch (detection) {
197
- case 'opt-in':
198
- {
199
- var _newExpressionPath$no;
200
- if (!((_newExpressionPath$no = newExpressionPath.node.leadingComments) != null && _newExpressionPath$no.some(function (comment) {
201
- return comment.value.includes(COMMENT_OPT_IN_MARKER);
202
- }))) {
203
- return;
204
- }
205
- newExpressionPath.node.leadingComments = newExpressionPath.node.leadingComments.filter(function (comment) {
206
- return !comment.value.includes(COMMENT_OPT_IN_MARKER);
207
- });
208
- break;
209
- }
210
- case 'opt-out':
211
- {
212
- var _newExpressionPath$no2;
213
- if ((_newExpressionPath$no2 = newExpressionPath.node.leadingComments) != null && _newExpressionPath$no2.some(function (comment) {
214
- return comment.value.includes(COMMENT_OPT_OUT_MARKER);
215
- })) {
216
- newExpressionPath.node.leadingComments = newExpressionPath.node.leadingComments.filter(function (comment) {
217
- return !comment.value.includes(COMMENT_OPT_OUT_MARKER);
218
- });
219
- return;
220
- }
221
- break;
222
- }
223
- default:
224
- {
225
- throw new Error("Unknown detection option: ".concat(detection));
226
- }
227
- }
228
- var messagePath = newExpressionPath.get('arguments')[0];
229
- if (!messagePath) {
230
- return;
231
- }
232
- var messageNode = messagePath.node;
233
- if (t.isSpreadElement(messageNode) || t.isArgumentPlaceholder(messageNode)) {
234
- handleUnminifyableError(missingError, newExpressionPath);
235
- return;
236
- }
237
- var transformedMessage = transformMessage(t, newExpressionPath, messageNode, state, errorCodesLookup, missingError, runtimeModule, outExtension);
238
- if (transformedMessage) {
239
- messagePath.replaceWith(transformedMessage);
240
- }
241
- }
242
- },
243
- post: function post() {
244
- if (missingError === 'write' && this.updatedErrorCodes) {
245
- var invertedErrorCodes = Object.fromEntries(Array.from(errorCodesLookup, function (_ref5) {
246
- var _ref6 = _slicedToArray(_ref5, 2),
247
- key = _ref6[0],
248
- value = _ref6[1];
249
- return [value, key];
250
- }));
251
- fs.writeFileSync(errorCodesPath, "".concat(JSON.stringify(invertedErrorCodes, null, 2), "\n"));
252
- }
253
- }
254
- };
255
- }
package/esm/package.json DELETED
@@ -1 +0,0 @@
1
- {"type":"module","sideEffects":false}
package/index.d.ts DELETED
@@ -1,25 +0,0 @@
1
- import * as babel from '@babel/core';
2
- export interface PluginState extends babel.PluginPass {
3
- updatedErrorCodes?: boolean;
4
- formatErrorMessageIdentifier?: babel.types.Identifier;
5
- }
6
- export type MissingError = 'annotate' | 'throw' | 'write';
7
- export interface Options {
8
- errorCodesPath: string;
9
- missingError?: MissingError;
10
- runtimeModule?: string;
11
- detection?: 'opt-in' | 'opt-out';
12
- outExtension?: string;
13
- }
14
- /**
15
- * Babel plugin for minifying error messages.
16
- */
17
- export default function plugin({
18
- types: t
19
- }: typeof babel, {
20
- errorCodesPath,
21
- missingError,
22
- runtimeModule,
23
- detection,
24
- outExtension
25
- }: Options): babel.PluginObj<PluginState>;
package/index.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../home/runner/work/mui-public/mui-public/packages/babel-plugin-minify-errors/src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AAuBrC,MAAM,WAAW,WAAY,SAAQ,KAAK,CAAC,UAAU;IACnD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,4BAA4B,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC;CACvD;AAED,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AAE1D,MAAM,WAAW,OAAO;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAkLD;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAC5B,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,OAAO,KAAK,EAC1B,EACE,cAAc,EACd,YAAyB,EACzB,aAAqC,EACrC,SAAoB,EACpB,YAAoB,GACrB,EAAE,OAAO,GACT,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CA6F9B"}