@strapi/strapi 5.47.0 → 5.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/cli/commands/build.d.ts.map +1 -1
  2. package/dist/cli/commands/develop.d.ts.map +1 -1
  3. package/dist/cli/utils/data-transfer.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/develop.d.ts +7 -1
  11. package/dist/node/develop.d.ts.map +1 -1
  12. package/dist/package.json.js +1 -1
  13. package/dist/package.json.mjs +1 -1
  14. package/dist/src/cli/commands/build.js +1 -1
  15. package/dist/src/cli/commands/build.js.map +1 -1
  16. package/dist/src/cli/commands/build.mjs +1 -1
  17. package/dist/src/cli/commands/build.mjs.map +1 -1
  18. package/dist/src/cli/commands/develop.js +1 -1
  19. package/dist/src/cli/commands/develop.js.map +1 -1
  20. package/dist/src/cli/commands/develop.mjs +1 -1
  21. package/dist/src/cli/commands/develop.mjs.map +1 -1
  22. package/dist/src/cli/utils/data-transfer.js +7 -2
  23. package/dist/src/cli/utils/data-transfer.js.map +1 -1
  24. package/dist/src/cli/utils/data-transfer.mjs +7 -2
  25. package/dist/src/cli/utils/data-transfer.mjs.map +1 -1
  26. package/dist/src/node/build.js +6 -8
  27. package/dist/src/node/build.js.map +1 -1
  28. package/dist/src/node/build.mjs +6 -8
  29. package/dist/src/node/build.mjs.map +1 -1
  30. package/dist/src/node/core/dependencies.js +136 -103
  31. package/dist/src/node/core/dependencies.js.map +1 -1
  32. package/dist/src/node/core/dependencies.mjs +126 -103
  33. package/dist/src/node/core/dependencies.mjs.map +1 -1
  34. package/dist/src/node/core/ensure-admin-dependencies.js +70 -0
  35. package/dist/src/node/core/ensure-admin-dependencies.js.map +1 -0
  36. package/dist/src/node/core/ensure-admin-dependencies.mjs +67 -0
  37. package/dist/src/node/core/ensure-admin-dependencies.mjs.map +1 -0
  38. package/dist/src/node/create-build-context.js +1 -1
  39. package/dist/src/node/create-build-context.js.map +1 -1
  40. package/dist/src/node/create-build-context.mjs +1 -1
  41. package/dist/src/node/create-build-context.mjs.map +1 -1
  42. package/dist/src/node/develop.js +36 -46
  43. package/dist/src/node/develop.js.map +1 -1
  44. package/dist/src/node/develop.mjs +36 -27
  45. package/dist/src/node/develop.mjs.map +1 -1
  46. package/package.json +22 -22
@@ -1 +1 @@
1
- {"version":3,"file":"dependencies.js","sources":["../../../../src/node/core/dependencies.ts"],"sourcesContent":["import os from 'node:os';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\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\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 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 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":["PEER_DEPS","react","checkRequiredDependencies","cwd","logger","process","env","USE_EXPERIMENTAL_DEPENDENCIES","warn","didInstall","pkg","readPkgUp","Error","debug","os","EOL","packageJson","install","review","Object","entries","reduce","acc","name","version","dependencies","declaredVersion","devDependencies","push","wantedVersion","length","info","map","join","installDependencies","file","args","argv","execa","stdio","errors","dep","minDeclaredVersion","semver","minVersion","err","satisfies","installedVersion","getModuleVersion","NODE_ENV","getModule","modulePackagePath","resolveFrom","silent","path","fs","readFile","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.js","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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"}
@@ -1,142 +1,143 @@
1
1
  import os from 'node:os';
2
2
  import fs from 'node:fs/promises';
3
3
  import path from 'node:path';
4
+ import crypto from 'node:crypto';
4
5
  import semver from 'semver';
5
6
  import resolveFrom from 'resolve-from';
6
7
  import execa from 'execa';
7
8
  import readPkgUp from 'read-pkg-up';
8
9
  import { getPackageManager } from './managers.mjs';
9
10
 
11
+ const CACHE_PATH = path.join('node_modules', '.strapi', 'deps-check.hash');
12
+ const hashPackageJson = async (cwd)=>{
13
+ try {
14
+ const content = await fs.readFile(path.join(cwd, 'package.json'), 'utf8');
15
+ return crypto.createHash('sha1').update(content).digest('hex');
16
+ } catch {
17
+ return null;
18
+ }
19
+ };
20
+ const readCachedHash = (cwd)=>fs.readFile(path.join(cwd, CACHE_PATH), 'utf8').catch(()=>null);
21
+ const writeCachedHash = async (cwd, hash)=>{
22
+ try {
23
+ await fs.mkdir(path.dirname(path.join(cwd, CACHE_PATH)), {
24
+ recursive: true
25
+ });
26
+ await fs.writeFile(path.join(cwd, CACHE_PATH), hash, 'utf8');
27
+ } catch {
28
+ // best-effort cache write — silently ignore
29
+ }
30
+ };
10
31
  /**
11
32
  * From V5 this will be imported from the package.json of `@strapi/strapi`.
12
- */ const PEER_DEPS = {
33
+ */ const ADMIN_PEER_DEPS = {
13
34
  react: '^18.0.0',
14
35
  'react-dom': '^18.0.0',
15
36
  'react-router-dom': '^6.0.0',
16
37
  'styled-components': '^6.0.0'
17
38
  };
18
- /**
19
- * Checks the user's project that it has declared and installed the required dependencies
20
- * needed by the Strapi admin project. Whilst generally speaking most modules will be
21
- * declared by the actual packages there are some packages where you only really want one of
22
- * and thus they are declared as peer dependencies – react / styled-components / etc.
23
- *
24
- * If these deps are not installed or declared, then we prompt the user to correct this. In
25
- * V4 this is not a hard requirement, but in V5 it will be. Might as well get people started now.
26
- */ const checkRequiredDependencies = async ({ cwd, logger })=>{
27
- /**
28
- * This enables us to use experimental deps for libraries like
29
- * react or styled-components. This is useful for testing against.
30
- */ if (process.env.USE_EXPERIMENTAL_DEPENDENCIES === 'true') {
31
- logger.warn('You are using experimental dependencies that may not be compatible with Strapi.');
32
- return {
33
- didInstall: false
34
- };
39
+ class MissingAdminPeerDepsError extends Error {
40
+ constructor(missing){
41
+ super('Missing required dependencies. Please install them and re-run this command.');
42
+ this.name = 'MissingAdminPeerDepsError';
43
+ this.missing = missing;
35
44
  }
45
+ }
46
+ const loadProjectPackageJson = async (cwd)=>{
36
47
  const pkg = await readPkgUp({
37
48
  cwd
38
49
  });
39
50
  if (!pkg) {
40
51
  throw new Error(`Could not find package.json at path: ${cwd}`);
41
52
  }
42
- logger.debug('Loaded package.json:', os.EOL, pkg.packageJson);
43
- /**
44
- * Run through each of the peer deps and figure out if they need to be
45
- * installed or they need their version checked against.
46
- */ const { install, review } = Object.entries(PEER_DEPS).reduce((acc, [name, version])=>{
47
- if (!pkg.packageJson.dependencies) {
48
- throw new Error(`Could not find dependencies in package.json at path: ${cwd}`);
49
- }
50
- const declaredVersion = pkg.packageJson.dependencies[name] ?? pkg.packageJson.devDependencies?.[name];
53
+ if (!pkg.packageJson.dependencies) {
54
+ throw new Error(`Could not find dependencies in package.json at path: ${cwd}`);
55
+ }
56
+ return pkg;
57
+ };
58
+ /**
59
+ * Returns admin peer dependencies that are not declared in the project's package.json.
60
+ */ const findUndeclaredAdminPeerDeps = async (cwd)=>{
61
+ const pkg = await loadProjectPackageJson(cwd);
62
+ return Object.entries(ADMIN_PEER_DEPS).reduce((missing, [name, version])=>{
63
+ const declaredVersion = pkg.packageJson.dependencies?.[name] ?? pkg.packageJson.devDependencies?.[name];
51
64
  if (!declaredVersion) {
52
- acc.install.push({
65
+ missing.push({
53
66
  name,
54
67
  wantedVersion: version
55
68
  });
56
- } else {
57
- acc.review.push({
69
+ }
70
+ return missing;
71
+ }, []);
72
+ };
73
+ const getDeclaredAdminPeerDeps = (packageJson)=>{
74
+ return Object.entries(ADMIN_PEER_DEPS).reduce((declared, [name, version])=>{
75
+ const declaredVersion = packageJson.dependencies?.[name] ?? packageJson.devDependencies?.[name];
76
+ if (declaredVersion) {
77
+ declared.push({
58
78
  name,
59
79
  wantedVersion: version,
60
80
  declaredVersion
61
81
  });
62
82
  }
63
- return acc;
64
- }, {
65
- install: [],
66
- review: []
67
- });
68
- if (install.length > 0) {
69
- logger.info('The Strapi admin needs to install the following dependencies:', os.EOL, install.map(({ name, wantedVersion })=>` - ${name}@${wantedVersion}`).join(os.EOL));
70
- await installDependencies(install, {
71
- cwd,
72
- logger
73
- });
74
- const [file, ...args] = process.argv;
75
- /**
76
- * Re-run the same command after installation e.g. strapi build because the yarn.lock might
77
- * not be the same and could break installations. It's not the best solution, but it works.
78
- */ await execa(file, args, {
79
- cwd,
80
- stdio: 'inherit'
81
- });
82
- return {
83
- didInstall: true
84
- };
83
+ return declared;
84
+ }, []);
85
+ };
86
+ const getInstallCommandHint = (missing)=>{
87
+ const packages = missing.map(({ name, wantedVersion })=>`${name}@${wantedVersion}`).join(' ');
88
+ const packageManager = getPackageManager();
89
+ if (packageManager === 'yarn') {
90
+ return `yarn add ${packages}`;
91
+ }
92
+ if (packageManager === 'pnpm') {
93
+ return `pnpm add --save-prod ${packages}`;
85
94
  }
86
- if (review.length) {
87
- const errors = [];
88
- for (const dep of review){
89
- // The version specified in package.json could be incorrect, eg `foo`
90
- let minDeclaredVersion = null;
91
- try {
92
- minDeclaredVersion = semver.minVersion(dep.declaredVersion);
93
- } catch (err) {
94
- // Intentional fall-through (variable will be left as null, throwing below)
95
- }
96
- if (!minDeclaredVersion) {
97
- errors.push(`The declared dependency, ${dep.name} has an invalid version in package.json: ${dep.declaredVersion}`);
98
- } else if (!semver.satisfies(minDeclaredVersion, dep.wantedVersion)) {
99
- /**
100
- * The delcared version should be semver compatible with our required version
101
- * of the dependency. If it's not, we should advise the user to change it.
102
- */ logger.warn([
103
- `Declared version of ${dep.name} (${minDeclaredVersion}) is not compatible with the version required by Strapi (${dep.wantedVersion}).`,
104
- 'You may experience issues, we recommend you change this.'
105
- ].join(os.EOL));
106
- }
107
- const installedVersion = await getModuleVersion(dep.name, cwd);
108
- if (!installedVersion) {
109
- /**
110
- * TODO: when we know the packageManager we can advise the actual install command.
111
- */ errors.push(`The declared dependency, ${dep.name} is not installed. You should install before re-running this command`);
112
- } else if (!semver.satisfies(installedVersion, dep.wantedVersion)) {
113
- logger.warn([
114
- `Declared version of ${dep.name} (${installedVersion}) is not compatible with the version required by Strapi (${dep.wantedVersion}).`,
115
- 'You may experience issues, we recommend you change this.'
116
- ].join(os.EOL));
117
- }
95
+ return `npm install --legacy-peer-deps --save ${packages}`;
96
+ };
97
+ const reportMissingAdminPeerDeps = (logger, missing)=>{
98
+ logger.error('The Strapi admin is missing required dependencies:', os.EOL, missing.map(({ name, wantedVersion })=>` - ${name}@${wantedVersion}`).join(os.EOL));
99
+ logger.error('Please install them manually before re-running this command:', os.EOL, ` ${getInstallCommandHint(missing)}`);
100
+ };
101
+ /**
102
+ * Validates declared admin peer dependencies (versions and node_modules presence).
103
+ */ const validateDeclaredAdminPeerDeps = async (cwd, logger)=>{
104
+ const pkg = await loadProjectPackageJson(cwd);
105
+ const declared = getDeclaredAdminPeerDeps(pkg.packageJson);
106
+ if (!declared.length) {
107
+ return;
108
+ }
109
+ logger.debug('Loaded package.json:', os.EOL, pkg.packageJson);
110
+ const errors = [];
111
+ for (const dep of declared){
112
+ let minDeclaredVersion = null;
113
+ try {
114
+ minDeclaredVersion = semver.minVersion(dep.declaredVersion);
115
+ } catch (err) {
116
+ // Intentional fall-through (variable will be left as null, throwing below)
117
+ }
118
+ if (!minDeclaredVersion) {
119
+ errors.push(`The declared dependency, ${dep.name} has an invalid version in package.json: ${dep.declaredVersion}`);
120
+ } else if (!semver.satisfies(minDeclaredVersion, dep.wantedVersion)) {
121
+ logger.warn([
122
+ `Declared version of ${dep.name} (${minDeclaredVersion}) is not compatible with the version required by Strapi (${dep.wantedVersion}).`,
123
+ 'You may experience issues, we recommend you change this.'
124
+ ].join(os.EOL));
118
125
  }
119
- if (errors.length > 0 && process.env.NODE_ENV === 'development') {
120
- throw new Error(`${os.EOL}- ${errors.join(`${os.EOL}- `)}`);
126
+ const installedVersion = await getModuleVersion(dep.name, cwd);
127
+ if (!installedVersion) {
128
+ errors.push(`The declared dependency, ${dep.name} is not installed. You should install before re-running this command`);
129
+ } else if (!semver.satisfies(installedVersion, dep.wantedVersion)) {
130
+ logger.warn([
131
+ `Declared version of ${dep.name} (${installedVersion}) is not compatible with the version required by Strapi (${dep.wantedVersion}).`,
132
+ 'You may experience issues, we recommend you change this.'
133
+ ].join(os.EOL));
121
134
  }
122
135
  }
123
- return {
124
- didInstall: false
125
- };
126
- };
127
- const getModule = async (name, cwd)=>{
128
- const modulePackagePath = resolveFrom.silent(cwd, path.join(name, 'package.json'));
129
- if (!modulePackagePath) {
130
- return null;
136
+ if (errors.length > 0 && process.env.NODE_ENV === 'development') {
137
+ throw new Error(`${os.EOL}- ${errors.join(`${os.EOL}- `)}`);
131
138
  }
132
- const file = await fs.readFile(modulePackagePath, 'utf8').then((res)=>JSON.parse(res));
133
- return file;
134
139
  };
135
- const getModuleVersion = async (name, cwd)=>{
136
- const pkg = await getModule(name, cwd);
137
- return pkg?.version || null;
138
- };
139
- const installDependencies = async (install, { cwd, logger })=>{
140
+ const installAdminPeerDeps = async (missing, { cwd, logger })=>{
140
141
  const packageManager = getPackageManager();
141
142
  if (!packageManager) {
142
143
  logger.error('Could not find a supported package manager, please install the dependencies manually.');
@@ -147,7 +148,7 @@ const installDependencies = async (install, { cwd, logger })=>{
147
148
  cwd,
148
149
  stdio: 'inherit'
149
150
  };
150
- const packages = install.map(({ name, wantedVersion })=>`${name}@${wantedVersion}`);
151
+ const packages = missing.map(({ name, wantedVersion })=>`${name}@${wantedVersion}`);
151
152
  let result;
152
153
  if (packageManager === 'npm') {
153
154
  const npmArgs = [
@@ -178,6 +179,28 @@ const installDependencies = async (install, { cwd, logger })=>{
178
179
  throw new Error('Package installation failed');
179
180
  }
180
181
  };
182
+ const reexecCurrentCommand = async (cwd)=>{
183
+ const [file, ...args] = process.argv;
184
+ /**
185
+ * Re-run the same command after installation e.g. strapi build because the yarn.lock might
186
+ * not be the same and could break installations. It's not the best solution, but it works.
187
+ */ await execa(file, args, {
188
+ cwd,
189
+ stdio: 'inherit'
190
+ });
191
+ };
192
+ const getModule = async (name, cwd)=>{
193
+ const modulePackagePath = resolveFrom.silent(cwd, path.join(name, 'package.json'));
194
+ if (!modulePackagePath) {
195
+ return null;
196
+ }
197
+ const file = await fs.readFile(modulePackagePath, 'utf8').then((res)=>JSON.parse(res));
198
+ return file;
199
+ };
200
+ const getModuleVersion = async (name, cwd)=>{
201
+ const pkg = await getModule(name, cwd);
202
+ return pkg?.version || null;
203
+ };
181
204
 
182
- export { checkRequiredDependencies, getModule };
205
+ export { ADMIN_PEER_DEPS, MissingAdminPeerDepsError, findUndeclaredAdminPeerDeps, getInstallCommandHint, getModule, hashPackageJson, installAdminPeerDeps, readCachedHash, reexecCurrentCommand, reportMissingAdminPeerDeps, validateDeclaredAdminPeerDeps, writeCachedHash };
183
206
  //# sourceMappingURL=dependencies.mjs.map
@@ -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 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\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 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 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":["PEER_DEPS","react","checkRequiredDependencies","cwd","logger","process","env","USE_EXPERIMENTAL_DEPENDENCIES","warn","didInstall","pkg","readPkgUp","Error","debug","os","EOL","packageJson","install","review","Object","entries","reduce","acc","name","version","dependencies","declaredVersion","devDependencies","push","wantedVersion","length","info","map","join","installDependencies","file","args","argv","execa","stdio","errors","dep","minDeclaredVersion","semver","minVersion","err","satisfies","installedVersion","getModuleVersion","NODE_ENV","getModule","modulePackagePath","resolveFrom","silent","path","fs","readFile","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;;;;"}