1- import { isFile } from '@metamask/snaps-utils/node' ;
1+ import { handlerEndowments } from '@metamask/snaps-rpc-methods' ;
2+ import { checkManifest , isFile } from '@metamask/snaps-utils/node' ;
3+ import { writeManifest } from '@metamask/snaps-webpack-plugin' ;
24import { assert } from '@metamask/utils' ;
3- import { resolve as pathResolve } from 'path' ;
5+ import { red , reset , yellow } from 'chalk' ;
6+ import { readFile } from 'fs/promises' ;
7+ import { dirname , resolve as pathResolve } from 'path' ;
48
59import { build } from './implementation' ;
610import { getBundleAnalyzerPort } from './utils' ;
711import type { ProcessedConfig } from '../../config' ;
812import { CommandError } from '../../errors' ;
913import type { Steps } from '../../utils' ;
10- import { success , executeSteps , info } from '../../utils' ;
14+ import { error , success , executeSteps , info , warn } from '../../utils' ;
15+ import { formatError } from '../../webpack/utils' ;
1116import { evaluate } from '../eval' ;
1217
1318type BuildContext = {
1419 analyze : boolean ;
1520 config : ProcessedConfig ;
1621 port ?: number ;
22+ exports ?: string [ ] ;
1723} ;
1824
1925const steps : Steps < BuildContext > = [
@@ -24,13 +30,13 @@ const steps: Steps<BuildContext> = [
2430
2531 if ( ! ( await isFile ( input ) ) ) {
2632 throw new CommandError (
27- `Input file not found: "${ input } ". Make sure that the "input" field in your snap config is correct.` ,
33+ `Input file not found: "${ input } ". Make sure that the "input" field in your Snap config is correct.` ,
2834 ) ;
2935 }
3036 } ,
3137 } ,
3238 {
33- name : 'Building the snap bundle.' ,
39+ name : 'Building the Snap bundle.' ,
3440 task : async ( { analyze, config, spinner } ) => {
3541 // We don't evaluate the bundle here, because it's done in a separate
3642 // step.
@@ -53,18 +59,85 @@ const steps: Steps<BuildContext> = [
5359 } ,
5460 } ,
5561 {
56- name : 'Evaluating the snap bundle.' ,
62+ name : 'Evaluating the Snap bundle.' ,
5763 condition : ( { config } ) => config . evaluate ,
58- task : async ( { config, spinner } ) => {
64+ task : async ( context ) => {
65+ const { config, spinner } = context ;
5966 const path = pathResolve (
6067 process . cwd ( ) ,
6168 config . output . path ,
6269 config . output . filename ,
6370 ) ;
6471
65- await evaluate ( path ) ;
72+ const { exports } = await evaluate ( path ) ;
6673
6774 info ( `Snap bundle evaluated successfully.` , spinner ) ;
75+
76+ return {
77+ ...context ,
78+ exports,
79+ } ;
80+ } ,
81+ } ,
82+
83+ // TODO: Share this between the `build` and `manifest` commands.
84+ {
85+ name : 'Validating the Snap manifest.' ,
86+ condition : ( { config } ) => config . evaluate ,
87+ task : async ( { config, exports, spinner } ) => {
88+ const bundlePath = pathResolve (
89+ process . cwd ( ) ,
90+ config . output . path ,
91+ config . output . filename ,
92+ ) ;
93+
94+ const { reports } = await checkManifest ( dirname ( config . manifest . path ) , {
95+ updateAndWriteManifest : config . manifest . update ,
96+ sourceCode : await readFile ( bundlePath , 'utf-8' ) ,
97+ exports,
98+ handlerEndowments,
99+ writeFileFn : async ( path , data ) => {
100+ return writeManifest ( path , data ) ;
101+ } ,
102+ } ) ;
103+
104+ // TODO: Use `Object.groupBy` when available.
105+ const errors = reports
106+ . filter ( ( report ) => report . severity === 'error' && ! report . wasFixed )
107+ . map ( ( report ) => report . message ) ;
108+ const warnings = reports
109+ . filter ( ( report ) => report . severity === 'warning' && ! report . wasFixed )
110+ . map ( ( report ) => report . message ) ;
111+ const fixed = reports
112+ . filter ( ( report ) => report . wasFixed )
113+ . map ( ( report ) => report . message ) ;
114+
115+ if ( errors . length > 0 ) {
116+ error (
117+ `The following errors were found in the manifest:\n\n${ errors
118+ . map ( ( value ) => formatError ( value , '' , red ) )
119+ . join ( '\n\n' ) } \n`,
120+ spinner ,
121+ ) ;
122+ }
123+
124+ if ( warnings . length > 0 ) {
125+ warn (
126+ `The following warnings were found in the manifest:\n\n${ warnings
127+ . map ( ( value ) => formatError ( value , '' , yellow ) )
128+ . join ( '\n\n' ) } \n`,
129+ spinner ,
130+ ) ;
131+ }
132+
133+ if ( fixed . length > 0 ) {
134+ info (
135+ `The following issues were fixed in the manifest:\n\n${ reset (
136+ fixed . map ( ( value ) => formatError ( value , '' , reset ) ) . join ( '\n\n' ) ,
137+ ) } \n`,
138+ spinner ,
139+ ) ;
140+ }
68141 } ,
69142 } ,
70143 {
0 commit comments