mirror of
https://github.com/strapi/strapi.git
synced 2026-05-03 16:22:30 +00:00
131 lines
4.6 KiB
JavaScript
131 lines
4.6 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Ensures all workspace package.json files that have a "version" field use the
|
|
* same version as the canonical source (@strapi/strapi). Run from repo root.
|
|
*
|
|
* Usage:
|
|
* node scripts/check-package-versions.mjs # check only, exit 1 if mismatch
|
|
* node scripts/check-package-versions.mjs --fix # write canonical version to mismatched packages
|
|
* node scripts/check-package-versions.mjs --fix --prompt # prompt for each package before fixing
|
|
*/
|
|
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
import readline from 'readline';
|
|
import { fileURLToPath } from 'url';
|
|
import { globSync } from 'glob';
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
|
|
function ask(question) {
|
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
return new Promise((resolve) => {
|
|
rl.question(question, (answer) => {
|
|
rl.close();
|
|
resolve((answer || '').trim().toLowerCase());
|
|
});
|
|
});
|
|
}
|
|
|
|
const ROOT = path.resolve(__dirname, '..');
|
|
const CANONICAL_PACKAGE = path.join(ROOT, 'packages/core/strapi/package.json');
|
|
|
|
// Same scope as syncpack: root + all package.json under repo (exclude node_modules)
|
|
function findPackageJsonFiles() {
|
|
const rootPkg = path.join(ROOT, 'package.json');
|
|
const all = globSync('**/package.json', {
|
|
cwd: ROOT,
|
|
absolute: true,
|
|
ignore: ['**/node_modules/**'],
|
|
});
|
|
const set = new Set(all);
|
|
set.add(rootPkg);
|
|
return [...set];
|
|
}
|
|
|
|
function getCanonicalVersion() {
|
|
const data = JSON.parse(fs.readFileSync(CANONICAL_PACKAGE, 'utf8'));
|
|
if (!data.version) {
|
|
throw new Error(`${CANONICAL_PACKAGE} has no "version" field`);
|
|
}
|
|
return data.version;
|
|
}
|
|
|
|
// Only enforce alignment for packages that share the same major as canonical (e.g. 5.x.x).
|
|
// Skip examples/test-apps/docs that use 0.0.0 or 0.1.0.
|
|
// NOTE: yarn catalog references ("catalog:", "catalog:default", …) only appear in dependency
|
|
// fields — never in the "version" field — so they are invisible to this script and need no
|
|
// special handling here. Version consistency of catalog-referenced packages is instead
|
|
// enforced by .syncpackrc.json (see the "Yarn catalog references" version group).
|
|
function shouldEnforceVersion(currentVersion, canonicalVersion) {
|
|
// Defensive guard: a version field that starts with "catalog:" is not a semver string and
|
|
// should never be enforced. In practice this cannot happen, but we guard anyway.
|
|
if (currentVersion.startsWith('catalog:') === true) return false;
|
|
const canonicalMajor = canonicalVersion.split('.')[0];
|
|
const currentMajor = currentVersion.split('.')[0];
|
|
return currentMajor === canonicalMajor;
|
|
}
|
|
|
|
async function main() {
|
|
const hasFixArg = process.argv.includes('--fix');
|
|
const hasPromptArg = process.argv.includes('--prompt');
|
|
const canonicalVersion = getCanonicalVersion();
|
|
const files = findPackageJsonFiles();
|
|
const mismatches = [];
|
|
|
|
for (const file of files) {
|
|
const rel = path.relative(ROOT, file);
|
|
const content = fs.readFileSync(file, 'utf8');
|
|
let data;
|
|
try {
|
|
data = JSON.parse(content);
|
|
} catch {
|
|
continue;
|
|
}
|
|
if (data.version === undefined) continue;
|
|
if (data.version === canonicalVersion) continue;
|
|
if (!shouldEnforceVersion(data.version, canonicalVersion)) continue;
|
|
mismatches.push({ file, rel, current: data.version });
|
|
}
|
|
|
|
if (mismatches.length === 0) {
|
|
console.log(`All package versions are aligned at ${canonicalVersion}.`);
|
|
process.exit(0);
|
|
return;
|
|
}
|
|
|
|
if (hasFixArg) {
|
|
let fixed = 0;
|
|
for (const { file, rel, current } of mismatches) {
|
|
if (hasPromptArg) {
|
|
const answer = await ask(`${rel}: ${current} → ${canonicalVersion}? (y/n) `);
|
|
if (answer !== 'y' && answer !== 'yes') continue;
|
|
}
|
|
const content = fs.readFileSync(file, 'utf8');
|
|
const updated = content.replace(/("version"\s*:\s*)"[^"]*"/, `$1"${canonicalVersion}"`);
|
|
if (updated === content) {
|
|
console.error(`Could not update version in ${rel}`);
|
|
process.exit(1);
|
|
}
|
|
fs.writeFileSync(file, updated, 'utf8');
|
|
console.log(`${rel}: ${current} → ${canonicalVersion}`);
|
|
fixed += 1;
|
|
}
|
|
console.log(`Updated ${fixed} package(s) to ${canonicalVersion}.`);
|
|
process.exit(0);
|
|
return;
|
|
}
|
|
|
|
console.error(
|
|
`Package version mismatch (canonical: ${canonicalVersion} from packages/core/strapi/package.json):`
|
|
);
|
|
for (const { rel, current } of mismatches) {
|
|
console.error(` ${rel}: ${current} → ${canonicalVersion}`);
|
|
}
|
|
console.error(`Run: node scripts/check-package-versions.mjs --fix [--prompt]`);
|
|
process.exit(1);
|
|
}
|
|
|
|
main();
|