Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): remove backup/restore/force options from set-version #1687

Merged
merged 4 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/lucky-clocks-love.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@latticexyz/cli": major
---

Removes `.mudbackup` file handling and `--backup`, `--restore`, and `--force` options from `mud set-version` command.

To revert to a previous MUD version, use `git diff` to find the version that you changed from and want to revert to and run `pnpm mud set-version <prior-version>` again.
1 change: 1 addition & 0 deletions examples/minimal/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"test": "pnpm recursive run test"
},
"devDependencies": {
"@latticexyz/cli": "link:../../packages/cli",
"@typescript-eslint/eslint-plugin": "5.46.1",
"@typescript-eslint/parser": "5.46.1",
"concurrently": "^8.0.1",
Expand Down
3 changes: 3 additions & 0 deletions examples/minimal/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

79 changes: 19 additions & 60 deletions packages/cli/src/commands/set-version.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import chalk from "chalk";
import { existsSync, readFileSync, rmSync, writeFileSync } from "fs";
import { readFileSync, writeFileSync } from "fs";
import path from "path";
import type { CommandModule } from "yargs";
import { MUDError } from "@latticexyz/common/errors";
import { logError } from "../utils/errors";
import localPackageJson from "../../package.json" assert { type: "json" };
import glob from "glob";
import { mudPackages } from "../mudPackages";

type Options = {
backup?: boolean;
Expand All @@ -17,22 +18,13 @@ type Options = {
link?: string;
};

const BACKUP_FILE = ".mudbackup";
const MUD_PREFIX = "@latticexyz";

const commandModule: CommandModule<Options, Options> = {
command: "set-version",

describe: "Set MUD version in all package.json files and optionally backup the previously installed version",

builder(yargs) {
return yargs.options({
backup: { type: "boolean", description: `Back up the current MUD versions to "${BACKUP_FILE}"` },
force: {
type: "boolean",
description: `Backup fails if a "${BACKUP_FILE}" file is found, unless --force is provided`,
},
restore: { type: "boolean", description: `Restore the previous MUD versions from "${BACKUP_FILE}"` },
mudVersion: { alias: "v", type: "string", description: "Set MUD to the given version" },
tag: {
alias: "t",
Expand Down Expand Up @@ -117,63 +109,39 @@ async function resolveVersion(options: Options) {
}

function updatePackageJson(filePath: string, options: Options): { workspaces?: string[] } {
const { restore, force, link } = options;
let { backup, mudVersion } = options;

const backupFilePath = path.join(path.dirname(filePath), BACKUP_FILE);
const backupFileExists = existsSync(backupFilePath);

// Create a backup file for previous MUD versions by default if linking to local MUD
if (link && !backupFileExists) backup = true;

// If `backup` is true and force not set, check if a backup file already exists and throw an error if it does
if (backup && !force && backupFileExists) {
throw new MUDError(
`A backup file already exists at ${backupFilePath}.\nUse --force to overwrite it or --restore to restore it.`
);
}
const { link } = options;
let { mudVersion } = options;

const packageJson = readPackageJson(filePath);

// Load .mudbackup if `restore` is true
const backupJson = restore ? readPackageJson(backupFilePath) : undefined;
const mudPackageNames = Object.keys(mudPackages);

// Find all MUD dependencies
const mudDependencies: Record<string, string> = {};
for (const key in packageJson.dependencies) {
if (key.startsWith(MUD_PREFIX)) {
mudDependencies[key] = packageJson.dependencies[key];
for (const packageName in packageJson.dependencies) {
if (mudPackageNames.includes(packageName)) {
mudDependencies[packageName] = packageJson.dependencies[packageName];
}
}

// Find all MUD devDependencies
const mudDevDependencies: Record<string, string> = {};
for (const key in packageJson.devDependencies) {
if (key.startsWith(MUD_PREFIX)) {
mudDevDependencies[key] = packageJson.devDependencies[key];
for (const packageName in packageJson.devDependencies) {
if (mudPackageNames.includes(packageName)) {
mudDevDependencies[packageName] = packageJson.devDependencies[packageName];
}
}

// Back up the current dependencies if `backup` is true
if (backup) {
writeFileSync(
backupFilePath,
JSON.stringify({ dependencies: mudDependencies, devDependencies: mudDevDependencies }, null, 2)
);
console.log(chalk.green(`Backed up MUD dependencies from ${filePath} to ${backupFilePath}`));
}

// Update the dependencies
for (const key in packageJson.dependencies) {
if (key.startsWith(MUD_PREFIX)) {
packageJson.dependencies[key] = resolveMudVersion(key, "dependencies");
for (const packageName in packageJson.dependencies) {
if (mudPackageNames.includes(packageName)) {
packageJson.dependencies[packageName] = resolveMudVersion(packageName, "dependencies");
}
}

// Update the devDependencies
for (const key in packageJson.devDependencies) {
if (key.startsWith(MUD_PREFIX)) {
packageJson.devDependencies[key] = resolveMudVersion(key, "devDependencies");
for (const packageName in packageJson.devDependencies) {
if (mudPackageNames.includes(packageName)) {
packageJson.devDependencies[packageName] = resolveMudVersion(packageName, "devDependencies");
}
}

Expand All @@ -184,17 +152,9 @@ function updatePackageJson(filePath: string, options: Options): { workspaces?: s
logComparison(mudDependencies, packageJson.dependencies);
logComparison(mudDevDependencies, packageJson.devDependencies);

// Remove the backup file if `restore` is true and `backup` is false
// because the old backup file is no longer needed
if (restore && !backup) {
rmSync(backupFilePath);
console.log(chalk.green(`Cleaned up ${backupFilePath}`));
}

return packageJson;

function resolveMudVersion(key: string, type: "dependencies" | "devDependencies") {
if (restore && backupJson) return backupJson[type][key];
if (link) mudVersion = resolveLinkPath(filePath, link, key);
if (!mudVersion) return packageJson[type][key];
return mudVersion;
Expand Down Expand Up @@ -225,10 +185,9 @@ function logComparison(prev: Record<string, string>, curr: Record<string, string
/**
* Returns path of the package to link, given a path to a local MUD clone and a package
*/
function resolveLinkPath(packageJsonPath: string, mudLinkPath: string, pkg: string) {
const pkgName = pkg.replace(MUD_PREFIX, "");
function resolveLinkPath(packageJsonPath: string, mudLinkPath: string, packageName: string) {
const packageJsonToRootPath = path.relative(path.dirname(packageJsonPath), process.cwd());
const linkPath = path.join(packageJsonToRootPath, mudLinkPath, "packages", pkgName);
const linkPath = path.join(packageJsonToRootPath, mudLinkPath, mudPackages[packageName].localPath);
return "link:" + linkPath;
}

Expand Down
1 change: 1 addition & 0 deletions packages/cli/src/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type MudPackages = Record<string, { localPath: string }>;
24 changes: 24 additions & 0 deletions packages/cli/src/mudPackages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ZodError, z } from "zod";
import { MudPackages } from "./common";

const envSchema = z.object({
MUD_PACKAGES: z.string().transform((value) => JSON.parse(value) as MudPackages),
});

function parseEnv(): z.infer<typeof envSchema> {
try {
return envSchema.parse({
// tsup replaces the env vars with their values at compile time
MUD_PACKAGES: process.env.MUD_PACKAGES,
});
} catch (error) {
if (error instanceof ZodError) {
const { _errors, ...invalidEnvVars } = error.format();
console.error(`\nMissing or invalid environment variables:\n\n ${Object.keys(invalidEnvVars).join("\n ")}\n`);
process.exit(1);
}
throw error;
}
}

export const mudPackages = parseEnv().MUD_PACKAGES;
20 changes: 20 additions & 0 deletions packages/cli/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
import { defineConfig } from "tsup";
import glob from "glob";
import { readFileSync } from "node:fs";
import path from "node:path";
import { MudPackages } from "./src/common";

const mudWorkspace = path.normalize(`${__dirname}/../..`);

const mudPackages: MudPackages = Object.fromEntries(
glob
.sync(path.join(mudWorkspace, `packages/*/package.json`))
.map((filename) => [
path.relative(mudWorkspace, path.dirname(filename)),
JSON.parse(readFileSync(filename, "utf8")),
])
.filter(([, packageJson]) => !packageJson.private)
.map(([localPath, packageJson]) => [packageJson.name, { localPath }])
);

export default defineConfig({
entry: ["src/index.ts", "src/mud.ts"],
Expand All @@ -8,4 +25,7 @@ export default defineConfig({
sourcemap: true,
clean: true,
minify: true,
env: {
MUD_PACKAGES: JSON.stringify(mudPackages),
},
});