contrib: Add switch-version tool
Allows for easilly switching between version; either between local or published or from published to latest published
This commit is contained in:
parent
8c02f72eee
commit
b855aa5dcb
1 changed files with 180 additions and 0 deletions
180
contrib/switch-versions.mjs
Executable file
180
contrib/switch-versions.mjs
Executable file
|
|
@ -0,0 +1,180 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Switch between local and published versions of @wizardconnect packages
|
||||
*
|
||||
* Usage:
|
||||
* node /path/to/wizardconnect/contrib/switch-versions.js [local|published]
|
||||
*
|
||||
* This script modifies package.json in the current working directory to switch
|
||||
* between local file: references and published npm versions of @wizardconnect packages.
|
||||
*/
|
||||
|
||||
import { readFileSync, writeFileSync, existsSync, readdirSync } from 'fs';
|
||||
import { resolve, dirname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
|
||||
// Get the wizardconnect root directory (one level up from contrib)
|
||||
const LIB_ROOT = resolve(__dirname, '..');
|
||||
|
||||
const PACKAGE_SCOPE = '@wizardconnect/';
|
||||
|
||||
// Dynamically discover packages from workspace configuration
|
||||
function discoverPackages() {
|
||||
const packages = {};
|
||||
|
||||
try {
|
||||
const rootPackageJsonPath = resolve(LIB_ROOT, 'package.json');
|
||||
const rootPackageJson = JSON.parse(readFileSync(rootPackageJsonPath, 'utf8'));
|
||||
|
||||
if (rootPackageJson.workspaces) {
|
||||
for (const workspace of rootPackageJson.workspaces) {
|
||||
const workspacePattern = typeof workspace === 'string' ? workspace : workspace.package;
|
||||
const baseDir = workspacePattern.split('*')[0].replace(/\/$/, '');
|
||||
const baseDirPath = resolve(LIB_ROOT, baseDir);
|
||||
|
||||
if (existsSync(baseDirPath)) {
|
||||
const entries = readdirSync(baseDirPath, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory()) {
|
||||
const workspacePath = `${baseDir}/${entry.name}`;
|
||||
const packageJsonPath = resolve(LIB_ROOT, workspacePath, 'package.json');
|
||||
|
||||
if (existsSync(packageJsonPath)) {
|
||||
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
||||
if (packageJson.name && packageJson.name.startsWith(PACKAGE_SCOPE)) {
|
||||
packages[packageJson.name] = workspacePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error: Could not read workspace configuration:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return packages;
|
||||
}
|
||||
|
||||
function getLatestPublishedVersions(packages) {
|
||||
const versions = {};
|
||||
|
||||
for (const packageName of Object.keys(packages)) {
|
||||
try {
|
||||
console.log(`Querying npm for latest version of ${packageName}...`);
|
||||
const result = execSync(`npm view ${packageName} version`, {
|
||||
encoding: 'utf8',
|
||||
stdio: ['pipe', 'pipe', 'pipe']
|
||||
});
|
||||
const latestVersion = result.trim();
|
||||
versions[packageName] = latestVersion;
|
||||
console.log(` Found latest version: ${packageName}@${latestVersion}`);
|
||||
} catch (error) {
|
||||
console.warn(` Could not get latest version for ${packageName}: ${error.message}`);
|
||||
// Fall back to local version if npm query fails
|
||||
const packagePath = packages[packageName];
|
||||
const packageJsonPath = resolve(LIB_ROOT, packagePath, 'package.json');
|
||||
if (existsSync(packageJsonPath)) {
|
||||
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
||||
versions[packageName] = packageJson.version;
|
||||
console.log(` Using local version: ${packageName}@${packageJson.version}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return versions;
|
||||
}
|
||||
|
||||
function switchDeps(deps, packages, mode, versions) {
|
||||
let changed = false;
|
||||
if (!deps) return changed;
|
||||
|
||||
for (const [packageName, localPath] of Object.entries(packages)) {
|
||||
if (!deps[packageName]) continue;
|
||||
|
||||
if (mode === 'local') {
|
||||
const absolutePath = resolve(LIB_ROOT, localPath);
|
||||
deps[packageName] = `file:${absolutePath}`;
|
||||
changed = true;
|
||||
console.log(` ${packageName} -> file:${absolutePath}`);
|
||||
} else {
|
||||
const currentValue = deps[packageName];
|
||||
const newValue = `^${versions[packageName]}`;
|
||||
if (currentValue !== newValue) {
|
||||
deps[packageName] = newValue;
|
||||
changed = true;
|
||||
console.log(` ${packageName} -> ${newValue}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const args = process.argv.slice(2);
|
||||
const mode = args[0];
|
||||
|
||||
if (!mode || !['local', 'published'].includes(mode)) {
|
||||
console.error('Usage: node switch-versions.js [local|published]');
|
||||
console.error('');
|
||||
console.error(' local - Switch to local file: references');
|
||||
console.error(' published - Switch to latest published npm versions');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const packageJsonPath = resolve(process.cwd(), 'package.json');
|
||||
if (!existsSync(packageJsonPath)) {
|
||||
console.error('Error: No package.json found in current directory');
|
||||
console.error('Please run this script from a project directory that contains package.json');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
try {
|
||||
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
|
||||
const packages = discoverPackages();
|
||||
|
||||
if (Object.keys(packages).length === 0) {
|
||||
console.error('Error: No @wizardconnect packages found in workspace');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(`Found packages: ${Object.keys(packages).join(', ')}`);
|
||||
console.log('');
|
||||
|
||||
let versions = {};
|
||||
if (mode === 'published') {
|
||||
versions = getLatestPublishedVersions(packages);
|
||||
console.log('');
|
||||
}
|
||||
|
||||
console.log(`Switching to ${mode} versions:`);
|
||||
const changed =
|
||||
switchDeps(packageJson.dependencies, packages, mode, versions) |
|
||||
switchDeps(packageJson.devDependencies, packages, mode, versions);
|
||||
|
||||
if (!changed) {
|
||||
console.log('No @wizardconnect packages found to switch');
|
||||
return;
|
||||
}
|
||||
|
||||
writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
|
||||
|
||||
console.log('');
|
||||
console.log(`Successfully switched to ${mode} versions`);
|
||||
console.log('Remember to run "npm install" to update your node_modules');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
Loading…
Add table
Reference in a new issue