@metamask/snaps-cli 7.1.0 → 8.0.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.
Files changed (71) hide show
  1. package/.browserslistrc +2 -2
  2. package/CHANGELOG.md +22 -1
  3. package/dist/builders.cjs +4 -0
  4. package/dist/builders.cjs.map +1 -1
  5. package/dist/builders.d.cts +4 -0
  6. package/dist/builders.d.cts.map +1 -1
  7. package/dist/builders.d.mts +4 -0
  8. package/dist/builders.d.mts.map +1 -1
  9. package/dist/builders.mjs +4 -0
  10. package/dist/builders.mjs.map +1 -1
  11. package/dist/commands/build/build.cjs +8 -23
  12. package/dist/commands/build/build.cjs.map +1 -1
  13. package/dist/commands/build/build.d.cts +1 -0
  14. package/dist/commands/build/build.d.cts.map +1 -1
  15. package/dist/commands/build/build.d.mts +1 -0
  16. package/dist/commands/build/build.d.mts.map +1 -1
  17. package/dist/commands/build/build.mjs +9 -24
  18. package/dist/commands/build/build.mjs.map +1 -1
  19. package/dist/commands/build/implementation.cjs.map +1 -1
  20. package/dist/commands/build/implementation.d.cts.map +1 -1
  21. package/dist/commands/build/implementation.d.mts.map +1 -1
  22. package/dist/commands/build/implementation.mjs.map +1 -1
  23. package/dist/commands/build/index.cjs +1 -2
  24. package/dist/commands/build/index.cjs.map +1 -1
  25. package/dist/commands/build/index.d.cts.map +1 -1
  26. package/dist/commands/build/index.d.mts.map +1 -1
  27. package/dist/commands/build/index.mjs +1 -2
  28. package/dist/commands/build/index.mjs.map +1 -1
  29. package/dist/commands/manifest/implementation.cjs +8 -4
  30. package/dist/commands/manifest/implementation.cjs.map +1 -1
  31. package/dist/commands/manifest/implementation.d.cts +2 -1
  32. package/dist/commands/manifest/implementation.d.cts.map +1 -1
  33. package/dist/commands/manifest/implementation.d.mts +2 -1
  34. package/dist/commands/manifest/implementation.d.mts.map +1 -1
  35. package/dist/commands/manifest/implementation.mjs +8 -4
  36. package/dist/commands/manifest/implementation.mjs.map +1 -1
  37. package/dist/commands/manifest/index.cjs +5 -1
  38. package/dist/commands/manifest/index.cjs.map +1 -1
  39. package/dist/commands/manifest/index.d.cts.map +1 -1
  40. package/dist/commands/manifest/index.d.mts.map +1 -1
  41. package/dist/commands/manifest/index.mjs +5 -1
  42. package/dist/commands/manifest/index.mjs.map +1 -1
  43. package/dist/commands/manifest/manifest.cjs +20 -4
  44. package/dist/commands/manifest/manifest.cjs.map +1 -1
  45. package/dist/commands/manifest/manifest.d.cts +1 -0
  46. package/dist/commands/manifest/manifest.d.cts.map +1 -1
  47. package/dist/commands/manifest/manifest.d.mts +1 -0
  48. package/dist/commands/manifest/manifest.d.mts.map +1 -1
  49. package/dist/commands/manifest/manifest.mjs +21 -5
  50. package/dist/commands/manifest/manifest.mjs.map +1 -1
  51. package/dist/commands/watch/watch.cjs +1 -1
  52. package/dist/commands/watch/watch.cjs.map +1 -1
  53. package/dist/commands/watch/watch.mjs +1 -1
  54. package/dist/commands/watch/watch.mjs.map +1 -1
  55. package/dist/webpack/config.cjs +1 -1
  56. package/dist/webpack/config.cjs.map +1 -1
  57. package/dist/webpack/config.d.cts.map +1 -1
  58. package/dist/webpack/config.d.mts.map +1 -1
  59. package/dist/webpack/config.mjs +1 -1
  60. package/dist/webpack/config.mjs.map +1 -1
  61. package/dist/webpack/loaders/wasm.cjs +1 -2
  62. package/dist/webpack/loaders/wasm.cjs.map +1 -1
  63. package/dist/webpack/loaders/wasm.mjs +1 -2
  64. package/dist/webpack/loaders/wasm.mjs.map +1 -1
  65. package/dist/webpack/plugins.cjs +149 -119
  66. package/dist/webpack/plugins.cjs.map +1 -1
  67. package/dist/webpack/plugins.d.cts.map +1 -1
  68. package/dist/webpack/plugins.d.mts.map +1 -1
  69. package/dist/webpack/plugins.mjs +148 -118
  70. package/dist/webpack/plugins.mjs.map +1 -1
  71. package/package.json +11 -10
@@ -1,15 +1,3 @@
1
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
- if (kind === "m") throw new TypeError("Private method is not writable");
3
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
- };
7
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
- };
12
- var _SnapsStatsPlugin_instances, _SnapsStatsPlugin_spinner, _SnapsStatsPlugin_getStatsErrorMessage, _SnapsWatchPlugin_instances, _SnapsWatchPlugin_spinner, _SnapsWatchPlugin_safeEvaluate, _SnapsBuiltInResolver_source, _SnapsBundleWarningsPlugin_instances, _SnapsBundleWarningsPlugin_checkBuiltIns, _SnapsBundleWarningsPlugin_isProvidePlugin, _SnapsBundleWarningsPlugin_checkBuffer;
13
1
  import { assert, hasProperty, isObject } from "@metamask/utils";
14
2
  import $chalk from "chalk";
15
3
  const { bold, dim, red, yellow } = $chalk;
@@ -24,16 +12,19 @@ import { error, getErrorMessage, info, warn } from "../utils/index.mjs";
24
12
  * the number of files compiled, and the time taken to compile them.
25
13
  */
26
14
  export class SnapsStatsPlugin {
15
+ /**
16
+ * The options for the plugin.
17
+ */
18
+ options;
19
+ /**
20
+ * The spinner to use for logging.
21
+ */
22
+ #spinner;
27
23
  constructor(options = {
28
24
  verbose: false,
29
25
  }, spinner) {
30
- _SnapsStatsPlugin_instances.add(this);
31
- /**
32
- * The spinner to use for logging.
33
- */
34
- _SnapsStatsPlugin_spinner.set(this, void 0);
35
26
  this.options = options;
36
- __classPrivateFieldSet(this, _SnapsStatsPlugin_spinner, spinner, "f");
27
+ this.#spinner = spinner;
37
28
  }
38
29
  /**
39
30
  * Apply the plugin to the Webpack compiler.
@@ -50,57 +41,67 @@ export class SnapsStatsPlugin {
50
41
  assert(time, 'Time must be defined in stats.');
51
42
  if (errors?.length) {
52
43
  const formattedErrors = errors
53
- .map((statsError) => __classPrivateFieldGet(this, _SnapsStatsPlugin_instances, "m", _SnapsStatsPlugin_getStatsErrorMessage).call(this, statsError))
44
+ .map((statsError) => this.#getStatsErrorMessage(statsError, red))
54
45
  .join('\n\n');
55
- error(`Compiled ${modules.length} ${pluralize(modules.length, 'file')} in ${time}ms with ${errors.length} ${pluralize(errors.length, 'error')}.\n\n${formattedErrors}\n`, __classPrivateFieldGet(this, _SnapsStatsPlugin_spinner, "f"));
56
- __classPrivateFieldGet(this, _SnapsStatsPlugin_spinner, "f")?.stop();
46
+ error(`Compiled ${modules.length} ${pluralize(modules.length, 'file')} in ${time}ms with ${errors.length} ${pluralize(errors.length, 'error')}.\n\n${formattedErrors}\n`, this.#spinner);
47
+ this.#spinner?.stop();
57
48
  process.exitCode = 1;
58
49
  return;
59
50
  }
60
51
  if (warnings?.length) {
61
52
  const formattedWarnings = warnings
62
- .map((statsWarning) => __classPrivateFieldGet(this, _SnapsStatsPlugin_instances, "m", _SnapsStatsPlugin_getStatsErrorMessage).call(this, statsWarning, yellow))
53
+ .map((statsWarning) => this.#getStatsErrorMessage(statsWarning, yellow))
63
54
  .join('\n\n');
64
- warn(`Compiled ${modules.length} ${pluralize(modules.length, 'file')} in ${time}ms with ${warnings.length} ${pluralize(warnings.length, 'warning')}.\n\n${formattedWarnings}\n`, __classPrivateFieldGet(this, _SnapsStatsPlugin_spinner, "f"));
55
+ warn(`Compiled ${modules.length} ${pluralize(modules.length, 'file')} in ${time}ms with ${warnings.length} ${pluralize(warnings.length, 'warning')}.\n\n${formattedWarnings}\n`, this.#spinner);
65
56
  }
66
57
  else {
67
- info(`Compiled ${modules.length} ${pluralize(modules.length, 'file')} in ${time}ms.`, __classPrivateFieldGet(this, _SnapsStatsPlugin_spinner, "f"));
58
+ info(`Compiled ${modules.length} ${pluralize(modules.length, 'file')} in ${time}ms.`, this.#spinner);
68
59
  }
69
60
  if (compiler.watchMode) {
70
61
  // The spinner may be restarted by the watch plugin, outside of the
71
62
  // `executeSteps` flow, so we stop it here just in case.
72
- __classPrivateFieldGet(this, _SnapsStatsPlugin_spinner, "f")?.succeed('Done!');
63
+ this.#spinner?.succeed('Done!');
73
64
  }
74
65
  });
75
66
  }
67
+ /**
68
+ * Get the error message for the given stats error.
69
+ *
70
+ * @param statsError - The stats error.
71
+ * @param color - The color to use for the error message.
72
+ * @returns The error message.
73
+ */
74
+ #getStatsErrorMessage(statsError, color) {
75
+ const baseMessage = this.options.verbose
76
+ ? getErrorMessage(statsError)
77
+ : statsError.message;
78
+ const [first, ...rest] = baseMessage.split('\n');
79
+ return [
80
+ color(formatText(`• ${first}`, 4, 2)),
81
+ ...rest.map((message) => formatText(color(message), 4)),
82
+ statsError.details && `\n${formatText(dim(statsError.details), 6)}`,
83
+ ]
84
+ .filter(Boolean)
85
+ .join('\n');
86
+ }
76
87
  }
77
- _SnapsStatsPlugin_spinner = new WeakMap(), _SnapsStatsPlugin_instances = new WeakSet(), _SnapsStatsPlugin_getStatsErrorMessage = function _SnapsStatsPlugin_getStatsErrorMessage(statsError, color = red) {
78
- const baseMessage = this.options.verbose
79
- ? getErrorMessage(statsError)
80
- : statsError.message;
81
- const [first, ...rest] = baseMessage.split('\n');
82
- return [
83
- color(formatText(`• ${first}`, 4, 2)),
84
- ...rest.map((message) => formatText(color(message), 4)),
85
- statsError.details && `\n${formatText(dim(statsError.details), 6)}`,
86
- ]
87
- .filter(Boolean)
88
- .join('\n');
89
- };
90
88
  /**
91
89
  * A plugin that adds extra files to watch. This is useful for watching files
92
90
  * that are not imported by the entry point, such as the `snap.manifest.json`
93
91
  * file.
94
92
  */
95
93
  export class SnapsWatchPlugin {
94
+ /**
95
+ * The options for the plugin.
96
+ */
97
+ options;
98
+ /**
99
+ * The spinner to use for logging.
100
+ */
101
+ #spinner;
96
102
  constructor(options, spinner) {
97
- _SnapsWatchPlugin_instances.add(this);
98
- /**
99
- * The spinner to use for logging.
100
- */
101
- _SnapsWatchPlugin_spinner.set(this, void 0);
102
103
  this.options = options;
103
- __classPrivateFieldSet(this, _SnapsWatchPlugin_spinner, spinner, "f");
104
+ this.#spinner = spinner;
104
105
  }
105
106
  /**
106
107
  * Apply the plugin to the Webpack compiler.
@@ -109,35 +110,34 @@ export class SnapsWatchPlugin {
109
110
  */
110
111
  apply(compiler) {
111
112
  compiler.hooks.invalid.tap(this.constructor.name, (file) => {
112
- __classPrivateFieldGet(this, _SnapsWatchPlugin_spinner, "f")?.start();
113
- info(`Changes detected in ${yellow(file)}, recompiling.`, __classPrivateFieldGet(this, _SnapsWatchPlugin_spinner, "f"));
113
+ this.#spinner?.start();
114
+ info(`Changes detected in ${yellow(file)}, recompiling.`, this.#spinner);
114
115
  });
115
116
  compiler.hooks.afterEmit.tapPromise(this.constructor.name, async ({ fileDependencies }) => {
116
117
  this.options.files?.forEach(fileDependencies.add.bind(fileDependencies));
117
118
  if (this.options.bundle && this.options.evaluate) {
118
- await __classPrivateFieldGet(this, _SnapsWatchPlugin_instances, "m", _SnapsWatchPlugin_safeEvaluate).call(this, this.options.bundle);
119
+ await this.#safeEvaluate(this.options.bundle);
119
120
  }
120
121
  });
121
122
  }
122
- }
123
- _SnapsWatchPlugin_spinner = new WeakMap(), _SnapsWatchPlugin_instances = new WeakSet(), _SnapsWatchPlugin_safeEvaluate =
124
- /**
125
- * Safely evaluate the bundle at the given path. If an error occurs, it will
126
- * be logged to the console, rather than throwing an error.
127
- *
128
- * This function should never throw an error.
129
- *
130
- * @param bundlePath - The path to the bundle.
131
- */
132
- async function _SnapsWatchPlugin_safeEvaluate(bundlePath) {
133
- try {
134
- await evaluate(bundlePath);
135
- info(`Snap bundle evaluated successfully.`, __classPrivateFieldGet(this, _SnapsWatchPlugin_spinner, "f"));
136
- }
137
- catch (evaluateError) {
138
- error(evaluateError.message, __classPrivateFieldGet(this, _SnapsWatchPlugin_spinner, "f"));
123
+ /**
124
+ * Safely evaluate the bundle at the given path. If an error occurs, it will
125
+ * be logged to the console, rather than throwing an error.
126
+ *
127
+ * This function should never throw an error.
128
+ *
129
+ * @param bundlePath - The path to the bundle.
130
+ */
131
+ async #safeEvaluate(bundlePath) {
132
+ try {
133
+ await evaluate(bundlePath);
134
+ info(`Snap bundle evaluated successfully.`, this.#spinner);
135
+ }
136
+ catch (evaluateError) {
137
+ error(evaluateError.message, this.#spinner);
138
+ }
139
139
  }
140
- };
140
+ }
141
141
  /**
142
142
  * A plugin that logs a message when a built-in module is not resolved. The
143
143
  * MetaMask Snaps CLI does not support built-in modules by default, and this
@@ -145,17 +145,21 @@ async function _SnapsWatchPlugin_safeEvaluate(bundlePath) {
145
145
  * when no fallback is configured.
146
146
  */
147
147
  export class SnapsBuiltInResolver {
148
+ /**
149
+ * The built-in modules that have been imported, but not resolved.
150
+ */
151
+ unresolvedModules = new Set();
152
+ /**
153
+ * The name of the resolver hook to tap into.
154
+ */
155
+ #source = 'described-resolve';
156
+ /**
157
+ * The options for the plugin.
158
+ */
159
+ options;
148
160
  constructor(options = {
149
161
  ignore: [],
150
162
  }) {
151
- /**
152
- * The built-in modules that have been imported, but not resolved.
153
- */
154
- this.unresolvedModules = new Set();
155
- /**
156
- * The name of the resolver hook to tap into.
157
- */
158
- _SnapsBuiltInResolver_source.set(this, 'described-resolve');
159
163
  this.options = options;
160
164
  }
161
165
  /**
@@ -165,7 +169,7 @@ export class SnapsBuiltInResolver {
165
169
  */
166
170
  apply(resolver) {
167
171
  resolver
168
- .getHook(__classPrivateFieldGet(this, _SnapsBuiltInResolver_source, "f"))
172
+ .getHook(this.#source)
169
173
  .tapAsync(this.constructor.name, ({ module: isModule, request }, _, callback) => {
170
174
  if (!isModule || !request) {
171
175
  return callback();
@@ -182,7 +186,6 @@ export class SnapsBuiltInResolver {
182
186
  });
183
187
  }
184
188
  }
185
- _SnapsBuiltInResolver_source = new WeakMap();
186
189
  /**
187
190
  * A plugin that logs a message when:
188
191
  *
@@ -200,11 +203,14 @@ _SnapsBuiltInResolver_source = new WeakMap();
200
203
  * plugin doesn't have access to the resolver.
201
204
  */
202
205
  export class SnapsBundleWarningsPlugin {
206
+ /**
207
+ * The options for the plugin.
208
+ */
209
+ options;
203
210
  constructor(options = {
204
211
  buffer: true,
205
212
  builtIns: true,
206
213
  }) {
207
- _SnapsBundleWarningsPlugin_instances.add(this);
208
214
  this.options = options;
209
215
  }
210
216
  /**
@@ -214,54 +220,78 @@ export class SnapsBundleWarningsPlugin {
214
220
  */
215
221
  apply(compiler) {
216
222
  if (this.options.builtIns) {
217
- __classPrivateFieldGet(this, _SnapsBundleWarningsPlugin_instances, "m", _SnapsBundleWarningsPlugin_checkBuiltIns).call(this, compiler);
223
+ this.#checkBuiltIns(compiler);
218
224
  }
219
225
  if (this.options.buffer) {
220
- __classPrivateFieldGet(this, _SnapsBundleWarningsPlugin_instances, "m", _SnapsBundleWarningsPlugin_checkBuffer).call(this, compiler);
226
+ this.#checkBuffer(compiler);
221
227
  }
222
228
  }
223
- }
224
- _SnapsBundleWarningsPlugin_instances = new WeakSet(), _SnapsBundleWarningsPlugin_checkBuiltIns = function _SnapsBundleWarningsPlugin_checkBuiltIns(compiler) {
225
- compiler.hooks.afterCompile.tap(this.constructor.name, (compilation) => {
226
- if (!this.options.builtInResolver) {
227
- return;
228
- }
229
- const { unresolvedModules } = this.options.builtInResolver;
230
- if (unresolvedModules.size === 0) {
231
- return;
232
- }
233
- const formattedModules = new Array(...unresolvedModules)
234
- .map((name) => `• ${name}`)
235
- .join('\n');
236
- const webpackError = new WebpackError(`The snap attempted to use one or more Node.js builtins, but no browser fallback has been provided. The MetaMask Snaps CLI does not support Node.js builtins by default. If you want to use this module, you must set ${bold('`polyfills`')} to ${bold('`true`')} or an object with the builtins to polyfill as the key and ${bold('`true`')} as the value. To disable this warning, set ${bold('`stats.builtIns`')} to ${bold('`false`')} in your snap config file, or add the module to the ${bold('`stats.builtIns.ignore`')} array.`);
237
- webpackError.details = formattedModules;
238
- compilation.warnings.push(webpackError);
239
- });
240
- }, _SnapsBundleWarningsPlugin_isProvidePlugin = function _SnapsBundleWarningsPlugin_isProvidePlugin(instance) {
241
- return (isObject(instance) &&
242
- instance.constructor.name === 'ProvidePlugin' &&
243
- hasProperty(instance, 'definitions'));
244
- }, _SnapsBundleWarningsPlugin_checkBuffer = function _SnapsBundleWarningsPlugin_checkBuffer(compiler) {
245
- const plugin = compiler.options.plugins?.find((instance) => __classPrivateFieldGet(this, _SnapsBundleWarningsPlugin_instances, "m", _SnapsBundleWarningsPlugin_isProvidePlugin).call(this, instance));
246
- // If the `ProvidePlugin` is configured to provide `Buffer`, then we don't
247
- // need to warn the user.
248
- if (plugin) {
249
- const { definitions } = plugin;
250
- if (definitions.Buffer) {
251
- return;
252
- }
229
+ /**
230
+ * Check if a built-in module is used, but not provided by Webpack's
231
+ * `fallback` configuration.
232
+ *
233
+ * @param compiler - The Webpack compiler.
234
+ */
235
+ #checkBuiltIns(compiler) {
236
+ compiler.hooks.afterCompile.tap(this.constructor.name, (compilation) => {
237
+ if (!this.options.builtInResolver) {
238
+ return;
239
+ }
240
+ const { unresolvedModules } = this.options.builtInResolver;
241
+ if (unresolvedModules.size === 0) {
242
+ return;
243
+ }
244
+ const formattedModules = new Array(...unresolvedModules)
245
+ .map((name) => `• ${name}`)
246
+ .join('\n');
247
+ const webpackError = new WebpackError(`The snap attempted to use one or more Node.js builtins, but no browser fallback has been provided. The MetaMask Snaps CLI does not support Node.js builtins by default. If you want to use this module, you must set ${bold('`polyfills`')} to ${bold('`true`')} or an object with the builtins to polyfill as the key and ${bold('`true`')} as the value. To disable this warning, set ${bold('`stats.builtIns`')} to ${bold('`false`')} in your snap config file, or add the module to the ${bold('`stats.builtIns.ignore`')} array.`);
248
+ webpackError.details = formattedModules;
249
+ compilation.warnings.push(webpackError);
250
+ });
251
+ }
252
+ /**
253
+ * Check if the given instance is a `ProvidePlugin`. This is not guaranteed to
254
+ * be accurate, but it's good enough for our purposes. If we were to use
255
+ * `instanceof` instead, it might not work if multiple versions of Webpack are
256
+ * installed.
257
+ *
258
+ * @param instance - The instance to check.
259
+ * @returns Whether the instance is a `ProvidePlugin`, i.e., whether it's an
260
+ * object with the name `ProvidePlugin` and a `definitions` property.
261
+ */
262
+ #isProvidePlugin(instance) {
263
+ return (isObject(instance) &&
264
+ instance.constructor.name === 'ProvidePlugin' &&
265
+ hasProperty(instance, 'definitions'));
253
266
  }
254
- compiler.hooks.compilation.tap(this.constructor.name, (compilation) => {
255
- compilation.hooks.afterProcessAssets.tap(this.constructor.name, (assets) => {
256
- // Check if assets use `Buffer`.
257
- const bufferAssets = Object.entries(assets)
258
- .filter(([name]) => name.endsWith('.js'))
259
- .filter(([, asset]) => asset.source().includes('Buffer'));
260
- if (bufferAssets.length === 0) {
267
+ /**
268
+ * Check if the `Buffer` global is used, but not provided by Webpack's
269
+ * `DefinePlugin`.
270
+ *
271
+ * @param compiler - The Webpack compiler.
272
+ */
273
+ #checkBuffer(compiler) {
274
+ const plugin = compiler.options.plugins?.find((instance) => this.#isProvidePlugin(instance));
275
+ // If the `ProvidePlugin` is configured to provide `Buffer`, then we don't
276
+ // need to warn the user.
277
+ if (plugin) {
278
+ const { definitions } = plugin;
279
+ if (definitions.Buffer) {
261
280
  return;
262
281
  }
263
- compilation.warnings.push(new WebpackError(`The snap attempted to use the Node.js Buffer global, which is not supported in the MetaMask Snaps CLI by default. To use the Buffer global, you must polyfill Buffer by setting ${bold('`buffer`')} to ${bold('`true`')} in the ${bold('`polyfills`')} config object in your snap config. To disable this warning, set ${bold('`stats.buffer`')} to ${bold('`false`')} in your snap config file.`));
282
+ }
283
+ compiler.hooks.compilation.tap(this.constructor.name, (compilation) => {
284
+ compilation.hooks.afterProcessAssets.tap(this.constructor.name, (assets) => {
285
+ // Check if assets use `Buffer`.
286
+ const bufferAssets = Object.entries(assets)
287
+ .filter(([name]) => name.endsWith('.js'))
288
+ .filter(([, asset]) => asset.source().includes('Buffer'));
289
+ if (bufferAssets.length === 0) {
290
+ return;
291
+ }
292
+ compilation.warnings.push(new WebpackError(`The snap attempted to use the Node.js Buffer global, which is not supported in the MetaMask Snaps CLI by default. To use the Buffer global, you must polyfill Buffer by setting ${bold('`buffer`')} to ${bold('`true`')} in the ${bold('`polyfills`')} config object in your snap config. To disable this warning, set ${bold('`stats.buffer`')} to ${bold('`false`')} in your snap config file.`));
293
+ });
264
294
  });
265
- });
266
- };
295
+ }
296
+ }
267
297
  //# sourceMappingURL=plugins.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugins.mjs","sourceRoot":"","sources":["../../src/webpack/plugins.ts"],"names":[],"mappings":"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","sourcesContent":["import { assert, hasProperty, isObject } from '@metamask/utils';\nimport { bold, dim, red, yellow } from 'chalk';\nimport { isBuiltin } from 'module';\nimport type { Ora } from 'ora';\nimport type {\n Compiler,\n ProvidePlugin,\n Resolver,\n StatsError,\n WebpackPluginInstance,\n} from 'webpack';\nimport { WebpackError } from 'webpack';\n\nimport { formatText, pluralize } from './utils';\nimport { evaluate } from '../commands/eval';\nimport { error, getErrorMessage, info, warn } from '../utils';\n\nexport type SnapsStatsPluginOptions = {\n /**\n * Whether to log the verbose stats.\n */\n verbose?: boolean;\n};\n\n/**\n * A plugin that logs the stats after compilation. This is useful for logging\n * the number of files compiled, and the time taken to compile them.\n */\nexport class SnapsStatsPlugin implements WebpackPluginInstance {\n /**\n * The options for the plugin.\n */\n readonly options: SnapsStatsPluginOptions;\n\n /**\n * The spinner to use for logging.\n */\n readonly #spinner?: Ora;\n\n constructor(\n options: SnapsStatsPluginOptions = {\n verbose: false,\n },\n spinner?: Ora,\n ) {\n this.options = options;\n this.#spinner = spinner;\n }\n\n /**\n * Apply the plugin to the Webpack compiler.\n *\n * @param compiler - The Webpack compiler.\n */\n apply(compiler: Compiler) {\n compiler.hooks.afterDone.tap(this.constructor.name, (stats) => {\n if (!stats) {\n return;\n }\n\n const { modules, time, errors, warnings } = stats.toJson();\n\n assert(modules, 'Modules must be defined in stats.');\n assert(time, 'Time must be defined in stats.');\n\n if (errors?.length) {\n const formattedErrors = errors\n .map((statsError) => this.#getStatsErrorMessage(statsError))\n .join('\\n\\n');\n\n error(\n `Compiled ${modules.length} ${pluralize(\n modules.length,\n 'file',\n )} in ${time}ms with ${errors.length} ${pluralize(\n errors.length,\n 'error',\n )}.\\n\\n${formattedErrors}\\n`,\n this.#spinner,\n );\n\n this.#spinner?.stop();\n\n process.exitCode = 1;\n return;\n }\n\n if (warnings?.length) {\n const formattedWarnings = warnings\n .map((statsWarning) =>\n this.#getStatsErrorMessage(statsWarning, yellow),\n )\n .join('\\n\\n');\n\n warn(\n `Compiled ${modules.length} ${pluralize(\n modules.length,\n 'file',\n )} in ${time}ms with ${warnings.length} ${pluralize(\n warnings.length,\n 'warning',\n )}.\\n\\n${formattedWarnings}\\n`,\n this.#spinner,\n );\n } else {\n info(\n `Compiled ${modules.length} ${pluralize(\n modules.length,\n 'file',\n )} in ${time}ms.`,\n this.#spinner,\n );\n }\n\n if (compiler.watchMode) {\n // The spinner may be restarted by the watch plugin, outside of the\n // `executeSteps` flow, so we stop it here just in case.\n this.#spinner?.succeed('Done!');\n }\n });\n }\n\n /**\n * Get the error message for the given stats error.\n *\n * @param statsError - The stats error.\n * @param color - The color to use for the error message.\n * @returns The error message.\n */\n #getStatsErrorMessage(statsError: StatsError, color = red) {\n const baseMessage = this.options.verbose\n ? getErrorMessage(statsError)\n : statsError.message;\n\n const [first, ...rest] = baseMessage.split('\\n');\n\n return [\n color(formatText(`• ${first}`, 4, 2)),\n ...rest.map((message) => formatText(color(message), 4)),\n statsError.details && `\\n${formatText(dim(statsError.details), 6)}`,\n ]\n .filter(Boolean)\n .join('\\n');\n }\n}\n\n/**\n * The options for the {@link SnapsWatchPlugin}.\n */\nexport type SnapsWatchPluginOptions = {\n /**\n * The bundle path. This is the file that will be evaluated, if the `evaluate`\n * option is set.\n */\n bundle?: string;\n\n /**\n * Whether to evaluate the bundle. This only applies if the `bundle` option is\n * set.\n */\n evaluate?: boolean;\n\n /**\n * The extra files to watch.\n */\n files?: string[];\n};\n\n/**\n * A plugin that adds extra files to watch. This is useful for watching files\n * that are not imported by the entry point, such as the `snap.manifest.json`\n * file.\n */\nexport class SnapsWatchPlugin implements WebpackPluginInstance {\n /**\n * The options for the plugin.\n */\n readonly options: SnapsWatchPluginOptions;\n\n /**\n * The spinner to use for logging.\n */\n readonly #spinner?: Ora;\n\n constructor(options: SnapsWatchPluginOptions, spinner?: Ora) {\n this.options = options;\n this.#spinner = spinner;\n }\n\n /**\n * Apply the plugin to the Webpack compiler.\n *\n * @param compiler - The Webpack compiler.\n */\n apply(compiler: Compiler) {\n compiler.hooks.invalid.tap(this.constructor.name, (file) => {\n this.#spinner?.start();\n info(`Changes detected in ${yellow(file)}, recompiling.`, this.#spinner);\n });\n\n compiler.hooks.afterEmit.tapPromise(\n this.constructor.name,\n async ({ fileDependencies }) => {\n this.options.files?.forEach(\n fileDependencies.add.bind(fileDependencies),\n );\n\n if (this.options.bundle && this.options.evaluate) {\n await this.#safeEvaluate(this.options.bundle);\n }\n },\n );\n }\n\n /**\n * Safely evaluate the bundle at the given path. If an error occurs, it will\n * be logged to the console, rather than throwing an error.\n *\n * This function should never throw an error.\n *\n * @param bundlePath - The path to the bundle.\n */\n async #safeEvaluate(bundlePath: string) {\n try {\n await evaluate(bundlePath);\n info(`Snap bundle evaluated successfully.`, this.#spinner);\n } catch (evaluateError) {\n error(evaluateError.message, this.#spinner);\n }\n }\n}\n\n/**\n * The options for the {@link SnapsBuiltInResolver}.\n */\nexport type SnapsBuiltInResolverOptions = {\n /**\n * The built-in modules to ignore.\n */\n ignore?: string[];\n};\n\n/**\n * A Webpack resolve plugin.\n *\n * Copied from Webpack's own types, because the `ResolvePluginInstance` type is\n * a union, and can't be used as a type for a class.\n */\ntype ResolvePlugin = {\n apply: (resolver: Resolver) => void;\n};\n\n/**\n * A plugin that logs a message when a built-in module is not resolved. The\n * MetaMask Snaps CLI does not support built-in modules by default, and this\n * plugin is used to warn the user when they try to import a built-in module,\n * when no fallback is configured.\n */\nexport class SnapsBuiltInResolver implements ResolvePlugin {\n /**\n * The built-in modules that have been imported, but not resolved.\n */\n readonly unresolvedModules = new Set<string>();\n\n /**\n * The name of the resolver hook to tap into.\n */\n readonly #source = 'described-resolve';\n\n /**\n * The options for the plugin.\n */\n readonly options: SnapsBuiltInResolverOptions;\n\n constructor(\n options: SnapsBuiltInResolverOptions = {\n ignore: [],\n },\n ) {\n this.options = options;\n }\n\n /**\n * Apply the plugin to the Webpack resolver.\n *\n * @param resolver - The Webpack resolver.\n */\n apply(resolver: Resolver) {\n resolver\n .getHook(this.#source)\n .tapAsync(\n this.constructor.name,\n ({ module: isModule, request }, _, callback) => {\n if (!isModule || !request) {\n return callback();\n }\n\n const baseRequest = request.split('/')[0];\n if (\n isBuiltin(baseRequest) &&\n !this.options.ignore?.includes(baseRequest)\n ) {\n const fallback = resolver.options.fallback.find(\n ({ name }) => name === baseRequest,\n );\n\n if (fallback && !fallback.alias) {\n this.unresolvedModules.add(baseRequest);\n }\n }\n\n return callback();\n },\n );\n }\n}\n\n/**\n * The options for the {@link SnapsBundleWarningsPlugin}.\n */\nexport type SnapsBundleWarningsPluginOptions = {\n /**\n * The {@link SnapsBuiltInResolver} instance to use for detecting built-in\n * modules.\n */\n builtInResolver?: SnapsBuiltInResolver | false;\n\n /**\n * Whether to show warnings if built-in modules are used, but not provided by\n * Webpack's `fallback` configuration.\n */\n builtIns?: boolean;\n\n /**\n * Whether to show warnings if the `Buffer` global is used, but not provided\n * by Webpack's `DefinePlugin`.\n */\n buffer?: boolean;\n};\n\n/**\n * A plugin that logs a message when:\n *\n * - A built-in module is not resolved. The MetaMask Snaps CLI does not support\n * built-in modules by default, and this plugin is used to warn the user when\n * they try to import a built-in module, when no fallback is configured.\n * - A snap uses the `Buffer` global. The MetaMask Snaps CLI does not support\n * the `Buffer` global by default, and this plugin is used to warn the user when\n * they try to use the `Buffer` global.\n *\n * We use both a resolver and a plugin, because the resolver is used to detect\n * when a built-in module is imported, and the plugin is used to log a single\n * message when the compilation is complete. We can't do everything in a single\n * plugin, because the resolver doesn't have access to the compilation, and the\n * plugin doesn't have access to the resolver.\n */\n\nexport class SnapsBundleWarningsPlugin implements WebpackPluginInstance {\n /**\n * The options for the plugin.\n */\n readonly options: SnapsBundleWarningsPluginOptions;\n\n constructor(\n options: SnapsBundleWarningsPluginOptions = {\n buffer: true,\n builtIns: true,\n },\n ) {\n this.options = options;\n }\n\n /**\n * Apply the plugin to the Webpack compiler.\n *\n * @param compiler - The Webpack compiler.\n */\n apply(compiler: Compiler) {\n if (this.options.builtIns) {\n this.#checkBuiltIns(compiler);\n }\n\n if (this.options.buffer) {\n this.#checkBuffer(compiler);\n }\n }\n\n /**\n * Check if a built-in module is used, but not provided by Webpack's\n * `fallback` configuration.\n *\n * @param compiler - The Webpack compiler.\n */\n #checkBuiltIns(compiler: Compiler) {\n compiler.hooks.afterCompile.tap(this.constructor.name, (compilation) => {\n if (!this.options.builtInResolver) {\n return;\n }\n\n const { unresolvedModules } = this.options.builtInResolver;\n if (unresolvedModules.size === 0) {\n return;\n }\n\n const formattedModules = new Array(...unresolvedModules)\n .map((name) => `• ${name}`)\n .join('\\n');\n\n const webpackError = new WebpackError(\n `The snap attempted to use one or more Node.js builtins, but no browser fallback has been provided. The MetaMask Snaps CLI does not support Node.js builtins by default. If you want to use this module, you must set ${bold(\n '`polyfills`',\n )} to ${bold(\n '`true`',\n )} or an object with the builtins to polyfill as the key and ${bold(\n '`true`',\n )} as the value. To disable this warning, set ${bold(\n '`stats.builtIns`',\n )} to ${bold(\n '`false`',\n )} in your snap config file, or add the module to the ${bold(\n '`stats.builtIns.ignore`',\n )} array.`,\n );\n\n webpackError.details = formattedModules;\n compilation.warnings.push(webpackError);\n });\n }\n\n /**\n * Check if the given instance is a `ProvidePlugin`. This is not guaranteed to\n * be accurate, but it's good enough for our purposes. If we were to use\n * `instanceof` instead, it might not work if multiple versions of Webpack are\n * installed.\n *\n * @param instance - The instance to check.\n * @returns Whether the instance is a `ProvidePlugin`, i.e., whether it's an\n * object with the name `ProvidePlugin` and a `definitions` property.\n */\n #isProvidePlugin(instance: unknown): instance is ProvidePlugin {\n return (\n isObject(instance) &&\n instance.constructor.name === 'ProvidePlugin' &&\n hasProperty(instance, 'definitions')\n );\n }\n\n /**\n * Check if the `Buffer` global is used, but not provided by Webpack's\n * `DefinePlugin`.\n *\n * @param compiler - The Webpack compiler.\n */\n #checkBuffer(compiler: Compiler) {\n const plugin = compiler.options.plugins?.find((instance) =>\n this.#isProvidePlugin(instance),\n ) as ProvidePlugin | undefined;\n\n // If the `ProvidePlugin` is configured to provide `Buffer`, then we don't\n // need to warn the user.\n if (plugin) {\n const { definitions } = plugin;\n if (definitions.Buffer) {\n return;\n }\n }\n\n compiler.hooks.compilation.tap(this.constructor.name, (compilation) => {\n compilation.hooks.afterProcessAssets.tap(\n this.constructor.name,\n (assets) => {\n // Check if assets use `Buffer`.\n const bufferAssets = Object.entries(assets)\n .filter(([name]) => name.endsWith('.js'))\n .filter(([, asset]) => asset.source().includes('Buffer'));\n\n if (bufferAssets.length === 0) {\n return;\n }\n\n compilation.warnings.push(\n new WebpackError(\n `The snap attempted to use the Node.js Buffer global, which is not supported in the MetaMask Snaps CLI by default. To use the Buffer global, you must polyfill Buffer by setting ${bold(\n '`buffer`',\n )} to ${bold('`true`')} in the ${bold(\n '`polyfills`',\n )} config object in your snap config. To disable this warning, set ${bold(\n '`stats.buffer`',\n )} to ${bold('`false`')} in your snap config file.`,\n ),\n );\n },\n );\n });\n }\n}\n"]}
1
+ {"version":3,"file":"plugins.mjs","sourceRoot":"","sources":["../../src/webpack/plugins.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,wBAAwB;;;AAEhE,OAAO,EAAE,SAAS,EAAE,eAAe;;;AAWnC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,oBAAgB;AAChD,OAAO,EAAE,QAAQ,EAAE,mCAAyB;AAC5C,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,IAAI,EAAE,2BAAiB;AAS9D;;;GAGG;AACH,MAAM,OAAO,gBAAgB;IAC3B;;OAEG;IACM,OAAO,CAA0B;IAE1C;;OAEG;IACM,QAAQ,CAAO;IAExB,YACE,UAAmC;QACjC,OAAO,EAAE,KAAK;KACf,EACD,OAAa;QAEb,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,QAAkB;QACtB,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE;YAC5D,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO;YACT,CAAC;YAED,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;YAE3D,MAAM,CAAC,OAAO,EAAE,mCAAmC,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,EAAE,gCAAgC,CAAC,CAAC;YAE/C,IAAI,MAAM,EAAE,MAAM,EAAE,CAAC;gBACnB,MAAM,eAAe,GAAG,MAAM;qBAC3B,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,qBAAqB,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;qBAChE,IAAI,CAAC,MAAM,CAAC,CAAC;gBAEhB,KAAK,CACH,YAAY,OAAO,CAAC,MAAM,IAAI,SAAS,CACrC,OAAO,CAAC,MAAM,EACd,MAAM,CACP,OAAO,IAAI,WAAW,MAAM,CAAC,MAAM,IAAI,SAAS,CAC/C,MAAM,CAAC,MAAM,EACb,OAAO,CACR,QAAQ,eAAe,IAAI,EAC5B,IAAI,CAAC,QAAQ,CACd,CAAC;gBAEF,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;gBAEtB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;gBACrB,OAAO;YACT,CAAC;YAED,IAAI,QAAQ,EAAE,MAAM,EAAE,CAAC;gBACrB,MAAM,iBAAiB,GAAG,QAAQ;qBAC/B,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CACpB,IAAI,CAAC,qBAAqB,CAAC,YAAY,EAAE,MAAM,CAAC,CACjD;qBACA,IAAI,CAAC,MAAM,CAAC,CAAC;gBAEhB,IAAI,CACF,YAAY,OAAO,CAAC,MAAM,IAAI,SAAS,CACrC,OAAO,CAAC,MAAM,EACd,MAAM,CACP,OAAO,IAAI,WAAW,QAAQ,CAAC,MAAM,IAAI,SAAS,CACjD,QAAQ,CAAC,MAAM,EACf,SAAS,CACV,QAAQ,iBAAiB,IAAI,EAC9B,IAAI,CAAC,QAAQ,CACd,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,IAAI,CACF,YAAY,OAAO,CAAC,MAAM,IAAI,SAAS,CACrC,OAAO,CAAC,MAAM,EACd,MAAM,CACP,OAAO,IAAI,KAAK,EACjB,IAAI,CAAC,QAAQ,CACd,CAAC;YACJ,CAAC;YAED,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;gBACvB,mEAAmE;gBACnE,wDAAwD;gBACxD,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YAClC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,qBAAqB,CACnB,UAAsB,EACtB,KAAiC;QAEjC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO;YACtC,CAAC,CAAC,eAAe,CAAC,UAAU,CAAC;YAC7B,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC;QAEvB,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEjD,OAAO;YACL,KAAK,CAAC,UAAU,CAAC,KAAK,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACrC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;YACvD,UAAU,CAAC,OAAO,IAAI,KAAK,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE;SACpE;aACE,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;CACF;AAwBD;;;;GAIG;AACH,MAAM,OAAO,gBAAgB;IAC3B;;OAEG;IACM,OAAO,CAA0B;IAE1C;;OAEG;IACM,QAAQ,CAAO;IAExB,YAAY,OAAgC,EAAE,OAAa;QACzD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,QAAkB;QACtB,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE;YACzD,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC,uBAAuB,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,UAAU,CACjC,IAAI,CAAC,WAAW,CAAC,IAAI,EACrB,KAAK,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE;YAC7B,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CACzB,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAC5C,CAAC;YAEF,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACjD,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAChD,CAAC;QACH,CAAC,CACF,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,aAAa,CAAC,UAAkB;QACpC,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,UAAU,CAAC,CAAC;YAC3B,IAAI,CAAC,qCAAqC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC7D,CAAC;QAAC,OAAO,aAAa,EAAE,CAAC;YACvB,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;CACF;AAsBD;;;;;GAKG;AACH,MAAM,OAAO,oBAAoB;IAC/B;;OAEG;IACM,iBAAiB,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/C;;OAEG;IACM,OAAO,GAAG,mBAAmB,CAAC;IAEvC;;OAEG;IACM,OAAO,CAA8B;IAE9C,YACE,UAAuC;QACrC,MAAM,EAAE,EAAE;KACX;QAED,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,QAAkB;QACtB,QAAQ;aACL,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC;aACrB,QAAQ,CACP,IAAI,CAAC,WAAW,CAAC,IAAI,EACrB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE;YAC7C,IAAI,CAAC,QAAQ,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC1B,OAAO,QAAQ,EAAE,CAAC;YACpB,CAAC;YAED,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1C,IACE,SAAS,CAAC,WAAW,CAAC;gBACtB,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,EAC3C,CAAC;gBACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAC7C,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,KAAK,WAAW,CACnC,CAAC;gBAEF,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;oBAChC,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBAC1C,CAAC;YACH,CAAC;YAED,OAAO,QAAQ,EAAE,CAAC;QACpB,CAAC,CACF,CAAC;IACN,CAAC;CACF;AAyBD;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,OAAO,yBAAyB;IACpC;;OAEG;IACM,OAAO,CAAmC;IAEnD,YACE,UAA4C;QAC1C,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,IAAI;KACf;QAED,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,QAAkB;QACtB,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC1B,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACxB,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,cAAc,CAAC,QAAkB;QAC/B,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE;YACrE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC;gBAClC,OAAO;YACT,CAAC;YAED,MAAM,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC;YAC3D,IAAI,iBAAiB,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBACjC,OAAO;YACT,CAAC;YAED,MAAM,gBAAgB,GAAG,IAAI,KAAK,CAAC,GAAG,iBAAiB,CAAC;iBACrD,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;iBAC1B,IAAI,CAAC,IAAI,CAAC,CAAC;YAEd,MAAM,YAAY,GAAG,IAAI,YAAY,CACnC,wNAAwN,IAAI,CAC1N,aAAa,CACd,OAAO,IAAI,CACV,QAAQ,CACT,8DAA8D,IAAI,CACjE,QAAQ,CACT,+CAA+C,IAAI,CAClD,kBAAkB,CACnB,OAAO,IAAI,CACV,SAAS,CACV,uDAAuD,IAAI,CAC1D,yBAAyB,CAC1B,SAAS,CACX,CAAC;YAEF,YAAY,CAAC,OAAO,GAAG,gBAAgB,CAAC;YACxC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;;;OASG;IACH,gBAAgB,CAAC,QAAiB;QAChC,OAAO,CACL,QAAQ,CAAC,QAAQ,CAAC;YAClB,QAAQ,CAAC,WAAW,CAAC,IAAI,KAAK,eAAe;YAC7C,WAAW,CAAC,QAAQ,EAAE,aAAa,CAAC,CACrC,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,YAAY,CAAC,QAAkB;QAC7B,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CACzD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CACH,CAAC;QAE/B,0EAA0E;QAC1E,yBAAyB;QACzB,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAAC;YAC/B,IAAI,WAAW,CAAC,MAAM,EAAE,CAAC;gBACvB,OAAO;YACT,CAAC;QACH,CAAC;QAED,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE;YACpE,WAAW,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAG,CACtC,IAAI,CAAC,WAAW,CAAC,IAAI,EACrB,CAAC,MAAM,EAAE,EAAE;gBACT,gCAAgC;gBAChC,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;qBACxC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;qBACxC,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAE5D,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC9B,OAAO;gBACT,CAAC;gBAED,WAAW,CAAC,QAAQ,CAAC,IAAI,CACvB,IAAI,YAAY,CACd,mLAAmL,IAAI,CACrL,UAAU,CACX,OAAO,IAAI,CAAC,QAAQ,CAAC,WAAW,IAAI,CACnC,aAAa,CACd,oEAAoE,IAAI,CACvE,gBAAgB,CACjB,OAAO,IAAI,CAAC,SAAS,CAAC,4BAA4B,CACpD,CACF,CAAC;YACJ,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["import { assert, hasProperty, isObject } from '@metamask/utils';\nimport { bold, dim, red, yellow } from 'chalk';\nimport { isBuiltin } from 'module';\nimport type { Ora } from 'ora';\nimport type {\n Compiler,\n ProvidePlugin,\n Resolver,\n StatsError,\n WebpackPluginInstance,\n} from 'webpack';\nimport { WebpackError } from 'webpack';\n\nimport { formatText, pluralize } from './utils';\nimport { evaluate } from '../commands/eval';\nimport { error, getErrorMessage, info, warn } from '../utils';\n\nexport type SnapsStatsPluginOptions = {\n /**\n * Whether to log the verbose stats.\n */\n verbose?: boolean;\n};\n\n/**\n * A plugin that logs the stats after compilation. This is useful for logging\n * the number of files compiled, and the time taken to compile them.\n */\nexport class SnapsStatsPlugin implements WebpackPluginInstance {\n /**\n * The options for the plugin.\n */\n readonly options: SnapsStatsPluginOptions;\n\n /**\n * The spinner to use for logging.\n */\n readonly #spinner?: Ora;\n\n constructor(\n options: SnapsStatsPluginOptions = {\n verbose: false,\n },\n spinner?: Ora,\n ) {\n this.options = options;\n this.#spinner = spinner;\n }\n\n /**\n * Apply the plugin to the Webpack compiler.\n *\n * @param compiler - The Webpack compiler.\n */\n apply(compiler: Compiler) {\n compiler.hooks.afterDone.tap(this.constructor.name, (stats) => {\n if (!stats) {\n return;\n }\n\n const { modules, time, errors, warnings } = stats.toJson();\n\n assert(modules, 'Modules must be defined in stats.');\n assert(time, 'Time must be defined in stats.');\n\n if (errors?.length) {\n const formattedErrors = errors\n .map((statsError) => this.#getStatsErrorMessage(statsError, red))\n .join('\\n\\n');\n\n error(\n `Compiled ${modules.length} ${pluralize(\n modules.length,\n 'file',\n )} in ${time}ms with ${errors.length} ${pluralize(\n errors.length,\n 'error',\n )}.\\n\\n${formattedErrors}\\n`,\n this.#spinner,\n );\n\n this.#spinner?.stop();\n\n process.exitCode = 1;\n return;\n }\n\n if (warnings?.length) {\n const formattedWarnings = warnings\n .map((statsWarning) =>\n this.#getStatsErrorMessage(statsWarning, yellow),\n )\n .join('\\n\\n');\n\n warn(\n `Compiled ${modules.length} ${pluralize(\n modules.length,\n 'file',\n )} in ${time}ms with ${warnings.length} ${pluralize(\n warnings.length,\n 'warning',\n )}.\\n\\n${formattedWarnings}\\n`,\n this.#spinner,\n );\n } else {\n info(\n `Compiled ${modules.length} ${pluralize(\n modules.length,\n 'file',\n )} in ${time}ms.`,\n this.#spinner,\n );\n }\n\n if (compiler.watchMode) {\n // The spinner may be restarted by the watch plugin, outside of the\n // `executeSteps` flow, so we stop it here just in case.\n this.#spinner?.succeed('Done!');\n }\n });\n }\n\n /**\n * Get the error message for the given stats error.\n *\n * @param statsError - The stats error.\n * @param color - The color to use for the error message.\n * @returns The error message.\n */\n #getStatsErrorMessage(\n statsError: StatsError,\n color: typeof red | typeof yellow,\n ) {\n const baseMessage = this.options.verbose\n ? getErrorMessage(statsError)\n : statsError.message;\n\n const [first, ...rest] = baseMessage.split('\\n');\n\n return [\n color(formatText(`• ${first}`, 4, 2)),\n ...rest.map((message) => formatText(color(message), 4)),\n statsError.details && `\\n${formatText(dim(statsError.details), 6)}`,\n ]\n .filter(Boolean)\n .join('\\n');\n }\n}\n\n/**\n * The options for the {@link SnapsWatchPlugin}.\n */\nexport type SnapsWatchPluginOptions = {\n /**\n * The bundle path. This is the file that will be evaluated, if the `evaluate`\n * option is set.\n */\n bundle?: string;\n\n /**\n * Whether to evaluate the bundle. This only applies if the `bundle` option is\n * set.\n */\n evaluate?: boolean;\n\n /**\n * The extra files to watch.\n */\n files?: string[];\n};\n\n/**\n * A plugin that adds extra files to watch. This is useful for watching files\n * that are not imported by the entry point, such as the `snap.manifest.json`\n * file.\n */\nexport class SnapsWatchPlugin implements WebpackPluginInstance {\n /**\n * The options for the plugin.\n */\n readonly options: SnapsWatchPluginOptions;\n\n /**\n * The spinner to use for logging.\n */\n readonly #spinner?: Ora;\n\n constructor(options: SnapsWatchPluginOptions, spinner?: Ora) {\n this.options = options;\n this.#spinner = spinner;\n }\n\n /**\n * Apply the plugin to the Webpack compiler.\n *\n * @param compiler - The Webpack compiler.\n */\n apply(compiler: Compiler) {\n compiler.hooks.invalid.tap(this.constructor.name, (file) => {\n this.#spinner?.start();\n info(`Changes detected in ${yellow(file)}, recompiling.`, this.#spinner);\n });\n\n compiler.hooks.afterEmit.tapPromise(\n this.constructor.name,\n async ({ fileDependencies }) => {\n this.options.files?.forEach(\n fileDependencies.add.bind(fileDependencies),\n );\n\n if (this.options.bundle && this.options.evaluate) {\n await this.#safeEvaluate(this.options.bundle);\n }\n },\n );\n }\n\n /**\n * Safely evaluate the bundle at the given path. If an error occurs, it will\n * be logged to the console, rather than throwing an error.\n *\n * This function should never throw an error.\n *\n * @param bundlePath - The path to the bundle.\n */\n async #safeEvaluate(bundlePath: string) {\n try {\n await evaluate(bundlePath);\n info(`Snap bundle evaluated successfully.`, this.#spinner);\n } catch (evaluateError) {\n error(evaluateError.message, this.#spinner);\n }\n }\n}\n\n/**\n * The options for the {@link SnapsBuiltInResolver}.\n */\nexport type SnapsBuiltInResolverOptions = {\n /**\n * The built-in modules to ignore.\n */\n ignore?: string[];\n};\n\n/**\n * A Webpack resolve plugin.\n *\n * Copied from Webpack's own types, because the `ResolvePluginInstance` type is\n * a union, and can't be used as a type for a class.\n */\ntype ResolvePlugin = {\n apply: (resolver: Resolver) => void;\n};\n\n/**\n * A plugin that logs a message when a built-in module is not resolved. The\n * MetaMask Snaps CLI does not support built-in modules by default, and this\n * plugin is used to warn the user when they try to import a built-in module,\n * when no fallback is configured.\n */\nexport class SnapsBuiltInResolver implements ResolvePlugin {\n /**\n * The built-in modules that have been imported, but not resolved.\n */\n readonly unresolvedModules = new Set<string>();\n\n /**\n * The name of the resolver hook to tap into.\n */\n readonly #source = 'described-resolve';\n\n /**\n * The options for the plugin.\n */\n readonly options: SnapsBuiltInResolverOptions;\n\n constructor(\n options: SnapsBuiltInResolverOptions = {\n ignore: [],\n },\n ) {\n this.options = options;\n }\n\n /**\n * Apply the plugin to the Webpack resolver.\n *\n * @param resolver - The Webpack resolver.\n */\n apply(resolver: Resolver) {\n resolver\n .getHook(this.#source)\n .tapAsync(\n this.constructor.name,\n ({ module: isModule, request }, _, callback) => {\n if (!isModule || !request) {\n return callback();\n }\n\n const baseRequest = request.split('/')[0];\n if (\n isBuiltin(baseRequest) &&\n !this.options.ignore?.includes(baseRequest)\n ) {\n const fallback = resolver.options.fallback.find(\n ({ name }) => name === baseRequest,\n );\n\n if (fallback && !fallback.alias) {\n this.unresolvedModules.add(baseRequest);\n }\n }\n\n return callback();\n },\n );\n }\n}\n\n/**\n * The options for the {@link SnapsBundleWarningsPlugin}.\n */\nexport type SnapsBundleWarningsPluginOptions = {\n /**\n * The {@link SnapsBuiltInResolver} instance to use for detecting built-in\n * modules.\n */\n builtInResolver?: SnapsBuiltInResolver | false;\n\n /**\n * Whether to show warnings if built-in modules are used, but not provided by\n * Webpack's `fallback` configuration.\n */\n builtIns?: boolean;\n\n /**\n * Whether to show warnings if the `Buffer` global is used, but not provided\n * by Webpack's `DefinePlugin`.\n */\n buffer?: boolean;\n};\n\n/**\n * A plugin that logs a message when:\n *\n * - A built-in module is not resolved. The MetaMask Snaps CLI does not support\n * built-in modules by default, and this plugin is used to warn the user when\n * they try to import a built-in module, when no fallback is configured.\n * - A snap uses the `Buffer` global. The MetaMask Snaps CLI does not support\n * the `Buffer` global by default, and this plugin is used to warn the user when\n * they try to use the `Buffer` global.\n *\n * We use both a resolver and a plugin, because the resolver is used to detect\n * when a built-in module is imported, and the plugin is used to log a single\n * message when the compilation is complete. We can't do everything in a single\n * plugin, because the resolver doesn't have access to the compilation, and the\n * plugin doesn't have access to the resolver.\n */\n\nexport class SnapsBundleWarningsPlugin implements WebpackPluginInstance {\n /**\n * The options for the plugin.\n */\n readonly options: SnapsBundleWarningsPluginOptions;\n\n constructor(\n options: SnapsBundleWarningsPluginOptions = {\n buffer: true,\n builtIns: true,\n },\n ) {\n this.options = options;\n }\n\n /**\n * Apply the plugin to the Webpack compiler.\n *\n * @param compiler - The Webpack compiler.\n */\n apply(compiler: Compiler) {\n if (this.options.builtIns) {\n this.#checkBuiltIns(compiler);\n }\n\n if (this.options.buffer) {\n this.#checkBuffer(compiler);\n }\n }\n\n /**\n * Check if a built-in module is used, but not provided by Webpack's\n * `fallback` configuration.\n *\n * @param compiler - The Webpack compiler.\n */\n #checkBuiltIns(compiler: Compiler) {\n compiler.hooks.afterCompile.tap(this.constructor.name, (compilation) => {\n if (!this.options.builtInResolver) {\n return;\n }\n\n const { unresolvedModules } = this.options.builtInResolver;\n if (unresolvedModules.size === 0) {\n return;\n }\n\n const formattedModules = new Array(...unresolvedModules)\n .map((name) => `• ${name}`)\n .join('\\n');\n\n const webpackError = new WebpackError(\n `The snap attempted to use one or more Node.js builtins, but no browser fallback has been provided. The MetaMask Snaps CLI does not support Node.js builtins by default. If you want to use this module, you must set ${bold(\n '`polyfills`',\n )} to ${bold(\n '`true`',\n )} or an object with the builtins to polyfill as the key and ${bold(\n '`true`',\n )} as the value. To disable this warning, set ${bold(\n '`stats.builtIns`',\n )} to ${bold(\n '`false`',\n )} in your snap config file, or add the module to the ${bold(\n '`stats.builtIns.ignore`',\n )} array.`,\n );\n\n webpackError.details = formattedModules;\n compilation.warnings.push(webpackError);\n });\n }\n\n /**\n * Check if the given instance is a `ProvidePlugin`. This is not guaranteed to\n * be accurate, but it's good enough for our purposes. If we were to use\n * `instanceof` instead, it might not work if multiple versions of Webpack are\n * installed.\n *\n * @param instance - The instance to check.\n * @returns Whether the instance is a `ProvidePlugin`, i.e., whether it's an\n * object with the name `ProvidePlugin` and a `definitions` property.\n */\n #isProvidePlugin(instance: unknown): instance is ProvidePlugin {\n return (\n isObject(instance) &&\n instance.constructor.name === 'ProvidePlugin' &&\n hasProperty(instance, 'definitions')\n );\n }\n\n /**\n * Check if the `Buffer` global is used, but not provided by Webpack's\n * `DefinePlugin`.\n *\n * @param compiler - The Webpack compiler.\n */\n #checkBuffer(compiler: Compiler) {\n const plugin = compiler.options.plugins?.find((instance) =>\n this.#isProvidePlugin(instance),\n ) as ProvidePlugin | undefined;\n\n // If the `ProvidePlugin` is configured to provide `Buffer`, then we don't\n // need to warn the user.\n if (plugin) {\n const { definitions } = plugin;\n if (definitions.Buffer) {\n return;\n }\n }\n\n compiler.hooks.compilation.tap(this.constructor.name, (compilation) => {\n compilation.hooks.afterProcessAssets.tap(\n this.constructor.name,\n (assets) => {\n // Check if assets use `Buffer`.\n const bufferAssets = Object.entries(assets)\n .filter(([name]) => name.endsWith('.js'))\n .filter(([, asset]) => asset.source().includes('Buffer'));\n\n if (bufferAssets.length === 0) {\n return;\n }\n\n compilation.warnings.push(\n new WebpackError(\n `The snap attempted to use the Node.js Buffer global, which is not supported in the MetaMask Snaps CLI by default. To use the Buffer global, you must polyfill Buffer by setting ${bold(\n '`buffer`',\n )} to ${bold('`true`')} in the ${bold(\n '`polyfills`',\n )} config object in your snap config. To disable this warning, set ${bold(\n '`stats.buffer`',\n )} to ${bold('`false`')} in your snap config file.`,\n ),\n );\n },\n );\n });\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/snaps-cli",
3
- "version": "7.1.0",
3
+ "version": "8.0.0",
4
4
  "description": "A CLI for developing MetaMask Snaps",
5
5
  "keywords": [
6
6
  "MetaMask",
@@ -64,13 +64,14 @@
64
64
  "test:watch": "jest --watch"
65
65
  },
66
66
  "dependencies": {
67
+ "@metamask/snaps-rpc-methods": "^13.0.0",
67
68
  "@metamask/snaps-sandbox": "^1.0.0",
68
- "@metamask/snaps-sdk": "^6.22.0",
69
- "@metamask/snaps-utils": "^9.2.0",
70
- "@metamask/snaps-webpack-plugin": "^4.2.1",
69
+ "@metamask/snaps-sdk": "^8.0.0",
70
+ "@metamask/snaps-utils": "^10.0.0",
71
+ "@metamask/snaps-webpack-plugin": "^4.3.0",
71
72
  "@metamask/superstruct": "^3.2.1",
72
73
  "@metamask/utils": "^11.4.0",
73
- "@swc/core": "1.3.78",
74
+ "@swc/core": "1.11.31",
74
75
  "assert": "^2.0.0",
75
76
  "browserify-zlib": "^0.2.0",
76
77
  "buffer": "^6.0.3",
@@ -95,7 +96,7 @@
95
96
  "stream-http": "^3.2.0",
96
97
  "string_decoder": "^1.3.0",
97
98
  "strip-ansi": "^6.0.1",
98
- "swc-loader": "^0.2.3",
99
+ "swc-loader": "^0.2.6",
99
100
  "terser-webpack-plugin": "^5.3.9",
100
101
  "timers-browserify": "^2.0.12",
101
102
  "tty-browserify": "^0.0.1",
@@ -108,9 +109,9 @@
108
109
  "yargs": "^17.7.1"
109
110
  },
110
111
  "devDependencies": {
111
- "@lavamoat/allow-scripts": "^3.0.4",
112
- "@metamask/auto-changelog": "^5.0.1",
113
- "@swc/jest": "^0.2.26",
112
+ "@lavamoat/allow-scripts": "^3.3.3",
113
+ "@metamask/auto-changelog": "^5.0.2",
114
+ "@swc/jest": "^0.2.38",
114
115
  "@ts-bridge/cli": "^0.6.1",
115
116
  "@types/express": "^5.0.1",
116
117
  "@types/jest": "^27.5.1",
@@ -131,7 +132,7 @@
131
132
  "typescript": "~5.3.3"
132
133
  },
133
134
  "engines": {
134
- "node": "^18.16 || >=20"
135
+ "node": "^20 || >=22"
135
136
  },
136
137
  "publishConfig": {
137
138
  "access": "public",