Skip to content

Commit

Permalink
feat(cli): remove backup/restore/force options from set-version (#1687)
Browse files Browse the repository at this point in the history
  • Loading branch information
holic authored Oct 3, 2023
1 parent 94d7f1e commit 3d0b3ed
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 60 deletions.
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),
},
});

1 comment on commit 3d0b3ed

@vercel
Copy link

@vercel vercel bot commented on 3d0b3ed Oct 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.