{"version":3,"file":"plugins.mjs","sources":["../../../../src/node/core/plugins.ts"],"sourcesContent":["import os from 'node:os';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport camelCase from 'lodash/camelCase';\nimport { env } from '@strapi/utils';\nimport { getModule, PackageJson } from './dependencies';\nimport { convertModulePathToSystemPath, convertSystemPathToModulePath, loadFile } from './files';\nimport type { BaseContext } from '../types';\nimport { isError } from './errors';\n\ninterface LocalPluginMeta {\n name: string;\n /**\n * camelCased version of the plugin name\n */\n importName: string;\n /**\n * The path to the plugin, relative to the app's root directory\n * in system format\n */\n path: string;\n /**\n * The path to the plugin, relative to the runtime directory\n * in module format (i.e. with forward slashes) because thats\n * where it should be used as an import\n */\n modulePath: string;\n type: 'local';\n}\n\ninterface ModulePluginMeta {\n name: string;\n /**\n * camelCased version of the plugin name\n */\n importName: string;\n /**\n * Modules don't have a path because we never resolve them to their node_modules\n * because we simply do not require it.\n */\n path?: never;\n /**\n * The path to the plugin, relative to the app's root directory\n * in module format (i.e. with forward slashes)\n */\n modulePath: string;\n type: 'module';\n}\n\ntype PluginMeta = LocalPluginMeta | ModulePluginMeta;\n\ninterface StrapiPlugin extends PackageJson {\n strapi: {\n description?: string;\n displayName?: string;\n kind: 'plugin';\n name?: string;\n required?: boolean;\n };\n}\n\nconst validatePackageHasStrapi = (\n pkg: PackageJson\n): pkg is PackageJson & { strapi: Record } =>\n 'strapi' in pkg &&\n typeof pkg.strapi === 'object' &&\n !Array.isArray(pkg.strapi) &&\n pkg.strapi !== null;\n\nconst validatePackageIsPlugin = (pkg: PackageJson): pkg is StrapiPlugin =>\n validatePackageHasStrapi(pkg) && pkg.strapi.kind === 'plugin';\n\nconst getEnabledPlugins = async ({\n cwd,\n logger,\n runtimeDir,\n strapi,\n}: Pick): Promise<\n Record\n> => {\n const plugins: Record = {};\n\n /**\n * This is the list of dependencies that are installed in the user's project.\n * It will include libraries like \"react\", so we need to collect the ones that\n * are plugins.\n */\n const deps = strapi.config.get('info.dependencies', {});\n\n logger.debug(\"Dependencies from user's project\", os.EOL, deps);\n\n for (const dep of Object.keys(deps)) {\n const pkg = await getModule(dep, cwd);\n\n if (pkg && validatePackageIsPlugin(pkg)) {\n const name = pkg.strapi.name || pkg.name;\n\n if (!name) {\n /**\n * Unlikely to happen, but you never know.\n */\n throw Error(\n \"You're trying to import a plugin that doesn't have a name – check the package.json of that plugin!\"\n );\n }\n\n plugins[name] = {\n name,\n importName: camelCase(name),\n type: 'module',\n modulePath: dep,\n };\n }\n }\n\n const userPluginsFile = await loadUserPluginsFile(strapi.dirs.app.config);\n\n logger.debug(\"User's plugins file\", os.EOL, userPluginsFile);\n\n for (const [userPluginName, userPluginConfig] of Object.entries(userPluginsFile)) {\n if (userPluginConfig.enabled && userPluginConfig.resolve) {\n const sysPath = convertModulePathToSystemPath(userPluginConfig.resolve);\n plugins[userPluginName] = {\n name: userPluginName,\n importName: camelCase(userPluginName),\n type: 'local',\n /**\n * User plugin paths are resolved from the entry point\n * of the app, because that's how you import them.\n */\n modulePath: convertSystemPathToModulePath(path.relative(runtimeDir, sysPath)),\n path: sysPath,\n };\n }\n }\n\n return plugins;\n};\n\nconst PLUGIN_CONFIGS = ['plugins.js', 'plugins.mjs', 'plugins.ts'];\n\ntype UserPluginConfigFile = Record;\n\nconst loadUserPluginsFile = async (root: string): Promise => {\n for (const file of PLUGIN_CONFIGS) {\n const filePath = path.join(root, file);\n const configFile = await loadFile(filePath);\n\n if (configFile) {\n /**\n * Configs can be a function or they can be just an object!\n */\n return typeof configFile === 'function' ? configFile({ env }) : configFile;\n }\n }\n\n return {};\n};\n\nconst getMapOfPluginsWithAdmin = (plugins: Record) => {\n /**\n * This variable stores the import paths for plugins.\n * The keys are the module paths of the plugins, and the values are the paths\n * to the admin part of the plugins, which is either loaded from the\n * package.json exports or from the legacy strapi-admin.js file.\n */\n const pluginImportPaths: Record = {};\n\n return Object.values(plugins)\n .filter((plugin) => {\n if (!plugin) {\n return false;\n }\n\n /**\n * There are two ways a plugin should be imported, either it's local to the strapi app,\n * or it's an actual npm module that's installed and resolved via node_modules.\n *\n * We first check if the plugin is local to the strapi app, using a regular `fs.existsSync` because\n * the pathToPlugin will be relative i.e. `/Users/my-name/strapi-app/src/plugins/my-plugin`.\n *\n * If the file doesn't exist well then it's probably a node_module, so instead we use `require.resolve`\n * which will resolve the path to the module in node_modules. If it fails with the specific code `MODULE_NOT_FOUND`\n * then it doesn't have an admin part to the package.\n */\n try {\n const localPluginPath = plugin.path;\n if (localPluginPath) {\n // Here we are loading a locally installed plugin\n const packageJsonPath = path.join(localPluginPath, 'package.json');\n\n if (fs.existsSync(packageJsonPath)) {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));\n const localAdminPath = packageJson?.exports?.['./strapi-admin']?.import;\n\n if (localAdminPath) {\n pluginImportPaths[plugin.modulePath] = localAdminPath;\n return true;\n }\n }\n\n // Check if legacy admin file exists in local plugin\n if (fs.existsSync(path.join(localPluginPath, 'strapi-admin.js'))) {\n pluginImportPaths[plugin.modulePath] = 'strapi-admin';\n return true;\n }\n }\n\n // This plugin is a module, so we need to check if it has a strapi-admin export\n if (require.resolve(`${plugin.modulePath}/strapi-admin`)) {\n pluginImportPaths[plugin.modulePath] = 'strapi-admin';\n return true;\n }\n\n return false;\n } catch (err) {\n if (\n isError(err) &&\n 'code' in err &&\n (err.code === 'MODULE_NOT_FOUND' || err.code === 'ERR_PACKAGE_PATH_NOT_EXPORTED')\n ) {\n /**\n * the plugin does not contain FE code, so we\n * don't want to import it anyway\n */\n return false;\n }\n\n throw err;\n }\n })\n .map((plugin) => ({\n ...plugin,\n modulePath: `${plugin.modulePath}/${pluginImportPaths[plugin.modulePath]}`,\n }));\n};\n\nexport { getEnabledPlugins, getMapOfPluginsWithAdmin };\nexport type { PluginMeta, LocalPluginMeta, ModulePluginMeta };\n"],"names":["validatePackageHasStrapi","pkg","strapi","Array","isArray","validatePackageIsPlugin","kind","getEnabledPlugins","cwd","logger","runtimeDir","plugins","deps","config","get","debug","os","EOL","dep","Object","keys","getModule","name","Error","importName","camelCase","type","modulePath","userPluginsFile","loadUserPluginsFile","dirs","app","userPluginName","userPluginConfig","entries","enabled","resolve","sysPath","convertModulePathToSystemPath","convertSystemPathToModulePath","path","relative","PLUGIN_CONFIGS","root","file","filePath","join","configFile","loadFile","env","getMapOfPluginsWithAdmin","pluginImportPaths","values","filter","plugin","localPluginPath","packageJsonPath","fs","existsSync","packageJson","JSON","parse","readFileSync","localAdminPath","exports","import","require","err","isError","code","map"],"mappings":"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"}