@strapi/strapi 5.47.1 → 5.48.1

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.
Files changed (53) hide show
  1. package/README.md +9 -9
  2. package/dist/cli/commands/build.d.ts.map +1 -1
  3. package/dist/cli/commands/develop.d.ts.map +1 -1
  4. package/dist/node/build.d.ts +7 -1
  5. package/dist/node/build.d.ts.map +1 -1
  6. package/dist/node/core/dependencies.d.ts +35 -13
  7. package/dist/node/core/dependencies.d.ts.map +1 -1
  8. package/dist/node/core/ensure-admin-dependencies.d.ts +25 -0
  9. package/dist/node/core/ensure-admin-dependencies.d.ts.map +1 -0
  10. package/dist/node/core/plugins.d.ts.map +1 -1
  11. package/dist/node/develop.d.ts +7 -1
  12. package/dist/node/develop.d.ts.map +1 -1
  13. package/dist/node/vite/config.d.ts.map +1 -1
  14. package/dist/node/webpack/config.d.ts.map +1 -1
  15. package/dist/package.json.js +1 -1
  16. package/dist/package.json.mjs +1 -1
  17. package/dist/src/cli/commands/build.js +1 -1
  18. package/dist/src/cli/commands/build.js.map +1 -1
  19. package/dist/src/cli/commands/build.mjs +1 -1
  20. package/dist/src/cli/commands/build.mjs.map +1 -1
  21. package/dist/src/cli/commands/develop.js +1 -1
  22. package/dist/src/cli/commands/develop.js.map +1 -1
  23. package/dist/src/cli/commands/develop.mjs +1 -1
  24. package/dist/src/cli/commands/develop.mjs.map +1 -1
  25. package/dist/src/node/build.js +6 -8
  26. package/dist/src/node/build.js.map +1 -1
  27. package/dist/src/node/build.mjs +6 -8
  28. package/dist/src/node/build.mjs.map +1 -1
  29. package/dist/src/node/core/dependencies.js +115 -118
  30. package/dist/src/node/core/dependencies.js.map +1 -1
  31. package/dist/src/node/core/dependencies.mjs +105 -118
  32. package/dist/src/node/core/dependencies.mjs.map +1 -1
  33. package/dist/src/node/core/ensure-admin-dependencies.js +70 -0
  34. package/dist/src/node/core/ensure-admin-dependencies.js.map +1 -0
  35. package/dist/src/node/core/ensure-admin-dependencies.mjs +67 -0
  36. package/dist/src/node/core/ensure-admin-dependencies.mjs.map +1 -0
  37. package/dist/src/node/core/plugins.js +19 -3
  38. package/dist/src/node/core/plugins.js.map +1 -1
  39. package/dist/src/node/core/plugins.mjs +19 -3
  40. package/dist/src/node/core/plugins.mjs.map +1 -1
  41. package/dist/src/node/develop.js +6 -8
  42. package/dist/src/node/develop.js.map +1 -1
  43. package/dist/src/node/develop.mjs +6 -8
  44. package/dist/src/node/develop.mjs.map +1 -1
  45. package/dist/src/node/vite/config.js +9 -2
  46. package/dist/src/node/vite/config.js.map +1 -1
  47. package/dist/src/node/vite/config.mjs +9 -2
  48. package/dist/src/node/vite/config.mjs.map +1 -1
  49. package/dist/src/node/webpack/config.js +2 -1
  50. package/dist/src/node/webpack/config.js.map +1 -1
  51. package/dist/src/node/webpack/config.mjs +2 -1
  52. package/dist/src/node/webpack/config.mjs.map +1 -1
  53. package/package.json +26 -26
@@ -1 +1 @@
1
- {"version":3,"file":"dependencies.mjs","sources":["../../../../src/node/core/dependencies.ts"],"sourcesContent":["import os from 'node:os';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport semver, { SemVer } from 'semver';\nimport resolveFrom from 'resolve-from';\nimport execa, { CommonOptions, ExecaReturnValue } from 'execa';\nimport readPkgUp, { PackageJson } from 'read-pkg-up';\nimport type { BuildOptions } from '../build';\nimport { getPackageManager } from './managers';\n\nconst CACHE_PATH = path.join('node_modules', '.strapi', 'deps-check.hash');\n\nconst hashPackageJson = async (cwd: string): Promise<string | null> => {\n try {\n const content = await fs.readFile(path.join(cwd, 'package.json'), 'utf8');\n return crypto.createHash('sha1').update(content).digest('hex');\n } catch {\n return null;\n }\n};\n\nconst readCachedHash = (cwd: string): Promise<string | null> =>\n fs.readFile(path.join(cwd, CACHE_PATH), 'utf8').catch(() => null);\n\nconst writeCachedHash = async (cwd: string, hash: string): Promise<void> => {\n try {\n await fs.mkdir(path.dirname(path.join(cwd, CACHE_PATH)), { recursive: true });\n await fs.writeFile(path.join(cwd, CACHE_PATH), hash, 'utf8');\n } catch {\n // best-effort cache write — silently ignore\n }\n};\n\n/**\n * From V5 this will be imported from the package.json of `@strapi/strapi`.\n */\nconst PEER_DEPS = {\n react: '^18.0.0',\n 'react-dom': '^18.0.0',\n 'react-router-dom': '^6.0.0',\n 'styled-components': '^6.0.0',\n};\n\ninterface CheckRequiredDependenciesResult {\n didInstall: boolean;\n}\n\ninterface DepToInstall {\n name: string;\n wantedVersion: string;\n declaredVersion?: never;\n}\n\n/**\n * Checks the user's project that it has declared and installed the required dependencies\n * needed by the Strapi admin project. Whilst generally speaking most modules will be\n * declared by the actual packages there are some packages where you only really want one of\n * and thus they are declared as peer dependencies – react / styled-components / etc.\n *\n * If these deps are not installed or declared, then we prompt the user to correct this. In\n * V4 this is not a hard requirement, but in V5 it will be. Might as well get people started now.\n */\nconst checkRequiredDependencies = async ({\n cwd,\n logger,\n}: Pick<BuildOptions, 'cwd' | 'logger'>): Promise<CheckRequiredDependenciesResult> => {\n /**\n * This enables us to use experimental deps for libraries like\n * react or styled-components. This is useful for testing against.\n */\n if (process.env.USE_EXPERIMENTAL_DEPENDENCIES === 'true') {\n logger.warn('You are using experimental dependencies that may not be compatible with Strapi.');\n return { didInstall: false };\n }\n\n // Hash-cache: skip the full check when package.json hasn't changed since\n // the last successful pass. The cache lives under node_modules so it's\n // already gitignored and disposable (a `yarn install` wipe re-runs it).\n const currentHash = await hashPackageJson(cwd);\n if (currentHash) {\n const cachedHash = await readCachedHash(cwd);\n if (cachedHash === currentHash) {\n return { didInstall: false };\n }\n }\n\n const pkg = await readPkgUp({ cwd });\n\n if (!pkg) {\n throw new Error(`Could not find package.json at path: ${cwd}`);\n }\n\n logger.debug('Loaded package.json:', os.EOL, pkg.packageJson);\n\n interface DepToReview {\n name: string;\n wantedVersion: string;\n declaredVersion: string;\n }\n\n /**\n * Run through each of the peer deps and figure out if they need to be\n * installed or they need their version checked against.\n */\n const { install, review } = Object.entries(PEER_DEPS).reduce<{\n install: DepToInstall[];\n review: DepToReview[];\n }>(\n (acc, [name, version]) => {\n if (!pkg.packageJson.dependencies) {\n throw new Error(`Could not find dependencies in package.json at path: ${cwd}`);\n }\n\n const declaredVersion =\n pkg.packageJson.dependencies[name] ?? pkg.packageJson.devDependencies?.[name];\n\n if (!declaredVersion) {\n acc.install.push({\n name,\n wantedVersion: version,\n });\n } else {\n acc.review.push({\n name,\n wantedVersion: version,\n declaredVersion,\n });\n }\n\n return acc;\n },\n {\n install: [],\n review: [],\n }\n );\n\n if (install.length > 0) {\n logger.info(\n 'The Strapi admin needs to install the following dependencies:',\n os.EOL,\n install.map(({ name, wantedVersion }) => ` - ${name}@${wantedVersion}`).join(os.EOL)\n );\n\n await installDependencies(install, {\n cwd,\n logger,\n });\n\n const [file, ...args] = process.argv;\n\n /**\n * Re-run the same command after installation e.g. strapi build because the yarn.lock might\n * not be the same and could break installations. It's not the best solution, but it works.\n */\n await execa(file, args, { cwd, stdio: 'inherit' });\n return { didInstall: true };\n }\n\n if (review.length) {\n const errors: string[] = [];\n\n for (const dep of review) {\n // The version specified in package.json could be incorrect, eg `foo`\n let minDeclaredVersion: SemVer | null = null;\n try {\n minDeclaredVersion = semver.minVersion(dep.declaredVersion);\n } catch (err) {\n // Intentional fall-through (variable will be left as null, throwing below)\n }\n\n if (!minDeclaredVersion) {\n errors.push(\n `The declared dependency, ${dep.name} has an invalid version in package.json: ${dep.declaredVersion}`\n );\n } else if (!semver.satisfies(minDeclaredVersion, dep.wantedVersion)) {\n /**\n * The delcared version should be semver compatible with our required version\n * of the dependency. If it's not, we should advise the user to change it.\n */\n logger.warn(\n [\n `Declared version of ${dep.name} (${minDeclaredVersion}) is not compatible with the version required by Strapi (${dep.wantedVersion}).`,\n 'You may experience issues, we recommend you change this.',\n ].join(os.EOL)\n );\n }\n\n const installedVersion = await getModuleVersion(dep.name, cwd);\n\n if (!installedVersion) {\n /**\n * TODO: when we know the packageManager we can advise the actual install command.\n */\n errors.push(\n `The declared dependency, ${dep.name} is not installed. You should install before re-running this command`\n );\n } else if (!semver.satisfies(installedVersion, dep.wantedVersion)) {\n logger.warn(\n [\n `Declared version of ${dep.name} (${installedVersion}) is not compatible with the version required by Strapi (${dep.wantedVersion}).`,\n 'You may experience issues, we recommend you change this.',\n ].join(os.EOL)\n );\n }\n }\n\n if (errors.length > 0 && process.env.NODE_ENV === 'development') {\n throw new Error(`${os.EOL}- ${errors.join(`${os.EOL}- `)}`);\n }\n }\n\n if (currentHash) {\n await writeCachedHash(cwd, currentHash);\n }\n\n return { didInstall: false };\n};\n\nconst getModule = async (name: string, cwd: string): Promise<PackageJson | null> => {\n const modulePackagePath = resolveFrom.silent(cwd, path.join(name, 'package.json'));\n if (!modulePackagePath) {\n return null;\n }\n const file = await fs.readFile(modulePackagePath, 'utf8').then((res) => JSON.parse(res));\n\n return file;\n};\n\nconst getModuleVersion = async (name: string, cwd: string): Promise<string | null> => {\n const pkg = await getModule(name, cwd);\n\n return pkg?.version || null;\n};\n\nconst installDependencies = async (\n install: DepToInstall[],\n { cwd, logger }: Pick<BuildOptions, 'cwd' | 'logger'>\n) => {\n const packageManager = getPackageManager();\n\n if (!packageManager) {\n logger.error(\n 'Could not find a supported package manager, please install the dependencies manually.'\n );\n process.exit(1);\n }\n\n const execOptions: CommonOptions<'utf8'> = {\n encoding: 'utf8',\n cwd,\n stdio: 'inherit',\n };\n\n const packages = install.map(({ name, wantedVersion }) => `${name}@${wantedVersion}`);\n\n let result: ExecaReturnValue<string> | undefined;\n\n if (packageManager === 'npm') {\n const npmArgs = ['install', '--legacy-peer-deps', '--save', ...packages];\n logger.info(`Running 'npm ${npmArgs.join(' ')}'`);\n result = await execa('npm', npmArgs, execOptions);\n } else if (packageManager === 'yarn') {\n const yarnArgs = ['add', ...packages];\n logger.info(`Running 'yarn ${yarnArgs.join(' ')}'`);\n result = await execa('yarn', yarnArgs, execOptions);\n } else if (packageManager === 'pnpm') {\n const pnpmArgs = ['add', '--save-prod', ...packages];\n logger.info(`Running 'pnpm ${pnpmArgs.join(' ')}'`);\n result = await execa('pnpm', pnpmArgs, execOptions);\n }\n\n if (result?.exitCode || result?.failed) {\n throw new Error('Package installation failed');\n }\n};\n\nexport { checkRequiredDependencies, getModule };\nexport type { CheckRequiredDependenciesResult, PackageJson };\n"],"names":["CACHE_PATH","path","join","hashPackageJson","cwd","content","fs","readFile","crypto","createHash","update","digest","readCachedHash","catch","writeCachedHash","hash","mkdir","dirname","recursive","writeFile","PEER_DEPS","react","checkRequiredDependencies","logger","process","env","USE_EXPERIMENTAL_DEPENDENCIES","warn","didInstall","currentHash","cachedHash","pkg","readPkgUp","Error","debug","os","EOL","packageJson","install","review","Object","entries","reduce","acc","name","version","dependencies","declaredVersion","devDependencies","push","wantedVersion","length","info","map","installDependencies","file","args","argv","execa","stdio","errors","dep","minDeclaredVersion","semver","minVersion","err","satisfies","installedVersion","getModuleVersion","NODE_ENV","getModule","modulePackagePath","resolveFrom","silent","then","res","JSON","parse","packageManager","getPackageManager","error","exit","execOptions","encoding","packages","result","npmArgs","yarnArgs","pnpmArgs","exitCode","failed"],"mappings":"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"}
1
+ {"version":3,"file":"dependencies.mjs","sources":["../../../../src/node/core/dependencies.ts"],"sourcesContent":["import os from 'node:os';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport crypto from 'node:crypto';\nimport semver, { SemVer } from 'semver';\nimport resolveFrom from 'resolve-from';\nimport execa, { CommonOptions, ExecaReturnValue } from 'execa';\nimport readPkgUp, { PackageJson } from 'read-pkg-up';\n\nimport type { Logger } from '../../cli/utils/logger';\nimport { getPackageManager } from './managers';\n\nconst CACHE_PATH = path.join('node_modules', '.strapi', 'deps-check.hash');\n\nconst hashPackageJson = async (cwd: string): Promise<string | null> => {\n try {\n const content = await fs.readFile(path.join(cwd, 'package.json'), 'utf8');\n return crypto.createHash('sha1').update(content).digest('hex');\n } catch {\n return null;\n }\n};\n\nconst readCachedHash = (cwd: string): Promise<string | null> =>\n fs.readFile(path.join(cwd, CACHE_PATH), 'utf8').catch(() => null);\n\nconst writeCachedHash = async (cwd: string, hash: string): Promise<void> => {\n try {\n await fs.mkdir(path.dirname(path.join(cwd, CACHE_PATH)), { recursive: true });\n await fs.writeFile(path.join(cwd, CACHE_PATH), hash, 'utf8');\n } catch {\n // best-effort cache write — silently ignore\n }\n};\n\n/**\n * From V5 this will be imported from the package.json of `@strapi/strapi`.\n */\nconst ADMIN_PEER_DEPS = {\n react: '^18.0.0',\n 'react-dom': '^18.0.0',\n 'react-router-dom': '^6.0.0',\n 'styled-components': '^6.0.0',\n} as const;\n\ninterface AdminPeerDep {\n name: string;\n wantedVersion: string;\n}\n\ninterface DeclaredAdminPeerDep extends AdminPeerDep {\n declaredVersion: string;\n}\n\nclass MissingAdminPeerDepsError extends Error {\n readonly missing: AdminPeerDep[];\n\n constructor(missing: AdminPeerDep[]) {\n super('Missing required dependencies. Please install them and re-run this command.');\n this.name = 'MissingAdminPeerDepsError';\n this.missing = missing;\n }\n}\n\nconst loadProjectPackageJson = async (cwd: string) => {\n const pkg = await readPkgUp({ cwd });\n\n if (!pkg) {\n throw new Error(`Could not find package.json at path: ${cwd}`);\n }\n\n if (!pkg.packageJson.dependencies) {\n throw new Error(`Could not find dependencies in package.json at path: ${cwd}`);\n }\n\n return pkg;\n};\n\n/**\n * Returns admin peer dependencies that are not declared in the project's package.json.\n */\nconst findUndeclaredAdminPeerDeps = async (cwd: string): Promise<AdminPeerDep[]> => {\n const pkg = await loadProjectPackageJson(cwd);\n\n return Object.entries(ADMIN_PEER_DEPS).reduce<AdminPeerDep[]>((missing, [name, version]) => {\n const declaredVersion =\n pkg.packageJson.dependencies?.[name] ?? pkg.packageJson.devDependencies?.[name];\n\n if (!declaredVersion) {\n missing.push({\n name,\n wantedVersion: version,\n });\n }\n\n return missing;\n }, []);\n};\n\nconst getDeclaredAdminPeerDeps = (packageJson: PackageJson): DeclaredAdminPeerDep[] => {\n return Object.entries(ADMIN_PEER_DEPS).reduce<DeclaredAdminPeerDep[]>(\n (declared, [name, version]) => {\n const declaredVersion =\n packageJson.dependencies?.[name] ?? packageJson.devDependencies?.[name];\n\n if (declaredVersion) {\n declared.push({\n name,\n wantedVersion: version,\n declaredVersion,\n });\n }\n\n return declared;\n },\n []\n );\n};\n\nconst getInstallCommandHint = (missing: AdminPeerDep[]) => {\n const packages = missing.map(({ name, wantedVersion }) => `${name}@${wantedVersion}`).join(' ');\n const packageManager = getPackageManager();\n\n if (packageManager === 'yarn') {\n return `yarn add ${packages}`;\n }\n\n if (packageManager === 'pnpm') {\n return `pnpm add --save-prod ${packages}`;\n }\n\n return `npm install --legacy-peer-deps --save ${packages}`;\n};\n\nconst reportMissingAdminPeerDeps = (logger: Logger, missing: AdminPeerDep[]) => {\n logger.error(\n 'The Strapi admin is missing required dependencies:',\n os.EOL,\n missing.map(({ name, wantedVersion }) => ` - ${name}@${wantedVersion}`).join(os.EOL)\n );\n logger.error(\n 'Please install them manually before re-running this command:',\n os.EOL,\n ` ${getInstallCommandHint(missing)}`\n );\n};\n\n/**\n * Validates declared admin peer dependencies (versions and node_modules presence).\n */\nconst validateDeclaredAdminPeerDeps = async (cwd: string, logger: Logger) => {\n const pkg = await loadProjectPackageJson(cwd);\n const declared = getDeclaredAdminPeerDeps(pkg.packageJson);\n\n if (!declared.length) {\n return;\n }\n\n logger.debug('Loaded package.json:', os.EOL, pkg.packageJson);\n\n const errors: string[] = [];\n\n for (const dep of declared) {\n let minDeclaredVersion: SemVer | null = null;\n\n try {\n minDeclaredVersion = semver.minVersion(dep.declaredVersion);\n } catch (err) {\n // Intentional fall-through (variable will be left as null, throwing below)\n }\n\n if (!minDeclaredVersion) {\n errors.push(\n `The declared dependency, ${dep.name} has an invalid version in package.json: ${dep.declaredVersion}`\n );\n } else if (!semver.satisfies(minDeclaredVersion, dep.wantedVersion)) {\n logger.warn(\n [\n `Declared version of ${dep.name} (${minDeclaredVersion}) is not compatible with the version required by Strapi (${dep.wantedVersion}).`,\n 'You may experience issues, we recommend you change this.',\n ].join(os.EOL)\n );\n }\n\n const installedVersion = await getModuleVersion(dep.name, cwd);\n\n if (!installedVersion) {\n errors.push(\n `The declared dependency, ${dep.name} is not installed. You should install before re-running this command`\n );\n } else if (!semver.satisfies(installedVersion, dep.wantedVersion)) {\n logger.warn(\n [\n `Declared version of ${dep.name} (${installedVersion}) is not compatible with the version required by Strapi (${dep.wantedVersion}).`,\n 'You may experience issues, we recommend you change this.',\n ].join(os.EOL)\n );\n }\n }\n\n if (errors.length > 0 && process.env.NODE_ENV === 'development') {\n throw new Error(`${os.EOL}- ${errors.join(`${os.EOL}- `)}`);\n }\n};\n\nconst installAdminPeerDeps = async (\n missing: AdminPeerDep[],\n { cwd, logger }: { cwd: string; logger: Logger }\n) => {\n const packageManager = getPackageManager();\n\n if (!packageManager) {\n logger.error(\n 'Could not find a supported package manager, please install the dependencies manually.'\n );\n process.exit(1);\n }\n\n const execOptions: CommonOptions<'utf8'> = {\n encoding: 'utf8',\n cwd,\n stdio: 'inherit',\n };\n\n const packages = missing.map(({ name, wantedVersion }) => `${name}@${wantedVersion}`);\n\n let result: ExecaReturnValue<string> | undefined;\n\n if (packageManager === 'npm') {\n const npmArgs = ['install', '--legacy-peer-deps', '--save', ...packages];\n logger.info(`Running 'npm ${npmArgs.join(' ')}'`);\n result = await execa('npm', npmArgs, execOptions);\n } else if (packageManager === 'yarn') {\n const yarnArgs = ['add', ...packages];\n logger.info(`Running 'yarn ${yarnArgs.join(' ')}'`);\n result = await execa('yarn', yarnArgs, execOptions);\n } else if (packageManager === 'pnpm') {\n const pnpmArgs = ['add', '--save-prod', ...packages];\n logger.info(`Running 'pnpm ${pnpmArgs.join(' ')}'`);\n result = await execa('pnpm', pnpmArgs, execOptions);\n }\n\n if (result?.exitCode || result?.failed) {\n throw new Error('Package installation failed');\n }\n};\n\nconst reexecCurrentCommand = async (cwd: string) => {\n const [file, ...args] = process.argv;\n\n /**\n * Re-run the same command after installation e.g. strapi build because the yarn.lock might\n * not be the same and could break installations. It's not the best solution, but it works.\n */\n await execa(file, args, { cwd, stdio: 'inherit' });\n};\n\nconst getModule = async (name: string, cwd: string): Promise<PackageJson | null> => {\n const modulePackagePath = resolveFrom.silent(cwd, path.join(name, 'package.json'));\n if (!modulePackagePath) {\n return null;\n }\n const file = await fs.readFile(modulePackagePath, 'utf8').then((res) => JSON.parse(res));\n\n return file;\n};\n\nconst getModuleVersion = async (name: string, cwd: string): Promise<string | null> => {\n const pkg = await getModule(name, cwd);\n\n return pkg?.version || null;\n};\n\nexport {\n ADMIN_PEER_DEPS,\n findUndeclaredAdminPeerDeps,\n validateDeclaredAdminPeerDeps,\n installAdminPeerDeps,\n reexecCurrentCommand,\n reportMissingAdminPeerDeps,\n getInstallCommandHint,\n MissingAdminPeerDepsError,\n getModule,\n hashPackageJson,\n readCachedHash,\n writeCachedHash,\n};\nexport type { AdminPeerDep, PackageJson };\n"],"names":["CACHE_PATH","path","join","hashPackageJson","cwd","content","fs","readFile","crypto","createHash","update","digest","readCachedHash","catch","writeCachedHash","hash","mkdir","dirname","recursive","writeFile","ADMIN_PEER_DEPS","react","MissingAdminPeerDepsError","Error","missing","name","loadProjectPackageJson","pkg","readPkgUp","packageJson","dependencies","findUndeclaredAdminPeerDeps","Object","entries","reduce","version","declaredVersion","devDependencies","push","wantedVersion","getDeclaredAdminPeerDeps","declared","getInstallCommandHint","packages","map","packageManager","getPackageManager","reportMissingAdminPeerDeps","logger","error","os","EOL","validateDeclaredAdminPeerDeps","length","debug","errors","dep","minDeclaredVersion","semver","minVersion","err","satisfies","warn","installedVersion","getModuleVersion","process","env","NODE_ENV","installAdminPeerDeps","exit","execOptions","encoding","stdio","result","npmArgs","info","execa","yarnArgs","pnpmArgs","exitCode","failed","reexecCurrentCommand","file","args","argv","getModule","modulePackagePath","resolveFrom","silent","then","res","JSON","parse"],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ 'use strict';
2
+
3
+ var os = require('node:os');
4
+ var dependencies = require('./dependencies.js');
5
+
6
+ /**
7
+ * Ensures admin peer dependencies are declared (and optionally auto-installed).
8
+ *
9
+ * Policy (`installIfMissing`) is decided by the caller — e.g. build vs develop CLI flags.
10
+ * Checking and installation are command-agnostic.
11
+ */ const ensureAdminDependencies = async ({ cwd, logger, installIfMissing })=>{
12
+ if (process.env.USE_EXPERIMENTAL_DEPENDENCIES === 'true') {
13
+ logger.warn('You are using experimental dependencies that may not be compatible with Strapi.');
14
+ return {
15
+ didInstall: false
16
+ };
17
+ }
18
+ // Hash-cache: skip the full check when package.json hasn't changed since
19
+ // the last successful pass. The cache lives under node_modules so it's
20
+ // already gitignored and disposable (a `yarn install` wipe re-runs it).
21
+ const currentHash = await dependencies.hashPackageJson(cwd);
22
+ if (currentHash) {
23
+ const cachedHash = await dependencies.readCachedHash(cwd);
24
+ if (cachedHash === currentHash) {
25
+ return {
26
+ didInstall: false
27
+ };
28
+ }
29
+ }
30
+ const missing = await dependencies.findUndeclaredAdminPeerDeps(cwd);
31
+ if (missing.length > 0) {
32
+ if (installIfMissing) {
33
+ logger.info('The Strapi admin needs to install the following dependencies:', os.EOL, missing.map(({ name, wantedVersion })=>` - ${name}@${wantedVersion}`).join(os.EOL));
34
+ await dependencies.installAdminPeerDeps(missing, {
35
+ cwd,
36
+ logger
37
+ });
38
+ await dependencies.reexecCurrentCommand(cwd);
39
+ return {
40
+ didInstall: true
41
+ };
42
+ }
43
+ dependencies.reportMissingAdminPeerDeps(logger, missing);
44
+ throw new dependencies.MissingAdminPeerDepsError(missing);
45
+ }
46
+ await dependencies.validateDeclaredAdminPeerDeps(cwd, logger);
47
+ if (currentHash) {
48
+ await dependencies.writeCachedHash(cwd, currentHash);
49
+ }
50
+ return {
51
+ didInstall: false
52
+ };
53
+ };
54
+ /**
55
+ * Runs {@link ensureAdminDependencies} and exits the process on failure.
56
+ *
57
+ * @returns `true` when the caller should continue, `false` when a re-exec was triggered.
58
+ */ const handleAdminDependencies = async (options)=>{
59
+ try {
60
+ const { didInstall } = await ensureAdminDependencies(options);
61
+ return !didInstall;
62
+ } catch (err) {
63
+ options.logger.error(err instanceof Error ? err.message : String(err));
64
+ process.exit(1);
65
+ }
66
+ };
67
+
68
+ exports.ensureAdminDependencies = ensureAdminDependencies;
69
+ exports.handleAdminDependencies = handleAdminDependencies;
70
+ //# sourceMappingURL=ensure-admin-dependencies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ensure-admin-dependencies.js","sources":["../../../../src/node/core/ensure-admin-dependencies.ts"],"sourcesContent":["import os from 'node:os';\n\nimport type { Logger } from '../../cli/utils/logger';\nimport {\n findUndeclaredAdminPeerDeps,\n hashPackageJson,\n installAdminPeerDeps,\n MissingAdminPeerDepsError,\n readCachedHash,\n reexecCurrentCommand,\n reportMissingAdminPeerDeps,\n validateDeclaredAdminPeerDeps,\n writeCachedHash,\n} from './dependencies';\n\ninterface EnsureAdminDependenciesOptions {\n cwd: string;\n logger: Logger;\n installIfMissing: boolean;\n}\n\ninterface EnsureAdminDependenciesResult {\n didInstall: boolean;\n}\n\n/**\n * Ensures admin peer dependencies are declared (and optionally auto-installed).\n *\n * Policy (`installIfMissing`) is decided by the caller — e.g. build vs develop CLI flags.\n * Checking and installation are command-agnostic.\n */\nconst ensureAdminDependencies = async ({\n cwd,\n logger,\n installIfMissing,\n}: EnsureAdminDependenciesOptions): Promise<EnsureAdminDependenciesResult> => {\n if (process.env.USE_EXPERIMENTAL_DEPENDENCIES === 'true') {\n logger.warn('You are using experimental dependencies that may not be compatible with Strapi.');\n return { didInstall: false };\n }\n\n // Hash-cache: skip the full check when package.json hasn't changed since\n // the last successful pass. The cache lives under node_modules so it's\n // already gitignored and disposable (a `yarn install` wipe re-runs it).\n const currentHash = await hashPackageJson(cwd);\n if (currentHash) {\n const cachedHash = await readCachedHash(cwd);\n if (cachedHash === currentHash) {\n return { didInstall: false };\n }\n }\n\n const missing = await findUndeclaredAdminPeerDeps(cwd);\n\n if (missing.length > 0) {\n if (installIfMissing) {\n logger.info(\n 'The Strapi admin needs to install the following dependencies:',\n os.EOL,\n missing.map(({ name, wantedVersion }) => ` - ${name}@${wantedVersion}`).join(os.EOL)\n );\n\n await installAdminPeerDeps(missing, { cwd, logger });\n await reexecCurrentCommand(cwd);\n\n return { didInstall: true };\n }\n\n reportMissingAdminPeerDeps(logger, missing);\n throw new MissingAdminPeerDepsError(missing);\n }\n\n await validateDeclaredAdminPeerDeps(cwd, logger);\n\n if (currentHash) {\n await writeCachedHash(cwd, currentHash);\n }\n\n return { didInstall: false };\n};\n\n/**\n * Runs {@link ensureAdminDependencies} and exits the process on failure.\n *\n * @returns `true` when the caller should continue, `false` when a re-exec was triggered.\n */\nconst handleAdminDependencies = async (\n options: EnsureAdminDependenciesOptions\n): Promise<boolean> => {\n try {\n const { didInstall } = await ensureAdminDependencies(options);\n\n return !didInstall;\n } catch (err) {\n options.logger.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n};\n\nexport { ensureAdminDependencies, handleAdminDependencies };\nexport type { EnsureAdminDependenciesOptions, EnsureAdminDependenciesResult };\n"],"names":["ensureAdminDependencies","cwd","logger","installIfMissing","process","env","USE_EXPERIMENTAL_DEPENDENCIES","warn","didInstall","currentHash","hashPackageJson","cachedHash","readCachedHash","missing","findUndeclaredAdminPeerDeps","length","info","os","EOL","map","name","wantedVersion","join","installAdminPeerDeps","reexecCurrentCommand","reportMissingAdminPeerDeps","MissingAdminPeerDepsError","validateDeclaredAdminPeerDeps","writeCachedHash","handleAdminDependencies","options","err","error","Error","message","String","exit"],"mappings":";;;;;AAyBA;;;;;IAMA,MAAMA,0BAA0B,OAAO,EACrCC,GAAG,EACHC,MAAM,EACNC,gBAAgB,EACe,GAAA;AAC/B,IAAA,IAAIC,OAAAA,CAAQC,GAAG,CAACC,6BAA6B,KAAK,MAAA,EAAQ;AACxDJ,QAAAA,MAAAA,CAAOK,IAAI,CAAC,iFAAA,CAAA;QACZ,OAAO;YAAEC,UAAAA,EAAY;AAAM,SAAA;AAC7B,IAAA;;;;IAKA,MAAMC,WAAAA,GAAc,MAAMC,4BAAAA,CAAgBT,GAAAA,CAAAA;AAC1C,IAAA,IAAIQ,WAAAA,EAAa;QACf,MAAME,UAAAA,GAAa,MAAMC,2BAAAA,CAAeX,GAAAA,CAAAA;AACxC,QAAA,IAAIU,eAAeF,WAAAA,EAAa;YAC9B,OAAO;gBAAED,UAAAA,EAAY;AAAM,aAAA;AAC7B,QAAA;AACF,IAAA;IAEA,MAAMK,OAAAA,GAAU,MAAMC,wCAAAA,CAA4Bb,GAAAA,CAAAA;IAElD,IAAIY,OAAAA,CAAQE,MAAM,GAAG,CAAA,EAAG;AACtB,QAAA,IAAIZ,gBAAAA,EAAkB;YACpBD,MAAAA,CAAOc,IAAI,CACT,+DAAA,EACAC,EAAAA,CAAGC,GAAG,EACNL,OAAAA,CAAQM,GAAG,CAAC,CAAC,EAAEC,IAAI,EAAEC,aAAa,EAAE,GAAK,CAAC,IAAI,EAAED,IAAAA,CAAK,CAAC,EAAEC,aAAAA,CAAAA,CAAe,CAAA,CAAEC,IAAI,CAACL,EAAAA,CAAGC,GAAG,CAAA,CAAA;AAGtF,YAAA,MAAMK,kCAAqBV,OAAAA,EAAS;AAAEZ,gBAAAA,GAAAA;AAAKC,gBAAAA;AAAO,aAAA,CAAA;AAClD,YAAA,MAAMsB,iCAAAA,CAAqBvB,GAAAA,CAAAA;YAE3B,OAAO;gBAAEO,UAAAA,EAAY;AAAK,aAAA;AAC5B,QAAA;AAEAiB,QAAAA,uCAAAA,CAA2BvB,MAAAA,EAAQW,OAAAA,CAAAA;AACnC,QAAA,MAAM,IAAIa,sCAAAA,CAA0Bb,OAAAA,CAAAA;AACtC,IAAA;AAEA,IAAA,MAAMc,2CAA8B1B,GAAAA,EAAKC,MAAAA,CAAAA;AAEzC,IAAA,IAAIO,WAAAA,EAAa;AACf,QAAA,MAAMmB,6BAAgB3B,GAAAA,EAAKQ,WAAAA,CAAAA;AAC7B,IAAA;IAEA,OAAO;QAAED,UAAAA,EAAY;AAAM,KAAA;AAC7B;AAEA;;;;IAKA,MAAMqB,0BAA0B,OAC9BC,OAAAA,GAAAA;IAEA,IAAI;AACF,QAAA,MAAM,EAAEtB,UAAU,EAAE,GAAG,MAAMR,uBAAAA,CAAwB8B,OAAAA,CAAAA;AAErD,QAAA,OAAO,CAACtB,UAAAA;AACV,IAAA,CAAA,CAAE,OAAOuB,GAAAA,EAAK;QACZD,OAAAA,CAAQ5B,MAAM,CAAC8B,KAAK,CAACD,eAAeE,KAAAA,GAAQF,GAAAA,CAAIG,OAAO,GAAGC,MAAAA,CAAOJ,GAAAA,CAAAA,CAAAA;AACjE3B,QAAAA,OAAAA,CAAQgC,IAAI,CAAC,CAAA,CAAA;AACf,IAAA;AACF;;;;;"}
@@ -0,0 +1,67 @@
1
+ import os from 'node:os';
2
+ import { hashPackageJson, readCachedHash, findUndeclaredAdminPeerDeps, installAdminPeerDeps, reexecCurrentCommand, reportMissingAdminPeerDeps, MissingAdminPeerDepsError, validateDeclaredAdminPeerDeps, writeCachedHash } from './dependencies.mjs';
3
+
4
+ /**
5
+ * Ensures admin peer dependencies are declared (and optionally auto-installed).
6
+ *
7
+ * Policy (`installIfMissing`) is decided by the caller — e.g. build vs develop CLI flags.
8
+ * Checking and installation are command-agnostic.
9
+ */ const ensureAdminDependencies = async ({ cwd, logger, installIfMissing })=>{
10
+ if (process.env.USE_EXPERIMENTAL_DEPENDENCIES === 'true') {
11
+ logger.warn('You are using experimental dependencies that may not be compatible with Strapi.');
12
+ return {
13
+ didInstall: false
14
+ };
15
+ }
16
+ // Hash-cache: skip the full check when package.json hasn't changed since
17
+ // the last successful pass. The cache lives under node_modules so it's
18
+ // already gitignored and disposable (a `yarn install` wipe re-runs it).
19
+ const currentHash = await hashPackageJson(cwd);
20
+ if (currentHash) {
21
+ const cachedHash = await readCachedHash(cwd);
22
+ if (cachedHash === currentHash) {
23
+ return {
24
+ didInstall: false
25
+ };
26
+ }
27
+ }
28
+ const missing = await findUndeclaredAdminPeerDeps(cwd);
29
+ if (missing.length > 0) {
30
+ if (installIfMissing) {
31
+ logger.info('The Strapi admin needs to install the following dependencies:', os.EOL, missing.map(({ name, wantedVersion })=>` - ${name}@${wantedVersion}`).join(os.EOL));
32
+ await installAdminPeerDeps(missing, {
33
+ cwd,
34
+ logger
35
+ });
36
+ await reexecCurrentCommand(cwd);
37
+ return {
38
+ didInstall: true
39
+ };
40
+ }
41
+ reportMissingAdminPeerDeps(logger, missing);
42
+ throw new MissingAdminPeerDepsError(missing);
43
+ }
44
+ await validateDeclaredAdminPeerDeps(cwd, logger);
45
+ if (currentHash) {
46
+ await writeCachedHash(cwd, currentHash);
47
+ }
48
+ return {
49
+ didInstall: false
50
+ };
51
+ };
52
+ /**
53
+ * Runs {@link ensureAdminDependencies} and exits the process on failure.
54
+ *
55
+ * @returns `true` when the caller should continue, `false` when a re-exec was triggered.
56
+ */ const handleAdminDependencies = async (options)=>{
57
+ try {
58
+ const { didInstall } = await ensureAdminDependencies(options);
59
+ return !didInstall;
60
+ } catch (err) {
61
+ options.logger.error(err instanceof Error ? err.message : String(err));
62
+ process.exit(1);
63
+ }
64
+ };
65
+
66
+ export { ensureAdminDependencies, handleAdminDependencies };
67
+ //# sourceMappingURL=ensure-admin-dependencies.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ensure-admin-dependencies.mjs","sources":["../../../../src/node/core/ensure-admin-dependencies.ts"],"sourcesContent":["import os from 'node:os';\n\nimport type { Logger } from '../../cli/utils/logger';\nimport {\n findUndeclaredAdminPeerDeps,\n hashPackageJson,\n installAdminPeerDeps,\n MissingAdminPeerDepsError,\n readCachedHash,\n reexecCurrentCommand,\n reportMissingAdminPeerDeps,\n validateDeclaredAdminPeerDeps,\n writeCachedHash,\n} from './dependencies';\n\ninterface EnsureAdminDependenciesOptions {\n cwd: string;\n logger: Logger;\n installIfMissing: boolean;\n}\n\ninterface EnsureAdminDependenciesResult {\n didInstall: boolean;\n}\n\n/**\n * Ensures admin peer dependencies are declared (and optionally auto-installed).\n *\n * Policy (`installIfMissing`) is decided by the caller — e.g. build vs develop CLI flags.\n * Checking and installation are command-agnostic.\n */\nconst ensureAdminDependencies = async ({\n cwd,\n logger,\n installIfMissing,\n}: EnsureAdminDependenciesOptions): Promise<EnsureAdminDependenciesResult> => {\n if (process.env.USE_EXPERIMENTAL_DEPENDENCIES === 'true') {\n logger.warn('You are using experimental dependencies that may not be compatible with Strapi.');\n return { didInstall: false };\n }\n\n // Hash-cache: skip the full check when package.json hasn't changed since\n // the last successful pass. The cache lives under node_modules so it's\n // already gitignored and disposable (a `yarn install` wipe re-runs it).\n const currentHash = await hashPackageJson(cwd);\n if (currentHash) {\n const cachedHash = await readCachedHash(cwd);\n if (cachedHash === currentHash) {\n return { didInstall: false };\n }\n }\n\n const missing = await findUndeclaredAdminPeerDeps(cwd);\n\n if (missing.length > 0) {\n if (installIfMissing) {\n logger.info(\n 'The Strapi admin needs to install the following dependencies:',\n os.EOL,\n missing.map(({ name, wantedVersion }) => ` - ${name}@${wantedVersion}`).join(os.EOL)\n );\n\n await installAdminPeerDeps(missing, { cwd, logger });\n await reexecCurrentCommand(cwd);\n\n return { didInstall: true };\n }\n\n reportMissingAdminPeerDeps(logger, missing);\n throw new MissingAdminPeerDepsError(missing);\n }\n\n await validateDeclaredAdminPeerDeps(cwd, logger);\n\n if (currentHash) {\n await writeCachedHash(cwd, currentHash);\n }\n\n return { didInstall: false };\n};\n\n/**\n * Runs {@link ensureAdminDependencies} and exits the process on failure.\n *\n * @returns `true` when the caller should continue, `false` when a re-exec was triggered.\n */\nconst handleAdminDependencies = async (\n options: EnsureAdminDependenciesOptions\n): Promise<boolean> => {\n try {\n const { didInstall } = await ensureAdminDependencies(options);\n\n return !didInstall;\n } catch (err) {\n options.logger.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n }\n};\n\nexport { ensureAdminDependencies, handleAdminDependencies };\nexport type { EnsureAdminDependenciesOptions, EnsureAdminDependenciesResult };\n"],"names":["ensureAdminDependencies","cwd","logger","installIfMissing","process","env","USE_EXPERIMENTAL_DEPENDENCIES","warn","didInstall","currentHash","hashPackageJson","cachedHash","readCachedHash","missing","findUndeclaredAdminPeerDeps","length","info","os","EOL","map","name","wantedVersion","join","installAdminPeerDeps","reexecCurrentCommand","reportMissingAdminPeerDeps","MissingAdminPeerDepsError","validateDeclaredAdminPeerDeps","writeCachedHash","handleAdminDependencies","options","err","error","Error","message","String","exit"],"mappings":";;;AAyBA;;;;;IAMA,MAAMA,0BAA0B,OAAO,EACrCC,GAAG,EACHC,MAAM,EACNC,gBAAgB,EACe,GAAA;AAC/B,IAAA,IAAIC,OAAAA,CAAQC,GAAG,CAACC,6BAA6B,KAAK,MAAA,EAAQ;AACxDJ,QAAAA,MAAAA,CAAOK,IAAI,CAAC,iFAAA,CAAA;QACZ,OAAO;YAAEC,UAAAA,EAAY;AAAM,SAAA;AAC7B,IAAA;;;;IAKA,MAAMC,WAAAA,GAAc,MAAMC,eAAAA,CAAgBT,GAAAA,CAAAA;AAC1C,IAAA,IAAIQ,WAAAA,EAAa;QACf,MAAME,UAAAA,GAAa,MAAMC,cAAAA,CAAeX,GAAAA,CAAAA;AACxC,QAAA,IAAIU,eAAeF,WAAAA,EAAa;YAC9B,OAAO;gBAAED,UAAAA,EAAY;AAAM,aAAA;AAC7B,QAAA;AACF,IAAA;IAEA,MAAMK,OAAAA,GAAU,MAAMC,2BAAAA,CAA4Bb,GAAAA,CAAAA;IAElD,IAAIY,OAAAA,CAAQE,MAAM,GAAG,CAAA,EAAG;AACtB,QAAA,IAAIZ,gBAAAA,EAAkB;YACpBD,MAAAA,CAAOc,IAAI,CACT,+DAAA,EACAC,EAAAA,CAAGC,GAAG,EACNL,OAAAA,CAAQM,GAAG,CAAC,CAAC,EAAEC,IAAI,EAAEC,aAAa,EAAE,GAAK,CAAC,IAAI,EAAED,IAAAA,CAAK,CAAC,EAAEC,aAAAA,CAAAA,CAAe,CAAA,CAAEC,IAAI,CAACL,EAAAA,CAAGC,GAAG,CAAA,CAAA;AAGtF,YAAA,MAAMK,qBAAqBV,OAAAA,EAAS;AAAEZ,gBAAAA,GAAAA;AAAKC,gBAAAA;AAAO,aAAA,CAAA;AAClD,YAAA,MAAMsB,oBAAAA,CAAqBvB,GAAAA,CAAAA;YAE3B,OAAO;gBAAEO,UAAAA,EAAY;AAAK,aAAA;AAC5B,QAAA;AAEAiB,QAAAA,0BAAAA,CAA2BvB,MAAAA,EAAQW,OAAAA,CAAAA;AACnC,QAAA,MAAM,IAAIa,yBAAAA,CAA0Bb,OAAAA,CAAAA;AACtC,IAAA;AAEA,IAAA,MAAMc,8BAA8B1B,GAAAA,EAAKC,MAAAA,CAAAA;AAEzC,IAAA,IAAIO,WAAAA,EAAa;AACf,QAAA,MAAMmB,gBAAgB3B,GAAAA,EAAKQ,WAAAA,CAAAA;AAC7B,IAAA;IAEA,OAAO;QAAED,UAAAA,EAAY;AAAM,KAAA;AAC7B;AAEA;;;;IAKA,MAAMqB,0BAA0B,OAC9BC,OAAAA,GAAAA;IAEA,IAAI;AACF,QAAA,MAAM,EAAEtB,UAAU,EAAE,GAAG,MAAMR,uBAAAA,CAAwB8B,OAAAA,CAAAA;AAErD,QAAA,OAAO,CAACtB,UAAAA;AACV,IAAA,CAAA,CAAE,OAAOuB,GAAAA,EAAK;QACZD,OAAAA,CAAQ5B,MAAM,CAAC8B,KAAK,CAACD,eAAeE,KAAAA,GAAQF,GAAAA,CAAIG,OAAO,GAAGC,MAAAA,CAAOJ,GAAAA,CAAAA,CAAAA;AACjE3B,QAAAA,OAAAA,CAAQgC,IAAI,CAAC,CAAA,CAAA;AACf,IAAA;AACF;;;;"}
@@ -11,6 +11,12 @@ var errors = require('./errors.js');
11
11
 
12
12
  const validatePackageHasStrapi = (pkg)=>'strapi' in pkg && typeof pkg.strapi === 'object' && !Array.isArray(pkg.strapi) && pkg.strapi !== null;
13
13
  const validatePackageIsPlugin = (pkg)=>validatePackageHasStrapi(pkg) && pkg.strapi.kind === 'plugin';
14
+ const isPluginConfigEnabled = (config)=>{
15
+ if (typeof config === 'boolean') {
16
+ return config;
17
+ }
18
+ return config.enabled !== false;
19
+ };
14
20
  const getEnabledPlugins = async ({ cwd, logger, runtimeDir, strapi })=>{
15
21
  const plugins = {};
16
22
  /**
@@ -19,6 +25,8 @@ const getEnabledPlugins = async ({ cwd, logger, runtimeDir, strapi })=>{
19
25
  * are plugins.
20
26
  */ const deps = strapi.config.get('info.dependencies', {});
21
27
  logger.debug("Dependencies from user's project", os.EOL, deps);
28
+ const userPluginsFile = await loadUserPluginsFile(strapi.dirs.app.config);
29
+ logger.debug("User's plugins file", os.EOL, userPluginsFile);
22
30
  for (const dep of Object.keys(deps)){
23
31
  const pkg = await dependencies.getModule(dep, cwd);
24
32
  if (pkg && validatePackageIsPlugin(pkg)) {
@@ -28,6 +36,10 @@ const getEnabledPlugins = async ({ cwd, logger, runtimeDir, strapi })=>{
28
36
  * Unlikely to happen, but you never know.
29
37
  */ throw Error("You're trying to import a plugin that doesn't have a name – check the package.json of that plugin!");
30
38
  }
39
+ const userPluginConfig = userPluginsFile[name];
40
+ if (userPluginConfig !== undefined && !isPluginConfigEnabled(userPluginConfig)) {
41
+ continue;
42
+ }
31
43
  plugins[name] = {
32
44
  name,
33
45
  importName: camelCase(name),
@@ -36,10 +48,14 @@ const getEnabledPlugins = async ({ cwd, logger, runtimeDir, strapi })=>{
36
48
  };
37
49
  }
38
50
  }
39
- const userPluginsFile = await loadUserPluginsFile(strapi.dirs.app.config);
40
- logger.debug("User's plugins file", os.EOL, userPluginsFile);
41
51
  for (const [userPluginName, userPluginConfig] of Object.entries(userPluginsFile)){
42
- if (userPluginConfig.enabled && userPluginConfig.resolve) {
52
+ /**
53
+ * Local plugins must be explicitly enabled to be registered, matching the
54
+ * server-side loader (`@strapi/core` get-enabled-plugins), which drops a
55
+ * `{ resolve }` declaration without a truthy `enabled`. Treating an omitted
56
+ * `enabled` as enabled here would bundle the plugin into the admin while the
57
+ * server leaves it unloaded.
58
+ */ if (typeof userPluginConfig === 'object' && userPluginConfig.enabled && userPluginConfig.resolve) {
43
59
  const sysPath = files.convertModulePathToSystemPath(userPluginConfig.resolve);
44
60
  plugins[userPluginName] = {
45
61
  name: userPluginName,
@@ -1 +1 @@
1
- {"version":3,"file":"plugins.js","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<string, unknown> } =>\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<BaseContext, 'cwd' | 'logger' | 'strapi' | 'runtimeDir'>): Promise<\n Record<string, PluginMeta>\n> => {\n const plugins: Record<string, PluginMeta> = {};\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<string, { enabled: boolean; resolve: string }>;\n\nconst loadUserPluginsFile = async (root: string): Promise<UserPluginConfigFile> => {\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<string, PluginMeta>) => {\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<string, string> = {};\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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"}
1
+ {"version":3,"file":"plugins.js","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<string, unknown> } =>\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\ntype UserPluginConfig = boolean | { enabled?: boolean; resolve?: string };\n\nconst isPluginConfigEnabled = (config: UserPluginConfig): boolean => {\n if (typeof config === 'boolean') {\n return config;\n }\n\n return config.enabled !== false;\n};\n\nconst getEnabledPlugins = async ({\n cwd,\n logger,\n runtimeDir,\n strapi,\n}: Pick<BaseContext, 'cwd' | 'logger' | 'strapi' | 'runtimeDir'>): Promise<\n Record<string, PluginMeta>\n> => {\n const plugins: Record<string, PluginMeta> = {};\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 const userPluginsFile = await loadUserPluginsFile(strapi.dirs.app.config);\n\n logger.debug(\"User's plugins file\", os.EOL, userPluginsFile);\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 const userPluginConfig = userPluginsFile[name];\n\n if (userPluginConfig !== undefined && !isPluginConfigEnabled(userPluginConfig)) {\n continue;\n }\n\n plugins[name] = {\n name,\n importName: camelCase(name),\n type: 'module',\n modulePath: dep,\n };\n }\n }\n\n for (const [userPluginName, userPluginConfig] of Object.entries(userPluginsFile)) {\n /**\n * Local plugins must be explicitly enabled to be registered, matching the\n * server-side loader (`@strapi/core` get-enabled-plugins), which drops a\n * `{ resolve }` declaration without a truthy `enabled`. Treating an omitted\n * `enabled` as enabled here would bundle the plugin into the admin while the\n * server leaves it unloaded.\n */\n if (\n typeof userPluginConfig === 'object' &&\n userPluginConfig.enabled &&\n userPluginConfig.resolve\n ) {\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<string, UserPluginConfig>;\n\nconst loadUserPluginsFile = async (root: string): Promise<UserPluginConfigFile> => {\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<string, PluginMeta>) => {\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<string, string> = {};\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","isPluginConfigEnabled","config","enabled","getEnabledPlugins","cwd","logger","runtimeDir","plugins","deps","get","debug","os","EOL","userPluginsFile","loadUserPluginsFile","dirs","app","dep","Object","keys","getModule","name","Error","userPluginConfig","undefined","importName","camelCase","type","modulePath","userPluginName","entries","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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"}
@@ -9,6 +9,12 @@ import { isError } from './errors.mjs';
9
9
 
10
10
  const validatePackageHasStrapi = (pkg)=>'strapi' in pkg && typeof pkg.strapi === 'object' && !Array.isArray(pkg.strapi) && pkg.strapi !== null;
11
11
  const validatePackageIsPlugin = (pkg)=>validatePackageHasStrapi(pkg) && pkg.strapi.kind === 'plugin';
12
+ const isPluginConfigEnabled = (config)=>{
13
+ if (typeof config === 'boolean') {
14
+ return config;
15
+ }
16
+ return config.enabled !== false;
17
+ };
12
18
  const getEnabledPlugins = async ({ cwd, logger, runtimeDir, strapi })=>{
13
19
  const plugins = {};
14
20
  /**
@@ -17,6 +23,8 @@ const getEnabledPlugins = async ({ cwd, logger, runtimeDir, strapi })=>{
17
23
  * are plugins.
18
24
  */ const deps = strapi.config.get('info.dependencies', {});
19
25
  logger.debug("Dependencies from user's project", os.EOL, deps);
26
+ const userPluginsFile = await loadUserPluginsFile(strapi.dirs.app.config);
27
+ logger.debug("User's plugins file", os.EOL, userPluginsFile);
20
28
  for (const dep of Object.keys(deps)){
21
29
  const pkg = await getModule(dep, cwd);
22
30
  if (pkg && validatePackageIsPlugin(pkg)) {
@@ -26,6 +34,10 @@ const getEnabledPlugins = async ({ cwd, logger, runtimeDir, strapi })=>{
26
34
  * Unlikely to happen, but you never know.
27
35
  */ throw Error("You're trying to import a plugin that doesn't have a name – check the package.json of that plugin!");
28
36
  }
37
+ const userPluginConfig = userPluginsFile[name];
38
+ if (userPluginConfig !== undefined && !isPluginConfigEnabled(userPluginConfig)) {
39
+ continue;
40
+ }
29
41
  plugins[name] = {
30
42
  name,
31
43
  importName: camelCase(name),
@@ -34,10 +46,14 @@ const getEnabledPlugins = async ({ cwd, logger, runtimeDir, strapi })=>{
34
46
  };
35
47
  }
36
48
  }
37
- const userPluginsFile = await loadUserPluginsFile(strapi.dirs.app.config);
38
- logger.debug("User's plugins file", os.EOL, userPluginsFile);
39
49
  for (const [userPluginName, userPluginConfig] of Object.entries(userPluginsFile)){
40
- if (userPluginConfig.enabled && userPluginConfig.resolve) {
50
+ /**
51
+ * Local plugins must be explicitly enabled to be registered, matching the
52
+ * server-side loader (`@strapi/core` get-enabled-plugins), which drops a
53
+ * `{ resolve }` declaration without a truthy `enabled`. Treating an omitted
54
+ * `enabled` as enabled here would bundle the plugin into the admin while the
55
+ * server leaves it unloaded.
56
+ */ if (typeof userPluginConfig === 'object' && userPluginConfig.enabled && userPluginConfig.resolve) {
41
57
  const sysPath = convertModulePathToSystemPath(userPluginConfig.resolve);
42
58
  plugins[userPluginName] = {
43
59
  name: userPluginName,
@@ -1 +1 @@
1
- {"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<string, unknown> } =>\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<BaseContext, 'cwd' | 'logger' | 'strapi' | 'runtimeDir'>): Promise<\n Record<string, PluginMeta>\n> => {\n const plugins: Record<string, PluginMeta> = {};\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<string, { enabled: boolean; resolve: string }>;\n\nconst loadUserPluginsFile = async (root: string): Promise<UserPluginConfigFile> => {\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<string, PluginMeta>) => {\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<string, string> = {};\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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"}
1
+ {"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<string, unknown> } =>\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\ntype UserPluginConfig = boolean | { enabled?: boolean; resolve?: string };\n\nconst isPluginConfigEnabled = (config: UserPluginConfig): boolean => {\n if (typeof config === 'boolean') {\n return config;\n }\n\n return config.enabled !== false;\n};\n\nconst getEnabledPlugins = async ({\n cwd,\n logger,\n runtimeDir,\n strapi,\n}: Pick<BaseContext, 'cwd' | 'logger' | 'strapi' | 'runtimeDir'>): Promise<\n Record<string, PluginMeta>\n> => {\n const plugins: Record<string, PluginMeta> = {};\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 const userPluginsFile = await loadUserPluginsFile(strapi.dirs.app.config);\n\n logger.debug(\"User's plugins file\", os.EOL, userPluginsFile);\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 const userPluginConfig = userPluginsFile[name];\n\n if (userPluginConfig !== undefined && !isPluginConfigEnabled(userPluginConfig)) {\n continue;\n }\n\n plugins[name] = {\n name,\n importName: camelCase(name),\n type: 'module',\n modulePath: dep,\n };\n }\n }\n\n for (const [userPluginName, userPluginConfig] of Object.entries(userPluginsFile)) {\n /**\n * Local plugins must be explicitly enabled to be registered, matching the\n * server-side loader (`@strapi/core` get-enabled-plugins), which drops a\n * `{ resolve }` declaration without a truthy `enabled`. Treating an omitted\n * `enabled` as enabled here would bundle the plugin into the admin while the\n * server leaves it unloaded.\n */\n if (\n typeof userPluginConfig === 'object' &&\n userPluginConfig.enabled &&\n userPluginConfig.resolve\n ) {\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<string, UserPluginConfig>;\n\nconst loadUserPluginsFile = async (root: string): Promise<UserPluginConfigFile> => {\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<string, PluginMeta>) => {\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<string, string> = {};\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","isPluginConfigEnabled","config","enabled","getEnabledPlugins","cwd","logger","runtimeDir","plugins","deps","get","debug","os","EOL","userPluginsFile","loadUserPluginsFile","dirs","app","dep","Object","keys","getModule","name","Error","userPluginConfig","undefined","importName","camelCase","type","modulePath","userPluginName","entries","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":";;;;;;;;;AA6DA,MAAMA,2BAA2B,CAC/BC,GAAAA,GAEA,YAAYA,GAAAA,IACZ,OAAOA,IAAIC,MAAM,KAAK,YACtB,CAACC,KAAAA,CAAMC,OAAO,CAACH,GAAAA,CAAIC,MAAM,CAAA,IACzBD,GAAAA,CAAIC,MAAM,KAAK,IAAA;AAEjB,MAAMG,uBAAAA,GAA0B,CAACJ,GAAAA,GAC/BD,wBAAAA,CAAyBC,QAAQA,GAAAA,CAAIC,MAAM,CAACI,IAAI,KAAK,QAAA;AAIvD,MAAMC,wBAAwB,CAACC,MAAAA,GAAAA;IAC7B,IAAI,OAAOA,WAAW,SAAA,EAAW;QAC/B,OAAOA,MAAAA;AACT,IAAA;IAEA,OAAOA,MAAAA,CAAOC,OAAO,KAAK,KAAA;AAC5B,CAAA;AAEA,MAAMC,iBAAAA,GAAoB,OAAO,EAC/BC,GAAG,EACHC,MAAM,EACNC,UAAU,EACVX,MAAM,EACwD,GAAA;AAG9D,IAAA,MAAMY,UAAsC,EAAC;AAE7C;;;;MAKA,MAAMC,OAAOb,MAAAA,CAAOM,MAAM,CAACQ,GAAG,CAAC,qBAAqB,EAAC,CAAA;AAErDJ,IAAAA,MAAAA,CAAOK,KAAK,CAAC,kCAAA,EAAoCC,EAAAA,CAAGC,GAAG,EAAEJ,IAAAA,CAAAA;IAEzD,MAAMK,eAAAA,GAAkB,MAAMC,mBAAAA,CAAoBnB,MAAAA,CAAOoB,IAAI,CAACC,GAAG,CAACf,MAAM,CAAA;AAExEI,IAAAA,MAAAA,CAAOK,KAAK,CAAC,qBAAA,EAAuBC,EAAAA,CAAGC,GAAG,EAAEC,eAAAA,CAAAA;AAE5C,IAAA,KAAK,MAAMI,GAAAA,IAAOC,MAAAA,CAAOC,IAAI,CAACX,IAAAA,CAAAA,CAAO;QACnC,MAAMd,GAAAA,GAAM,MAAM0B,SAAAA,CAAUH,GAAAA,EAAKb,GAAAA,CAAAA;QAEjC,IAAIV,GAAAA,IAAOI,wBAAwBJ,GAAAA,CAAAA,EAAM;AACvC,YAAA,MAAM2B,OAAO3B,GAAAA,CAAIC,MAAM,CAAC0B,IAAI,IAAI3B,IAAI2B,IAAI;AAExC,YAAA,IAAI,CAACA,IAAAA,EAAM;AACT;;AAEC,YACD,MAAMC,KAAAA,CACJ,oGAAA,CAAA;AAEJ,YAAA;YAEA,MAAMC,gBAAAA,GAAmBV,eAAe,CAACQ,IAAAA,CAAK;AAE9C,YAAA,IAAIE,gBAAAA,KAAqBC,SAAAA,IAAa,CAACxB,qBAAAA,CAAsBuB,gBAAAA,CAAAA,EAAmB;AAC9E,gBAAA;AACF,YAAA;YAEAhB,OAAO,CAACc,KAAK,GAAG;AACdA,gBAAAA,IAAAA;AACAI,gBAAAA,UAAAA,EAAYC,SAAAA,CAAUL,IAAAA,CAAAA;gBACtBM,IAAAA,EAAM,QAAA;gBACNC,UAAAA,EAAYX;AACd,aAAA;AACF,QAAA;AACF,IAAA;IAEA,KAAK,MAAM,CAACY,cAAAA,EAAgBN,gBAAAA,CAAiB,IAAIL,MAAAA,CAAOY,OAAO,CAACjB,eAAAA,CAAAA,CAAkB;AAChF;;;;;;QAOA,IACE,OAAOU,gBAAAA,KAAqB,QAAA,IAC5BA,iBAAiBrB,OAAO,IACxBqB,gBAAAA,CAAiBQ,OAAO,EACxB;YACA,MAAMC,OAAAA,GAAUC,6BAAAA,CAA8BV,gBAAAA,CAAiBQ,OAAO,CAAA;YACtExB,OAAO,CAACsB,eAAe,GAAG;gBACxBR,IAAAA,EAAMQ,cAAAA;AACNJ,gBAAAA,UAAAA,EAAYC,SAAAA,CAAUG,cAAAA,CAAAA;gBACtBF,IAAAA,EAAM,OAAA;AACN;;;AAGC,YACDC,UAAAA,EAAYM,6BAAAA,CAA8BC,IAAAA,CAAKC,QAAQ,CAAC9B,UAAAA,EAAY0B,OAAAA,CAAAA,CAAAA;gBACpEG,IAAAA,EAAMH;AACR,aAAA;AACF,QAAA;AACF,IAAA;IAEA,OAAOzB,OAAAA;AACT;AAEA,MAAM8B,cAAAA,GAAiB;AAAC,IAAA,YAAA;AAAc,IAAA,aAAA;AAAe,IAAA;AAAa,CAAA;AAIlE,MAAMvB,sBAAsB,OAAOwB,IAAAA,GAAAA;IACjC,KAAK,MAAMC,QAAQF,cAAAA,CAAgB;AACjC,QAAA,MAAMG,QAAAA,GAAWL,IAAAA,CAAKM,IAAI,CAACH,IAAAA,EAAMC,IAAAA,CAAAA;QACjC,MAAMG,UAAAA,GAAa,MAAMC,QAAAA,CAASH,QAAAA,CAAAA;AAElC,QAAA,IAAIE,UAAAA,EAAY;AACd;;AAEC,UACD,OAAO,OAAOA,UAAAA,KAAe,UAAA,GAAaA,UAAAA,CAAW;AAAEE,gBAAAA;aAAI,CAAA,GAAKF,UAAAA;AAClE,QAAA;AACF,IAAA;AAEA,IAAA,OAAO,EAAC;AACV,CAAA;AAEA,MAAMG,2BAA2B,CAACtC,OAAAA,GAAAA;AAChC;;;;;MAMA,MAAMuC,oBAA4C,EAAC;AAEnD,IAAA,OAAO5B,OAAO6B,MAAM,CAACxC,OAAAA,CAAAA,CAClByC,MAAM,CAAC,CAACC,MAAAA,GAAAA;AACP,QAAA,IAAI,CAACA,MAAAA,EAAQ;YACX,OAAO,KAAA;AACT,QAAA;AAEA;;;;;;;;;;AAUC,UACD,IAAI;YACF,MAAMC,eAAAA,GAAkBD,OAAOd,IAAI;AACnC,YAAA,IAAIe,eAAAA,EAAiB;;AAEnB,gBAAA,MAAMC,eAAAA,GAAkBhB,IAAAA,CAAKM,IAAI,CAACS,eAAAA,EAAiB,cAAA,CAAA;gBAEnD,IAAIE,EAAAA,CAAGC,UAAU,CAACF,eAAAA,CAAAA,EAAkB;AAClC,oBAAA,MAAMG,cAAcC,IAAAA,CAAKC,KAAK,CAACJ,EAAAA,CAAGK,YAAY,CAACN,eAAAA,EAAiB,OAAA,CAAA,CAAA;AAChE,oBAAA,MAAMO,cAAAA,GAAiBJ,WAAAA,EAAaK,OAAAA,GAAU,iBAAiB,EAAEC,MAAAA;AAEjE,oBAAA,IAAIF,cAAAA,EAAgB;AAClBZ,wBAAAA,iBAAiB,CAACG,MAAAA,CAAOrB,UAAU,CAAC,GAAG8B,cAAAA;wBACvC,OAAO,IAAA;AACT,oBAAA;AACF,gBAAA;;AAGA,gBAAA,IAAIN,GAAGC,UAAU,CAAClB,KAAKM,IAAI,CAACS,iBAAiB,iBAAA,CAAA,CAAA,EAAqB;AAChEJ,oBAAAA,iBAAiB,CAACG,MAAAA,CAAOrB,UAAU,CAAC,GAAG,cAAA;oBACvC,OAAO,IAAA;AACT,gBAAA;AACF,YAAA;;YAGA,IAAIiC,OAAAA,CAAQ9B,OAAO,CAAC,CAAA,EAAGkB,OAAOrB,UAAU,CAAC,aAAa,CAAC,CAAA,EAAG;AACxDkB,gBAAAA,iBAAiB,CAACG,MAAAA,CAAOrB,UAAU,CAAC,GAAG,cAAA;gBACvC,OAAO,IAAA;AACT,YAAA;YAEA,OAAO,KAAA;AACT,QAAA,CAAA,CAAE,OAAOkC,GAAAA,EAAK;AACZ,YAAA,IACEC,OAAAA,CAAQD,GAAAA,CAAAA,IACR,MAAA,IAAUA,GAAAA,KACTA,GAAAA,CAAIE,IAAI,KAAK,kBAAA,IAAsBF,GAAAA,CAAIE,IAAI,KAAK,+BAA8B,CAAA,EAC/E;AACA;;;AAGC,cACD,OAAO,KAAA;AACT,YAAA;YAEA,MAAMF,GAAAA;AACR,QAAA;AACF,IAAA,CAAA,CAAA,CACCG,GAAG,CAAC,CAAChB,MAAAA,IAAY;AAChB,YAAA,GAAGA,MAAM;YACTrB,UAAAA,EAAY,CAAA,EAAGqB,MAAAA,CAAOrB,UAAU,CAAC,CAAC,EAAEkB,iBAAiB,CAACG,MAAAA,CAAOrB,UAAU,CAAC,CAAA;SAC1E,CAAA,CAAA;AACJ;;;;"}
@@ -3,7 +3,7 @@
3
3
  var fs = require('node:fs/promises');
4
4
  var path = require('node:path');
5
5
  var cluster = require('node:cluster');
6
- var dependencies = require('./core/dependencies.js');
6
+ var ensureAdminDependencies = require('./core/ensure-admin-dependencies.js');
7
7
  var timer = require('./core/timer.js');
8
8
 
9
9
  // Lazy: worker-only deps; primary cluster process should not pay for them
@@ -53,17 +53,15 @@ const cleanupDistDirectory = async ({ tsconfig, logger, timer: timer$1 })=>{
53
53
  cleaningSpinner.text = `Cleaning dist dir (${timer.prettyTime(generatingDuration)})`;
54
54
  cleaningSpinner?.succeed();
55
55
  };
56
- const develop = async ({ cwd, polling, logger, tsconfig, watchAdmin, buildAdmin, ...options })=>{
56
+ const develop = async ({ cwd, polling, logger, tsconfig, watchAdmin, buildAdmin, installDeps = true, ...options })=>{
57
57
  const timer$1 = timer.getTimer();
58
58
  if (cluster.isPrimary) {
59
- const { didInstall } = await dependencies.checkRequiredDependencies({
59
+ const shouldContinue = await ensureAdminDependencies.handleAdminDependencies({
60
60
  cwd,
61
- logger
62
- }).catch((err)=>{
63
- logger.error(err.message);
64
- process.exit(1);
61
+ logger,
62
+ installIfMissing: installDeps
65
63
  });
66
- if (didInstall) {
64
+ if (!shouldContinue) {
67
65
  return;
68
66
  }
69
67
  if (tsconfig?.config) {