{"version":3,"file":"unused-exports.cjs","sourceRoot":"","sources":["../../../src/manifest/validators/unused-exports.ts"],"names":[],"mappings":"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","sourcesContent":["import type { InitialPermissions } from '@metamask/snaps-sdk';\n\nimport type { ValidatorMeta } from '../validator-types';\n\n// Special case endowments that should be ignored.\nconst IGNORED_ENDOWMENTS = ['endowment:network-access'];\n\n/**\n * Check if the Snap exports handlers that are not requested in the manifest, or\n * if the Snap requests permissions for handlers that are not exported.\n */\nexport const unusedExports: ValidatorMeta = {\n  severity: 'warning',\n  semanticCheck(files, context) {\n    const { handlerEndowments, exports } = context.options ?? {};\n\n    // The handler endowments or exports must be provided for this check to be\n    // performed.\n    if (!handlerEndowments || !exports) {\n      return;\n    }\n\n    // Endowments used based on the exports from the Snap. This is used to\n    // filter endowments that are used by multiple handlers, e.g., the lifecycle\n    // handlers.\n    const usedEndowments = Object.entries(handlerEndowments)\n      .filter(\n        ([handler, endowment]) =>\n          endowment === null || exports.includes(handler),\n      )\n      .map(([, endowment]) => endowment);\n\n    const unusedHandlers = Object.entries(handlerEndowments)\n      .filter(([handler, endowment]) => {\n        if (endowment === null) {\n          return false;\n        }\n\n        return (\n          exports.includes(handler) &&\n          !files.manifest.mergedManifest.initialPermissions[\n            endowment as keyof InitialPermissions\n          ]\n        );\n      })\n      .map(([handler, endowment]) => `${handler} (${endowment})`);\n\n    const unusedEndowments = Object.entries(handlerEndowments).filter(\n      ([handler, endowment]) => {\n        if (endowment === null || IGNORED_ENDOWMENTS.includes(endowment)) {\n          return false;\n        }\n\n        return (\n          !usedEndowments.includes(endowment) &&\n          files.manifest.mergedManifest.initialPermissions[\n            endowment as keyof InitialPermissions\n          ] &&\n          !exports.includes(handler)\n        );\n      },\n    );\n\n    if (unusedHandlers.length > 0) {\n      // We don't specify a fix function here, because:\n      // 1. Removing the export from the Snap bundle is complicated, as it\n      //    requires AST manipulation.\n      // 2. Adding the permission to the manifest is not always possible, as it\n      //    may require additional configuration in the manifest.\n      context.report(\n        `unused-exports`,\n        `The Snap exports the following handlers, but does not request permission for them: ${unusedHandlers.join(\n          ', ',\n        )}.`,\n      );\n    }\n\n    if (unusedEndowments.length > 0) {\n      const formattedEndowments = unusedEndowments\n        .map(([handler, endowment]) => `${handler} (${endowment})`)\n        .join(', ');\n\n      context.report(\n        `unused-endowments`,\n        `The Snap requests permission for the following handlers, but does not export them: ${formattedEndowments}.`,\n        ({ manifest }) => {\n          unusedEndowments.forEach(([, endowment]) => {\n            delete manifest.mainManifest.result.initialPermissions?.[\n              endowment as keyof InitialPermissions\n            ];\n          });\n\n          return { manifest };\n        },\n      );\n    }\n  },\n};\n"]}