@strapi/strapi 5.47.1 → 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.
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/develop.d.ts.map +1 -1
- package/dist/node/build.d.ts +7 -1
- package/dist/node/build.d.ts.map +1 -1
- package/dist/node/core/dependencies.d.ts +35 -13
- package/dist/node/core/dependencies.d.ts.map +1 -1
- package/dist/node/core/ensure-admin-dependencies.d.ts +25 -0
- package/dist/node/core/ensure-admin-dependencies.d.ts.map +1 -0
- package/dist/node/develop.d.ts +7 -1
- package/dist/node/develop.d.ts.map +1 -1
- package/dist/package.json.js +1 -1
- package/dist/package.json.mjs +1 -1
- package/dist/src/cli/commands/build.js +1 -1
- package/dist/src/cli/commands/build.js.map +1 -1
- package/dist/src/cli/commands/build.mjs +1 -1
- package/dist/src/cli/commands/build.mjs.map +1 -1
- package/dist/src/cli/commands/develop.js +1 -1
- package/dist/src/cli/commands/develop.js.map +1 -1
- package/dist/src/cli/commands/develop.mjs +1 -1
- package/dist/src/cli/commands/develop.mjs.map +1 -1
- package/dist/src/node/build.js +6 -8
- package/dist/src/node/build.js.map +1 -1
- package/dist/src/node/build.mjs +6 -8
- package/dist/src/node/build.mjs.map +1 -1
- package/dist/src/node/core/dependencies.js +115 -118
- package/dist/src/node/core/dependencies.js.map +1 -1
- package/dist/src/node/core/dependencies.mjs +105 -118
- package/dist/src/node/core/dependencies.mjs.map +1 -1
- package/dist/src/node/core/ensure-admin-dependencies.js +70 -0
- package/dist/src/node/core/ensure-admin-dependencies.js.map +1 -0
- package/dist/src/node/core/ensure-admin-dependencies.mjs +67 -0
- package/dist/src/node/core/ensure-admin-dependencies.mjs.map +1 -0
- package/dist/src/node/develop.js +6 -8
- package/dist/src/node/develop.js.map +1 -1
- package/dist/src/node/develop.mjs +6 -8
- package/dist/src/node/develop.mjs.map +1 -1
- package/package.json +22 -22
|
@@ -32,149 +32,114 @@ const writeCachedHash = async (cwd, hash)=>{
|
|
|
32
32
|
};
|
|
33
33
|
/**
|
|
34
34
|
* From V5 this will be imported from the package.json of `@strapi/strapi`.
|
|
35
|
-
*/ const
|
|
35
|
+
*/ const ADMIN_PEER_DEPS = {
|
|
36
36
|
react: '^18.0.0',
|
|
37
37
|
'react-dom': '^18.0.0',
|
|
38
38
|
'react-router-dom': '^6.0.0',
|
|
39
39
|
'styled-components': '^6.0.0'
|
|
40
40
|
};
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
*
|
|
47
|
-
* If these deps are not installed or declared, then we prompt the user to correct this. In
|
|
48
|
-
* V4 this is not a hard requirement, but in V5 it will be. Might as well get people started now.
|
|
49
|
-
*/ const checkRequiredDependencies = async ({ cwd, logger })=>{
|
|
50
|
-
/**
|
|
51
|
-
* This enables us to use experimental deps for libraries like
|
|
52
|
-
* react or styled-components. This is useful for testing against.
|
|
53
|
-
*/ if (process.env.USE_EXPERIMENTAL_DEPENDENCIES === 'true') {
|
|
54
|
-
logger.warn('You are using experimental dependencies that may not be compatible with Strapi.');
|
|
55
|
-
return {
|
|
56
|
-
didInstall: false
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
// Hash-cache: skip the full check when package.json hasn't changed since
|
|
60
|
-
// the last successful pass. The cache lives under node_modules so it's
|
|
61
|
-
// already gitignored and disposable (a `yarn install` wipe re-runs it).
|
|
62
|
-
const currentHash = await hashPackageJson(cwd);
|
|
63
|
-
if (currentHash) {
|
|
64
|
-
const cachedHash = await readCachedHash(cwd);
|
|
65
|
-
if (cachedHash === currentHash) {
|
|
66
|
-
return {
|
|
67
|
-
didInstall: false
|
|
68
|
-
};
|
|
69
|
-
}
|
|
41
|
+
class MissingAdminPeerDepsError extends Error {
|
|
42
|
+
constructor(missing){
|
|
43
|
+
super('Missing required dependencies. Please install them and re-run this command.');
|
|
44
|
+
this.name = 'MissingAdminPeerDepsError';
|
|
45
|
+
this.missing = missing;
|
|
70
46
|
}
|
|
47
|
+
}
|
|
48
|
+
const loadProjectPackageJson = async (cwd)=>{
|
|
71
49
|
const pkg = await readPkgUp({
|
|
72
50
|
cwd
|
|
73
51
|
});
|
|
74
52
|
if (!pkg) {
|
|
75
53
|
throw new Error(`Could not find package.json at path: ${cwd}`);
|
|
76
54
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
55
|
+
if (!pkg.packageJson.dependencies) {
|
|
56
|
+
throw new Error(`Could not find dependencies in package.json at path: ${cwd}`);
|
|
57
|
+
}
|
|
58
|
+
return pkg;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Returns admin peer dependencies that are not declared in the project's package.json.
|
|
62
|
+
*/ const findUndeclaredAdminPeerDeps = async (cwd)=>{
|
|
63
|
+
const pkg = await loadProjectPackageJson(cwd);
|
|
64
|
+
return Object.entries(ADMIN_PEER_DEPS).reduce((missing, [name, version])=>{
|
|
65
|
+
const declaredVersion = pkg.packageJson.dependencies?.[name] ?? pkg.packageJson.devDependencies?.[name];
|
|
86
66
|
if (!declaredVersion) {
|
|
87
|
-
|
|
67
|
+
missing.push({
|
|
88
68
|
name,
|
|
89
69
|
wantedVersion: version
|
|
90
70
|
});
|
|
91
|
-
}
|
|
92
|
-
|
|
71
|
+
}
|
|
72
|
+
return missing;
|
|
73
|
+
}, []);
|
|
74
|
+
};
|
|
75
|
+
const getDeclaredAdminPeerDeps = (packageJson)=>{
|
|
76
|
+
return Object.entries(ADMIN_PEER_DEPS).reduce((declared, [name, version])=>{
|
|
77
|
+
const declaredVersion = packageJson.dependencies?.[name] ?? packageJson.devDependencies?.[name];
|
|
78
|
+
if (declaredVersion) {
|
|
79
|
+
declared.push({
|
|
93
80
|
name,
|
|
94
81
|
wantedVersion: version,
|
|
95
82
|
declaredVersion
|
|
96
83
|
});
|
|
97
84
|
}
|
|
98
|
-
return
|
|
99
|
-
},
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
const [file, ...args] = process.argv;
|
|
110
|
-
/**
|
|
111
|
-
* Re-run the same command after installation e.g. strapi build because the yarn.lock might
|
|
112
|
-
* not be the same and could break installations. It's not the best solution, but it works.
|
|
113
|
-
*/ await execa(file, args, {
|
|
114
|
-
cwd,
|
|
115
|
-
stdio: 'inherit'
|
|
116
|
-
});
|
|
117
|
-
return {
|
|
118
|
-
didInstall: true
|
|
119
|
-
};
|
|
85
|
+
return declared;
|
|
86
|
+
}, []);
|
|
87
|
+
};
|
|
88
|
+
const getInstallCommandHint = (missing)=>{
|
|
89
|
+
const packages = missing.map(({ name, wantedVersion })=>`${name}@${wantedVersion}`).join(' ');
|
|
90
|
+
const packageManager = managers.getPackageManager();
|
|
91
|
+
if (packageManager === 'yarn') {
|
|
92
|
+
return `yarn add ${packages}`;
|
|
93
|
+
}
|
|
94
|
+
if (packageManager === 'pnpm') {
|
|
95
|
+
return `pnpm add --save-prod ${packages}`;
|
|
120
96
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (!installedVersion) {
|
|
144
|
-
/**
|
|
145
|
-
* TODO: when we know the packageManager we can advise the actual install command.
|
|
146
|
-
*/ errors.push(`The declared dependency, ${dep.name} is not installed. You should install before re-running this command`);
|
|
147
|
-
} else if (!semver.satisfies(installedVersion, dep.wantedVersion)) {
|
|
148
|
-
logger.warn([
|
|
149
|
-
`Declared version of ${dep.name} (${installedVersion}) is not compatible with the version required by Strapi (${dep.wantedVersion}).`,
|
|
150
|
-
'You may experience issues, we recommend you change this.'
|
|
151
|
-
].join(os.EOL));
|
|
152
|
-
}
|
|
97
|
+
return `npm install --legacy-peer-deps --save ${packages}`;
|
|
98
|
+
};
|
|
99
|
+
const reportMissingAdminPeerDeps = (logger, missing)=>{
|
|
100
|
+
logger.error('The Strapi admin is missing required dependencies:', os.EOL, missing.map(({ name, wantedVersion })=>` - ${name}@${wantedVersion}`).join(os.EOL));
|
|
101
|
+
logger.error('Please install them manually before re-running this command:', os.EOL, ` ${getInstallCommandHint(missing)}`);
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Validates declared admin peer dependencies (versions and node_modules presence).
|
|
105
|
+
*/ const validateDeclaredAdminPeerDeps = async (cwd, logger)=>{
|
|
106
|
+
const pkg = await loadProjectPackageJson(cwd);
|
|
107
|
+
const declared = getDeclaredAdminPeerDeps(pkg.packageJson);
|
|
108
|
+
if (!declared.length) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
logger.debug('Loaded package.json:', os.EOL, pkg.packageJson);
|
|
112
|
+
const errors = [];
|
|
113
|
+
for (const dep of declared){
|
|
114
|
+
let minDeclaredVersion = null;
|
|
115
|
+
try {
|
|
116
|
+
minDeclaredVersion = semver.minVersion(dep.declaredVersion);
|
|
117
|
+
} catch (err) {
|
|
118
|
+
// Intentional fall-through (variable will be left as null, throwing below)
|
|
153
119
|
}
|
|
154
|
-
if (
|
|
155
|
-
|
|
120
|
+
if (!minDeclaredVersion) {
|
|
121
|
+
errors.push(`The declared dependency, ${dep.name} has an invalid version in package.json: ${dep.declaredVersion}`);
|
|
122
|
+
} else if (!semver.satisfies(minDeclaredVersion, dep.wantedVersion)) {
|
|
123
|
+
logger.warn([
|
|
124
|
+
`Declared version of ${dep.name} (${minDeclaredVersion}) is not compatible with the version required by Strapi (${dep.wantedVersion}).`,
|
|
125
|
+
'You may experience issues, we recommend you change this.'
|
|
126
|
+
].join(os.EOL));
|
|
127
|
+
}
|
|
128
|
+
const installedVersion = await getModuleVersion(dep.name, cwd);
|
|
129
|
+
if (!installedVersion) {
|
|
130
|
+
errors.push(`The declared dependency, ${dep.name} is not installed. You should install before re-running this command`);
|
|
131
|
+
} else if (!semver.satisfies(installedVersion, dep.wantedVersion)) {
|
|
132
|
+
logger.warn([
|
|
133
|
+
`Declared version of ${dep.name} (${installedVersion}) is not compatible with the version required by Strapi (${dep.wantedVersion}).`,
|
|
134
|
+
'You may experience issues, we recommend you change this.'
|
|
135
|
+
].join(os.EOL));
|
|
156
136
|
}
|
|
157
137
|
}
|
|
158
|
-
if (
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
return {
|
|
162
|
-
didInstall: false
|
|
163
|
-
};
|
|
164
|
-
};
|
|
165
|
-
const getModule = async (name, cwd)=>{
|
|
166
|
-
const modulePackagePath = resolveFrom.silent(cwd, path.join(name, 'package.json'));
|
|
167
|
-
if (!modulePackagePath) {
|
|
168
|
-
return null;
|
|
138
|
+
if (errors.length > 0 && process.env.NODE_ENV === 'development') {
|
|
139
|
+
throw new Error(`${os.EOL}- ${errors.join(`${os.EOL}- `)}`);
|
|
169
140
|
}
|
|
170
|
-
const file = await fs.readFile(modulePackagePath, 'utf8').then((res)=>JSON.parse(res));
|
|
171
|
-
return file;
|
|
172
|
-
};
|
|
173
|
-
const getModuleVersion = async (name, cwd)=>{
|
|
174
|
-
const pkg = await getModule(name, cwd);
|
|
175
|
-
return pkg?.version || null;
|
|
176
141
|
};
|
|
177
|
-
const
|
|
142
|
+
const installAdminPeerDeps = async (missing, { cwd, logger })=>{
|
|
178
143
|
const packageManager = managers.getPackageManager();
|
|
179
144
|
if (!packageManager) {
|
|
180
145
|
logger.error('Could not find a supported package manager, please install the dependencies manually.');
|
|
@@ -185,7 +150,7 @@ const installDependencies = async (install, { cwd, logger })=>{
|
|
|
185
150
|
cwd,
|
|
186
151
|
stdio: 'inherit'
|
|
187
152
|
};
|
|
188
|
-
const packages =
|
|
153
|
+
const packages = missing.map(({ name, wantedVersion })=>`${name}@${wantedVersion}`);
|
|
189
154
|
let result;
|
|
190
155
|
if (packageManager === 'npm') {
|
|
191
156
|
const npmArgs = [
|
|
@@ -216,7 +181,39 @@ const installDependencies = async (install, { cwd, logger })=>{
|
|
|
216
181
|
throw new Error('Package installation failed');
|
|
217
182
|
}
|
|
218
183
|
};
|
|
184
|
+
const reexecCurrentCommand = async (cwd)=>{
|
|
185
|
+
const [file, ...args] = process.argv;
|
|
186
|
+
/**
|
|
187
|
+
* Re-run the same command after installation e.g. strapi build because the yarn.lock might
|
|
188
|
+
* not be the same and could break installations. It's not the best solution, but it works.
|
|
189
|
+
*/ await execa(file, args, {
|
|
190
|
+
cwd,
|
|
191
|
+
stdio: 'inherit'
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
const getModule = async (name, cwd)=>{
|
|
195
|
+
const modulePackagePath = resolveFrom.silent(cwd, path.join(name, 'package.json'));
|
|
196
|
+
if (!modulePackagePath) {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
const file = await fs.readFile(modulePackagePath, 'utf8').then((res)=>JSON.parse(res));
|
|
200
|
+
return file;
|
|
201
|
+
};
|
|
202
|
+
const getModuleVersion = async (name, cwd)=>{
|
|
203
|
+
const pkg = await getModule(name, cwd);
|
|
204
|
+
return pkg?.version || null;
|
|
205
|
+
};
|
|
219
206
|
|
|
220
|
-
exports.
|
|
207
|
+
exports.ADMIN_PEER_DEPS = ADMIN_PEER_DEPS;
|
|
208
|
+
exports.MissingAdminPeerDepsError = MissingAdminPeerDepsError;
|
|
209
|
+
exports.findUndeclaredAdminPeerDeps = findUndeclaredAdminPeerDeps;
|
|
210
|
+
exports.getInstallCommandHint = getInstallCommandHint;
|
|
221
211
|
exports.getModule = getModule;
|
|
212
|
+
exports.hashPackageJson = hashPackageJson;
|
|
213
|
+
exports.installAdminPeerDeps = installAdminPeerDeps;
|
|
214
|
+
exports.readCachedHash = readCachedHash;
|
|
215
|
+
exports.reexecCurrentCommand = reexecCurrentCommand;
|
|
216
|
+
exports.reportMissingAdminPeerDeps = reportMissingAdminPeerDeps;
|
|
217
|
+
exports.validateDeclaredAdminPeerDeps = validateDeclaredAdminPeerDeps;
|
|
218
|
+
exports.writeCachedHash = writeCachedHash;
|
|
222
219
|
//# sourceMappingURL=dependencies.js.map
|
|
@@ -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 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.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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"}
|
|
@@ -30,149 +30,114 @@ const writeCachedHash = async (cwd, hash)=>{
|
|
|
30
30
|
};
|
|
31
31
|
/**
|
|
32
32
|
* From V5 this will be imported from the package.json of `@strapi/strapi`.
|
|
33
|
-
*/ const
|
|
33
|
+
*/ const ADMIN_PEER_DEPS = {
|
|
34
34
|
react: '^18.0.0',
|
|
35
35
|
'react-dom': '^18.0.0',
|
|
36
36
|
'react-router-dom': '^6.0.0',
|
|
37
37
|
'styled-components': '^6.0.0'
|
|
38
38
|
};
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
*
|
|
45
|
-
* If these deps are not installed or declared, then we prompt the user to correct this. In
|
|
46
|
-
* V4 this is not a hard requirement, but in V5 it will be. Might as well get people started now.
|
|
47
|
-
*/ const checkRequiredDependencies = async ({ cwd, logger })=>{
|
|
48
|
-
/**
|
|
49
|
-
* This enables us to use experimental deps for libraries like
|
|
50
|
-
* react or styled-components. This is useful for testing against.
|
|
51
|
-
*/ if (process.env.USE_EXPERIMENTAL_DEPENDENCIES === 'true') {
|
|
52
|
-
logger.warn('You are using experimental dependencies that may not be compatible with Strapi.');
|
|
53
|
-
return {
|
|
54
|
-
didInstall: false
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
// Hash-cache: skip the full check when package.json hasn't changed since
|
|
58
|
-
// the last successful pass. The cache lives under node_modules so it's
|
|
59
|
-
// already gitignored and disposable (a `yarn install` wipe re-runs it).
|
|
60
|
-
const currentHash = await hashPackageJson(cwd);
|
|
61
|
-
if (currentHash) {
|
|
62
|
-
const cachedHash = await readCachedHash(cwd);
|
|
63
|
-
if (cachedHash === currentHash) {
|
|
64
|
-
return {
|
|
65
|
-
didInstall: false
|
|
66
|
-
};
|
|
67
|
-
}
|
|
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;
|
|
68
44
|
}
|
|
45
|
+
}
|
|
46
|
+
const loadProjectPackageJson = async (cwd)=>{
|
|
69
47
|
const pkg = await readPkgUp({
|
|
70
48
|
cwd
|
|
71
49
|
});
|
|
72
50
|
if (!pkg) {
|
|
73
51
|
throw new Error(`Could not find package.json at path: ${cwd}`);
|
|
74
52
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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];
|
|
84
64
|
if (!declaredVersion) {
|
|
85
|
-
|
|
65
|
+
missing.push({
|
|
86
66
|
name,
|
|
87
67
|
wantedVersion: version
|
|
88
68
|
});
|
|
89
|
-
}
|
|
90
|
-
|
|
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({
|
|
91
78
|
name,
|
|
92
79
|
wantedVersion: version,
|
|
93
80
|
declaredVersion
|
|
94
81
|
});
|
|
95
82
|
}
|
|
96
|
-
return
|
|
97
|
-
},
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
const [file, ...args] = process.argv;
|
|
108
|
-
/**
|
|
109
|
-
* Re-run the same command after installation e.g. strapi build because the yarn.lock might
|
|
110
|
-
* not be the same and could break installations. It's not the best solution, but it works.
|
|
111
|
-
*/ await execa(file, args, {
|
|
112
|
-
cwd,
|
|
113
|
-
stdio: 'inherit'
|
|
114
|
-
});
|
|
115
|
-
return {
|
|
116
|
-
didInstall: true
|
|
117
|
-
};
|
|
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}`;
|
|
118
94
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (!installedVersion) {
|
|
142
|
-
/**
|
|
143
|
-
* TODO: when we know the packageManager we can advise the actual install command.
|
|
144
|
-
*/ errors.push(`The declared dependency, ${dep.name} is not installed. You should install before re-running this command`);
|
|
145
|
-
} else if (!semver.satisfies(installedVersion, dep.wantedVersion)) {
|
|
146
|
-
logger.warn([
|
|
147
|
-
`Declared version of ${dep.name} (${installedVersion}) is not compatible with the version required by Strapi (${dep.wantedVersion}).`,
|
|
148
|
-
'You may experience issues, we recommend you change this.'
|
|
149
|
-
].join(os.EOL));
|
|
150
|
-
}
|
|
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)
|
|
151
117
|
}
|
|
152
|
-
if (
|
|
153
|
-
|
|
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));
|
|
125
|
+
}
|
|
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));
|
|
154
134
|
}
|
|
155
135
|
}
|
|
156
|
-
if (
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
return {
|
|
160
|
-
didInstall: false
|
|
161
|
-
};
|
|
162
|
-
};
|
|
163
|
-
const getModule = async (name, cwd)=>{
|
|
164
|
-
const modulePackagePath = resolveFrom.silent(cwd, path.join(name, 'package.json'));
|
|
165
|
-
if (!modulePackagePath) {
|
|
166
|
-
return null;
|
|
136
|
+
if (errors.length > 0 && process.env.NODE_ENV === 'development') {
|
|
137
|
+
throw new Error(`${os.EOL}- ${errors.join(`${os.EOL}- `)}`);
|
|
167
138
|
}
|
|
168
|
-
const file = await fs.readFile(modulePackagePath, 'utf8').then((res)=>JSON.parse(res));
|
|
169
|
-
return file;
|
|
170
|
-
};
|
|
171
|
-
const getModuleVersion = async (name, cwd)=>{
|
|
172
|
-
const pkg = await getModule(name, cwd);
|
|
173
|
-
return pkg?.version || null;
|
|
174
139
|
};
|
|
175
|
-
const
|
|
140
|
+
const installAdminPeerDeps = async (missing, { cwd, logger })=>{
|
|
176
141
|
const packageManager = getPackageManager();
|
|
177
142
|
if (!packageManager) {
|
|
178
143
|
logger.error('Could not find a supported package manager, please install the dependencies manually.');
|
|
@@ -183,7 +148,7 @@ const installDependencies = async (install, { cwd, logger })=>{
|
|
|
183
148
|
cwd,
|
|
184
149
|
stdio: 'inherit'
|
|
185
150
|
};
|
|
186
|
-
const packages =
|
|
151
|
+
const packages = missing.map(({ name, wantedVersion })=>`${name}@${wantedVersion}`);
|
|
187
152
|
let result;
|
|
188
153
|
if (packageManager === 'npm') {
|
|
189
154
|
const npmArgs = [
|
|
@@ -214,6 +179,28 @@ const installDependencies = async (install, { cwd, logger })=>{
|
|
|
214
179
|
throw new Error('Package installation failed');
|
|
215
180
|
}
|
|
216
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
|
+
};
|
|
217
204
|
|
|
218
|
-
export {
|
|
205
|
+
export { ADMIN_PEER_DEPS, MissingAdminPeerDepsError, findUndeclaredAdminPeerDeps, getInstallCommandHint, getModule, hashPackageJson, installAdminPeerDeps, readCachedHash, reexecCurrentCommand, reportMissingAdminPeerDeps, validateDeclaredAdminPeerDeps, writeCachedHash };
|
|
219
206
|
//# sourceMappingURL=dependencies.mjs.map
|