@metamask/snaps-utils 11.7.0 → 12.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.
- package/CHANGELOG.md +28 -1
- package/dist/checksum.cjs +1 -9
- package/dist/checksum.cjs.map +1 -1
- package/dist/checksum.d.cts.map +1 -1
- package/dist/checksum.d.mts.map +1 -1
- package/dist/checksum.mjs +2 -10
- package/dist/checksum.mjs.map +1 -1
- package/dist/handlers/assets-market-data.cjs +2 -2
- package/dist/handlers/assets-market-data.cjs.map +1 -1
- package/dist/handlers/assets-market-data.d.cts +2 -2
- package/dist/handlers/assets-market-data.d.mts +2 -2
- package/dist/handlers/assets-market-data.mjs +2 -2
- package/dist/handlers/assets-market-data.mjs.map +1 -1
- package/dist/iframe.cjs +1 -1
- package/dist/iframe.cjs.map +1 -1
- package/dist/iframe.d.cts.map +1 -1
- package/dist/iframe.d.mts.map +1 -1
- package/dist/iframe.mjs +1 -1
- package/dist/iframe.mjs.map +1 -1
- package/dist/localization.d.cts +1 -0
- package/dist/localization.d.cts.map +1 -1
- package/dist/localization.d.mts +1 -0
- package/dist/localization.d.mts.map +1 -1
- package/dist/manifest/manifest.cjs +99 -27
- package/dist/manifest/manifest.cjs.map +1 -1
- package/dist/manifest/manifest.d.cts +18 -5
- package/dist/manifest/manifest.d.cts.map +1 -1
- package/dist/manifest/manifest.d.mts +18 -5
- package/dist/manifest/manifest.d.mts.map +1 -1
- package/dist/manifest/manifest.mjs +106 -28
- package/dist/manifest/manifest.mjs.map +1 -1
- package/dist/manifest/validation.cjs +1 -0
- package/dist/manifest/validation.cjs.map +1 -1
- package/dist/manifest/validation.d.cts +2 -0
- package/dist/manifest/validation.d.cts.map +1 -1
- package/dist/manifest/validation.d.mts +2 -0
- package/dist/manifest/validation.d.mts.map +1 -1
- package/dist/manifest/validation.mjs +1 -0
- package/dist/manifest/validation.mjs.map +1 -1
- package/dist/manifest/validator-types.cjs.map +1 -1
- package/dist/manifest/validator-types.d.cts +4 -5
- package/dist/manifest/validator-types.d.cts.map +1 -1
- package/dist/manifest/validator-types.d.mts +4 -5
- package/dist/manifest/validator-types.d.mts.map +1 -1
- package/dist/manifest/validator-types.mjs.map +1 -1
- package/dist/manifest/validator.cjs +1 -1
- package/dist/manifest/validator.cjs.map +1 -1
- package/dist/manifest/validator.d.cts +3 -3
- package/dist/manifest/validator.d.cts.map +1 -1
- package/dist/manifest/validator.d.mts +3 -3
- package/dist/manifest/validator.d.mts.map +1 -1
- package/dist/manifest/validator.mjs +1 -1
- package/dist/manifest/validator.mjs.map +1 -1
- package/dist/manifest/validators/checksum.cjs +11 -3
- package/dist/manifest/validators/checksum.cjs.map +1 -1
- package/dist/manifest/validators/checksum.d.cts.map +1 -1
- package/dist/manifest/validators/checksum.d.mts.map +1 -1
- package/dist/manifest/validators/checksum.mjs +11 -3
- package/dist/manifest/validators/checksum.mjs.map +1 -1
- package/dist/manifest/validators/icon-declared.cjs +1 -1
- package/dist/manifest/validators/icon-declared.cjs.map +1 -1
- package/dist/manifest/validators/icon-declared.mjs +1 -1
- package/dist/manifest/validators/icon-declared.mjs.map +1 -1
- package/dist/manifest/validators/icon-missing.cjs +1 -1
- package/dist/manifest/validators/icon-missing.cjs.map +1 -1
- package/dist/manifest/validators/icon-missing.d.cts.map +1 -1
- package/dist/manifest/validators/icon-missing.d.mts.map +1 -1
- package/dist/manifest/validators/icon-missing.mjs +1 -1
- package/dist/manifest/validators/icon-missing.mjs.map +1 -1
- package/dist/manifest/validators/is-snap-manifest.cjs +1 -1
- package/dist/manifest/validators/is-snap-manifest.cjs.map +1 -1
- package/dist/manifest/validators/is-snap-manifest.mjs +1 -1
- package/dist/manifest/validators/is-snap-manifest.mjs.map +1 -1
- package/dist/manifest/validators/manifest-localization.cjs +1 -1
- package/dist/manifest/validators/manifest-localization.cjs.map +1 -1
- package/dist/manifest/validators/manifest-localization.mjs +1 -1
- package/dist/manifest/validators/manifest-localization.mjs.map +1 -1
- package/dist/manifest/validators/package-name-match.cjs +6 -2
- package/dist/manifest/validators/package-name-match.cjs.map +1 -1
- package/dist/manifest/validators/package-name-match.d.cts.map +1 -1
- package/dist/manifest/validators/package-name-match.d.mts.map +1 -1
- package/dist/manifest/validators/package-name-match.mjs +6 -2
- package/dist/manifest/validators/package-name-match.mjs.map +1 -1
- package/dist/manifest/validators/platform-version.cjs +4 -4
- package/dist/manifest/validators/platform-version.cjs.map +1 -1
- package/dist/manifest/validators/platform-version.d.cts.map +1 -1
- package/dist/manifest/validators/platform-version.d.mts.map +1 -1
- package/dist/manifest/validators/platform-version.mjs +4 -4
- package/dist/manifest/validators/platform-version.mjs.map +1 -1
- package/dist/manifest/validators/production-platform-version.cjs +1 -1
- package/dist/manifest/validators/production-platform-version.cjs.map +1 -1
- package/dist/manifest/validators/production-platform-version.d.cts.map +1 -1
- package/dist/manifest/validators/production-platform-version.d.mts.map +1 -1
- package/dist/manifest/validators/production-platform-version.mjs +1 -1
- package/dist/manifest/validators/production-platform-version.mjs.map +1 -1
- package/dist/manifest/validators/repository-match.cjs +2 -2
- package/dist/manifest/validators/repository-match.cjs.map +1 -1
- package/dist/manifest/validators/repository-match.d.cts.map +1 -1
- package/dist/manifest/validators/repository-match.d.mts.map +1 -1
- package/dist/manifest/validators/repository-match.mjs +2 -2
- package/dist/manifest/validators/repository-match.mjs.map +1 -1
- package/dist/manifest/validators/unused-exports.cjs +3 -3
- package/dist/manifest/validators/unused-exports.cjs.map +1 -1
- package/dist/manifest/validators/unused-exports.mjs +3 -3
- package/dist/manifest/validators/unused-exports.mjs.map +1 -1
- package/dist/manifest/validators/version-match.cjs +2 -2
- package/dist/manifest/validators/version-match.cjs.map +1 -1
- package/dist/manifest/validators/version-match.mjs +2 -2
- package/dist/manifest/validators/version-match.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +66 -1
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +66 -1
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/package.json +5 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.cjs","sourceRoot":"","sources":["../../src/manifest/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["import { getErrorMessage } from '@metamask/snaps-sdk';\nimport type { Json } from '@metamask/utils';\nimport { assert, isPlainObject } from '@metamask/utils';\nimport { promises as fs } from 'fs';\nimport pathUtils from 'path';\n\nimport type { SnapManifest } from './validation';\nimport type { ValidatorResults } from './validator';\nimport { isReportFixable, hasFixes, runValidators } from './validator';\nimport type { ValidatorMeta, ValidatorReport } from './validator-types';\nimport * as defaultValidators from './validators';\nimport { deepClone } from '../deep-clone';\nimport { readJsonFile } from '../fs';\nimport { parseJson } from '../json';\nimport type { SnapFiles, UnvalidatedSnapFiles } from '../types';\nimport { NpmSnapFileNames } from '../types';\nimport { readVirtualFile, VirtualFile } from '../virtual-file/node';\n\nconst MANIFEST_SORT_ORDER: Record<keyof SnapManifest, number> = {\n $schema: 1,\n version: 2,\n description: 3,\n proposedName: 4,\n repository: 5,\n source: 6,\n initialConnections: 7,\n initialPermissions: 8,\n platformVersion: 9,\n manifestVersion: 10,\n};\n\nexport type CheckManifestReport = Omit<ValidatorReport, 'fix'> & {\n wasFixed?: boolean;\n};\n\n/**\n * The options for the `checkManifest` function.\n */\nexport type CheckManifestOptions = {\n /**\n * Whether to auto-magically try to fix errors and then write the manifest to\n * disk.\n */\n updateAndWriteManifest?: boolean;\n\n /**\n * The source code of the Snap.\n */\n sourceCode?: string;\n\n /**\n * The function to use to write the manifest to disk.\n */\n writeFileFn?: WriteFileFunction;\n\n /**\n * The exports detected by evaluating the bundle. This may be used by one or\n * more validators to determine whether the Snap is valid.\n */\n exports?: string[];\n\n /**\n * An object containing the names of the handlers and their respective\n * permission name. This must be provided to avoid circular dependencies\n * between `@metamask/snaps-utils` and `@metamask/snaps-rpc-methods`.\n */\n handlerEndowments?: Record<string, string | null>;\n\n /**\n * Whether the compiler is running in watch mode. This is used to determine\n * whether to fix warnings or errors only.\n */\n watchMode?: boolean;\n};\n\n/**\n * The result from the `checkManifest` function.\n *\n * @property manifest - The fixed manifest object.\n * @property updated - Whether the manifest was written and updated.\n */\nexport type CheckManifestResult = {\n files?: SnapFiles;\n updated: boolean;\n reports: CheckManifestReport[];\n};\n\nexport type WriteFileFunction = (path: string, data: string) => Promise<void>;\n\n/**\n * Validates a snap.manifest.json file. Attempts to fix the manifest and write\n * the fixed version to disk if `writeManifest` is true. Throws if validation\n * fails.\n *\n * @param basePath - The path to the folder with the manifest files.\n * @param options - Additional options for the function.\n * @param options.sourceCode - The source code of the Snap.\n * @param options.writeFileFn - The function to use to write the manifest to\n * disk.\n * @param options.updateAndWriteManifest - Whether to auto-magically try to fix\n * errors and then write the manifest to disk.\n * @param options.exports - The exports detected by evaluating the bundle. This\n * may be used by one or more validators to determine whether the Snap is valid.\n * @param options.handlerEndowments - An object containing the names of the\n * handlers and their respective permission name. This must be provided to avoid\n * circular dependencies between `@metamask/snaps-utils` and\n * `@metamask/snaps-rpc-methods`.\n * @param options.watchMode - Whether the compiler is running in watch mode.\n * This is used to determine whether to fix warnings or errors only.\n * @returns Whether the manifest was updated, and an array of warnings that\n * were encountered during processing of the manifest files.\n */\nexport async function checkManifest(\n basePath: string,\n {\n updateAndWriteManifest = true,\n sourceCode,\n writeFileFn = fs.writeFile,\n exports,\n handlerEndowments,\n watchMode = false,\n }: CheckManifestOptions = {},\n): Promise<CheckManifestResult> {\n const manifestPath = pathUtils.join(basePath, NpmSnapFileNames.Manifest);\n const manifestFile = await readJsonFile(manifestPath);\n const unvalidatedManifest = manifestFile.result;\n\n const packageFile = await readJsonFile(\n pathUtils.join(basePath, NpmSnapFileNames.PackageJson),\n );\n\n const auxiliaryFilePaths = getSnapFilePaths(\n unvalidatedManifest,\n (manifest) => manifest?.source?.files,\n );\n\n const localizationFilePaths = getSnapFilePaths(\n unvalidatedManifest,\n (manifest) => manifest?.source?.locales,\n );\n const localizationFiles =\n (await getSnapFiles(basePath, localizationFilePaths)) ?? [];\n for (const localization of localizationFiles) {\n try {\n localization.result = parseJson(localization.toString());\n } catch (error) {\n assert(error instanceof SyntaxError, error);\n throw new Error(\n `Failed to parse localization file \"${localization.path}\" as JSON.`,\n );\n }\n }\n\n const snapFiles: UnvalidatedSnapFiles = {\n manifest: manifestFile,\n packageJson: packageFile,\n sourceCode: await getSnapSourceCode(\n basePath,\n unvalidatedManifest,\n sourceCode,\n ),\n svgIcon: await getSnapIcon(basePath, unvalidatedManifest),\n // Intentionally pass null as the encoding here since the files may be binary\n auxiliaryFiles:\n (await getSnapFiles(basePath, auxiliaryFilePaths, null)) ?? [],\n localizationFiles,\n };\n\n const validatorResults = await runValidators(\n snapFiles,\n Object.values(defaultValidators),\n { exports, handlerEndowments },\n );\n\n let manifestResults: CheckManifestResult = {\n updated: false,\n files: validatorResults.files,\n reports: validatorResults.reports,\n };\n\n if (updateAndWriteManifest && hasFixes(manifestResults, watchMode)) {\n const fixedResults = await runFixes(validatorResults, undefined, watchMode);\n\n if (fixedResults.updated) {\n manifestResults = fixedResults;\n\n assert(manifestResults.files);\n\n try {\n await writeFileFn(\n pathUtils.join(basePath, NpmSnapFileNames.Manifest),\n manifestResults.files.manifest.toString(),\n );\n } catch (error) {\n // Note: This error isn't pushed to the errors array, because it's not an\n // error in the manifest itself.\n throw new Error(\n `Failed to update \"snap.manifest.json\": ${getErrorMessage(error)}`,\n );\n }\n }\n }\n\n return manifestResults;\n}\n\n/**\n * Run the algorithm for automatically fixing errors in manifest.\n *\n * The algorithm updates the manifest by fixing all fixable problems,\n * and then run validation again to check if the new manifest is now correct.\n * If not correct, the algorithm will use the manifest from previous iteration\n * and try again `MAX_ATTEMPTS` times to update it before bailing and\n * resulting in failure.\n *\n * @param results - Results of the initial run of validation.\n * @param rules - Optional list of rules to run the fixes with.\n * @param errorsOnly - Whether to only run fixes for errors, not warnings.\n * @returns The updated manifest and whether it was updated.\n */\nexport async function runFixes(\n results: ValidatorResults,\n rules?: ValidatorMeta[],\n errorsOnly = false,\n): Promise<CheckManifestResult> {\n let shouldRunFixes = true;\n const MAX_ATTEMPTS = 10;\n\n assert(results.files);\n\n let fixResults: ValidatorResults = results;\n assert(fixResults.files);\n fixResults.files.manifest = fixResults.files.manifest.clone();\n\n const mergedReports: ValidatorReport[] = deepClone(fixResults.reports);\n\n for (\n let attempts = 1;\n shouldRunFixes && attempts <= MAX_ATTEMPTS;\n attempts++\n ) {\n assert(fixResults.files);\n\n let manifest = fixResults.files.manifest.result;\n\n const fixable = fixResults.reports.filter((report) =>\n isReportFixable(report, errorsOnly),\n );\n\n for (const report of fixable) {\n assert(report.fix);\n ({ manifest } = await report.fix({ manifest }));\n }\n\n fixResults.files.manifest.value = `${JSON.stringify(\n getWritableManifest(manifest),\n null,\n 2,\n )}\\n`;\n fixResults.files.manifest.result = manifest;\n\n fixResults = await runValidators(fixResults.files, rules);\n shouldRunFixes = hasFixes(fixResults, errorsOnly);\n\n fixResults.reports\n .filter(\n (report) =>\n !mergedReports.some((mergedReport) => mergedReport.id === report.id),\n )\n .forEach((report) => mergedReports.push(report));\n }\n\n const allReports: (CheckManifestReport & ValidatorReport)[] =\n deepClone(mergedReports);\n\n // Was fixed\n if (!shouldRunFixes) {\n for (const report of allReports) {\n if (report.fix) {\n report.wasFixed = true;\n delete report.fix;\n }\n }\n\n return {\n files: fixResults.files,\n updated: true,\n reports: allReports,\n };\n }\n\n for (const report of allReports) {\n delete report.fix;\n }\n\n return {\n files: results.files,\n updated: false,\n reports: allReports,\n };\n}\n\n/**\n * Given an unvalidated Snap manifest, attempts to extract the location of the\n * bundle source file location and read the file.\n *\n * @param basePath - The path to the folder with the manifest files.\n * @param manifest - The unvalidated Snap manifest file contents.\n * @param sourceCode - Override source code for plugins.\n * @returns The contents of the bundle file, if any.\n */\nexport async function getSnapSourceCode(\n basePath: string,\n manifest: Json,\n sourceCode?: string,\n): Promise<VirtualFile | undefined> {\n if (!isPlainObject(manifest)) {\n return undefined;\n }\n\n const sourceFilePath = (manifest as Partial<SnapManifest>).source?.location\n ?.npm?.filePath;\n\n if (!sourceFilePath) {\n return undefined;\n }\n\n if (sourceCode) {\n return new VirtualFile({\n path: pathUtils.join(basePath, sourceFilePath),\n value: sourceCode,\n });\n }\n\n try {\n const virtualFile = await readVirtualFile(\n pathUtils.join(basePath, sourceFilePath),\n 'utf8',\n );\n return virtualFile;\n } catch (error) {\n throw new Error(\n `Failed to read snap bundle file: ${getErrorMessage(error)}`,\n );\n }\n}\n\n/**\n * Given an unvalidated Snap manifest, attempts to extract the location of the\n * icon and read the file.\n *\n * @param basePath - The path to the folder with the manifest files.\n * @param manifest - The unvalidated Snap manifest file contents.\n * @returns The contents of the icon, if any.\n */\nexport async function getSnapIcon(\n basePath: string,\n manifest: Json,\n): Promise<VirtualFile | undefined> {\n if (!isPlainObject(manifest)) {\n return undefined;\n }\n\n const iconPath = (manifest as Partial<SnapManifest>).source?.location?.npm\n ?.iconPath;\n\n if (!iconPath) {\n return undefined;\n }\n\n try {\n const virtualFile = await readVirtualFile(\n pathUtils.join(basePath, iconPath),\n 'utf8',\n );\n return virtualFile;\n } catch (error) {\n throw new Error(`Failed to read snap icon file: ${getErrorMessage(error)}`);\n }\n}\n\n/**\n * Get an array of paths from an unvalidated Snap manifest.\n *\n * @param manifest - The unvalidated Snap manifest file contents.\n * @param selector - A function that returns the paths to the files.\n * @returns The paths to the files, if any.\n */\nexport function getSnapFilePaths(\n manifest: Json,\n selector: (manifest: Partial<SnapManifest>) => string[] | undefined,\n) {\n if (!isPlainObject(manifest)) {\n return undefined;\n }\n\n const snapManifest = manifest as Partial<SnapManifest>;\n const paths = selector(snapManifest);\n\n if (!Array.isArray(paths)) {\n return undefined;\n }\n\n return paths;\n}\n\n/**\n * Given an unvalidated Snap manifest, attempts to extract the files with the\n * given paths and read them.\n *\n * @param basePath - The path to the folder with the manifest files.\n * @param paths - The paths to the files.\n * @param encoding - An optional encoding to pass down to readVirtualFile.\n * @returns A list of auxiliary files and their contents, if any.\n */\nexport async function getSnapFiles(\n basePath: string,\n paths: string[] | undefined,\n encoding: BufferEncoding | null = 'utf8',\n): Promise<VirtualFile[] | undefined> {\n if (!paths) {\n return undefined;\n }\n\n try {\n return await Promise.all(\n paths.map(async (filePath) =>\n readVirtualFile(pathUtils.join(basePath, filePath), encoding),\n ),\n );\n } catch (error) {\n throw new Error(`Failed to read snap files: ${getErrorMessage(error)}`);\n }\n}\n\n/**\n * Sorts the given manifest in our preferred sort order and removes the\n * `repository` field if it is falsy (it may be `null`).\n *\n * @param manifest - The manifest to sort and modify.\n * @returns The disk-ready manifest.\n */\nexport function getWritableManifest(manifest: SnapManifest): SnapManifest {\n const { repository, ...remaining } = manifest;\n\n const keys = Object.keys(\n repository ? { ...remaining, repository } : remaining,\n ) as (keyof SnapManifest)[];\n\n const writableManifest = keys\n .sort((a, b) => MANIFEST_SORT_ORDER[a] - MANIFEST_SORT_ORDER[b])\n .reduce<Partial<SnapManifest>>(\n (result, key) => ({\n ...result,\n [key]: manifest[key],\n }),\n {},\n );\n\n return writableManifest as SnapManifest;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"manifest.cjs","sourceRoot":"","sources":["../../src/manifest/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["import { getErrorMessage } from '@metamask/snaps-sdk';\nimport type { Json } from '@metamask/utils';\nimport { assert, isObject } from '@metamask/utils';\nimport deepmerge from 'deepmerge';\nimport { promises as fs } from 'fs';\nimport pathUtils, { dirname } from 'path';\n\nimport type { SnapManifest } from './validation';\nimport type { ValidatorResults } from './validator';\nimport { hasFixes, isReportFixable, runValidators } from './validator';\nimport type { ValidatorMeta, ValidatorReport } from './validator-types';\nimport * as defaultValidators from './validators';\nimport { deepClone } from '../deep-clone';\nimport { readJsonFile } from '../fs';\nimport { parseJson } from '../json';\nimport type {\n DeepPartial,\n ExtendableSnapFiles,\n UnvalidatedExtendableManifest,\n UnvalidatedSnapFiles,\n} from '../types';\nimport { NpmSnapFileNames } from '../types';\nimport { readVirtualFile, VirtualFile } from '../virtual-file/node';\n\nconst MANIFEST_SORT_ORDER: Record<keyof SnapManifest, number> = {\n $schema: 1,\n extends: 2,\n version: 3,\n description: 4,\n proposedName: 5,\n repository: 6,\n source: 7,\n initialConnections: 8,\n initialPermissions: 9,\n platformVersion: 10,\n manifestVersion: 11,\n};\n\ntype MergedManifest<Type> =\n Type extends DeepPartial<SnapManifest> ? SnapManifest : Json;\n\n/**\n * Merge two Snap manifests, with the extended manifest taking precedence\n * over the base manifest.\n *\n * @param mainManifest - The main manifest.\n * @param extendedManifest - The extended manifest.\n * @returns The merged manifest.\n */\nfunction mergeManifests<Type>(\n mainManifest: Type,\n extendedManifest?: Type,\n): MergedManifest<Type> {\n if (!extendedManifest) {\n return mainManifest as MergedManifest<Type>;\n }\n\n assert(isObject(mainManifest));\n assert(isObject(extendedManifest));\n\n const mergedManifest = deepmerge(extendedManifest, mainManifest);\n delete mergedManifest.extends;\n\n return getWritableManifest(mergedManifest) as MergedManifest<Type>;\n}\n\n/**\n * Load a manifest and its extended manifest if it has one.\n *\n * Note: This function does not validate the manifests.\n *\n * @param manifestPath - The path to the manifest file.\n * @param files - A set of already loaded manifest file paths to prevent\n * circular dependencies.\n * @param root - Whether this is the root manifest being loaded. Used for\n * recursive calls, and should not be set by callers.\n * @returns The base and extended manifests.\n */\nexport async function loadManifest(\n manifestPath: string,\n files = new Set<string>(),\n root = true,\n): Promise<UnvalidatedExtendableManifest> {\n assert(\n pathUtils.isAbsolute(manifestPath),\n 'The `loadManifest` function must be called with an absolute path.',\n );\n\n if (files.has(manifestPath)) {\n throw new Error(\n `Failed to load Snap manifest: Circular dependency detected when loading \"${manifestPath}\".`,\n );\n }\n\n const mainManifest = await readJsonFile(manifestPath);\n files.add(manifestPath);\n\n if (!isObject(mainManifest.result)) {\n throw new Error(\n `Failed to load Snap manifest: The Snap manifest file at \"${manifestPath}\" must contain a JSON object.`,\n );\n }\n\n if (\n mainManifest.result.extends &&\n typeof mainManifest.result.extends === 'string'\n ) {\n const fileName = pathUtils.basename(manifestPath);\n if (root && fileName === 'snap.manifest.json') {\n throw new Error(\n `Failed to load Snap manifest: The Snap manifest file at \"snap.manifest.json\" cannot extend another manifest.`,\n );\n }\n\n const extendedManifestPath = pathUtils.resolve(\n pathUtils.dirname(manifestPath),\n mainManifest.result.extends,\n );\n\n const extendedManifest = await loadManifest(\n extendedManifestPath,\n files,\n false,\n );\n\n return {\n mainManifest,\n extendedManifest: extendedManifest.mergedManifest,\n mergedManifest: mergeManifests(\n mainManifest.result,\n extendedManifest.mergedManifest,\n ),\n files,\n };\n }\n\n return {\n mainManifest,\n mergedManifest: mainManifest.result,\n files,\n };\n}\n\nexport type CheckManifestReport = Omit<ValidatorReport, 'fix'> & {\n wasFixed?: boolean;\n};\n\n/**\n * The options for the `checkManifest` function.\n */\nexport type CheckManifestOptions = {\n /**\n * Whether to auto-magically try to fix errors and then write the manifest to\n * disk.\n */\n updateAndWriteManifest?: boolean;\n\n /**\n * The source code of the Snap.\n */\n sourceCode?: string;\n\n /**\n * The function to use to write the manifest to disk.\n */\n writeFileFn?: WriteFileFunction;\n\n /**\n * The exports detected by evaluating the bundle. This may be used by one or\n * more validators to determine whether the Snap is valid.\n */\n exports?: string[];\n\n /**\n * An object containing the names of the handlers and their respective\n * permission name. This must be provided to avoid circular dependencies\n * between `@metamask/snaps-utils` and `@metamask/snaps-rpc-methods`.\n */\n handlerEndowments?: Record<string, string | null>;\n\n /**\n * Whether the compiler is running in watch mode. This is used to determine\n * whether to fix warnings or errors only.\n */\n watchMode?: boolean;\n};\n\n/**\n * The result from the `checkManifest` function.\n *\n * @property manifest - The fixed manifest object.\n * @property updated - Whether the manifest was written and updated.\n */\nexport type CheckManifestResult = {\n files?: ExtendableSnapFiles;\n updated: boolean;\n reports: CheckManifestReport[];\n};\n\nexport type WriteFileFunction = (path: string, data: string) => Promise<void>;\n\n/**\n * Validates a snap.manifest.json file. Attempts to fix the manifest and write\n * the fixed version to disk if `writeManifest` is true. Throws if validation\n * fails.\n *\n * @param manifestPath - The path to the manifest file.\n * @param options - Additional options for the function.\n * @param options.sourceCode - The source code of the Snap.\n * @param options.writeFileFn - The function to use to write the manifest to\n * disk.\n * @param options.updateAndWriteManifest - Whether to auto-magically try to fix\n * errors and then write the manifest to disk.\n * @param options.exports - The exports detected by evaluating the bundle. This\n * may be used by one or more validators to determine whether the Snap is valid.\n * @param options.handlerEndowments - An object containing the names of the\n * handlers and their respective permission name. This must be provided to avoid\n * circular dependencies between `@metamask/snaps-utils` and\n * `@metamask/snaps-rpc-methods`.\n * @param options.watchMode - Whether the compiler is running in watch mode.\n * This is used to determine whether to fix warnings or errors only.\n * @returns Whether the manifest was updated, and an array of warnings that\n * were encountered during processing of the manifest files.\n */\nexport async function checkManifest(\n manifestPath: string,\n {\n updateAndWriteManifest = true,\n sourceCode,\n writeFileFn = fs.writeFile,\n exports,\n handlerEndowments,\n watchMode = false,\n }: CheckManifestOptions = {},\n): Promise<CheckManifestResult> {\n const basePath = dirname(manifestPath);\n const extendableManifest = await loadManifest(manifestPath);\n const unvalidatedManifest = extendableManifest.mergedManifest;\n\n const packageFile = await readJsonFile(\n pathUtils.join(basePath, NpmSnapFileNames.PackageJson),\n );\n\n const auxiliaryFilePaths = getSnapFilePaths(\n unvalidatedManifest,\n (manifest) => manifest?.source?.files,\n );\n\n const localizationFilePaths = getSnapFilePaths(\n unvalidatedManifest,\n (manifest) => manifest?.source?.locales,\n );\n const localizationFiles =\n (await getSnapFiles(basePath, localizationFilePaths)) ?? [];\n for (const localization of localizationFiles) {\n try {\n localization.result = parseJson(localization.toString());\n } catch (error) {\n assert(error instanceof SyntaxError, error);\n throw new Error(\n `Failed to parse localization file \"${localization.path}\" as JSON.`,\n );\n }\n }\n\n const snapFiles: UnvalidatedSnapFiles = {\n manifest: extendableManifest,\n packageJson: packageFile,\n sourceCode: await getSnapSourceCode(\n basePath,\n unvalidatedManifest,\n sourceCode,\n ),\n svgIcon: await getSnapIcon(basePath, unvalidatedManifest),\n // Intentionally pass null as the encoding here since the files may be binary\n auxiliaryFiles:\n (await getSnapFiles(basePath, auxiliaryFilePaths, null)) ?? [],\n localizationFiles,\n };\n\n const validatorResults = await runValidators(\n snapFiles,\n Object.values(defaultValidators),\n { exports, handlerEndowments },\n );\n\n let manifestResults: CheckManifestResult = {\n updated: false,\n files: validatorResults.files,\n reports: validatorResults.reports,\n };\n\n if (updateAndWriteManifest && hasFixes(manifestResults, watchMode)) {\n const fixedResults = await runFixes(validatorResults, undefined, watchMode);\n\n if (fixedResults.updated) {\n manifestResults = fixedResults;\n\n assert(manifestResults.files);\n\n try {\n await writeFileFn(\n manifestPath,\n manifestResults.files.manifest.mainManifest.toString(),\n );\n } catch (error) {\n // Note: This error isn't pushed to the errors array, because it's not an\n // error in the manifest itself.\n throw new Error(\n `Failed to update \"snap.manifest.json\": ${getErrorMessage(error)}`,\n );\n }\n }\n }\n\n return manifestResults;\n}\n\n/**\n * Run the algorithm for automatically fixing errors in manifest.\n *\n * The algorithm updates the manifest by fixing all fixable problems,\n * and then run validation again to check if the new manifest is now correct.\n * If not correct, the algorithm will use the manifest from previous iteration\n * and try again `MAX_ATTEMPTS` times to update it before bailing and\n * resulting in failure.\n *\n * @param results - Results of the initial run of validation.\n * @param rules - Optional list of rules to run the fixes with.\n * @param errorsOnly - Whether to only run fixes for errors, not warnings.\n * @returns The updated manifest and whether it was updated.\n */\nexport async function runFixes(\n results: ValidatorResults,\n rules?: ValidatorMeta[],\n errorsOnly = false,\n): Promise<CheckManifestResult> {\n let shouldRunFixes = true;\n const MAX_ATTEMPTS = 10;\n\n assert(results.files);\n\n let fixResults: ValidatorResults = results;\n assert(fixResults.files);\n\n fixResults.files.manifest.mainManifest =\n fixResults.files.manifest.mainManifest.clone();\n\n const mergedReports: ValidatorReport[] = deepClone(fixResults.reports);\n\n for (\n let attempts = 1;\n shouldRunFixes && attempts <= MAX_ATTEMPTS;\n attempts++\n ) {\n assert(fixResults.files);\n\n const fixable = fixResults.reports.filter((report) =>\n isReportFixable(report, errorsOnly),\n );\n\n let { manifest } = fixResults.files;\n for (const report of fixable) {\n assert(report.fix);\n ({ manifest } = await report.fix({ manifest }));\n\n manifest.mergedManifest = mergeManifests(\n manifest.mainManifest.result,\n manifest.extendedManifest,\n );\n }\n\n // The `mainManifest` is always the first manifest loaded, and is the one\n // that should be updated with fixes. Any manifests that the main manifest\n // extends will not be updated.\n // We can revisit this in the future if we want to support fixing extended\n // manifests as well, but it adds complexity, as we'd need to track which\n // fixes apply to which manifest.\n fixResults.files.manifest.mainManifest.value = `${JSON.stringify(\n getWritableManifest(manifest.mainManifest.result),\n null,\n 2,\n )}\\n`;\n fixResults.files.manifest = manifest;\n fixResults.files.manifest.mergedManifest = mergeManifests(\n fixResults.files.manifest.mainManifest.result,\n fixResults.files.manifest.extendedManifest,\n );\n\n fixResults = await runValidators(fixResults.files, rules);\n shouldRunFixes = hasFixes(fixResults, errorsOnly);\n\n fixResults.reports\n .filter(\n (report) =>\n !mergedReports.some((mergedReport) => mergedReport.id === report.id),\n )\n .forEach((report) => mergedReports.push(report));\n }\n\n const allReports: (CheckManifestReport & ValidatorReport)[] =\n deepClone(mergedReports);\n\n // Was fixed\n if (!shouldRunFixes) {\n for (const report of allReports) {\n if (report.fix) {\n report.wasFixed = true;\n delete report.fix;\n }\n }\n\n return {\n files: fixResults.files,\n updated: true,\n reports: allReports,\n };\n }\n\n for (const report of allReports) {\n delete report.fix;\n }\n\n return {\n files: results.files,\n updated: false,\n reports: allReports,\n };\n}\n\n/**\n * Given an unvalidated Snap manifest, attempts to extract the location of the\n * bundle source file location and read the file.\n *\n * @param basePath - The path to the folder with the manifest files.\n * @param manifest - The unvalidated Snap manifest file contents.\n * @param sourceCode - Override source code for plugins.\n * @returns The contents of the bundle file, if any.\n */\nexport async function getSnapSourceCode(\n basePath: string,\n manifest: Json,\n sourceCode?: string,\n): Promise<VirtualFile | undefined> {\n if (!isObject(manifest)) {\n return undefined;\n }\n\n const sourceFilePath = (manifest as Partial<SnapManifest>).source?.location\n ?.npm?.filePath;\n\n if (!sourceFilePath) {\n return undefined;\n }\n\n if (sourceCode) {\n return new VirtualFile({\n path: pathUtils.join(basePath, sourceFilePath),\n value: sourceCode,\n });\n }\n\n try {\n const virtualFile = await readVirtualFile(\n pathUtils.join(basePath, sourceFilePath),\n 'utf8',\n );\n return virtualFile;\n } catch (error) {\n throw new Error(\n `Failed to read snap bundle file: ${getErrorMessage(error)}`,\n );\n }\n}\n\n/**\n * Given an unvalidated Snap manifest, attempts to extract the location of the\n * icon and read the file.\n *\n * @param basePath - The path to the folder with the manifest files.\n * @param manifest - The unvalidated Snap manifest file contents.\n * @returns The contents of the icon, if any.\n */\nexport async function getSnapIcon(\n basePath: string,\n manifest: Json,\n): Promise<VirtualFile | undefined> {\n if (!isObject(manifest)) {\n return undefined;\n }\n\n const iconPath = (manifest as Partial<SnapManifest>).source?.location?.npm\n ?.iconPath;\n\n if (!iconPath) {\n return undefined;\n }\n\n try {\n const virtualFile = await readVirtualFile(\n pathUtils.join(basePath, iconPath),\n 'utf8',\n );\n return virtualFile;\n } catch (error) {\n throw new Error(`Failed to read snap icon file: ${getErrorMessage(error)}`);\n }\n}\n\n/**\n * Get an array of paths from an unvalidated Snap manifest.\n *\n * @param manifest - The unvalidated Snap manifest file contents.\n * @param selector - A function that returns the paths to the files.\n * @returns The paths to the files, if any.\n */\nexport function getSnapFilePaths(\n manifest: Json,\n selector: (manifest: Partial<SnapManifest>) => string[] | undefined,\n) {\n if (!isObject(manifest)) {\n return undefined;\n }\n\n const snapManifest = manifest as Partial<SnapManifest>;\n const paths = selector(snapManifest);\n\n if (!Array.isArray(paths)) {\n return undefined;\n }\n\n return paths;\n}\n\n/**\n * Given an unvalidated Snap manifest, attempts to extract the files with the\n * given paths and read them.\n *\n * @param basePath - The path to the folder with the manifest files.\n * @param paths - The paths to the files.\n * @param encoding - An optional encoding to pass down to readVirtualFile.\n * @returns A list of auxiliary files and their contents, if any.\n */\nexport async function getSnapFiles(\n basePath: string,\n paths: string[] | undefined,\n encoding: BufferEncoding | null = 'utf8',\n): Promise<VirtualFile[] | undefined> {\n if (!paths) {\n return undefined;\n }\n\n try {\n return await Promise.all(\n paths.map(async (filePath) =>\n readVirtualFile(pathUtils.join(basePath, filePath), encoding),\n ),\n );\n } catch (error) {\n throw new Error(`Failed to read snap files: ${getErrorMessage(error)}`);\n }\n}\n\n/**\n * Sorts the given manifest in our preferred sort order and removes the\n * `repository` field if it is falsy (it may be `null`).\n *\n * @param manifest - The manifest to sort and modify.\n * @returns The disk-ready manifest.\n */\nexport function getWritableManifest(\n manifest: DeepPartial<SnapManifest>,\n): DeepPartial<SnapManifest> {\n const { repository, ...remaining } = manifest;\n\n const keys = Object.keys(\n repository ? { ...remaining, repository } : remaining,\n ) as (keyof SnapManifest)[];\n\n return keys\n .sort((a, b) => MANIFEST_SORT_ORDER[a] - MANIFEST_SORT_ORDER[b])\n .reduce<DeepPartial<SnapManifest>>(\n (result, key) => ({\n ...result,\n [key]: manifest[key],\n }),\n {},\n );\n}\n"]}
|
|
@@ -3,8 +3,21 @@ import type { Json } from "@metamask/utils";
|
|
|
3
3
|
import type { SnapManifest } from "./validation.cjs";
|
|
4
4
|
import type { ValidatorResults } from "./validator.cjs";
|
|
5
5
|
import type { ValidatorMeta, ValidatorReport } from "./validator-types.cjs";
|
|
6
|
-
import type {
|
|
6
|
+
import type { DeepPartial, ExtendableSnapFiles, UnvalidatedExtendableManifest } from "../types.cjs";
|
|
7
7
|
import { VirtualFile } from "../virtual-file/node.cjs";
|
|
8
|
+
/**
|
|
9
|
+
* Load a manifest and its extended manifest if it has one.
|
|
10
|
+
*
|
|
11
|
+
* Note: This function does not validate the manifests.
|
|
12
|
+
*
|
|
13
|
+
* @param manifestPath - The path to the manifest file.
|
|
14
|
+
* @param files - A set of already loaded manifest file paths to prevent
|
|
15
|
+
* circular dependencies.
|
|
16
|
+
* @param root - Whether this is the root manifest being loaded. Used for
|
|
17
|
+
* recursive calls, and should not be set by callers.
|
|
18
|
+
* @returns The base and extended manifests.
|
|
19
|
+
*/
|
|
20
|
+
export declare function loadManifest(manifestPath: string, files?: Set<string>, root?: boolean): Promise<UnvalidatedExtendableManifest>;
|
|
8
21
|
export type CheckManifestReport = Omit<ValidatorReport, 'fix'> & {
|
|
9
22
|
wasFixed?: boolean;
|
|
10
23
|
};
|
|
@@ -49,7 +62,7 @@ export type CheckManifestOptions = {
|
|
|
49
62
|
* @property updated - Whether the manifest was written and updated.
|
|
50
63
|
*/
|
|
51
64
|
export type CheckManifestResult = {
|
|
52
|
-
files?:
|
|
65
|
+
files?: ExtendableSnapFiles;
|
|
53
66
|
updated: boolean;
|
|
54
67
|
reports: CheckManifestReport[];
|
|
55
68
|
};
|
|
@@ -59,7 +72,7 @@ export type WriteFileFunction = (path: string, data: string) => Promise<void>;
|
|
|
59
72
|
* the fixed version to disk if `writeManifest` is true. Throws if validation
|
|
60
73
|
* fails.
|
|
61
74
|
*
|
|
62
|
-
* @param
|
|
75
|
+
* @param manifestPath - The path to the manifest file.
|
|
63
76
|
* @param options - Additional options for the function.
|
|
64
77
|
* @param options.sourceCode - The source code of the Snap.
|
|
65
78
|
* @param options.writeFileFn - The function to use to write the manifest to
|
|
@@ -77,7 +90,7 @@ export type WriteFileFunction = (path: string, data: string) => Promise<void>;
|
|
|
77
90
|
* @returns Whether the manifest was updated, and an array of warnings that
|
|
78
91
|
* were encountered during processing of the manifest files.
|
|
79
92
|
*/
|
|
80
|
-
export declare function checkManifest(
|
|
93
|
+
export declare function checkManifest(manifestPath: string, { updateAndWriteManifest, sourceCode, writeFileFn, exports, handlerEndowments, watchMode, }?: CheckManifestOptions): Promise<CheckManifestResult>;
|
|
81
94
|
/**
|
|
82
95
|
* Run the algorithm for automatically fixing errors in manifest.
|
|
83
96
|
*
|
|
@@ -137,5 +150,5 @@ export declare function getSnapFiles(basePath: string, paths: string[] | undefin
|
|
|
137
150
|
* @param manifest - The manifest to sort and modify.
|
|
138
151
|
* @returns The disk-ready manifest.
|
|
139
152
|
*/
|
|
140
|
-
export declare function getWritableManifest(manifest: SnapManifest): SnapManifest
|
|
153
|
+
export declare function getWritableManifest(manifest: DeepPartial<SnapManifest>): DeepPartial<SnapManifest>;
|
|
141
154
|
//# sourceMappingURL=manifest.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.cts","sourceRoot":"","sources":["../../src/manifest/manifest.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;
|
|
1
|
+
{"version":3,"file":"manifest.d.cts","sourceRoot":"","sources":["../../src/manifest/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,8 +3,21 @@ import type { Json } from "@metamask/utils";
|
|
|
3
3
|
import type { SnapManifest } from "./validation.mjs";
|
|
4
4
|
import type { ValidatorResults } from "./validator.mjs";
|
|
5
5
|
import type { ValidatorMeta, ValidatorReport } from "./validator-types.mjs";
|
|
6
|
-
import type {
|
|
6
|
+
import type { DeepPartial, ExtendableSnapFiles, UnvalidatedExtendableManifest } from "../types.mjs";
|
|
7
7
|
import { VirtualFile } from "../virtual-file/node.mjs";
|
|
8
|
+
/**
|
|
9
|
+
* Load a manifest and its extended manifest if it has one.
|
|
10
|
+
*
|
|
11
|
+
* Note: This function does not validate the manifests.
|
|
12
|
+
*
|
|
13
|
+
* @param manifestPath - The path to the manifest file.
|
|
14
|
+
* @param files - A set of already loaded manifest file paths to prevent
|
|
15
|
+
* circular dependencies.
|
|
16
|
+
* @param root - Whether this is the root manifest being loaded. Used for
|
|
17
|
+
* recursive calls, and should not be set by callers.
|
|
18
|
+
* @returns The base and extended manifests.
|
|
19
|
+
*/
|
|
20
|
+
export declare function loadManifest(manifestPath: string, files?: Set<string>, root?: boolean): Promise<UnvalidatedExtendableManifest>;
|
|
8
21
|
export type CheckManifestReport = Omit<ValidatorReport, 'fix'> & {
|
|
9
22
|
wasFixed?: boolean;
|
|
10
23
|
};
|
|
@@ -49,7 +62,7 @@ export type CheckManifestOptions = {
|
|
|
49
62
|
* @property updated - Whether the manifest was written and updated.
|
|
50
63
|
*/
|
|
51
64
|
export type CheckManifestResult = {
|
|
52
|
-
files?:
|
|
65
|
+
files?: ExtendableSnapFiles;
|
|
53
66
|
updated: boolean;
|
|
54
67
|
reports: CheckManifestReport[];
|
|
55
68
|
};
|
|
@@ -59,7 +72,7 @@ export type WriteFileFunction = (path: string, data: string) => Promise<void>;
|
|
|
59
72
|
* the fixed version to disk if `writeManifest` is true. Throws if validation
|
|
60
73
|
* fails.
|
|
61
74
|
*
|
|
62
|
-
* @param
|
|
75
|
+
* @param manifestPath - The path to the manifest file.
|
|
63
76
|
* @param options - Additional options for the function.
|
|
64
77
|
* @param options.sourceCode - The source code of the Snap.
|
|
65
78
|
* @param options.writeFileFn - The function to use to write the manifest to
|
|
@@ -77,7 +90,7 @@ export type WriteFileFunction = (path: string, data: string) => Promise<void>;
|
|
|
77
90
|
* @returns Whether the manifest was updated, and an array of warnings that
|
|
78
91
|
* were encountered during processing of the manifest files.
|
|
79
92
|
*/
|
|
80
|
-
export declare function checkManifest(
|
|
93
|
+
export declare function checkManifest(manifestPath: string, { updateAndWriteManifest, sourceCode, writeFileFn, exports, handlerEndowments, watchMode, }?: CheckManifestOptions): Promise<CheckManifestResult>;
|
|
81
94
|
/**
|
|
82
95
|
* Run the algorithm for automatically fixing errors in manifest.
|
|
83
96
|
*
|
|
@@ -137,5 +150,5 @@ export declare function getSnapFiles(basePath: string, paths: string[] | undefin
|
|
|
137
150
|
* @param manifest - The manifest to sort and modify.
|
|
138
151
|
* @returns The disk-ready manifest.
|
|
139
152
|
*/
|
|
140
|
-
export declare function getWritableManifest(manifest: SnapManifest): SnapManifest
|
|
153
|
+
export declare function getWritableManifest(manifest: DeepPartial<SnapManifest>): DeepPartial<SnapManifest>;
|
|
141
154
|
//# sourceMappingURL=manifest.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.mts","sourceRoot":"","sources":["../../src/manifest/manifest.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;
|
|
1
|
+
{"version":3,"file":"manifest.d.mts","sourceRoot":"","sources":["../../src/manifest/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
+
function $importDefault(module) {
|
|
2
|
+
if (module?.__esModule) {
|
|
3
|
+
return module.default;
|
|
4
|
+
}
|
|
5
|
+
return module;
|
|
6
|
+
}
|
|
1
7
|
import { getErrorMessage } from "@metamask/snaps-sdk";
|
|
2
|
-
import { assert,
|
|
8
|
+
import { assert, isObject } from "@metamask/utils";
|
|
9
|
+
import $deepmerge from "deepmerge";
|
|
10
|
+
const deepmerge = $importDefault($deepmerge);
|
|
3
11
|
import { promises as fs } from "fs";
|
|
4
|
-
import pathUtils from "path";
|
|
5
|
-
import {
|
|
12
|
+
import pathUtils, { dirname } from "path";
|
|
13
|
+
import { hasFixes, isReportFixable, runValidators } from "./validator.mjs";
|
|
6
14
|
import * as defaultValidators from "./validators/index.mjs";
|
|
7
15
|
import { deepClone } from "../deep-clone.mjs";
|
|
8
16
|
import { readJsonFile } from "../fs.mjs";
|
|
@@ -11,22 +19,84 @@ import { NpmSnapFileNames } from "../types.mjs";
|
|
|
11
19
|
import { readVirtualFile, VirtualFile } from "../virtual-file/node.mjs";
|
|
12
20
|
const MANIFEST_SORT_ORDER = {
|
|
13
21
|
$schema: 1,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
extends: 2,
|
|
23
|
+
version: 3,
|
|
24
|
+
description: 4,
|
|
25
|
+
proposedName: 5,
|
|
26
|
+
repository: 6,
|
|
27
|
+
source: 7,
|
|
28
|
+
initialConnections: 8,
|
|
29
|
+
initialPermissions: 9,
|
|
30
|
+
platformVersion: 10,
|
|
31
|
+
manifestVersion: 11,
|
|
23
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* Merge two Snap manifests, with the extended manifest taking precedence
|
|
35
|
+
* over the base manifest.
|
|
36
|
+
*
|
|
37
|
+
* @param mainManifest - The main manifest.
|
|
38
|
+
* @param extendedManifest - The extended manifest.
|
|
39
|
+
* @returns The merged manifest.
|
|
40
|
+
*/
|
|
41
|
+
function mergeManifests(mainManifest, extendedManifest) {
|
|
42
|
+
if (!extendedManifest) {
|
|
43
|
+
return mainManifest;
|
|
44
|
+
}
|
|
45
|
+
assert(isObject(mainManifest));
|
|
46
|
+
assert(isObject(extendedManifest));
|
|
47
|
+
const mergedManifest = deepmerge(extendedManifest, mainManifest);
|
|
48
|
+
delete mergedManifest.extends;
|
|
49
|
+
return getWritableManifest(mergedManifest);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Load a manifest and its extended manifest if it has one.
|
|
53
|
+
*
|
|
54
|
+
* Note: This function does not validate the manifests.
|
|
55
|
+
*
|
|
56
|
+
* @param manifestPath - The path to the manifest file.
|
|
57
|
+
* @param files - A set of already loaded manifest file paths to prevent
|
|
58
|
+
* circular dependencies.
|
|
59
|
+
* @param root - Whether this is the root manifest being loaded. Used for
|
|
60
|
+
* recursive calls, and should not be set by callers.
|
|
61
|
+
* @returns The base and extended manifests.
|
|
62
|
+
*/
|
|
63
|
+
export async function loadManifest(manifestPath, files = new Set(), root = true) {
|
|
64
|
+
assert(pathUtils.isAbsolute(manifestPath), 'The `loadManifest` function must be called with an absolute path.');
|
|
65
|
+
if (files.has(manifestPath)) {
|
|
66
|
+
throw new Error(`Failed to load Snap manifest: Circular dependency detected when loading "${manifestPath}".`);
|
|
67
|
+
}
|
|
68
|
+
const mainManifest = await readJsonFile(manifestPath);
|
|
69
|
+
files.add(manifestPath);
|
|
70
|
+
if (!isObject(mainManifest.result)) {
|
|
71
|
+
throw new Error(`Failed to load Snap manifest: The Snap manifest file at "${manifestPath}" must contain a JSON object.`);
|
|
72
|
+
}
|
|
73
|
+
if (mainManifest.result.extends &&
|
|
74
|
+
typeof mainManifest.result.extends === 'string') {
|
|
75
|
+
const fileName = pathUtils.basename(manifestPath);
|
|
76
|
+
if (root && fileName === 'snap.manifest.json') {
|
|
77
|
+
throw new Error(`Failed to load Snap manifest: The Snap manifest file at "snap.manifest.json" cannot extend another manifest.`);
|
|
78
|
+
}
|
|
79
|
+
const extendedManifestPath = pathUtils.resolve(pathUtils.dirname(manifestPath), mainManifest.result.extends);
|
|
80
|
+
const extendedManifest = await loadManifest(extendedManifestPath, files, false);
|
|
81
|
+
return {
|
|
82
|
+
mainManifest,
|
|
83
|
+
extendedManifest: extendedManifest.mergedManifest,
|
|
84
|
+
mergedManifest: mergeManifests(mainManifest.result, extendedManifest.mergedManifest),
|
|
85
|
+
files,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
mainManifest,
|
|
90
|
+
mergedManifest: mainManifest.result,
|
|
91
|
+
files,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
24
94
|
/**
|
|
25
95
|
* Validates a snap.manifest.json file. Attempts to fix the manifest and write
|
|
26
96
|
* the fixed version to disk if `writeManifest` is true. Throws if validation
|
|
27
97
|
* fails.
|
|
28
98
|
*
|
|
29
|
-
* @param
|
|
99
|
+
* @param manifestPath - The path to the manifest file.
|
|
30
100
|
* @param options - Additional options for the function.
|
|
31
101
|
* @param options.sourceCode - The source code of the Snap.
|
|
32
102
|
* @param options.writeFileFn - The function to use to write the manifest to
|
|
@@ -44,10 +114,10 @@ const MANIFEST_SORT_ORDER = {
|
|
|
44
114
|
* @returns Whether the manifest was updated, and an array of warnings that
|
|
45
115
|
* were encountered during processing of the manifest files.
|
|
46
116
|
*/
|
|
47
|
-
export async function checkManifest(
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
const unvalidatedManifest =
|
|
117
|
+
export async function checkManifest(manifestPath, { updateAndWriteManifest = true, sourceCode, writeFileFn = fs.writeFile, exports, handlerEndowments, watchMode = false, } = {}) {
|
|
118
|
+
const basePath = dirname(manifestPath);
|
|
119
|
+
const extendableManifest = await loadManifest(manifestPath);
|
|
120
|
+
const unvalidatedManifest = extendableManifest.mergedManifest;
|
|
51
121
|
const packageFile = await readJsonFile(pathUtils.join(basePath, NpmSnapFileNames.PackageJson));
|
|
52
122
|
const auxiliaryFilePaths = getSnapFilePaths(unvalidatedManifest, (manifest) => manifest?.source?.files);
|
|
53
123
|
const localizationFilePaths = getSnapFilePaths(unvalidatedManifest, (manifest) => manifest?.source?.locales);
|
|
@@ -62,7 +132,7 @@ export async function checkManifest(basePath, { updateAndWriteManifest = true, s
|
|
|
62
132
|
}
|
|
63
133
|
}
|
|
64
134
|
const snapFiles = {
|
|
65
|
-
manifest:
|
|
135
|
+
manifest: extendableManifest,
|
|
66
136
|
packageJson: packageFile,
|
|
67
137
|
sourceCode: await getSnapSourceCode(basePath, unvalidatedManifest, sourceCode),
|
|
68
138
|
svgIcon: await getSnapIcon(basePath, unvalidatedManifest),
|
|
@@ -82,7 +152,7 @@ export async function checkManifest(basePath, { updateAndWriteManifest = true, s
|
|
|
82
152
|
manifestResults = fixedResults;
|
|
83
153
|
assert(manifestResults.files);
|
|
84
154
|
try {
|
|
85
|
-
await writeFileFn(
|
|
155
|
+
await writeFileFn(manifestPath, manifestResults.files.manifest.mainManifest.toString());
|
|
86
156
|
}
|
|
87
157
|
catch (error) {
|
|
88
158
|
// Note: This error isn't pushed to the errors array, because it's not an
|
|
@@ -113,18 +183,27 @@ export async function runFixes(results, rules, errorsOnly = false) {
|
|
|
113
183
|
assert(results.files);
|
|
114
184
|
let fixResults = results;
|
|
115
185
|
assert(fixResults.files);
|
|
116
|
-
fixResults.files.manifest =
|
|
186
|
+
fixResults.files.manifest.mainManifest =
|
|
187
|
+
fixResults.files.manifest.mainManifest.clone();
|
|
117
188
|
const mergedReports = deepClone(fixResults.reports);
|
|
118
189
|
for (let attempts = 1; shouldRunFixes && attempts <= MAX_ATTEMPTS; attempts++) {
|
|
119
190
|
assert(fixResults.files);
|
|
120
|
-
let manifest = fixResults.files.manifest.result;
|
|
121
191
|
const fixable = fixResults.reports.filter((report) => isReportFixable(report, errorsOnly));
|
|
192
|
+
let { manifest } = fixResults.files;
|
|
122
193
|
for (const report of fixable) {
|
|
123
194
|
assert(report.fix);
|
|
124
195
|
({ manifest } = await report.fix({ manifest }));
|
|
196
|
+
manifest.mergedManifest = mergeManifests(manifest.mainManifest.result, manifest.extendedManifest);
|
|
125
197
|
}
|
|
126
|
-
|
|
127
|
-
|
|
198
|
+
// The `mainManifest` is always the first manifest loaded, and is the one
|
|
199
|
+
// that should be updated with fixes. Any manifests that the main manifest
|
|
200
|
+
// extends will not be updated.
|
|
201
|
+
// We can revisit this in the future if we want to support fixing extended
|
|
202
|
+
// manifests as well, but it adds complexity, as we'd need to track which
|
|
203
|
+
// fixes apply to which manifest.
|
|
204
|
+
fixResults.files.manifest.mainManifest.value = `${JSON.stringify(getWritableManifest(manifest.mainManifest.result), null, 2)}\n`;
|
|
205
|
+
fixResults.files.manifest = manifest;
|
|
206
|
+
fixResults.files.manifest.mergedManifest = mergeManifests(fixResults.files.manifest.mainManifest.result, fixResults.files.manifest.extendedManifest);
|
|
128
207
|
fixResults = await runValidators(fixResults.files, rules);
|
|
129
208
|
shouldRunFixes = hasFixes(fixResults, errorsOnly);
|
|
130
209
|
fixResults.reports
|
|
@@ -165,7 +244,7 @@ export async function runFixes(results, rules, errorsOnly = false) {
|
|
|
165
244
|
* @returns The contents of the bundle file, if any.
|
|
166
245
|
*/
|
|
167
246
|
export async function getSnapSourceCode(basePath, manifest, sourceCode) {
|
|
168
|
-
if (!
|
|
247
|
+
if (!isObject(manifest)) {
|
|
169
248
|
return undefined;
|
|
170
249
|
}
|
|
171
250
|
const sourceFilePath = manifest.source?.location
|
|
@@ -196,7 +275,7 @@ export async function getSnapSourceCode(basePath, manifest, sourceCode) {
|
|
|
196
275
|
* @returns The contents of the icon, if any.
|
|
197
276
|
*/
|
|
198
277
|
export async function getSnapIcon(basePath, manifest) {
|
|
199
|
-
if (!
|
|
278
|
+
if (!isObject(manifest)) {
|
|
200
279
|
return undefined;
|
|
201
280
|
}
|
|
202
281
|
const iconPath = manifest.source?.location?.npm
|
|
@@ -220,7 +299,7 @@ export async function getSnapIcon(basePath, manifest) {
|
|
|
220
299
|
* @returns The paths to the files, if any.
|
|
221
300
|
*/
|
|
222
301
|
export function getSnapFilePaths(manifest, selector) {
|
|
223
|
-
if (!
|
|
302
|
+
if (!isObject(manifest)) {
|
|
224
303
|
return undefined;
|
|
225
304
|
}
|
|
226
305
|
const snapManifest = manifest;
|
|
@@ -260,12 +339,11 @@ export async function getSnapFiles(basePath, paths, encoding = 'utf8') {
|
|
|
260
339
|
export function getWritableManifest(manifest) {
|
|
261
340
|
const { repository, ...remaining } = manifest;
|
|
262
341
|
const keys = Object.keys(repository ? { ...remaining, repository } : remaining);
|
|
263
|
-
|
|
342
|
+
return keys
|
|
264
343
|
.sort((a, b) => MANIFEST_SORT_ORDER[a] - MANIFEST_SORT_ORDER[b])
|
|
265
344
|
.reduce((result, key) => ({
|
|
266
345
|
...result,
|
|
267
346
|
[key]: manifest[key],
|
|
268
347
|
}), {});
|
|
269
|
-
return writableManifest;
|
|
270
348
|
}
|
|
271
349
|
//# sourceMappingURL=manifest.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.mjs","sourceRoot":"","sources":["../../src/manifest/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["import { getErrorMessage } from '@metamask/snaps-sdk';\nimport type { Json } from '@metamask/utils';\nimport { assert, isPlainObject } from '@metamask/utils';\nimport { promises as fs } from 'fs';\nimport pathUtils from 'path';\n\nimport type { SnapManifest } from './validation';\nimport type { ValidatorResults } from './validator';\nimport { isReportFixable, hasFixes, runValidators } from './validator';\nimport type { ValidatorMeta, ValidatorReport } from './validator-types';\nimport * as defaultValidators from './validators';\nimport { deepClone } from '../deep-clone';\nimport { readJsonFile } from '../fs';\nimport { parseJson } from '../json';\nimport type { SnapFiles, UnvalidatedSnapFiles } from '../types';\nimport { NpmSnapFileNames } from '../types';\nimport { readVirtualFile, VirtualFile } from '../virtual-file/node';\n\nconst MANIFEST_SORT_ORDER: Record<keyof SnapManifest, number> = {\n $schema: 1,\n version: 2,\n description: 3,\n proposedName: 4,\n repository: 5,\n source: 6,\n initialConnections: 7,\n initialPermissions: 8,\n platformVersion: 9,\n manifestVersion: 10,\n};\n\nexport type CheckManifestReport = Omit<ValidatorReport, 'fix'> & {\n wasFixed?: boolean;\n};\n\n/**\n * The options for the `checkManifest` function.\n */\nexport type CheckManifestOptions = {\n /**\n * Whether to auto-magically try to fix errors and then write the manifest to\n * disk.\n */\n updateAndWriteManifest?: boolean;\n\n /**\n * The source code of the Snap.\n */\n sourceCode?: string;\n\n /**\n * The function to use to write the manifest to disk.\n */\n writeFileFn?: WriteFileFunction;\n\n /**\n * The exports detected by evaluating the bundle. This may be used by one or\n * more validators to determine whether the Snap is valid.\n */\n exports?: string[];\n\n /**\n * An object containing the names of the handlers and their respective\n * permission name. This must be provided to avoid circular dependencies\n * between `@metamask/snaps-utils` and `@metamask/snaps-rpc-methods`.\n */\n handlerEndowments?: Record<string, string | null>;\n\n /**\n * Whether the compiler is running in watch mode. This is used to determine\n * whether to fix warnings or errors only.\n */\n watchMode?: boolean;\n};\n\n/**\n * The result from the `checkManifest` function.\n *\n * @property manifest - The fixed manifest object.\n * @property updated - Whether the manifest was written and updated.\n */\nexport type CheckManifestResult = {\n files?: SnapFiles;\n updated: boolean;\n reports: CheckManifestReport[];\n};\n\nexport type WriteFileFunction = (path: string, data: string) => Promise<void>;\n\n/**\n * Validates a snap.manifest.json file. Attempts to fix the manifest and write\n * the fixed version to disk if `writeManifest` is true. Throws if validation\n * fails.\n *\n * @param basePath - The path to the folder with the manifest files.\n * @param options - Additional options for the function.\n * @param options.sourceCode - The source code of the Snap.\n * @param options.writeFileFn - The function to use to write the manifest to\n * disk.\n * @param options.updateAndWriteManifest - Whether to auto-magically try to fix\n * errors and then write the manifest to disk.\n * @param options.exports - The exports detected by evaluating the bundle. This\n * may be used by one or more validators to determine whether the Snap is valid.\n * @param options.handlerEndowments - An object containing the names of the\n * handlers and their respective permission name. This must be provided to avoid\n * circular dependencies between `@metamask/snaps-utils` and\n * `@metamask/snaps-rpc-methods`.\n * @param options.watchMode - Whether the compiler is running in watch mode.\n * This is used to determine whether to fix warnings or errors only.\n * @returns Whether the manifest was updated, and an array of warnings that\n * were encountered during processing of the manifest files.\n */\nexport async function checkManifest(\n basePath: string,\n {\n updateAndWriteManifest = true,\n sourceCode,\n writeFileFn = fs.writeFile,\n exports,\n handlerEndowments,\n watchMode = false,\n }: CheckManifestOptions = {},\n): Promise<CheckManifestResult> {\n const manifestPath = pathUtils.join(basePath, NpmSnapFileNames.Manifest);\n const manifestFile = await readJsonFile(manifestPath);\n const unvalidatedManifest = manifestFile.result;\n\n const packageFile = await readJsonFile(\n pathUtils.join(basePath, NpmSnapFileNames.PackageJson),\n );\n\n const auxiliaryFilePaths = getSnapFilePaths(\n unvalidatedManifest,\n (manifest) => manifest?.source?.files,\n );\n\n const localizationFilePaths = getSnapFilePaths(\n unvalidatedManifest,\n (manifest) => manifest?.source?.locales,\n );\n const localizationFiles =\n (await getSnapFiles(basePath, localizationFilePaths)) ?? [];\n for (const localization of localizationFiles) {\n try {\n localization.result = parseJson(localization.toString());\n } catch (error) {\n assert(error instanceof SyntaxError, error);\n throw new Error(\n `Failed to parse localization file \"${localization.path}\" as JSON.`,\n );\n }\n }\n\n const snapFiles: UnvalidatedSnapFiles = {\n manifest: manifestFile,\n packageJson: packageFile,\n sourceCode: await getSnapSourceCode(\n basePath,\n unvalidatedManifest,\n sourceCode,\n ),\n svgIcon: await getSnapIcon(basePath, unvalidatedManifest),\n // Intentionally pass null as the encoding here since the files may be binary\n auxiliaryFiles:\n (await getSnapFiles(basePath, auxiliaryFilePaths, null)) ?? [],\n localizationFiles,\n };\n\n const validatorResults = await runValidators(\n snapFiles,\n Object.values(defaultValidators),\n { exports, handlerEndowments },\n );\n\n let manifestResults: CheckManifestResult = {\n updated: false,\n files: validatorResults.files,\n reports: validatorResults.reports,\n };\n\n if (updateAndWriteManifest && hasFixes(manifestResults, watchMode)) {\n const fixedResults = await runFixes(validatorResults, undefined, watchMode);\n\n if (fixedResults.updated) {\n manifestResults = fixedResults;\n\n assert(manifestResults.files);\n\n try {\n await writeFileFn(\n pathUtils.join(basePath, NpmSnapFileNames.Manifest),\n manifestResults.files.manifest.toString(),\n );\n } catch (error) {\n // Note: This error isn't pushed to the errors array, because it's not an\n // error in the manifest itself.\n throw new Error(\n `Failed to update \"snap.manifest.json\": ${getErrorMessage(error)}`,\n );\n }\n }\n }\n\n return manifestResults;\n}\n\n/**\n * Run the algorithm for automatically fixing errors in manifest.\n *\n * The algorithm updates the manifest by fixing all fixable problems,\n * and then run validation again to check if the new manifest is now correct.\n * If not correct, the algorithm will use the manifest from previous iteration\n * and try again `MAX_ATTEMPTS` times to update it before bailing and\n * resulting in failure.\n *\n * @param results - Results of the initial run of validation.\n * @param rules - Optional list of rules to run the fixes with.\n * @param errorsOnly - Whether to only run fixes for errors, not warnings.\n * @returns The updated manifest and whether it was updated.\n */\nexport async function runFixes(\n results: ValidatorResults,\n rules?: ValidatorMeta[],\n errorsOnly = false,\n): Promise<CheckManifestResult> {\n let shouldRunFixes = true;\n const MAX_ATTEMPTS = 10;\n\n assert(results.files);\n\n let fixResults: ValidatorResults = results;\n assert(fixResults.files);\n fixResults.files.manifest = fixResults.files.manifest.clone();\n\n const mergedReports: ValidatorReport[] = deepClone(fixResults.reports);\n\n for (\n let attempts = 1;\n shouldRunFixes && attempts <= MAX_ATTEMPTS;\n attempts++\n ) {\n assert(fixResults.files);\n\n let manifest = fixResults.files.manifest.result;\n\n const fixable = fixResults.reports.filter((report) =>\n isReportFixable(report, errorsOnly),\n );\n\n for (const report of fixable) {\n assert(report.fix);\n ({ manifest } = await report.fix({ manifest }));\n }\n\n fixResults.files.manifest.value = `${JSON.stringify(\n getWritableManifest(manifest),\n null,\n 2,\n )}\\n`;\n fixResults.files.manifest.result = manifest;\n\n fixResults = await runValidators(fixResults.files, rules);\n shouldRunFixes = hasFixes(fixResults, errorsOnly);\n\n fixResults.reports\n .filter(\n (report) =>\n !mergedReports.some((mergedReport) => mergedReport.id === report.id),\n )\n .forEach((report) => mergedReports.push(report));\n }\n\n const allReports: (CheckManifestReport & ValidatorReport)[] =\n deepClone(mergedReports);\n\n // Was fixed\n if (!shouldRunFixes) {\n for (const report of allReports) {\n if (report.fix) {\n report.wasFixed = true;\n delete report.fix;\n }\n }\n\n return {\n files: fixResults.files,\n updated: true,\n reports: allReports,\n };\n }\n\n for (const report of allReports) {\n delete report.fix;\n }\n\n return {\n files: results.files,\n updated: false,\n reports: allReports,\n };\n}\n\n/**\n * Given an unvalidated Snap manifest, attempts to extract the location of the\n * bundle source file location and read the file.\n *\n * @param basePath - The path to the folder with the manifest files.\n * @param manifest - The unvalidated Snap manifest file contents.\n * @param sourceCode - Override source code for plugins.\n * @returns The contents of the bundle file, if any.\n */\nexport async function getSnapSourceCode(\n basePath: string,\n manifest: Json,\n sourceCode?: string,\n): Promise<VirtualFile | undefined> {\n if (!isPlainObject(manifest)) {\n return undefined;\n }\n\n const sourceFilePath = (manifest as Partial<SnapManifest>).source?.location\n ?.npm?.filePath;\n\n if (!sourceFilePath) {\n return undefined;\n }\n\n if (sourceCode) {\n return new VirtualFile({\n path: pathUtils.join(basePath, sourceFilePath),\n value: sourceCode,\n });\n }\n\n try {\n const virtualFile = await readVirtualFile(\n pathUtils.join(basePath, sourceFilePath),\n 'utf8',\n );\n return virtualFile;\n } catch (error) {\n throw new Error(\n `Failed to read snap bundle file: ${getErrorMessage(error)}`,\n );\n }\n}\n\n/**\n * Given an unvalidated Snap manifest, attempts to extract the location of the\n * icon and read the file.\n *\n * @param basePath - The path to the folder with the manifest files.\n * @param manifest - The unvalidated Snap manifest file contents.\n * @returns The contents of the icon, if any.\n */\nexport async function getSnapIcon(\n basePath: string,\n manifest: Json,\n): Promise<VirtualFile | undefined> {\n if (!isPlainObject(manifest)) {\n return undefined;\n }\n\n const iconPath = (manifest as Partial<SnapManifest>).source?.location?.npm\n ?.iconPath;\n\n if (!iconPath) {\n return undefined;\n }\n\n try {\n const virtualFile = await readVirtualFile(\n pathUtils.join(basePath, iconPath),\n 'utf8',\n );\n return virtualFile;\n } catch (error) {\n throw new Error(`Failed to read snap icon file: ${getErrorMessage(error)}`);\n }\n}\n\n/**\n * Get an array of paths from an unvalidated Snap manifest.\n *\n * @param manifest - The unvalidated Snap manifest file contents.\n * @param selector - A function that returns the paths to the files.\n * @returns The paths to the files, if any.\n */\nexport function getSnapFilePaths(\n manifest: Json,\n selector: (manifest: Partial<SnapManifest>) => string[] | undefined,\n) {\n if (!isPlainObject(manifest)) {\n return undefined;\n }\n\n const snapManifest = manifest as Partial<SnapManifest>;\n const paths = selector(snapManifest);\n\n if (!Array.isArray(paths)) {\n return undefined;\n }\n\n return paths;\n}\n\n/**\n * Given an unvalidated Snap manifest, attempts to extract the files with the\n * given paths and read them.\n *\n * @param basePath - The path to the folder with the manifest files.\n * @param paths - The paths to the files.\n * @param encoding - An optional encoding to pass down to readVirtualFile.\n * @returns A list of auxiliary files and their contents, if any.\n */\nexport async function getSnapFiles(\n basePath: string,\n paths: string[] | undefined,\n encoding: BufferEncoding | null = 'utf8',\n): Promise<VirtualFile[] | undefined> {\n if (!paths) {\n return undefined;\n }\n\n try {\n return await Promise.all(\n paths.map(async (filePath) =>\n readVirtualFile(pathUtils.join(basePath, filePath), encoding),\n ),\n );\n } catch (error) {\n throw new Error(`Failed to read snap files: ${getErrorMessage(error)}`);\n }\n}\n\n/**\n * Sorts the given manifest in our preferred sort order and removes the\n * `repository` field if it is falsy (it may be `null`).\n *\n * @param manifest - The manifest to sort and modify.\n * @returns The disk-ready manifest.\n */\nexport function getWritableManifest(manifest: SnapManifest): SnapManifest {\n const { repository, ...remaining } = manifest;\n\n const keys = Object.keys(\n repository ? { ...remaining, repository } : remaining,\n ) as (keyof SnapManifest)[];\n\n const writableManifest = keys\n .sort((a, b) => MANIFEST_SORT_ORDER[a] - MANIFEST_SORT_ORDER[b])\n .reduce<Partial<SnapManifest>>(\n (result, key) => ({\n ...result,\n [key]: manifest[key],\n }),\n {},\n );\n\n return writableManifest as SnapManifest;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"manifest.mjs","sourceRoot":"","sources":["../../src/manifest/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["import { getErrorMessage } from '@metamask/snaps-sdk';\nimport type { Json } from '@metamask/utils';\nimport { assert, isObject } from '@metamask/utils';\nimport deepmerge from 'deepmerge';\nimport { promises as fs } from 'fs';\nimport pathUtils, { dirname } from 'path';\n\nimport type { SnapManifest } from './validation';\nimport type { ValidatorResults } from './validator';\nimport { hasFixes, isReportFixable, runValidators } from './validator';\nimport type { ValidatorMeta, ValidatorReport } from './validator-types';\nimport * as defaultValidators from './validators';\nimport { deepClone } from '../deep-clone';\nimport { readJsonFile } from '../fs';\nimport { parseJson } from '../json';\nimport type {\n DeepPartial,\n ExtendableSnapFiles,\n UnvalidatedExtendableManifest,\n UnvalidatedSnapFiles,\n} from '../types';\nimport { NpmSnapFileNames } from '../types';\nimport { readVirtualFile, VirtualFile } from '../virtual-file/node';\n\nconst MANIFEST_SORT_ORDER: Record<keyof SnapManifest, number> = {\n $schema: 1,\n extends: 2,\n version: 3,\n description: 4,\n proposedName: 5,\n repository: 6,\n source: 7,\n initialConnections: 8,\n initialPermissions: 9,\n platformVersion: 10,\n manifestVersion: 11,\n};\n\ntype MergedManifest<Type> =\n Type extends DeepPartial<SnapManifest> ? SnapManifest : Json;\n\n/**\n * Merge two Snap manifests, with the extended manifest taking precedence\n * over the base manifest.\n *\n * @param mainManifest - The main manifest.\n * @param extendedManifest - The extended manifest.\n * @returns The merged manifest.\n */\nfunction mergeManifests<Type>(\n mainManifest: Type,\n extendedManifest?: Type,\n): MergedManifest<Type> {\n if (!extendedManifest) {\n return mainManifest as MergedManifest<Type>;\n }\n\n assert(isObject(mainManifest));\n assert(isObject(extendedManifest));\n\n const mergedManifest = deepmerge(extendedManifest, mainManifest);\n delete mergedManifest.extends;\n\n return getWritableManifest(mergedManifest) as MergedManifest<Type>;\n}\n\n/**\n * Load a manifest and its extended manifest if it has one.\n *\n * Note: This function does not validate the manifests.\n *\n * @param manifestPath - The path to the manifest file.\n * @param files - A set of already loaded manifest file paths to prevent\n * circular dependencies.\n * @param root - Whether this is the root manifest being loaded. Used for\n * recursive calls, and should not be set by callers.\n * @returns The base and extended manifests.\n */\nexport async function loadManifest(\n manifestPath: string,\n files = new Set<string>(),\n root = true,\n): Promise<UnvalidatedExtendableManifest> {\n assert(\n pathUtils.isAbsolute(manifestPath),\n 'The `loadManifest` function must be called with an absolute path.',\n );\n\n if (files.has(manifestPath)) {\n throw new Error(\n `Failed to load Snap manifest: Circular dependency detected when loading \"${manifestPath}\".`,\n );\n }\n\n const mainManifest = await readJsonFile(manifestPath);\n files.add(manifestPath);\n\n if (!isObject(mainManifest.result)) {\n throw new Error(\n `Failed to load Snap manifest: The Snap manifest file at \"${manifestPath}\" must contain a JSON object.`,\n );\n }\n\n if (\n mainManifest.result.extends &&\n typeof mainManifest.result.extends === 'string'\n ) {\n const fileName = pathUtils.basename(manifestPath);\n if (root && fileName === 'snap.manifest.json') {\n throw new Error(\n `Failed to load Snap manifest: The Snap manifest file at \"snap.manifest.json\" cannot extend another manifest.`,\n );\n }\n\n const extendedManifestPath = pathUtils.resolve(\n pathUtils.dirname(manifestPath),\n mainManifest.result.extends,\n );\n\n const extendedManifest = await loadManifest(\n extendedManifestPath,\n files,\n false,\n );\n\n return {\n mainManifest,\n extendedManifest: extendedManifest.mergedManifest,\n mergedManifest: mergeManifests(\n mainManifest.result,\n extendedManifest.mergedManifest,\n ),\n files,\n };\n }\n\n return {\n mainManifest,\n mergedManifest: mainManifest.result,\n files,\n };\n}\n\nexport type CheckManifestReport = Omit<ValidatorReport, 'fix'> & {\n wasFixed?: boolean;\n};\n\n/**\n * The options for the `checkManifest` function.\n */\nexport type CheckManifestOptions = {\n /**\n * Whether to auto-magically try to fix errors and then write the manifest to\n * disk.\n */\n updateAndWriteManifest?: boolean;\n\n /**\n * The source code of the Snap.\n */\n sourceCode?: string;\n\n /**\n * The function to use to write the manifest to disk.\n */\n writeFileFn?: WriteFileFunction;\n\n /**\n * The exports detected by evaluating the bundle. This may be used by one or\n * more validators to determine whether the Snap is valid.\n */\n exports?: string[];\n\n /**\n * An object containing the names of the handlers and their respective\n * permission name. This must be provided to avoid circular dependencies\n * between `@metamask/snaps-utils` and `@metamask/snaps-rpc-methods`.\n */\n handlerEndowments?: Record<string, string | null>;\n\n /**\n * Whether the compiler is running in watch mode. This is used to determine\n * whether to fix warnings or errors only.\n */\n watchMode?: boolean;\n};\n\n/**\n * The result from the `checkManifest` function.\n *\n * @property manifest - The fixed manifest object.\n * @property updated - Whether the manifest was written and updated.\n */\nexport type CheckManifestResult = {\n files?: ExtendableSnapFiles;\n updated: boolean;\n reports: CheckManifestReport[];\n};\n\nexport type WriteFileFunction = (path: string, data: string) => Promise<void>;\n\n/**\n * Validates a snap.manifest.json file. Attempts to fix the manifest and write\n * the fixed version to disk if `writeManifest` is true. Throws if validation\n * fails.\n *\n * @param manifestPath - The path to the manifest file.\n * @param options - Additional options for the function.\n * @param options.sourceCode - The source code of the Snap.\n * @param options.writeFileFn - The function to use to write the manifest to\n * disk.\n * @param options.updateAndWriteManifest - Whether to auto-magically try to fix\n * errors and then write the manifest to disk.\n * @param options.exports - The exports detected by evaluating the bundle. This\n * may be used by one or more validators to determine whether the Snap is valid.\n * @param options.handlerEndowments - An object containing the names of the\n * handlers and their respective permission name. This must be provided to avoid\n * circular dependencies between `@metamask/snaps-utils` and\n * `@metamask/snaps-rpc-methods`.\n * @param options.watchMode - Whether the compiler is running in watch mode.\n * This is used to determine whether to fix warnings or errors only.\n * @returns Whether the manifest was updated, and an array of warnings that\n * were encountered during processing of the manifest files.\n */\nexport async function checkManifest(\n manifestPath: string,\n {\n updateAndWriteManifest = true,\n sourceCode,\n writeFileFn = fs.writeFile,\n exports,\n handlerEndowments,\n watchMode = false,\n }: CheckManifestOptions = {},\n): Promise<CheckManifestResult> {\n const basePath = dirname(manifestPath);\n const extendableManifest = await loadManifest(manifestPath);\n const unvalidatedManifest = extendableManifest.mergedManifest;\n\n const packageFile = await readJsonFile(\n pathUtils.join(basePath, NpmSnapFileNames.PackageJson),\n );\n\n const auxiliaryFilePaths = getSnapFilePaths(\n unvalidatedManifest,\n (manifest) => manifest?.source?.files,\n );\n\n const localizationFilePaths = getSnapFilePaths(\n unvalidatedManifest,\n (manifest) => manifest?.source?.locales,\n );\n const localizationFiles =\n (await getSnapFiles(basePath, localizationFilePaths)) ?? [];\n for (const localization of localizationFiles) {\n try {\n localization.result = parseJson(localization.toString());\n } catch (error) {\n assert(error instanceof SyntaxError, error);\n throw new Error(\n `Failed to parse localization file \"${localization.path}\" as JSON.`,\n );\n }\n }\n\n const snapFiles: UnvalidatedSnapFiles = {\n manifest: extendableManifest,\n packageJson: packageFile,\n sourceCode: await getSnapSourceCode(\n basePath,\n unvalidatedManifest,\n sourceCode,\n ),\n svgIcon: await getSnapIcon(basePath, unvalidatedManifest),\n // Intentionally pass null as the encoding here since the files may be binary\n auxiliaryFiles:\n (await getSnapFiles(basePath, auxiliaryFilePaths, null)) ?? [],\n localizationFiles,\n };\n\n const validatorResults = await runValidators(\n snapFiles,\n Object.values(defaultValidators),\n { exports, handlerEndowments },\n );\n\n let manifestResults: CheckManifestResult = {\n updated: false,\n files: validatorResults.files,\n reports: validatorResults.reports,\n };\n\n if (updateAndWriteManifest && hasFixes(manifestResults, watchMode)) {\n const fixedResults = await runFixes(validatorResults, undefined, watchMode);\n\n if (fixedResults.updated) {\n manifestResults = fixedResults;\n\n assert(manifestResults.files);\n\n try {\n await writeFileFn(\n manifestPath,\n manifestResults.files.manifest.mainManifest.toString(),\n );\n } catch (error) {\n // Note: This error isn't pushed to the errors array, because it's not an\n // error in the manifest itself.\n throw new Error(\n `Failed to update \"snap.manifest.json\": ${getErrorMessage(error)}`,\n );\n }\n }\n }\n\n return manifestResults;\n}\n\n/**\n * Run the algorithm for automatically fixing errors in manifest.\n *\n * The algorithm updates the manifest by fixing all fixable problems,\n * and then run validation again to check if the new manifest is now correct.\n * If not correct, the algorithm will use the manifest from previous iteration\n * and try again `MAX_ATTEMPTS` times to update it before bailing and\n * resulting in failure.\n *\n * @param results - Results of the initial run of validation.\n * @param rules - Optional list of rules to run the fixes with.\n * @param errorsOnly - Whether to only run fixes for errors, not warnings.\n * @returns The updated manifest and whether it was updated.\n */\nexport async function runFixes(\n results: ValidatorResults,\n rules?: ValidatorMeta[],\n errorsOnly = false,\n): Promise<CheckManifestResult> {\n let shouldRunFixes = true;\n const MAX_ATTEMPTS = 10;\n\n assert(results.files);\n\n let fixResults: ValidatorResults = results;\n assert(fixResults.files);\n\n fixResults.files.manifest.mainManifest =\n fixResults.files.manifest.mainManifest.clone();\n\n const mergedReports: ValidatorReport[] = deepClone(fixResults.reports);\n\n for (\n let attempts = 1;\n shouldRunFixes && attempts <= MAX_ATTEMPTS;\n attempts++\n ) {\n assert(fixResults.files);\n\n const fixable = fixResults.reports.filter((report) =>\n isReportFixable(report, errorsOnly),\n );\n\n let { manifest } = fixResults.files;\n for (const report of fixable) {\n assert(report.fix);\n ({ manifest } = await report.fix({ manifest }));\n\n manifest.mergedManifest = mergeManifests(\n manifest.mainManifest.result,\n manifest.extendedManifest,\n );\n }\n\n // The `mainManifest` is always the first manifest loaded, and is the one\n // that should be updated with fixes. Any manifests that the main manifest\n // extends will not be updated.\n // We can revisit this in the future if we want to support fixing extended\n // manifests as well, but it adds complexity, as we'd need to track which\n // fixes apply to which manifest.\n fixResults.files.manifest.mainManifest.value = `${JSON.stringify(\n getWritableManifest(manifest.mainManifest.result),\n null,\n 2,\n )}\\n`;\n fixResults.files.manifest = manifest;\n fixResults.files.manifest.mergedManifest = mergeManifests(\n fixResults.files.manifest.mainManifest.result,\n fixResults.files.manifest.extendedManifest,\n );\n\n fixResults = await runValidators(fixResults.files, rules);\n shouldRunFixes = hasFixes(fixResults, errorsOnly);\n\n fixResults.reports\n .filter(\n (report) =>\n !mergedReports.some((mergedReport) => mergedReport.id === report.id),\n )\n .forEach((report) => mergedReports.push(report));\n }\n\n const allReports: (CheckManifestReport & ValidatorReport)[] =\n deepClone(mergedReports);\n\n // Was fixed\n if (!shouldRunFixes) {\n for (const report of allReports) {\n if (report.fix) {\n report.wasFixed = true;\n delete report.fix;\n }\n }\n\n return {\n files: fixResults.files,\n updated: true,\n reports: allReports,\n };\n }\n\n for (const report of allReports) {\n delete report.fix;\n }\n\n return {\n files: results.files,\n updated: false,\n reports: allReports,\n };\n}\n\n/**\n * Given an unvalidated Snap manifest, attempts to extract the location of the\n * bundle source file location and read the file.\n *\n * @param basePath - The path to the folder with the manifest files.\n * @param manifest - The unvalidated Snap manifest file contents.\n * @param sourceCode - Override source code for plugins.\n * @returns The contents of the bundle file, if any.\n */\nexport async function getSnapSourceCode(\n basePath: string,\n manifest: Json,\n sourceCode?: string,\n): Promise<VirtualFile | undefined> {\n if (!isObject(manifest)) {\n return undefined;\n }\n\n const sourceFilePath = (manifest as Partial<SnapManifest>).source?.location\n ?.npm?.filePath;\n\n if (!sourceFilePath) {\n return undefined;\n }\n\n if (sourceCode) {\n return new VirtualFile({\n path: pathUtils.join(basePath, sourceFilePath),\n value: sourceCode,\n });\n }\n\n try {\n const virtualFile = await readVirtualFile(\n pathUtils.join(basePath, sourceFilePath),\n 'utf8',\n );\n return virtualFile;\n } catch (error) {\n throw new Error(\n `Failed to read snap bundle file: ${getErrorMessage(error)}`,\n );\n }\n}\n\n/**\n * Given an unvalidated Snap manifest, attempts to extract the location of the\n * icon and read the file.\n *\n * @param basePath - The path to the folder with the manifest files.\n * @param manifest - The unvalidated Snap manifest file contents.\n * @returns The contents of the icon, if any.\n */\nexport async function getSnapIcon(\n basePath: string,\n manifest: Json,\n): Promise<VirtualFile | undefined> {\n if (!isObject(manifest)) {\n return undefined;\n }\n\n const iconPath = (manifest as Partial<SnapManifest>).source?.location?.npm\n ?.iconPath;\n\n if (!iconPath) {\n return undefined;\n }\n\n try {\n const virtualFile = await readVirtualFile(\n pathUtils.join(basePath, iconPath),\n 'utf8',\n );\n return virtualFile;\n } catch (error) {\n throw new Error(`Failed to read snap icon file: ${getErrorMessage(error)}`);\n }\n}\n\n/**\n * Get an array of paths from an unvalidated Snap manifest.\n *\n * @param manifest - The unvalidated Snap manifest file contents.\n * @param selector - A function that returns the paths to the files.\n * @returns The paths to the files, if any.\n */\nexport function getSnapFilePaths(\n manifest: Json,\n selector: (manifest: Partial<SnapManifest>) => string[] | undefined,\n) {\n if (!isObject(manifest)) {\n return undefined;\n }\n\n const snapManifest = manifest as Partial<SnapManifest>;\n const paths = selector(snapManifest);\n\n if (!Array.isArray(paths)) {\n return undefined;\n }\n\n return paths;\n}\n\n/**\n * Given an unvalidated Snap manifest, attempts to extract the files with the\n * given paths and read them.\n *\n * @param basePath - The path to the folder with the manifest files.\n * @param paths - The paths to the files.\n * @param encoding - An optional encoding to pass down to readVirtualFile.\n * @returns A list of auxiliary files and their contents, if any.\n */\nexport async function getSnapFiles(\n basePath: string,\n paths: string[] | undefined,\n encoding: BufferEncoding | null = 'utf8',\n): Promise<VirtualFile[] | undefined> {\n if (!paths) {\n return undefined;\n }\n\n try {\n return await Promise.all(\n paths.map(async (filePath) =>\n readVirtualFile(pathUtils.join(basePath, filePath), encoding),\n ),\n );\n } catch (error) {\n throw new Error(`Failed to read snap files: ${getErrorMessage(error)}`);\n }\n}\n\n/**\n * Sorts the given manifest in our preferred sort order and removes the\n * `repository` field if it is falsy (it may be `null`).\n *\n * @param manifest - The manifest to sort and modify.\n * @returns The disk-ready manifest.\n */\nexport function getWritableManifest(\n manifest: DeepPartial<SnapManifest>,\n): DeepPartial<SnapManifest> {\n const { repository, ...remaining } = manifest;\n\n const keys = Object.keys(\n repository ? { ...remaining, repository } : remaining,\n ) as (keyof SnapManifest)[];\n\n return keys\n .sort((a, b) => MANIFEST_SORT_ORDER[a] - MANIFEST_SORT_ORDER[b])\n .reduce<DeepPartial<SnapManifest>>(\n (result, key) => ({\n ...result,\n [key]: manifest[key],\n }),\n {},\n );\n}\n"]}
|
|
@@ -137,6 +137,7 @@ exports.SnapAuxiliaryFilesStruct = (0, superstruct_1.array)((0, superstruct_1.st
|
|
|
137
137
|
exports.SnapAuxilaryFilesStruct = exports.SnapAuxiliaryFilesStruct;
|
|
138
138
|
exports.InitialConnectionsStruct = (0, superstruct_1.record)((0, superstruct_1.intersection)([(0, superstruct_1.string)(), (0, types_1.uri)()]), (0, superstruct_1.object)({}));
|
|
139
139
|
exports.SnapManifestStruct = (0, superstruct_1.object)({
|
|
140
|
+
extends: (0, superstruct_1.optional)((0, superstruct_1.size)((0, superstruct_1.string)(), 1, Infinity)),
|
|
140
141
|
version: utils_1.VersionStruct,
|
|
141
142
|
description: (0, superstruct_1.size)((0, superstruct_1.string)(), 1, 280),
|
|
142
143
|
proposedName: (0, superstruct_1.size)((0, superstruct_1.string)(), 1, 214),
|