Skip to content

Commit

Permalink
feat(cli): add build command (#1990)
Browse files Browse the repository at this point in the history
Co-authored-by: alvarius <alvarius@lattice.xyz>
  • Loading branch information
holic and alvrs committed Dec 1, 2023
1 parent e48fb3b commit 59d78c9
Show file tree
Hide file tree
Showing 12 changed files with 104 additions and 65 deletions.
5 changes: 5 additions & 0 deletions .changeset/ninety-lions-double.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@latticexyz/cli": minor
---

Added a `mud build` command that generates table libraries, system interfaces, and typed ABIs.
9 changes: 2 additions & 7 deletions e2e/packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,8 @@
"private": true,
"license": "MIT",
"scripts": {
"build": "pnpm run build:mud && pnpm run build:abi && pnpm run build:abi-ts",
"build:abi": "forge build",
"build:abi-ts": "mud abi-ts",
"build:mud": "mud tablegen && mud worldgen",
"clean": "pnpm run clean:abi && pnpm run clean:mud",
"clean:abi": "forge clean",
"clean:mud": "rimraf src/codegen",
"build": "mud build",
"clean": "forge clean && rimraf src/codegen",
"deploy:local": "mud deploy",
"test": "mud test",
"test:ci": "pnpm run test"
Expand Down
6 changes: 2 additions & 4 deletions examples/minimal/packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
"private": true,
"license": "MIT",
"scripts": {
"build": "pnpm run build:mud && pnpm run build:abi && pnpm run build:abi-ts",
"build:abi": "forge build",
"build:abi-ts": "mud abi-ts",
"build:mud": "rimraf src/codegen && mud tablegen && mud worldgen",
"build": "mud build",
"clean": "forge clean && rimraf src/codegen",
"deploy:local": "pnpm run build && mud deploy",
"deploy:testnet": "pnpm run build && mud deploy --profile=lattice-testnet",
"dev": "pnpm mud dev-contracts",
Expand Down
44 changes: 44 additions & 0 deletions packages/cli/src/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { existsSync, readFileSync, writeFileSync } from "node:fs";
import path from "node:path";
import { tablegen } from "@latticexyz/store/codegen";
import { worldgen } from "@latticexyz/world/node";
import { StoreConfig } from "@latticexyz/store";
import { WorldConfig } from "@latticexyz/world";
import { forge, getForgeConfig, getRemappings } from "@latticexyz/common/foundry";
import { getExistingContracts } from "./utils/getExistingContracts";
import { debug as parentDebug } from "./debug";
import { execa } from "execa";

const debug = parentDebug.extend("runDeploy");

type BuildOptions = {
foundryProfile?: string;
srcDir: string;
config: StoreConfig & WorldConfig;
};

export async function build({
config,
srcDir,
foundryProfile = process.env.FOUNDRY_PROFILE,
}: BuildOptions): Promise<void> {
const outPath = path.join(srcDir, config.codegenDirectory);
const remappings = await getRemappings(foundryProfile);
await Promise.all([tablegen(config, outPath, remappings), worldgen(config, getExistingContracts(srcDir), outPath)]);

// TODO remove when https://github.com/foundry-rs/foundry/issues/6241 is resolved
const forgeConfig = await getForgeConfig(foundryProfile);
if (forgeConfig.cache) {
const cacheFilePath = path.join(forgeConfig.cache_path, "solidity-files-cache.json");
if (existsSync(cacheFilePath)) {
debug("Unsetting cached content hash of IWorld.sol to force it to regenerate");
const solidityFilesCache = JSON.parse(readFileSync(cacheFilePath, "utf8"));
const worldInterfacePath = path.join(outPath, "world", "IWorld.sol");
solidityFilesCache["files"][worldInterfacePath]["contentHash"] = "";
writeFileSync(cacheFilePath, JSON.stringify(solidityFilesCache, null, 2));
}
}

await forge(["build"], { profile: foundryProfile });
await execa("mud", ["abi-ts"], { stdio: "inherit" });
}
36 changes: 36 additions & 0 deletions packages/cli/src/commands/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import type { CommandModule } from "yargs";
import { loadConfig } from "@latticexyz/config/node";
import { StoreConfig } from "@latticexyz/store";
import { WorldConfig } from "@latticexyz/world";

import { getSrcDirectory } from "@latticexyz/common/foundry";
import { build } from "../build";

type Options = {
configPath?: string;
profile?: string;
};

const commandModule: CommandModule<Options, Options> = {
command: "build",

describe: "Build contracts and generate MUD artifacts (table libraries, world interface, ABI)",

builder(yargs) {
return yargs.options({
configPath: { type: "string", desc: "Path to the config file" },
profile: { type: "string", desc: "The foundry profile to use" },
});
},

async handler({ configPath, profile }) {
const config = (await loadConfig(configPath)) as StoreConfig & WorldConfig;
const srcDir = await getSrcDirectory();

await build({ config, srcDir, foundryProfile: profile });

process.exit(0);
},
};

export default commandModule;
2 changes: 2 additions & 0 deletions packages/cli/src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { CommandModule } from "yargs";
import gasReport from "@latticexyz/gas-report";
import abiTs from "@latticexyz/abi-ts";

import build from "./build";
import devnode from "./devnode";
import faucet from "./faucet";
import hello from "./hello";
Expand All @@ -16,6 +17,7 @@ import devContracts from "./dev-contracts";

// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Each command has different options
export const commands: CommandModule<any, any>[] = [
build,
deploy,
devnode,
faucet,
Expand Down
37 changes: 3 additions & 34 deletions packages/cli/src/runDeploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,14 @@ import { privateKeyToAccount } from "viem/accounts";
import { loadConfig } from "@latticexyz/config/node";
import { StoreConfig } from "@latticexyz/store";
import { WorldConfig } from "@latticexyz/world";
import {
forge,
getForgeConfig,
getOutDirectory,
getRemappings,
getRpcUrl,
getSrcDirectory,
} from "@latticexyz/common/foundry";
import { getOutDirectory, getRpcUrl, getSrcDirectory } from "@latticexyz/common/foundry";
import chalk from "chalk";
import { execa } from "execa";
import { MUDError } from "@latticexyz/common/errors";
import { resolveConfig } from "./deploy/resolveConfig";
import { getChainId } from "viem/actions";
import { postDeploy } from "./utils/utils/postDeploy";
import { WorldDeploy } from "./deploy/common";
import { tablegen } from "@latticexyz/store/codegen";
import { worldgen } from "@latticexyz/world/node";
import { getExistingContracts } from "./utils/getExistingContracts";
import { debug as parentDebug } from "./debug";

const debug = parentDebug.extend("runDeploy");
import { build } from "./build";

export const deployOptions = {
configPath: { type: "string", desc: "Path to the config file" },
Expand Down Expand Up @@ -60,7 +47,6 @@ export async function runDeploy(opts: DeployOptions): Promise<WorldDeploy> {

const srcDir = opts.srcDir ?? (await getSrcDirectory(profile));
const outDir = await getOutDirectory(profile);
const remappings = await getRemappings();

const rpc = opts.rpc ?? (await getRpcUrl(profile));
console.log(
Expand All @@ -71,24 +57,7 @@ export async function runDeploy(opts: DeployOptions): Promise<WorldDeploy> {

// Run build
if (!opts.skipBuild) {
const outPath = path.join(srcDir, config.codegenDirectory);
await Promise.all([tablegen(config, outPath, remappings), worldgen(config, getExistingContracts(srcDir), outPath)]);

// TODO remove when https://github.com/foundry-rs/foundry/issues/6241 is resolved
const forgeConfig = await getForgeConfig(profile);
if (forgeConfig.cache) {
const cacheFilePath = path.join(forgeConfig.cache_path, "solidity-files-cache.json");
if (existsSync(cacheFilePath)) {
debug("Unsetting cached content hash of IWorld.sol to force it to regenerate");
const solidityFilesCache = JSON.parse(readFileSync(cacheFilePath, "utf8"));
const worldInterfacePath = path.join(outPath, "world", "IWorld.sol");
solidityFilesCache["files"][worldInterfacePath]["contentHash"] = "";
writeFileSync(cacheFilePath, JSON.stringify(solidityFilesCache, null, 2));
}
}

await forge(["build"], { profile });
await execa("mud", ["abi-ts"], { stdio: "inherit" });
await build({ config, srcDir, foundryProfile: profile });
}

const privateKey = process.env.PRIVATE_KEY as Hex;
Expand Down
6 changes: 2 additions & 4 deletions templates/phaser/packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
"private": true,
"license": "MIT",
"scripts": {
"build": "pnpm run build:mud && pnpm run build:abi && pnpm run build:abi-ts",
"build:abi": "forge build",
"build:abi-ts": "mud abi-ts",
"build:mud": "rimraf src/codegen && mud tablegen && mud worldgen",
"build": "mud build",
"clean": "forge clean && rimraf src/codegen",
"deploy:local": "pnpm run build && mud deploy",
"deploy:testnet": "pnpm run build && mud deploy --profile=lattice-testnet",
"dev": "pnpm mud dev-contracts",
Expand Down
6 changes: 2 additions & 4 deletions templates/react-ecs/packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
"private": true,
"license": "MIT",
"scripts": {
"build": "pnpm run build:mud && pnpm run build:abi && pnpm run build:abi-ts",
"build:abi": "forge build",
"build:abi-ts": "mud abi-ts",
"build:mud": "rimraf src/codegen && mud tablegen && mud worldgen",
"build": "mud build",
"clean": "forge clean && rimraf src/codegen",
"deploy:local": "pnpm run build && mud deploy",
"deploy:testnet": "pnpm run build && mud deploy --profile=lattice-testnet",
"dev": "pnpm mud dev-contracts",
Expand Down
6 changes: 2 additions & 4 deletions templates/react/packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
"private": true,
"license": "MIT",
"scripts": {
"build": "pnpm run build:mud && pnpm run build:abi && pnpm run build:abi-ts",
"build:abi": "forge build",
"build:abi-ts": "mud abi-ts",
"build:mud": "rimraf src/codegen && mud tablegen && mud worldgen",
"build": "mud build",
"clean": "forge clean && rimraf src/codegen",
"deploy:local": "pnpm run build && mud deploy",
"deploy:testnet": "pnpm run build && mud deploy --profile=lattice-testnet",
"dev": "pnpm mud dev-contracts",
Expand Down
6 changes: 2 additions & 4 deletions templates/threejs/packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
"private": true,
"license": "MIT",
"scripts": {
"build": "pnpm run build:mud && pnpm run build:abi && pnpm run build:abi-ts",
"build:abi": "forge build",
"build:abi-ts": "mud abi-ts",
"build:mud": "rimraf src/codegen && mud tablegen && mud worldgen",
"build": "mud build",
"clean": "forge clean && rimraf src/codegen",
"deploy:local": "pnpm run build && mud deploy",
"deploy:testnet": "pnpm run build && mud deploy --profile=lattice-testnet",
"dev": "pnpm mud dev-contracts",
Expand Down
6 changes: 2 additions & 4 deletions templates/vanilla/packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
"private": true,
"license": "MIT",
"scripts": {
"build": "pnpm run build:mud && pnpm run build:abi && pnpm run build:abi-ts",
"build:abi": "forge build",
"build:abi-ts": "mud abi-ts",
"build:mud": "rimraf src/codegen && mud tablegen && mud worldgen",
"build": "mud build",
"clean": "forge clean && rimraf src/codegen",
"deploy:local": "pnpm run build && mud deploy",
"deploy:testnet": "pnpm run build && mud deploy --profile=lattice-testnet",
"dev": "pnpm mud dev-contracts",
Expand Down

0 comments on commit 59d78c9

Please sign in to comment.