UNPKG

@metamask/snaps-browserify-plugin

Version:

A Browserify plugin to build MetaMask Snaps with Browserify

151 lines 7.44 kB
"use strict"; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); 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"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); 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"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var _SnapsBrowserifyTransform_data, _SnapsBrowserifyTransform_options; Object.defineProperty(exports, "__esModule", { value: true }); exports.SnapsBrowserifyTransform = void 0; const node_1 = require("@metamask/snaps-utils/node"); const convert_source_map_1 = require("convert-source-map"); const path_1 = __importDefault(require("path")); const readable_stream_1 = require("readable-stream"); /** * Run eval on the processed bundle and fix the manifest, if configured. * * @param options - The plugin options. * @param code - The code to eval, if the eval option is enabled. */ async function postBundle(options, code) { if (options.eval) { await (0, node_1.useTemporaryFile)('snaps-bundle.js', code, (path) => (0, node_1.evalBundle)(path)); } if (options.manifestPath) { const { reports } = await (0, node_1.checkManifest)(path_1.default.dirname(options.manifestPath), { sourceCode: code, updateAndWriteManifest: options.writeManifest, }); const errorsUnfixed = reports .filter((report) => report.severity === 'error' && !report.wasFixed) .map((report) => report.message); const warnings = reports .filter((report) => report.severity === 'warning' && !report.wasFixed) .map((report) => report.message); const fixed = reports .filter((report) => report.wasFixed) .map((report) => report.message); if (errorsUnfixed.length > 0) { throw new Error(`Manifest Error: The manifest is invalid.\n${errorsUnfixed.join('\n')}`); } if (warnings.length > 0) { (0, node_1.logWarning)('Manifest Warning: Validation of snap.manifest.json completed with warnings.'); warnings.forEach((warning) => (0, node_1.logWarning)(`Manifest Warning: ${warning}`)); } if (fixed.length > 0) { (0, node_1.logWarning)(`Manifest Warning: Validation of snap.manifest.json fixed following problems.`); fixed.forEach((error) => (0, node_1.logWarning)(`Manifest Problem Fixed: ${error}`)); } } } /** * A transform stream which can be used in the Browserify pipeline. It accepts a * string input, which is post-processed and pushed to the output stream. */ class SnapsBrowserifyTransform extends readable_stream_1.Transform { /** * Construct an instance of the transform stream. * * @param options - The post-processing options. * @param options.stripComments - Whether to strip comments. Defaults to `true`. * @param options.transformHtmlComments - Whether to transform HTML comments. * Defaults to `true`. */ constructor(options = {}) { super(); _SnapsBrowserifyTransform_data.set(this, []); _SnapsBrowserifyTransform_options.set(this, void 0); __classPrivateFieldSet(this, _SnapsBrowserifyTransform_options, { ...options }, "f"); } /** * Takes a chunk of data and pushes it into an internal array, for later * processing. * * @param chunk - The chunk of data to transform. * @param _encoding - The encoding of the chunk. * @param callback - The callback to call when the chunk is processed. */ _transform(chunk, _encoding, callback) { // Collects all the chunks into an array. __classPrivateFieldGet(this, _SnapsBrowserifyTransform_data, "f").push(chunk); callback(); } /** * Takes the internal array of chunks and processes them. The processed code * is pushed to the output stream. * * @param callback - The callback to call when the stream is finished. */ _flush(callback) { // Merges all the chunks into a single string and processes it. const code = Buffer.concat(__classPrivateFieldGet(this, _SnapsBrowserifyTransform_data, "f")).toString('utf-8'); // Browserify uses inline source maps, so we attempt to read it here, and // convert it to an object. const inputSourceMap = (0, convert_source_map_1.fromSource)(code)?.toObject() ?? undefined; const result = (0, node_1.postProcessBundle)(code, { ...__classPrivateFieldGet(this, _SnapsBrowserifyTransform_options, "f"), sourceMap: Boolean(inputSourceMap) && 'inline', inputSourceMap, }); if (result.warnings.length > 0) { (0, node_1.logWarning)(`Bundle Warning: Processing of the Snap bundle completed with warnings.\n${result.warnings.join('\n')}`); } postBundle(__classPrivateFieldGet(this, _SnapsBrowserifyTransform_options, "f"), result.code) .catch((error) => { callback(error); }) .finally(() => { this.push(result.code); callback(); }); } } exports.SnapsBrowserifyTransform = SnapsBrowserifyTransform; _SnapsBrowserifyTransform_data = new WeakMap(), _SnapsBrowserifyTransform_options = new WeakMap(); /** * The Browserify plugin function. Can be passed to the Browserify `plugin` * function, or used by simply passing the package name to `plugin`. * * @param browserifyInstance - The Browserify instance. * @param options - The plugin options. * @param options.stripComments - Whether to strip comments. Defaults to `true`. * @param options.eval - Whether to evaluate the bundle to test SES * compatibility. Defaults to `true`. * @param options.manifestPath - The path to the manifest file. If provided, * the manifest will be validated. Defaults to * `process.cwd() + '/snap.manifest.json'`. * @param options.writeManifest - Whether to fix the manifest. * Defaults to `true`. */ function plugin(browserifyInstance, options) { const defaultOptions = { eval: true, manifestPath: path_1.default.join(process.cwd(), 'snap.manifest.json'), writeManifest: true, ...options, }; // Pushes the transform stream at the end of Browserify's pipeline. This // ensures that the transform is run on the entire bundle. browserifyInstance.pipeline.push(new SnapsBrowserifyTransform(defaultOptions)); } exports.default = plugin; //# sourceMappingURL=plugin.cjs.map