Skip to content

Commit 84e8ede

Browse files
committed
Allow eval in watch mode
1 parent 554d5d0 commit 84e8ede

File tree

11 files changed

+200
-143
lines changed

11 files changed

+200
-143
lines changed

packages/snaps-cli/src/commands/watch/watch.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ describe('watchHandler', () => {
3434
expect(listen).toHaveBeenCalledWith(config.server.port);
3535
expect(watch).toHaveBeenCalledWith(config, {
3636
spinner: expect.any(Object),
37+
evaluate: true,
38+
spinner: expect.any(Object),
3739
});
3840

3941
expect(log).toHaveBeenCalledWith(

packages/snaps-cli/src/commands/watch/watch.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const steps: Steps<WatchContext> = [
4545
{
4646
name: 'Building the Snap bundle.',
4747
task: async ({ config, spinner }) => {
48-
await watch(config, { spinner });
48+
await watch(config, { spinner, evaluate: config.evaluate });
4949
},
5050
},
5151
];

packages/snaps-cli/src/webpack/__snapshots__/config.test.ts.snap

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2183,7 +2183,7 @@ exports[`getDefaultConfiguration returns the default Webpack configuration for t
21832183
"plugins": [
21842184
SnapsWebpackPlugin {
21852185
"options": {
2186-
"eval": false,
2186+
"eval": true,
21872187
"manifestPath": "/bar/snap.manifest.json",
21882188
"writeManifest": true,
21892189
},
@@ -2225,8 +2225,6 @@ exports[`getDefaultConfiguration returns the default Webpack configuration for t
22252225
},
22262226
SnapsWatchPlugin {
22272227
"options": {
2228-
"bundle": "/bar/baz/bundle.js",
2229-
"evaluate": true,
22302228
"files": [
22312229
"/bar/snap.manifest.json",
22322230
],
@@ -2750,8 +2748,6 @@ exports[`getDefaultConfiguration returns the default Webpack configuration for t
27502748
},
27512749
SnapsWatchPlugin {
27522750
"options": {
2753-
"bundle": "/bar/baz/bundle.js",
2754-
"evaluate": false,
27552751
"files": [
27562752
"/bar/snap.manifest.json",
27572753
],
@@ -2889,7 +2885,7 @@ exports[`getDefaultConfiguration returns the default Webpack configuration for t
28892885
"plugins": [
28902886
SnapsWebpackPlugin {
28912887
"options": {
2892-
"eval": false,
2888+
"eval": true,
28932889
"manifestPath": "/bar/snap.manifest.json",
28942890
"writeManifest": true,
28952891
},
@@ -2931,8 +2927,6 @@ exports[`getDefaultConfiguration returns the default Webpack configuration for t
29312927
},
29322928
SnapsWatchPlugin {
29332929
"options": {
2934-
"bundle": "/bar/baz/bundle.js",
2935-
"evaluate": true,
29362930
"files": [
29372931
"/bar/snap.manifest.json",
29382932
],

packages/snaps-cli/src/webpack/config.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import SnapsWebpackPlugin from '@metamask/snaps-webpack-plugin';
22
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
33
import type { Ora } from 'ora';
4-
import { resolve } from 'path';
54
import TerserPlugin from 'terser-webpack-plugin';
65
import type { Configuration } from 'webpack';
76
import { DefinePlugin, ProgressPlugin, ProvidePlugin } from 'webpack';
@@ -308,7 +307,7 @@ export async function getDefaultConfiguration(
308307
{
309308
manifestPath: config.manifest.path,
310309
writeManifest: config.manifest.update,
311-
eval: !options.watch && options.evaluate,
310+
eval: options.evaluate,
312311
},
313312
options.spinner,
314313
),
@@ -355,8 +354,6 @@ export async function getDefaultConfiguration(
355354
options.watch &&
356355
new SnapsWatchPlugin(
357356
{
358-
bundle: resolve(config.output.path, config.output.filename),
359-
evaluate: options.evaluate,
360357
files: [config.manifest.path],
361358
},
362359
options.spinner,

packages/snaps-cli/src/webpack/plugins.test.ts

Lines changed: 0 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
SnapsStatsPlugin,
1111
SnapsWatchPlugin,
1212
} from './plugins';
13-
import * as evalImplementation from '../commands/eval/implementation';
1413
import { compile, getCompiler } from '../test-utils';
1514

1615
jest.dontMock('fs');
@@ -264,93 +263,6 @@ describe('SnapsWatchPlugin', () => {
264263
const close = promisify(watcher.close.bind(watcher));
265264
await close();
266265
});
267-
268-
it('evaluates the bundle if enabled', async () => {
269-
const log = jest.spyOn(console, 'log').mockImplementation();
270-
const evaluate = jest
271-
.spyOn(evalImplementation, 'evaluate')
272-
.mockImplementation();
273-
274-
const fileSystem = createFsFromVolume(new Volume());
275-
const compiler = await getCompiler({
276-
fileSystem,
277-
config: {
278-
plugins: [
279-
new SnapsWatchPlugin({
280-
bundle: '/output.js',
281-
evaluate: true,
282-
files: [],
283-
}),
284-
],
285-
},
286-
});
287-
288-
// Wait for the initial compilation to complete.
289-
const watcher = await new Promise<Watching>((resolve) => {
290-
const innerWatcher = compiler.watch(
291-
{
292-
poll: 1,
293-
ignored: ['/output.js'],
294-
},
295-
() => {
296-
resolve(innerWatcher);
297-
},
298-
);
299-
});
300-
301-
expect(log).toHaveBeenCalledTimes(1);
302-
expect(log).toHaveBeenCalledWith(
303-
expect.stringMatching(/Snap bundle evaluated successfully\./u),
304-
);
305-
expect(evaluate).toHaveBeenCalled();
306-
307-
const close = promisify(watcher.close.bind(watcher));
308-
await close();
309-
});
310-
311-
it('logs evaluation errors', async () => {
312-
const log = jest.spyOn(console, 'log').mockImplementation();
313-
const error = jest.spyOn(console, 'error').mockImplementation();
314-
const evaluate = jest
315-
.spyOn(evalImplementation, 'evaluate')
316-
.mockRejectedValue(new Error('Evaluation error.'));
317-
318-
const fileSystem = createFsFromVolume(new Volume());
319-
const compiler = await getCompiler({
320-
fileSystem,
321-
config: {
322-
plugins: [
323-
new SnapsWatchPlugin({
324-
bundle: '/output.js',
325-
evaluate: true,
326-
files: [],
327-
}),
328-
],
329-
},
330-
});
331-
332-
// Wait for the initial compilation to complete.
333-
const watcher = await new Promise<Watching>((resolve) => {
334-
const innerWatcher = compiler.watch(
335-
{
336-
poll: 1,
337-
ignored: ['/output.js'],
338-
},
339-
() => {
340-
resolve(innerWatcher);
341-
},
342-
);
343-
});
344-
345-
expect(log).not.toHaveBeenCalled();
346-
expect(evaluate).toHaveBeenCalled();
347-
expect(error).toHaveBeenCalledWith(
348-
expect.stringContaining('Evaluation error.'),
349-
);
350-
351-
const close = promisify(watcher.close.bind(watcher));
352-
await close();
353-
});
354266
});
355267

356268
describe('SnapsBuiltInResolver', () => {

packages/snaps-cli/src/webpack/plugins.ts

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import type {
1212
import { WebpackError } from 'webpack';
1313

1414
import { formatText, pluralize } from './utils';
15-
import { evaluate } from '../commands/eval';
1615
import { error, getErrorMessage, info, warn } from '../utils';
1716

1817
export type SnapsStatsPluginOptions = {
@@ -151,18 +150,6 @@ export class SnapsStatsPlugin implements WebpackPluginInstance {
151150
* The options for the {@link SnapsWatchPlugin}.
152151
*/
153152
export type SnapsWatchPluginOptions = {
154-
/**
155-
* The bundle path. This is the file that will be evaluated, if the `evaluate`
156-
* option is set.
157-
*/
158-
bundle?: string;
159-
160-
/**
161-
* Whether to evaluate the bundle. This only applies if the `bundle` option is
162-
* set.
163-
*/
164-
evaluate?: boolean;
165-
166153
/**
167154
* The extra files to watch.
168155
*/
@@ -207,30 +194,9 @@ export class SnapsWatchPlugin implements WebpackPluginInstance {
207194
this.options.files?.forEach(
208195
fileDependencies.add.bind(fileDependencies),
209196
);
210-
211-
if (this.options.bundle && this.options.evaluate) {
212-
await this.#safeEvaluate(this.options.bundle);
213-
}
214197
},
215198
);
216199
}
217-
218-
/**
219-
* Safely evaluate the bundle at the given path. If an error occurs, it will
220-
* be logged to the console, rather than throwing an error.
221-
*
222-
* This function should never throw an error.
223-
*
224-
* @param bundlePath - The path to the bundle.
225-
*/
226-
async #safeEvaluate(bundlePath: string) {
227-
try {
228-
await evaluate(bundlePath);
229-
info(`Snap bundle evaluated successfully.`, this.#spinner);
230-
} catch (evaluateError) {
231-
error(evaluateError.message, this.#spinner);
232-
}
233-
}
234200
}
235201

236202
/**

packages/snaps-utils/src/manifest/manifest.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import pathUtils from 'path';
66

77
import type { SnapManifest } from './validation';
88
import type { ValidatorResults } from './validator';
9-
import { hasFixes, runValidators } from './validator';
9+
import { isReportFixable, hasFixes, runValidators } from './validator';
1010
import type { ValidatorMeta, ValidatorReport } from './validator-types';
1111
import * as defaultValidators from './validators';
1212
import { deepClone } from '../deep-clone';
@@ -65,6 +65,12 @@ export type CheckManifestOptions = {
6565
* between `@metamask/snaps-utils` and `@metamask/snaps-rpc-methods`.
6666
*/
6767
handlerEndowments?: Record<string, string | null>;
68+
69+
/**
70+
* Whether the compiler is running in watch mode. This is used to determine
71+
* whether to fix warnings or errors only.
72+
*/
73+
watchMode?: boolean;
6874
};
6975

7076
/**
@@ -99,6 +105,8 @@ export type WriteFileFunction = (path: string, data: string) => Promise<void>;
99105
* handlers and their respective permission name. This must be provided to avoid
100106
* circular dependencies between `@metamask/snaps-utils` and
101107
* `@metamask/snaps-rpc-methods`.
108+
* @param options.watchMode - Whether the compiler is running in watch mode.
109+
* This is used to determine whether to fix warnings or errors only.
102110
* @returns Whether the manifest was updated, and an array of warnings that
103111
* were encountered during processing of the manifest files.
104112
*/
@@ -110,6 +118,7 @@ export async function checkManifest(
110118
writeFileFn = fs.writeFile,
111119
exports,
112120
handlerEndowments,
121+
watchMode = false,
113122
}: CheckManifestOptions = {},
114123
): Promise<CheckManifestResult> {
115124
const manifestPath = pathUtils.join(basePath, NpmSnapFileNames.Manifest);
@@ -169,8 +178,8 @@ export async function checkManifest(
169178
reports: validatorResults.reports,
170179
};
171180

172-
if (updateAndWriteManifest && hasFixes(manifestResults)) {
173-
const fixedResults = await runFixes(validatorResults);
181+
if (updateAndWriteManifest && hasFixes(manifestResults, watchMode)) {
182+
const fixedResults = await runFixes(validatorResults, undefined, watchMode);
174183

175184
if (fixedResults.updated) {
176185
manifestResults = fixedResults;
@@ -206,11 +215,13 @@ export async function checkManifest(
206215
*
207216
* @param results - Results of the initial run of validation.
208217
* @param rules - Optional list of rules to run the fixes with.
218+
* @param errorsOnly - Whether to only run fixes for errors, not warnings.
209219
* @returns The updated manifest and whether it was updated.
210220
*/
211221
export async function runFixes(
212222
results: ValidatorResults,
213223
rules?: ValidatorMeta[],
224+
errorsOnly = false,
214225
): Promise<CheckManifestResult> {
215226
let shouldRunFixes = true;
216227
const MAX_ATTEMPTS = 10;
@@ -230,7 +241,10 @@ export async function runFixes(
230241

231242
let manifest = fixResults.files.manifest.result;
232243

233-
const fixable = fixResults.reports.filter((report) => report.fix);
244+
const fixable = fixResults.reports.filter((report) =>
245+
isReportFixable(report, errorsOnly),
246+
);
247+
234248
for (const report of fixable) {
235249
assert(report.fix);
236250
({ manifest } = await report.fix({ manifest }));
@@ -244,7 +258,7 @@ export async function runFixes(
244258
fixResults.files.manifest.result = manifest;
245259

246260
fixResults = await runValidators(fixResults.files, rules);
247-
shouldRunFixes = hasFixes(fixResults);
261+
shouldRunFixes = hasFixes(fixResults, errorsOnly);
248262
}
249263

250264
const initialReports: (CheckManifestReport & ValidatorReport)[] = deepClone(

0 commit comments

Comments
 (0)