@latticexyz/cli 2.0.0-next.10 → 2.0.0-next.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mud.js CHANGED
@@ -1,16 +1,20 @@
1
1
  #!/usr/bin/env node
2
- import{a as S,b as $,c as D}from"./chunk-TW3YGZ4D.js";import So from"yargs";import{hideBin as Oo}from"yargs/helpers";import xo from"@latticexyz/gas-report";import Mo from"@latticexyz/abi-ts";import{rmSync as de}from"fs";import{homedir as le}from"os";import pe from"path";import{execa as me}from"execa";var fe={command:"devnode",describe:"Start a local Ethereum node for development",builder(e){return e.options({blocktime:{type:"number",default:1,decs:"Interval in which new blocks are produced"}})},async handler({blocktime:e}){console.log("Clearing devnode history");let o=le();de(pe.join(o,".foundry","anvil","tmp"),{recursive:!0,force:!0});let t=["-b",String(e),"--block-base-fee-per-gas","0"];console.log(`Running: anvil ${t.join(" ")}`);let r=me("anvil",t,{stdio:["inherit","inherit","inherit"]});process.on("SIGINT",()=>{console.log(`
3
- gracefully shutting down from SIGINT (Crtl-C)`),r.kill(),process.exit()}),await r}},W=fe;import{FaucetServiceDefinition as ge}from"@latticexyz/services/faucet";import{createChannel as ue,createClient as ye}from"nice-grpc-web";import A from"chalk";import{NodeHttpTransport as he}from"@improbable-eng/grpc-web-node-http-transport";function be(e){return ye(ge,ue(e,he()))}var we={command:"faucet",describe:"Interact with a MUD faucet",builder(e){return e.options({dripDev:{type:"boolean",desc:"Request a drip from the dev endpoint (requires faucet to have dev mode enabled)",default:!0},faucetUrl:{type:"string",desc:"URL of the MUD faucet",default:"https://faucet.testnet-mud-services.linfra.xyz"},address:{type:"string",desc:"Ethereum address to fund",required:!0}})},async handler({dripDev:e,faucetUrl:o,address:t}){let r=be(o);e&&(console.log(A.yellow("Dripping to",t)),await r.dripDev({address:t}),console.log(A.yellow("Success"))),process.exit(0)}},E=we;var ve={command:"hello <name>",describe:"Greet <name> with Hello",builder(e){return e.options({upper:{type:"boolean"}}).positional("name",{type:"string",demandOption:!0})},handler({name:e}){let o=`Gm, ${e}!`;console.log(o),process.exit(0)}},I=ve;import De from"path";import{loadConfig as Ce}from"@latticexyz/config/node";import{tablegen as ke}from"@latticexyz/store/codegen";import{getRemappings as xe,getSrcDirectory as Me}from"@latticexyz/common/foundry";var Se={command:"tablegen",describe:"Autogenerate MUD Store table libraries based on the config file",builder(e){return e.options({configPath:{type:"string",desc:"Path to the config file"}})},async handler({configPath:e}){let o=await Ce(e),t=await Me(),r=await xe();await ke(o,De.join(t,o.codegenDirectory),r),process.exit(0)}},F=Se;import C from"chalk";import{ZodError as Oe}from"zod";import{fromZodError as Ue,ValidationError as Re}from"zod-validation-error";import{NotInsideProjectError as je}from"@latticexyz/config";import{MUDError as Pe}from"@latticexyz/common/errors";function u(e){if(e instanceof Re)console.log(C.redBright(e.message));else if(e instanceof Oe){let o=Ue(e,{prefixSeparator:`
2
+ import{a as k,b as R,c as y}from"./chunk-TW3YGZ4D.js";import Oo from"yargs";import{hideBin as Po}from"yargs/helpers";import Mo from"@latticexyz/gas-report";import So from"@latticexyz/abi-ts";import{rmSync as ae}from"fs";import{homedir as ce}from"os";import de from"path";import{execa as le}from"execa";var pe={command:"devnode",describe:"Start a local Ethereum node for development",builder(e){return e.options({blocktime:{type:"number",default:1,decs:"Interval in which new blocks are produced"}})},async handler({blocktime:e}){console.log("Clearing devnode history");let o=ce();ae(de.join(o,".foundry","anvil","tmp"),{recursive:!0,force:!0});let t=["-b",String(e),"--block-base-fee-per-gas","0"];console.log(`Running: anvil ${t.join(" ")}`);let n=le("anvil",t,{stdio:["inherit","inherit","inherit"]});process.on("SIGINT",()=>{console.log(`
3
+ gracefully shutting down from SIGINT (Crtl-C)`),n.kill(),process.exit()}),await n}},A=pe;import{FaucetServiceDefinition as me}from"@latticexyz/services/faucet";import{createChannel as fe,createClient as ge}from"nice-grpc-web";import E from"chalk";import{NodeHttpTransport as ue}from"@improbable-eng/grpc-web-node-http-transport";function ye(e){return ge(me,fe(e,ue()))}var he={command:"faucet",describe:"Interact with a MUD faucet",builder(e){return e.options({dripDev:{type:"boolean",desc:"Request a drip from the dev endpoint (requires faucet to have dev mode enabled)",default:!0},faucetUrl:{type:"string",desc:"URL of the MUD faucet",default:"https://faucet.testnet-mud-services.linfra.xyz"},address:{type:"string",desc:"Ethereum address to fund",required:!0}})},async handler({dripDev:e,faucetUrl:o,address:t}){let n=ye(o);e&&(console.log(E.yellow("Dripping to",t)),await n.dripDev({address:t}),console.log(E.yellow("Success"))),process.exit(0)}},W=he;var be={command:"hello <name>",describe:"Greet <name> with Hello",builder(e){return e.options({upper:{type:"boolean"}}).positional("name",{type:"string",demandOption:!0})},handler({name:e}){let o=`Gm, ${e}!`;console.log(o),process.exit(0)}},$=be;import we from"path";import{loadConfig as ve}from"@latticexyz/config/node";import{tablegen as De}from"@latticexyz/store/codegen";import{getRemappings as Ce,getSrcDirectory as ke}from"@latticexyz/common/foundry";var xe={command:"tablegen",describe:"Autogenerate MUD Store table libraries based on the config file",builder(e){return e.options({configPath:{type:"string",desc:"Path to the config file"}})},async handler({configPath:e}){let o=await ve(e),t=await ke(),n=await Ce();await De(o,we.join(t,o.codegenDirectory),n),process.exit(0)}},I=xe;import w from"chalk";import{ZodError as Me}from"zod";import{fromZodError as Se,ValidationError as Oe}from"zod-validation-error";import{NotInsideProjectError as Pe}from"@latticexyz/config";import{MUDError as je}from"@latticexyz/common/errors";function f(e){if(e instanceof Oe)console.log(w.redBright(e.message));else if(e instanceof Me){let o=Se(e,{prefixSeparator:`
4
4
  - `,issueSeparator:`
5
- - `});console.log(C.redBright(o.message))}else e instanceof je?(console.log(C.red(e.message)),console.log(""),console.log(C.blue("To learn more about MUD's configuration, please go to https://mud.dev/packages/cli/"))):e instanceof Pe?console.log(C.red(e)):console.log(e)}var R={configPath:{type:"string",desc:"Path to the config file"},clean:{type:"boolean",desc:"Remove the build forge artifacts and cache directories before building"},printConfig:{type:"boolean",desc:"Print the resolved config"},profile:{type:"string",desc:"The foundry profile to use"},debug:{type:"boolean",desc:"Print debug logs, like full error messages"},priorityFeeMultiplier:{type:"number",desc:"Multiply the estimated priority fee by the provided factor",default:1},saveDeployment:{type:"boolean",desc:"Save the deployment info to a file",default:!0},rpc:{type:"string",desc:"The RPC URL to use. Defaults to the RPC url from the local foundry.toml"},worldAddress:{type:"string",desc:"Deploy to an existing World at the given address"},srcDir:{type:"string",desc:"Source directory. Defaults to foundry src directory."},disableTxWait:{type:"boolean",desc:"Disable waiting for transactions to be confirmed.",default:!1},pollInterval:{type:"number",desc:"Interval in miliseconds to use to poll for transaction receipts / block inclusion",default:1e3},skipBuild:{type:"boolean",desc:"Skip rebuilding the contracts before deploying"}},$e={command:"deploy",describe:"Deploy MUD contracts",builder(e){return e.options(R)},async handler(e){try{await D(e)}catch(o){u(o),process.exit(1)}process.exit(0)}},z=$e;import{loadConfig as We}from"@latticexyz/config/node";import{worldgen as Ae}from"@latticexyz/world/node";import{getSrcDirectory as Ee}from"@latticexyz/common/foundry";import T from"path";import{rmSync as Ie}from"fs";var Fe={command:"worldgen",describe:"Autogenerate interfaces for Systems and World based on existing contracts and the config file",builder(e){return e.options({configPath:{type:"string",desc:"Path to the config file"},clean:{type:"boolean",desc:"Clear the worldgen directory before generating new interfaces (defaults to true)",default:!0}})},async handler(e){await j(e),process.exit(0)}};async function j(e){let o=e.srcDir??await Ee(),t=S(o),r=e.config??await We(e.configPath),i=T.join(o,r.codegenDirectory);e.clean&&Ie(T.join(i,r.worldgenDirectory),{recursive:!0,force:!0}),await Ae(r,t,i)}var J=Fe;import h from"chalk";import{existsSync as Te,readFileSync as Je,rmSync as He,writeFileSync as N}from"fs";import x from"path";import{MUDError as b}from"@latticexyz/common/errors";var H={name:"@latticexyz/cli",version:"2.0.0-next.10",description:"Command line interface for mud",repository:{type:"git",url:"https://github.com/latticexyz/mud.git",directory:"packages/cli"},license:"MIT",type:"module",exports:{".":"./dist/index.js"},types:"src/index.ts",bin:{mud:"./dist/mud.js"},scripts:{build:"pnpm run build:js && pnpm run build:test-tables","build:js":"tsup && chmod +x ./dist/mud.js","build:test-tables":"tsx ./scripts/generate-test-tables.ts",clean:"pnpm run clean:js && pnpm run clean:test-tables","clean:js":"rimraf dist","clean:test-tables":"rimraf src/codegen",dev:"tsup --watch",lint:"eslint . --ext .ts",prepare:"mkdir -p ./dist && touch ./dist/mud.js",test:"tsc --noEmit && forge test","test:ci":"pnpm run test"},dependencies:{"@ethersproject/abi":"^5.7.0","@ethersproject/providers":"^5.7.2","@improbable-eng/grpc-web":"^0.15.0","@improbable-eng/grpc-web-node-http-transport":"^0.15.0","@latticexyz/abi-ts":"workspace:*","@latticexyz/common":"workspace:*","@latticexyz/config":"workspace:*","@latticexyz/gas-report":"workspace:*","@latticexyz/protocol-parser":"workspace:*","@latticexyz/schema-type":"workspace:*","@latticexyz/services":"workspace:*","@latticexyz/store":"workspace:*","@latticexyz/utils":"workspace:*","@latticexyz/world":"workspace:*","@latticexyz/world-modules":"workspace:*",chalk:"^5.0.1",chokidar:"^3.5.3",dotenv:"^16.0.3",ejs:"^3.1.8",ethers:"^5.7.2",execa:"^7.0.0",glob:"^8.0.3","nice-grpc-web":"^2.0.1",openurl:"^1.1.1",path:"^0.12.7","throttle-debounce":"^5.0.0",typescript:"5.1.6",viem:"1.6.0",yargs:"^17.7.1",zod:"^3.21.4","zod-validation-error":"^1.3.0"},devDependencies:{"@types/ejs":"^3.1.1","@types/glob":"^7.2.0","@types/node":"^18.15.11","@types/openurl":"^1.0.0","@types/throttle-debounce":"^5.0.0","@types/yargs":"^17.0.10","ds-test":"https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0","forge-std":"https://github.com/foundry-rs/forge-std.git#74cfb77e308dd188d2f58864aaf44963ae6b88b1",tsup:"^6.7.0",tsx:"^3.12.6",vitest:"0.31.4"},gitHead:"914a1e0ae4a573d685841ca2ea921435057deb8f"};import Ne from"glob";var O=".mudbackup",k="@latticexyz",Ve={command:"set-version",describe:"Set MUD version in all package.json files and optionally backup the previously installed version",builder(e){return e.options({backup:{type:"boolean",description:`Back up the current MUD versions to "${O}"`},force:{type:"boolean",description:`Backup fails if a "${O}" file is found, unless --force is provided`},restore:{type:"boolean",description:`Restore the previous MUD versions from "${O}"`},mudVersion:{alias:"v",type:"string",description:"Set MUD to the given version"},tag:{alias:"t",type:"string",description:"Set MUD to the latest version with the given tag from npm"},commit:{alias:"c",type:"string",description:"Set MUD to the version based on a given git commit hash from npm"},link:{alias:"l",type:"string",description:"Relative path to the local MUD root directory to link"}})},async handler(e){try{let o=["mudVersion","link","tag","commit","restore"],t=o.reduce((i,d)=>e[d]?i+1:i,0);if(t===0)throw new b(`You need to provide one these options: ${o.join(", ")}`);if(t>1)throw new b(`These options are mutually exclusive: ${o.join(", ")}`);e.mudVersion=await Be(e);let r=Ne.sync("**/package.json").filter(i=>!i.includes("node_modules"));for(let i of r)Le(i,e)}catch(o){u(o)}finally{process.exit(0)}}};async function Be(e){e.mudVersion==="canary"&&(e.tag="main");let o;try{console.log(h.blue("Fetching available versions")),o=await(await fetch(`https://registry.npmjs.org/${H.name}`)).json()}catch{throw new b("Could not fetch available MUD versions")}if(e.tag){let t=o["dist-tags"][e.tag];if(!t)throw new b(`Could not find npm version with tag "${e.tag}"`);return console.log(h.green(`Latest version with tag ${e.tag}: ${t}`)),t}if(e.commit){let t=e.commit.substring(0,8),r=Object.keys(o.versions).find(i=>i.includes(t));if(!r)throw new b(`Could not find npm version based on commit "${e.commit}"`);return console.log(h.green(`Version from commit ${e.commit}: ${r}`)),r}return e.mudVersion}function Le(e,o){let{restore:t,force:r,link:i}=o,{backup:d,mudVersion:l}=o,s=x.join(x.dirname(e),O),m=Te(s);if(i&&!m&&(d=!0),d&&!r&&m)throw new b(`A backup file already exists at ${s}.
6
- Use --force to overwrite it or --restore to restore it.`);let a=V(e),y=t?V(s):void 0,p={};for(let n in a.dependencies)n.startsWith(k)&&(p[n]=a.dependencies[n]);let f={};for(let n in a.devDependencies)n.startsWith(k)&&(f[n]=a.devDependencies[n]);d&&(N(s,JSON.stringify({dependencies:p,devDependencies:f},null,2)),console.log(h.green(`Backed up MUD dependencies from ${e} to ${s}`)));for(let n in a.dependencies)n.startsWith(k)&&(a.dependencies[n]=w(n,"dependencies"));for(let n in a.devDependencies)n.startsWith(k)&&(a.devDependencies[n]=w(n,"devDependencies"));return N(e,JSON.stringify(a,null,2)+`
7
- `),console.log(`Updating ${e}`),B(p,a.dependencies),B(f,a.devDependencies),t&&!d&&(He(s),console.log(h.green(`Cleaned up ${s}`))),a;function w(n,c){return t&&y?y[c][n]:(i&&(l=_e(e,i,n)),l||a[c][n])}}function V(e){try{let o=Je(e,"utf8");return JSON.parse(o)}catch{throw new b("Could not read JSON at "+e)}}function B(e,o){for(let t in e)e[t]!==o[t]&&console.log(`${t}: ${h.red(e[t])} -> ${h.green(o[t])}`)}function _e(e,o,t){let r=t.replace(k,""),i=x.relative(x.dirname(e),process.cwd());return"link:"+x.join(i,o,"packages",r)}var L=Ve;import{anvil as qe,forge as Ge,getRpcUrl as Ye}from"@latticexyz/common/foundry";import Ze from"chalk";import{rmSync as _,writeFileSync as Ke}from"fs";var P=".mudtest",Xe={command:"test",describe:"Run tests in MUD contracts",builder(e){return e.options({...R,port:{type:"number",description:"Port to run internal node for fork testing on",default:4242},worldAddress:{type:"string",description:"Address of an existing world contract. If provided, deployment is skipped and the RPC provided in the foundry.toml is used for fork testing."},forgeOptions:{type:"string",description:"Options to pass to forge test"}})},async handler(e){if(!e.worldAddress){let i=["--block-base-fee-per-gas","0","--port",String(e.port)];qe(i)}let o=e.worldAddress?await Ye(e.profile):`http://127.0.0.1:${e.port}`,t=e.worldAddress??(await D({...e,saveDeployment:!1,rpc:o})).worldAddress;console.log(Ze.blue("World address",t)),Ke(P,t);let r=e.forgeOptions?.replaceAll("\\","").split(" ")??[];try{let i=await Ge(["test","--fork-url",o,...r],{profile:e.profile});console.log(i)}catch(i){console.error(i),_(P),process.exit(1)}_(P),process.exit(0)}},q=Xe;import{existsSync as Qe,readFileSync as eo}from"fs";import{ethers as G}from"ethers";import{loadConfig as oo}from"@latticexyz/config/node";import{MUDError as Y}from"@latticexyz/common/errors";import{cast as to,getRpcUrl as ro,getSrcDirectory as no}from"@latticexyz/common/foundry";import{resolveWorldConfig as io}from"@latticexyz/world";import so from"@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json"assert{type:"json"};import Z from"@latticexyz/world/mud.config.js";import{resourceIdToHex as X}from"@latticexyz/common";var K=X({type:"system",namespace:Z.namespace,name:Z.tables.Systems.name}),ao={command:"trace",describe:"Display the trace of a transaction",builder(e){return e.options({tx:{type:"string",required:!0,description:"Transaction hash to replay"},worldAddress:{type:"string",description:"World contract address. Defaults to the value from worlds.json, based on rpc's chainId"},configPath:{type:"string",description:"Path to the config file"},profile:{type:"string",description:"The foundry profile to use"},srcDir:{type:"string",description:"Source directory. Defaults to foundry src directory."},rpc:{type:"string",description:"json rpc endpoint. Defaults to foundry's configured eth_rpc_url"}})},async handler(e){e.profile??=process.env.FOUNDRY_PROFILE;let{profile:o}=e;e.srcDir??=await no(o),e.rpc??=await ro(o);let{tx:t,configPath:r,srcDir:i,rpc:d}=e,l=S(i),s=await oo(r),m=io(s,l.map(({basename:g})=>g)),a=e.worldAddress??await co(s.worldsFile,d),y=new G.providers.StaticJsonRpcProvider(d),p=new G.Contract(a,so,y),f=s.namespace,w=Object.values(m.systems).map(({name:g})=>g),n=await p.getFieldLayout(K),c=[];for(let g of w){let U=X({type:"system",namespace:f,name:g}),ce=await p.getField(K,[U],0,n);c.push({name:g,address:ce})}let v=await to(["run","--label",`${a}:World`,...c.map(({name:g,address:U})=>["--label",`${U}:${g}`]).flat(),`${t}`]);console.log(v),process.exit(0)}},Q=ao;async function co(e,o){if(Qe(e)){let t=await $(o),r=JSON.parse(eo(e,"utf-8"));if(!r[t])throw new Y(`chainId ${t} is missing in worldsFile "${e}"`);return r[t].address}else throw new Y("worldAddress is not specified and worldsFile is missing")}import{anvil as po,forge as oe,getRemappings as mo,getRpcUrl as fo,getScriptDirectory as go,getSrcDirectory as uo}from"@latticexyz/common/foundry";import M from"chalk";import yo from"chokidar";import{loadConfig as te,resolveConfigPath as ho}from"@latticexyz/config/node";import{tablegen as bo}from"@latticexyz/store/codegen";import re from"path";import{debounce as wo}from"throttle-debounce";import{homedir as vo}from"os";import{rmSync as Do}from"fs";import{execa as Co}from"execa";import lo from"chalk";function ee(){console.log(lo.yellow(`
5
+ - `});console.log(w.redBright(o.message))}else e instanceof Pe?(console.log(w.red(e.message)),console.log(""),console.log(w.blue("To learn more about MUD's configuration, please go to https://mud.dev/packages/cli/"))):e instanceof je?console.log(w.red(e)):console.log(e)}var S={configPath:{type:"string",desc:"Path to the config file"},clean:{type:"boolean",desc:"Remove the build forge artifacts and cache directories before building"},printConfig:{type:"boolean",desc:"Print the resolved config"},profile:{type:"string",desc:"The foundry profile to use"},debug:{type:"boolean",desc:"Print debug logs, like full error messages"},priorityFeeMultiplier:{type:"number",desc:"Multiply the estimated priority fee by the provided factor",default:1},saveDeployment:{type:"boolean",desc:"Save the deployment info to a file",default:!0},rpc:{type:"string",desc:"The RPC URL to use. Defaults to the RPC url from the local foundry.toml"},worldAddress:{type:"string",desc:"Deploy to an existing World at the given address"},srcDir:{type:"string",desc:"Source directory. Defaults to foundry src directory."},disableTxWait:{type:"boolean",desc:"Disable waiting for transactions to be confirmed.",default:!1},pollInterval:{type:"number",desc:"Interval in miliseconds to use to poll for transaction receipts / block inclusion",default:1e3},skipBuild:{type:"boolean",desc:"Skip rebuilding the contracts before deploying"}},Ue={command:"deploy",describe:"Deploy MUD contracts",builder(e){return e.options(S)},async handler(e){try{await y(e)}catch(o){f(o),process.exit(1)}process.exit(0)}},z=Ue;import{loadConfig as Re}from"@latticexyz/config/node";import{worldgen as Ae}from"@latticexyz/world/node";import{getSrcDirectory as Ee}from"@latticexyz/common/foundry";import T from"path";import{rmSync as We}from"fs";var $e={command:"worldgen",describe:"Autogenerate interfaces for Systems and World based on existing contracts and the config file",builder(e){return e.options({configPath:{type:"string",desc:"Path to the config file"},clean:{type:"boolean",desc:"Clear the worldgen directory before generating new interfaces (defaults to true)",default:!0}})},async handler(e){await O(e),process.exit(0)}};async function O(e){let o=e.srcDir??await Ee(),t=k(o),n=e.config??await Re(e.configPath),r=T.join(o,n.codegenDirectory);e.clean&&We(T.join(r,n.worldgenDirectory),{recursive:!0,force:!0}),await Ae(n,t,r)}var F=$e;import v from"chalk";import{readFileSync as Ne,writeFileSync as _e}from"fs";import j from"path";import{MUDError as h}from"@latticexyz/common/errors";var N={name:"@latticexyz/cli",version:"2.0.0-next.11",description:"Command line interface for mud",repository:{type:"git",url:"https://github.com/latticexyz/mud.git",directory:"packages/cli"},license:"MIT",type:"module",exports:{".":"./dist/index.js"},types:"src/index.ts",bin:{mud:"./dist/mud.js"},scripts:{build:"pnpm run build:js && pnpm run build:test-tables","build:js":"tsup && chmod +x ./dist/mud.js","build:test-tables":"tsx ./scripts/generate-test-tables.ts",clean:"pnpm run clean:js && pnpm run clean:test-tables","clean:js":"rimraf dist","clean:test-tables":"rimraf src/codegen",dev:"tsup --watch",lint:"eslint . --ext .ts",prepare:"mkdir -p ./dist && touch ./dist/mud.js",test:"tsc --noEmit && forge test","test:ci":"pnpm run test"},dependencies:{"@ethersproject/abi":"^5.7.0","@ethersproject/providers":"^5.7.2","@improbable-eng/grpc-web":"^0.15.0","@improbable-eng/grpc-web-node-http-transport":"^0.15.0","@latticexyz/abi-ts":"workspace:*","@latticexyz/common":"workspace:*","@latticexyz/config":"workspace:*","@latticexyz/gas-report":"workspace:*","@latticexyz/protocol-parser":"workspace:*","@latticexyz/schema-type":"workspace:*","@latticexyz/services":"workspace:*","@latticexyz/store":"workspace:*","@latticexyz/utils":"workspace:*","@latticexyz/world":"workspace:*","@latticexyz/world-modules":"workspace:*",chalk:"^5.0.1",chokidar:"^3.5.3",dotenv:"^16.0.3",ejs:"^3.1.8",ethers:"^5.7.2",execa:"^7.0.0",glob:"^8.0.3","nice-grpc-web":"^2.0.1",openurl:"^1.1.1",path:"^0.12.7","throttle-debounce":"^5.0.0",typescript:"5.1.6",viem:"1.14.0",yargs:"^17.7.1",zod:"^3.21.4","zod-validation-error":"^1.3.0"},devDependencies:{"@types/ejs":"^3.1.1","@types/glob":"^7.2.0","@types/node":"^18.15.11","@types/openurl":"^1.0.0","@types/throttle-debounce":"^5.0.0","@types/yargs":"^17.0.10","ds-test":"https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0","forge-std":"https://github.com/foundry-rs/forge-std.git#74cfb77e308dd188d2f58864aaf44963ae6b88b1",tsup:"^6.7.0",tsx:"^3.12.6",vitest:"0.31.4"},gitHead:"914a1e0ae4a573d685841ca2ea921435057deb8f"};import Je from"glob";import{ZodError as ze,z as _}from"zod";var Te=_.object({MUD_PACKAGES:_.string().transform(e=>JSON.parse(e))});function Fe(){try{return Te.parse({MUD_PACKAGES:'{"@latticexyz/abi-ts":{"localPath":"packages/abi-ts"},"@latticexyz/block-logs-stream":{"localPath":"packages/block-logs-stream"},"@latticexyz/cli":{"localPath":"packages/cli"},"@latticexyz/common":{"localPath":"packages/common"},"@latticexyz/config":{"localPath":"packages/config"},"create-mud":{"localPath":"packages/create-mud"},"@latticexyz/dev-tools":{"localPath":"packages/dev-tools"},"@latticexyz/faucet":{"localPath":"packages/faucet"},"@latticexyz/gas-report":{"localPath":"packages/gas-report"},"@latticexyz/noise":{"localPath":"packages/noise"},"@latticexyz/phaserx":{"localPath":"packages/phaserx"},"@latticexyz/protocol-parser":{"localPath":"packages/protocol-parser"},"@latticexyz/react":{"localPath":"packages/react"},"@latticexyz/recs":{"localPath":"packages/recs"},"@latticexyz/schema-type":{"localPath":"packages/schema-type"},"@latticexyz/services":{"localPath":"packages/services"},"solhint-config-mud":{"localPath":"packages/solhint-config-mud"},"solhint-plugin-mud":{"localPath":"packages/solhint-plugin-mud"},"@latticexyz/store-indexer":{"localPath":"packages/store-indexer"},"@latticexyz/store-sync":{"localPath":"packages/store-sync"},"@latticexyz/store":{"localPath":"packages/store"},"@latticexyz/utils":{"localPath":"packages/utils"},"@latticexyz/world-modules":{"localPath":"packages/world-modules"},"@latticexyz/world":{"localPath":"packages/world"}}'})}catch(e){if(e instanceof ze){let{_errors:o,...t}=e.format();console.error(`
6
+ Missing or invalid environment variables:
7
+
8
+ ${Object.keys(t).join(`
9
+ `)}
10
+ `),process.exit(1)}throw e}}var P=Fe().MUD_PACKAGES;var Ve={command:"set-version",describe:"Set MUD version in all package.json files and optionally backup the previously installed version",builder(e){return e.options({mudVersion:{alias:"v",type:"string",description:"Set MUD to the given version"},tag:{alias:"t",type:"string",description:"Set MUD to the latest version with the given tag from npm"},commit:{alias:"c",type:"string",description:"Set MUD to the version based on a given git commit hash from npm"},link:{alias:"l",type:"string",description:"Relative path to the local MUD root directory to link"}})},async handler(e){try{let o=["mudVersion","link","tag","commit","restore"],t=o.reduce((r,c)=>e[c]?r+1:r,0);if(t===0)throw new h(`You need to provide one these options: ${o.join(", ")}`);if(t>1)throw new h(`These options are mutually exclusive: ${o.join(", ")}`);e.mudVersion=await He(e);let n=Je.sync("**/package.json").filter(r=>!r.includes("node_modules"));for(let r of n)Le(r,e)}catch(o){f(o)}finally{process.exit(0)}}};async function He(e){e.mudVersion==="canary"&&(e.tag="main");let o;try{console.log(v.blue("Fetching available versions")),o=await(await fetch(`https://registry.npmjs.org/${N.name}`)).json()}catch{throw new h("Could not fetch available MUD versions")}if(e.tag){let t=o["dist-tags"][e.tag];if(!t)throw new h(`Could not find npm version with tag "${e.tag}"`);return console.log(v.green(`Latest version with tag ${e.tag}: ${t}`)),t}if(e.commit){let t=e.commit.substring(0,8),n=Object.keys(o.versions).find(r=>r.includes(t));if(!n)throw new h(`Could not find npm version based on commit "${e.commit}"`);return console.log(v.green(`Version from commit ${e.commit}: ${n}`)),n}return e.mudVersion}function Le(e,o){let{link:t}=o,{mudVersion:n}=o,r=Ge(e),c=Object.keys(P),l={};for(let i in r.dependencies)c.includes(i)&&(l[i]=r.dependencies[i]);let s={};for(let i in r.devDependencies)c.includes(i)&&(s[i]=r.devDependencies[i]);for(let i in r.dependencies)c.includes(i)&&(r.dependencies[i]=p(i,"dependencies"));for(let i in r.devDependencies)c.includes(i)&&(r.devDependencies[i]=p(i,"devDependencies"));return _e(e,JSON.stringify(r,null,2)+`
11
+ `),console.log(`Updating ${e}`),J(l,r.dependencies),J(s,r.devDependencies),r;function p(i,g){return t&&(n=Be(e,t,i)),n||r[g][i]}}function Ge(e){try{let o=Ne(e,"utf8");return JSON.parse(o)}catch{throw new h("Could not read JSON at "+e)}}function J(e,o){for(let t in e)e[t]!==o[t]&&console.log(`${t}: ${v.red(e[t])} -> ${v.green(o[t])}`)}function Be(e,o,t){let n=j.relative(j.dirname(e),process.cwd());return"link:"+j.join(n,o,P[t].localPath)}var V=Ve;import{anvil as qe,forge as Ke,getRpcUrl as Ze}from"@latticexyz/common/foundry";import Ye from"chalk";import{rmSync as H,writeFileSync as Qe}from"fs";var U=".mudtest",Xe={command:"test",describe:"Run tests in MUD contracts",builder(e){return e.options({...S,port:{type:"number",description:"Port to run internal node for fork testing on",default:4242},worldAddress:{type:"string",description:"Address of an existing world contract. If provided, deployment is skipped and the RPC provided in the foundry.toml is used for fork testing."},forgeOptions:{type:"string",description:"Options to pass to forge test"}})},async handler(e){if(!e.worldAddress){let r=["--block-base-fee-per-gas","0","--port",String(e.port)];qe(r)}let o=e.worldAddress?await Ze(e.profile):`http://127.0.0.1:${e.port}`,t=e.worldAddress??(await y({...e,saveDeployment:!1,rpc:o})).worldAddress;console.log(Ye.blue("World address",t)),Qe(U,t);let n=e.forgeOptions?.replaceAll("\\","").split(" ")??[];try{let r=await Ke(["test","--fork-url",o,...n],{profile:e.profile});console.log(r)}catch(r){console.error(r),H(U),process.exit(1)}H(U),process.exit(0)}},L=Xe;import{existsSync as eo,readFileSync as oo}from"fs";import{ethers as G}from"ethers";import{loadConfig as to}from"@latticexyz/config/node";import{MUDError as B}from"@latticexyz/common/errors";import{cast as ro,getRpcUrl as no,getSrcDirectory as io}from"@latticexyz/common/foundry";import{resolveWorldConfig as so}from"@latticexyz/world";import ao from"@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json"assert{type:"json"};import q from"@latticexyz/world/mud.config.js";import{resourceIdToHex as Z}from"@latticexyz/common";var K=Z({type:"system",namespace:q.namespace,name:q.tables.Systems.name}),co={command:"trace",describe:"Display the trace of a transaction",builder(e){return e.options({tx:{type:"string",required:!0,description:"Transaction hash to replay"},worldAddress:{type:"string",description:"World contract address. Defaults to the value from worlds.json, based on rpc's chainId"},configPath:{type:"string",description:"Path to the config file"},profile:{type:"string",description:"The foundry profile to use"},srcDir:{type:"string",description:"Source directory. Defaults to foundry src directory."},rpc:{type:"string",description:"json rpc endpoint. Defaults to foundry's configured eth_rpc_url"}})},async handler(e){e.profile??=process.env.FOUNDRY_PROFILE;let{profile:o}=e;e.srcDir??=await io(o),e.rpc??=await no(o);let{tx:t,configPath:n,srcDir:r,rpc:c}=e,l=k(r),s=await to(n),p=so(s,l.map(({basename:m})=>m)),i=e.worldAddress??await lo(s.worldsFile,c),g=new G.providers.StaticJsonRpcProvider(c),b=new G.Contract(i,ao,g),C=s.namespace,x=Object.values(p.systems).map(({name:m})=>m),d=await b.getFieldLayout(K),a=[];for(let m of x){let M=Z({type:"system",namespace:C,name:m}),se=await b.getField(K,[M],0,d);a.push({name:m,address:se})}let u=await ro(["run","--label",`${i}:World`,...a.map(({name:m,address:M})=>["--label",`${M}:${m}`]).flat(),`${t}`]);console.log(u),process.exit(0)}},Y=co;async function lo(e,o){if(eo(e)){let t=await R(o),n=JSON.parse(oo(e,"utf-8"));if(!n[t])throw new B(`chainId ${t} is missing in worldsFile "${e}"`);return n[t].address}else throw new B("worldAddress is not specified and worldsFile is missing")}import{anvil as mo,forge as X,getRemappings as fo,getRpcUrl as go,getScriptDirectory as uo,getSrcDirectory as yo}from"@latticexyz/common/foundry";import D from"chalk";import ho from"chokidar";import{loadConfig as ee,resolveConfigPath as bo}from"@latticexyz/config/node";import{tablegen as wo}from"@latticexyz/store/codegen";import oe from"path";import{debounce as vo}from"throttle-debounce";import{homedir as Do}from"os";import{rmSync as Co}from"fs";import{execa as ko}from"execa";import po from"chalk";function Q(){console.log(po.yellow(`
8
12
  .------..------..------.
9
13
  |M.--. ||U.--. ||D.--. |
10
14
  | (\\/) || (\\/) || :/\\: |
11
15
  | :\\/: || :\\/: || (__) |
12
16
  | '--'M|| '--'U|| '--'D|
13
17
  '------''------''------'
14
- `))}var ko={command:"dev-contracts",describe:"Start a development server for MUD contracts",builder(e){return e.options({rpc:{type:"string",decs:"RPC endpoint of the development node. If none is provided, an anvil instance is spawned in the background on port 8545."},configPath:{type:"string",decs:"Path to MUD config"}})},async handler(e){await oe(["clean"]);let o=e.rpc??await fo(),t=e.configPath??await ho(e.configPath),r=await uo(),i=await go(),d=await mo(),l=await te(t);if(await p(l),await f(l),!e.rpc){console.log(M.gray("Cleaning devnode cache"));let n=vo();Do(re.join(n,".foundry","anvil","tmp"),{recursive:!0,force:!0}),po(["--block-time","1","--block-base-fee-per-gas","0"])}let s={config:!1,contracts:!1},m={current:!1};yo.watch([t,r]).on("all",async(n,c)=>{if(c.includes(t)&&(s.config=!0,s.contracts=!0),c.includes(r)||c.includes(i)){if(c.includes(l.codegenDirectory))return;s.contracts=!0}y()});let y=wo(100,async()=>{if(m.current)return;m.current=!0;let{config:n,contracts:c}=s;s.config=!1,s.contracts=!1;try{let v=await te(t);n&&await p(v),c&&await f(v),await w()}catch(v){console.error(M.red(`MUD dev-contracts watcher failed to deploy config or contracts changes
15
- `)),u(v)}m.current=!1,(s.config||s.contracts)&&(console.log("Detected change while handling the previous change"),y()),ee(),console.log("MUD watching for changes...")});async function p(n){console.log(M.blue("mud.config.ts changed - regenerating tables and recs types"));let c=re.join(r,n.codegenDirectory);await bo(n,c,d)}async function f(n){console.log(M.blue("contracts changed - regenerating interfaces and contract types")),await j({config:n,clean:!0,srcDir:r}),await oe(["build","--skip","test","script"]),await Co("mud",["abi-ts"],{stdio:"inherit"})}async function w(){console.log(M.blue("redeploying World")),await D({configPath:t,skipBuild:!0,priorityFeeMultiplier:1,disableTxWait:!0,pollInterval:1e3,saveDeployment:!0,srcDir:r,rpc:o})}}},ne=ko;var ie=[z,W,E,xo,I,F,J,L,q,Q,ne,Mo];import*as ae from"dotenv";import se from"chalk";ae.config();So(Oo(process.argv)).scriptName("mud").command(ie).strict().fail((e,o)=>{console.error(se.red(e)),e.includes("Missing required argument")&&console.log(se.yellow(`Run 'pnpm mud ${process.argv[2]} --help' for a list of available and required arguments.`)),console.log(""),o!=null&&(u(o),console.log("")),process.exit(1)}).alias({h:"help"}).argv;
18
+ `))}var xo={command:"dev-contracts",describe:"Start a development server for MUD contracts",builder(e){return e.options({rpc:{type:"string",decs:"RPC endpoint of the development node. If none is provided, an anvil instance is spawned in the background on port 8545."},configPath:{type:"string",decs:"Path to MUD config"}})},async handler(e){await X(["clean"]);let o=e.rpc??await go(),t=e.configPath??await bo(e.configPath),n=await yo(),r=await uo(),c=await fo(),l=await ee(t);if(await b(l),await C(l),!e.rpc){console.log(D.gray("Cleaning devnode cache"));let d=Do();Co(oe.join(d,".foundry","anvil","tmp"),{recursive:!0,force:!0}),mo(["--block-time","1","--block-base-fee-per-gas","0"])}let s={config:!1,contracts:!1},p={current:!1};ho.watch([t,n]).on("all",async(d,a)=>{if(a.includes(t)&&(s.config=!0,s.contracts=!0),a.includes(n)||a.includes(r)){if(a.includes(l.codegenDirectory))return;s.contracts=!0}g()});let g=vo(100,async()=>{if(p.current)return;p.current=!0;let{config:d,contracts:a}=s;s.config=!1,s.contracts=!1;try{let u=await ee(t);d&&await b(u),a&&await C(u),await x()}catch(u){console.error(D.red(`MUD dev-contracts watcher failed to deploy config or contracts changes
19
+ `)),f(u)}p.current=!1,(s.config||s.contracts)&&(console.log("Detected change while handling the previous change"),g()),Q(),console.log("MUD watching for changes...")});async function b(d){console.log(D.blue("mud.config.ts changed - regenerating tables and recs types"));let a=oe.join(n,d.codegenDirectory);await wo(d,a,c)}async function C(d){console.log(D.blue("contracts changed - regenerating interfaces and contract types")),await O({config:d,clean:!0,srcDir:n}),await X(["build","--skip","test","script"]),await ko("mud",["abi-ts"],{stdio:"inherit"})}async function x(){console.log(D.blue("redeploying World")),await y({configPath:t,skipBuild:!0,priorityFeeMultiplier:1,disableTxWait:!0,pollInterval:1e3,saveDeployment:!0,srcDir:n,rpc:o})}}},te=xo;var re=[z,A,W,Mo,$,I,F,V,L,Y,te,So];import*as ie from"dotenv";import ne from"chalk";ie.config();Oo(Po(process.argv)).scriptName("mud").command(re).strict().fail((e,o)=>{console.error(ne.red(e)),e.includes("Missing required argument")&&console.log(ne.yellow(`Run 'pnpm mud ${process.argv[2]} --help' for a list of available and required arguments.`)),console.log(""),o!=null&&(f(o),console.log("")),process.exit(1)}).alias({h:"help"}).argv;
16
20
  //# sourceMappingURL=mud.js.map
package/dist/mud.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/mud.ts","../src/commands/index.ts","../src/commands/devnode.ts","../src/commands/faucet.ts","../src/commands/hello.ts","../src/commands/tablegen.ts","../src/utils/errors.ts","../src/commands/deploy.ts","../src/commands/worldgen.ts","../src/commands/set-version.ts","../package.json","../src/commands/test.ts","../src/commands/trace.ts","../src/commands/dev-contracts.ts","../src/utils/printMUD.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\nimport { commands } from \"./commands\";\nimport { logError } from \"./utils/errors\";\n\n// Load .env file into process.env\nimport * as dotenv from \"dotenv\";\nimport chalk from \"chalk\";\ndotenv.config();\n\nyargs(hideBin(process.argv))\n // Explicit name to display in help (by default it's the entry file, which may not be \"mud\" for e.g. ts-node)\n .scriptName(\"mud\")\n // Use the commands directory to scaffold\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- command array overload isn't typed, see https://github.com/yargs/yargs/blob/main/docs/advanced.md#esm-hierarchy\n .command(commands as any)\n // Enable strict mode.\n .strict()\n // Custom error handler\n .fail((msg, err) => {\n console.error(chalk.red(msg));\n if (msg.includes(\"Missing required argument\")) {\n console.log(\n chalk.yellow(`Run 'pnpm mud ${process.argv[2]} --help' for a list of available and required arguments.`)\n );\n }\n console.log(\"\");\n // Even though `.fail` type says we should get an `Error`, this can sometimes be undefined\n if (err != null) {\n logError(err);\n console.log(\"\");\n }\n\n process.exit(1);\n })\n // Useful aliases.\n .alias({ h: \"help\" }).argv;\n","import { CommandModule } from \"yargs\";\n\nimport gasReport from \"@latticexyz/gas-report\";\nimport abiTs from \"@latticexyz/abi-ts\";\n\nimport devnode from \"./devnode\";\nimport faucet from \"./faucet\";\nimport hello from \"./hello\";\nimport tablegen from \"./tablegen\";\nimport deploy from \"./deploy\";\nimport worldgen from \"./worldgen\";\nimport setVersion from \"./set-version\";\nimport test from \"./test\";\nimport trace from \"./trace\";\nimport devContracts from \"./dev-contracts\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Each command has different options\nexport const commands: CommandModule<any, any>[] = [\n deploy,\n devnode,\n faucet,\n gasReport as CommandModule,\n hello,\n tablegen,\n worldgen,\n setVersion,\n test,\n trace,\n devContracts,\n abiTs,\n];\n","import { rmSync } from \"fs\";\nimport { homedir } from \"os\";\nimport path from \"path\";\nimport type { CommandModule } from \"yargs\";\nimport { execa } from \"execa\";\n\ntype Options = {\n blocktime: number;\n};\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"devnode\",\n\n describe: \"Start a local Ethereum node for development\",\n\n builder(yargs) {\n return yargs.options({\n blocktime: { type: \"number\", default: 1, decs: \"Interval in which new blocks are produced\" },\n });\n },\n\n async handler({ blocktime }) {\n console.log(\"Clearing devnode history\");\n const userHomeDir = homedir();\n rmSync(path.join(userHomeDir, \".foundry\", \"anvil\", \"tmp\"), { recursive: true, force: true });\n\n const anvilArgs = [\"-b\", String(blocktime), \"--block-base-fee-per-gas\", \"0\"];\n console.log(`Running: anvil ${anvilArgs.join(\" \")}`);\n const child = execa(\"anvil\", anvilArgs, {\n stdio: [\"inherit\", \"inherit\", \"inherit\"],\n });\n\n process.on(\"SIGINT\", () => {\n console.log(\"\\ngracefully shutting down from SIGINT (Crtl-C)\");\n child.kill();\n process.exit();\n });\n await child;\n },\n};\n\nexport default commandModule;\n","import type { CommandModule } from \"yargs\";\nimport { FaucetServiceDefinition } from \"@latticexyz/services/faucet\";\nimport { createChannel, createClient } from \"nice-grpc-web\";\nimport chalk from \"chalk\";\nimport { NodeHttpTransport } from \"@improbable-eng/grpc-web-node-http-transport\";\n\ntype Options = {\n dripDev?: boolean;\n faucetUrl: string;\n address: string;\n};\n\n/**\n * Create a FaucetServiceClient\n * @param url FaucetService URL\n * @returns FaucetServiceClient\n */\nfunction createFaucetService(url: string) {\n return createClient(FaucetServiceDefinition, createChannel(url, NodeHttpTransport()));\n}\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"faucet\",\n\n describe: \"Interact with a MUD faucet\",\n\n builder(yargs) {\n return yargs.options({\n dripDev: {\n type: \"boolean\",\n desc: \"Request a drip from the dev endpoint (requires faucet to have dev mode enabled)\",\n default: true,\n },\n faucetUrl: {\n type: \"string\",\n desc: \"URL of the MUD faucet\",\n default: \"https://faucet.testnet-mud-services.linfra.xyz\",\n },\n address: {\n type: \"string\",\n desc: \"Ethereum address to fund\",\n required: true,\n },\n });\n },\n\n async handler({ dripDev, faucetUrl, address }) {\n const faucet = createFaucetService(faucetUrl);\n\n if (dripDev) {\n console.log(chalk.yellow(\"Dripping to\", address));\n await faucet.dripDev({ address });\n console.log(chalk.yellow(\"Success\"));\n }\n\n process.exit(0);\n },\n};\n\nexport default commandModule;\n","import type { CommandModule } from \"yargs\";\n\ntype Options = {\n name: string;\n upper: boolean | undefined;\n};\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"hello <name>\",\n\n describe: \"Greet <name> with Hello\",\n\n builder(yargs) {\n return yargs\n .options({\n upper: { type: \"boolean\" },\n })\n .positional(\"name\", { type: \"string\", demandOption: true });\n },\n\n handler({ name }) {\n const greeting = `Gm, ${name}!`;\n console.log(greeting);\n process.exit(0);\n },\n};\n\nexport default commandModule;\n","import path from \"path\";\nimport type { CommandModule } from \"yargs\";\nimport { loadConfig } from \"@latticexyz/config/node\";\nimport { StoreConfig } from \"@latticexyz/store\";\nimport { tablegen } from \"@latticexyz/store/codegen\";\nimport { getRemappings, getSrcDirectory } from \"@latticexyz/common/foundry\";\n\ntype Options = {\n configPath?: string;\n};\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"tablegen\",\n\n describe: \"Autogenerate MUD Store table libraries based on the config file\",\n\n builder(yargs) {\n return yargs.options({\n configPath: { type: \"string\", desc: \"Path to the config file\" },\n });\n },\n\n async handler({ configPath }) {\n const config = (await loadConfig(configPath)) as StoreConfig;\n const srcDir = await getSrcDirectory();\n const remappings = await getRemappings();\n\n await tablegen(config, path.join(srcDir, config.codegenDirectory), remappings);\n\n process.exit(0);\n },\n};\n\nexport default commandModule;\n","import chalk from \"chalk\";\nimport { ZodError } from \"zod\";\nimport { fromZodError, ValidationError } from \"zod-validation-error\";\nimport { NotInsideProjectError } from \"@latticexyz/config\";\nimport { MUDError } from \"@latticexyz/common/errors\";\n\nexport function logError(error: unknown) {\n if (error instanceof ValidationError) {\n console.log(chalk.redBright(error.message));\n } else if (error instanceof ZodError) {\n // TODO currently this error shouldn't happen, use `fromZodErrorCustom`\n // (see https://github.com/latticexyz/mud/issues/438)\n const validationError = fromZodError(error, {\n prefixSeparator: \"\\n- \",\n issueSeparator: \"\\n- \",\n });\n console.log(chalk.redBright(validationError.message));\n } else if (error instanceof NotInsideProjectError) {\n console.log(chalk.red(error.message));\n console.log(\"\");\n // TODO add docs to the website and update the link to the specific page\n // (see https://github.com/latticexyz/mud/issues/445)\n console.log(chalk.blue(`To learn more about MUD's configuration, please go to https://mud.dev/packages/cli/`));\n } else if (error instanceof MUDError) {\n console.log(chalk.red(error));\n } else {\n console.log(error);\n }\n}\n","import type { CommandModule, Options } from \"yargs\";\nimport { logError } from \"../utils/errors\";\nimport { DeployOptions, deployHandler } from \"../utils/deployHandler\";\n\nexport const yDeployOptions = {\n configPath: { type: \"string\", desc: \"Path to the config file\" },\n clean: { type: \"boolean\", desc: \"Remove the build forge artifacts and cache directories before building\" },\n printConfig: { type: \"boolean\", desc: \"Print the resolved config\" },\n profile: { type: \"string\", desc: \"The foundry profile to use\" },\n debug: { type: \"boolean\", desc: \"Print debug logs, like full error messages\" },\n priorityFeeMultiplier: {\n type: \"number\",\n desc: \"Multiply the estimated priority fee by the provided factor\",\n default: 1,\n },\n saveDeployment: { type: \"boolean\", desc: \"Save the deployment info to a file\", default: true },\n rpc: { type: \"string\", desc: \"The RPC URL to use. Defaults to the RPC url from the local foundry.toml\" },\n worldAddress: { type: \"string\", desc: \"Deploy to an existing World at the given address\" },\n srcDir: { type: \"string\", desc: \"Source directory. Defaults to foundry src directory.\" },\n disableTxWait: { type: \"boolean\", desc: \"Disable waiting for transactions to be confirmed.\", default: false },\n pollInterval: {\n type: \"number\",\n desc: \"Interval in miliseconds to use to poll for transaction receipts / block inclusion\",\n default: 1000,\n },\n skipBuild: { type: \"boolean\", desc: \"Skip rebuilding the contracts before deploying\" },\n} satisfies Record<keyof DeployOptions, Options>;\n\nconst commandModule: CommandModule<DeployOptions, DeployOptions> = {\n command: \"deploy\",\n\n describe: \"Deploy MUD contracts\",\n\n builder(yargs) {\n return yargs.options(yDeployOptions);\n },\n\n async handler(args) {\n try {\n await deployHandler(args);\n } catch (error: any) {\n logError(error);\n process.exit(1);\n }\n process.exit(0);\n },\n};\n\nexport default commandModule;\n","import type { CommandModule } from \"yargs\";\nimport { loadConfig } from \"@latticexyz/config/node\";\nimport { StoreConfig } from \"@latticexyz/store\";\nimport { WorldConfig } from \"@latticexyz/world\";\nimport { worldgen } from \"@latticexyz/world/node\";\nimport { getSrcDirectory } from \"@latticexyz/common/foundry\";\nimport path from \"path\";\nimport { rmSync } from \"fs\";\nimport { getExistingContracts } from \"../utils/getExistingContracts\";\n\ntype Options = {\n configPath?: string;\n clean?: boolean;\n srcDir?: string;\n config?: StoreConfig & WorldConfig;\n};\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"worldgen\",\n\n describe: \"Autogenerate interfaces for Systems and World based on existing contracts and the config file\",\n\n builder(yargs) {\n return yargs.options({\n configPath: { type: \"string\", desc: \"Path to the config file\" },\n clean: {\n type: \"boolean\",\n desc: \"Clear the worldgen directory before generating new interfaces (defaults to true)\",\n default: true,\n },\n });\n },\n\n async handler(args) {\n await worldgenHandler(args);\n process.exit(0);\n },\n};\n\nexport async function worldgenHandler(args: Options) {\n const srcDir = args.srcDir ?? (await getSrcDirectory());\n\n const existingContracts = getExistingContracts(srcDir);\n\n // Load the config\n const mudConfig = args.config ?? ((await loadConfig(args.configPath)) as StoreConfig & WorldConfig);\n\n const outputBaseDirectory = path.join(srcDir, mudConfig.codegenDirectory);\n\n // clear the worldgen directory\n if (args.clean) rmSync(path.join(outputBaseDirectory, mudConfig.worldgenDirectory), { recursive: true, force: true });\n\n // generate new interfaces\n await worldgen(mudConfig, existingContracts, outputBaseDirectory);\n}\n\nexport default commandModule;\n","import chalk from \"chalk\";\nimport { existsSync, readFileSync, rmSync, writeFileSync } from \"fs\";\nimport path from \"path\";\nimport type { CommandModule } from \"yargs\";\nimport { MUDError } from \"@latticexyz/common/errors\";\nimport { logError } from \"../utils/errors\";\nimport localPackageJson from \"../../package.json\" assert { type: \"json\" };\nimport glob from \"glob\";\n\ntype Options = {\n backup?: boolean;\n force?: boolean;\n restore?: boolean;\n mudVersion?: string;\n tag?: string;\n commit?: string;\n link?: string;\n};\n\nconst BACKUP_FILE = \".mudbackup\";\nconst MUD_PREFIX = \"@latticexyz\";\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"set-version\",\n\n describe: \"Set MUD version in all package.json files and optionally backup the previously installed version\",\n\n builder(yargs) {\n return yargs.options({\n backup: { type: \"boolean\", description: `Back up the current MUD versions to \"${BACKUP_FILE}\"` },\n force: {\n type: \"boolean\",\n description: `Backup fails if a \"${BACKUP_FILE}\" file is found, unless --force is provided`,\n },\n restore: { type: \"boolean\", description: `Restore the previous MUD versions from \"${BACKUP_FILE}\"` },\n mudVersion: { alias: \"v\", type: \"string\", description: \"Set MUD to the given version\" },\n tag: {\n alias: \"t\",\n type: \"string\",\n description: \"Set MUD to the latest version with the given tag from npm\",\n },\n commit: {\n alias: \"c\",\n type: \"string\",\n description: \"Set MUD to the version based on a given git commit hash from npm\",\n },\n link: { alias: \"l\", type: \"string\", description: \"Relative path to the local MUD root directory to link\" },\n });\n },\n\n async handler(options) {\n try {\n const mutuallyExclusiveOptions = [\"mudVersion\", \"link\", \"tag\", \"commit\", \"restore\"];\n const numMutuallyExclusiveOptions = mutuallyExclusiveOptions.reduce(\n (acc, opt) => (options[opt] ? acc + 1 : acc),\n 0\n );\n\n if (numMutuallyExclusiveOptions === 0) {\n throw new MUDError(`You need to provide one these options: ${mutuallyExclusiveOptions.join(\", \")}`);\n }\n\n if (numMutuallyExclusiveOptions > 1) {\n throw new MUDError(`These options are mutually exclusive: ${mutuallyExclusiveOptions.join(\", \")}`);\n }\n\n // Resolve the version number from available options like `tag` or `commit`\n options.mudVersion = await resolveVersion(options);\n\n // Update all package.json below the current working directory (except in node_modules)\n const packageJsons = glob.sync(\"**/package.json\").filter((p) => !p.includes(\"node_modules\"));\n for (const packageJson of packageJsons) {\n updatePackageJson(packageJson, options);\n }\n } catch (e) {\n logError(e);\n } finally {\n process.exit(0);\n }\n },\n};\n\nasync function resolveVersion(options: Options) {\n // Backwards compatibility to previous behavior of this script where passing \"canary\" as the version resolved to the latest commit on main\n if (options.mudVersion === \"canary\") options.tag = \"main\";\n\n let npmResult;\n try {\n console.log(chalk.blue(`Fetching available versions`));\n npmResult = await (await fetch(`https://registry.npmjs.org/${localPackageJson.name}`)).json();\n } catch (e) {\n throw new MUDError(`Could not fetch available MUD versions`);\n }\n\n if (options.tag) {\n const version = npmResult[\"dist-tags\"][options.tag];\n if (!version) {\n throw new MUDError(`Could not find npm version with tag \"${options.tag}\"`);\n }\n console.log(chalk.green(`Latest version with tag ${options.tag}: ${version}`));\n return version;\n }\n\n if (options.commit) {\n // Find a version with this commit hash\n const commit = options.commit.substring(0, 8); // changesets uses the first 8 characters of the commit hash as version for prereleases/snapshot releases\n const version = Object.keys(npmResult[\"versions\"]).find((v) => (v as string).includes(commit));\n if (!version) {\n throw new MUDError(`Could not find npm version based on commit \"${options.commit}\"`);\n }\n console.log(chalk.green(`Version from commit ${options.commit}: ${version}`));\n return version;\n }\n\n // If neither a tag nor a commit option is given, return the `mudVersion`\n return options.mudVersion;\n}\n\nfunction updatePackageJson(filePath: string, options: Options): { workspaces?: string[] } {\n const { restore, force, link } = options;\n let { backup, mudVersion } = options;\n\n const backupFilePath = path.join(path.dirname(filePath), BACKUP_FILE);\n const backupFileExists = existsSync(backupFilePath);\n\n // Create a backup file for previous MUD versions by default if linking to local MUD\n if (link && !backupFileExists) backup = true;\n\n // If `backup` is true and force not set, check if a backup file already exists and throw an error if it does\n if (backup && !force && backupFileExists) {\n throw new MUDError(\n `A backup file already exists at ${backupFilePath}.\\nUse --force to overwrite it or --restore to restore it.`\n );\n }\n\n const packageJson = readPackageJson(filePath);\n\n // Load .mudbackup if `restore` is true\n const backupJson = restore ? readPackageJson(backupFilePath) : undefined;\n\n // Find all MUD dependencies\n const mudDependencies: Record<string, string> = {};\n for (const key in packageJson.dependencies) {\n if (key.startsWith(MUD_PREFIX)) {\n mudDependencies[key] = packageJson.dependencies[key];\n }\n }\n\n // Find all MUD devDependencies\n const mudDevDependencies: Record<string, string> = {};\n for (const key in packageJson.devDependencies) {\n if (key.startsWith(MUD_PREFIX)) {\n mudDevDependencies[key] = packageJson.devDependencies[key];\n }\n }\n\n // Back up the current dependencies if `backup` is true\n if (backup) {\n writeFileSync(\n backupFilePath,\n JSON.stringify({ dependencies: mudDependencies, devDependencies: mudDevDependencies }, null, 2)\n );\n console.log(chalk.green(`Backed up MUD dependencies from ${filePath} to ${backupFilePath}`));\n }\n\n // Update the dependencies\n for (const key in packageJson.dependencies) {\n if (key.startsWith(MUD_PREFIX)) {\n packageJson.dependencies[key] = resolveMudVersion(key, \"dependencies\");\n }\n }\n\n // Update the devDependencies\n for (const key in packageJson.devDependencies) {\n if (key.startsWith(MUD_PREFIX)) {\n packageJson.devDependencies[key] = resolveMudVersion(key, \"devDependencies\");\n }\n }\n\n // Write the updated package.json\n writeFileSync(filePath, JSON.stringify(packageJson, null, 2) + \"\\n\");\n\n console.log(`Updating ${filePath}`);\n logComparison(mudDependencies, packageJson.dependencies);\n logComparison(mudDevDependencies, packageJson.devDependencies);\n\n // Remove the backup file if `restore` is true and `backup` is false\n // because the old backup file is no longer needed\n if (restore && !backup) {\n rmSync(backupFilePath);\n console.log(chalk.green(`Cleaned up ${backupFilePath}`));\n }\n\n return packageJson;\n\n function resolveMudVersion(key: string, type: \"dependencies\" | \"devDependencies\") {\n if (restore && backupJson) return backupJson[type][key];\n if (link) mudVersion = resolveLinkPath(filePath, link, key);\n if (!mudVersion) return packageJson[type][key];\n return mudVersion;\n }\n}\n\nfunction readPackageJson(path: string): {\n workspaces?: string[];\n dependencies: Record<string, string>;\n devDependencies: Record<string, string>;\n} {\n try {\n const jsonString = readFileSync(path, \"utf8\");\n return JSON.parse(jsonString);\n } catch {\n throw new MUDError(\"Could not read JSON at \" + path);\n }\n}\n\nfunction logComparison(prev: Record<string, string>, curr: Record<string, string>) {\n for (const key in prev) {\n if (prev[key] !== curr[key]) {\n console.log(`${key}: ${chalk.red(prev[key])} -> ${chalk.green(curr[key])}`);\n }\n }\n}\n\n/**\n * Returns path of the package to link, given a path to a local MUD clone and a package\n */\nfunction resolveLinkPath(packageJsonPath: string, mudLinkPath: string, pkg: string) {\n const pkgName = pkg.replace(MUD_PREFIX, \"\");\n const packageJsonToRootPath = path.relative(path.dirname(packageJsonPath), process.cwd());\n const linkPath = path.join(packageJsonToRootPath, mudLinkPath, \"packages\", pkgName);\n return \"link:\" + linkPath;\n}\n\nexport default commandModule;\n","{\n \"name\": \"@latticexyz/cli\",\n \"version\": \"2.0.0-next.10\",\n \"description\": \"Command line interface for mud\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/latticexyz/mud.git\",\n \"directory\": \"packages/cli\"\n },\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"exports\": {\n \".\": \"./dist/index.js\"\n },\n \"types\": \"src/index.ts\",\n \"bin\": {\n \"mud\": \"./dist/mud.js\"\n },\n \"scripts\": {\n \"build\": \"pnpm run build:js && pnpm run build:test-tables\",\n \"build:js\": \"tsup && chmod +x ./dist/mud.js\",\n \"build:test-tables\": \"tsx ./scripts/generate-test-tables.ts\",\n \"clean\": \"pnpm run clean:js && pnpm run clean:test-tables\",\n \"clean:js\": \"rimraf dist\",\n \"clean:test-tables\": \"rimraf src/codegen\",\n \"dev\": \"tsup --watch\",\n \"lint\": \"eslint . --ext .ts\",\n \"prepare\": \"mkdir -p ./dist && touch ./dist/mud.js\",\n \"test\": \"tsc --noEmit && forge test\",\n \"test:ci\": \"pnpm run test\"\n },\n \"dependencies\": {\n \"@ethersproject/abi\": \"^5.7.0\",\n \"@ethersproject/providers\": \"^5.7.2\",\n \"@improbable-eng/grpc-web\": \"^0.15.0\",\n \"@improbable-eng/grpc-web-node-http-transport\": \"^0.15.0\",\n \"@latticexyz/abi-ts\": \"workspace:*\",\n \"@latticexyz/common\": \"workspace:*\",\n \"@latticexyz/config\": \"workspace:*\",\n \"@latticexyz/gas-report\": \"workspace:*\",\n \"@latticexyz/protocol-parser\": \"workspace:*\",\n \"@latticexyz/schema-type\": \"workspace:*\",\n \"@latticexyz/services\": \"workspace:*\",\n \"@latticexyz/store\": \"workspace:*\",\n \"@latticexyz/utils\": \"workspace:*\",\n \"@latticexyz/world\": \"workspace:*\",\n \"@latticexyz/world-modules\": \"workspace:*\",\n \"chalk\": \"^5.0.1\",\n \"chokidar\": \"^3.5.3\",\n \"dotenv\": \"^16.0.3\",\n \"ejs\": \"^3.1.8\",\n \"ethers\": \"^5.7.2\",\n \"execa\": \"^7.0.0\",\n \"glob\": \"^8.0.3\",\n \"nice-grpc-web\": \"^2.0.1\",\n \"openurl\": \"^1.1.1\",\n \"path\": \"^0.12.7\",\n \"throttle-debounce\": \"^5.0.0\",\n \"typescript\": \"5.1.6\",\n \"viem\": \"1.6.0\",\n \"yargs\": \"^17.7.1\",\n \"zod\": \"^3.21.4\",\n \"zod-validation-error\": \"^1.3.0\"\n },\n \"devDependencies\": {\n \"@types/ejs\": \"^3.1.1\",\n \"@types/glob\": \"^7.2.0\",\n \"@types/node\": \"^18.15.11\",\n \"@types/openurl\": \"^1.0.0\",\n \"@types/throttle-debounce\": \"^5.0.0\",\n \"@types/yargs\": \"^17.0.10\",\n \"ds-test\": \"https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0\",\n \"forge-std\": \"https://github.com/foundry-rs/forge-std.git#74cfb77e308dd188d2f58864aaf44963ae6b88b1\",\n \"tsup\": \"^6.7.0\",\n \"tsx\": \"^3.12.6\",\n \"vitest\": \"0.31.4\"\n },\n \"gitHead\": \"914a1e0ae4a573d685841ca2ea921435057deb8f\"\n}\n","import type { CommandModule } from \"yargs\";\nimport { anvil, forge, getRpcUrl } from \"@latticexyz/common/foundry\";\nimport chalk from \"chalk\";\nimport { rmSync, writeFileSync } from \"fs\";\nimport { yDeployOptions } from \"./deploy\";\nimport { DeployOptions, deployHandler } from \"../utils/deployHandler\";\n\ntype Options = DeployOptions & { port?: number; worldAddress?: string; forgeOptions?: string };\n\nconst WORLD_ADDRESS_FILE = \".mudtest\";\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"test\",\n\n describe: \"Run tests in MUD contracts\",\n\n builder(yargs) {\n return yargs.options({\n ...yDeployOptions,\n port: { type: \"number\", description: \"Port to run internal node for fork testing on\", default: 4242 },\n worldAddress: {\n type: \"string\",\n description:\n \"Address of an existing world contract. If provided, deployment is skipped and the RPC provided in the foundry.toml is used for fork testing.\",\n },\n forgeOptions: { type: \"string\", description: \"Options to pass to forge test\" },\n });\n },\n\n async handler(args) {\n // Start an internal anvil process if no world address is provided\n if (!args.worldAddress) {\n const anvilArgs = [\"--block-base-fee-per-gas\", \"0\", \"--port\", String(args.port)];\n anvil(anvilArgs);\n }\n\n const forkRpc = args.worldAddress ? await getRpcUrl(args.profile) : `http://127.0.0.1:${args.port}`;\n\n const worldAddress =\n args.worldAddress ??\n (\n await deployHandler({\n ...args,\n saveDeployment: false,\n rpc: forkRpc,\n })\n ).worldAddress;\n\n console.log(chalk.blue(\"World address\", worldAddress));\n\n // Create a temporary file to pass the world address to the tests\n writeFileSync(WORLD_ADDRESS_FILE, worldAddress);\n\n const userOptions = args.forgeOptions?.replaceAll(\"\\\\\", \"\").split(\" \") ?? [];\n try {\n const testResult = await forge([\"test\", \"--fork-url\", forkRpc, ...userOptions], {\n profile: args.profile,\n });\n console.log(testResult);\n } catch (e) {\n console.error(e);\n rmSync(WORLD_ADDRESS_FILE);\n process.exit(1);\n }\n\n rmSync(WORLD_ADDRESS_FILE);\n process.exit(0);\n },\n};\n\nexport default commandModule;\n","import { existsSync, readFileSync } from \"fs\";\nimport type { CommandModule } from \"yargs\";\nimport { ethers } from \"ethers\";\n\nimport { loadConfig } from \"@latticexyz/config/node\";\nimport { MUDError } from \"@latticexyz/common/errors\";\nimport { cast, getRpcUrl, getSrcDirectory } from \"@latticexyz/common/foundry\";\nimport { StoreConfig } from \"@latticexyz/store\";\nimport { resolveWorldConfig, WorldConfig } from \"@latticexyz/world\";\nimport IBaseWorldAbi from \"@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json\" assert { type: \"json\" };\nimport worldConfig from \"@latticexyz/world/mud.config.js\";\nimport { resourceIdToHex } from \"@latticexyz/common\";\nimport { getExistingContracts } from \"../utils/getExistingContracts\";\nimport { getChainId } from \"../utils/utils/getChainId\";\n\n// TODO account for multiple namespaces (https://github.com/latticexyz/mud/issues/994)\nconst systemsTableId = resourceIdToHex({\n type: \"system\",\n namespace: worldConfig.namespace,\n name: worldConfig.tables.Systems.name,\n});\n\ntype Options = {\n tx: string;\n worldAddress?: string;\n configPath?: string;\n profile?: string;\n srcDir?: string;\n rpc?: string;\n};\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"trace\",\n\n describe: \"Display the trace of a transaction\",\n\n builder(yargs) {\n return yargs.options({\n tx: { type: \"string\", required: true, description: \"Transaction hash to replay\" },\n worldAddress: {\n type: \"string\",\n description: \"World contract address. Defaults to the value from worlds.json, based on rpc's chainId\",\n },\n configPath: { type: \"string\", description: \"Path to the config file\" },\n profile: { type: \"string\", description: \"The foundry profile to use\" },\n srcDir: { type: \"string\", description: \"Source directory. Defaults to foundry src directory.\" },\n rpc: { type: \"string\", description: \"json rpc endpoint. Defaults to foundry's configured eth_rpc_url\" },\n });\n },\n\n async handler(args) {\n args.profile ??= process.env.FOUNDRY_PROFILE;\n const { profile } = args;\n args.srcDir ??= await getSrcDirectory(profile);\n args.rpc ??= await getRpcUrl(profile);\n const { tx, configPath, srcDir, rpc } = args;\n\n const existingContracts = getExistingContracts(srcDir);\n\n // Load the config\n const mudConfig = (await loadConfig(configPath)) as StoreConfig & WorldConfig;\n\n const resolvedConfig = resolveWorldConfig(\n mudConfig,\n existingContracts.map(({ basename }) => basename)\n );\n\n // Get worldAddress either from args or from worldsFile\n const worldAddress = args.worldAddress ?? (await getWorldAddress(mudConfig.worldsFile, rpc));\n\n // Create World contract instance from deployed address\n const provider = new ethers.providers.StaticJsonRpcProvider(rpc);\n const WorldContract = new ethers.Contract(worldAddress, IBaseWorldAbi, provider);\n\n // TODO account for multiple namespaces (https://github.com/latticexyz/mud/issues/994)\n const namespace = mudConfig.namespace;\n const names = Object.values(resolvedConfig.systems).map(({ name }) => name);\n\n // Fetch system table field layout from chain\n const systemTableFieldLayout = await WorldContract.getFieldLayout(systemsTableId);\n const labels: { name: string; address: string }[] = [];\n for (const name of names) {\n const systemSelector = resourceIdToHex({ type: \"system\", namespace, name });\n // Get the first field of `Systems` table (the table maps system name to its address and other data)\n const address = await WorldContract.getField(systemsTableId, [systemSelector], 0, systemTableFieldLayout);\n labels.push({ name, address });\n }\n\n const result = await cast([\n \"run\",\n \"--label\",\n `${worldAddress}:World`,\n ...labels.map(({ name, address }) => [\"--label\", `${address}:${name}`]).flat(),\n `${tx}`,\n ]);\n console.log(result);\n\n process.exit(0);\n },\n};\n\nexport default commandModule;\n\nasync function getWorldAddress(worldsFile: string, rpc: string) {\n if (existsSync(worldsFile)) {\n const chainId = await getChainId(rpc);\n const deploys = JSON.parse(readFileSync(worldsFile, \"utf-8\"));\n\n if (!deploys[chainId]) {\n throw new MUDError(`chainId ${chainId} is missing in worldsFile \"${worldsFile}\"`);\n }\n return deploys[chainId].address as string;\n } else {\n throw new MUDError(\"worldAddress is not specified and worldsFile is missing\");\n }\n}\n","import type { CommandModule } from \"yargs\";\nimport {\n anvil,\n forge,\n getRemappings,\n getRpcUrl,\n getScriptDirectory,\n getSrcDirectory,\n} from \"@latticexyz/common/foundry\";\nimport chalk from \"chalk\";\nimport chokidar from \"chokidar\";\nimport { loadConfig, resolveConfigPath } from \"@latticexyz/config/node\";\nimport { StoreConfig } from \"@latticexyz/store\";\nimport { tablegen } from \"@latticexyz/store/codegen\";\nimport path from \"path\";\nimport { debounce } from \"throttle-debounce\";\nimport { worldgenHandler } from \"./worldgen\";\nimport { WorldConfig } from \"@latticexyz/world\";\nimport { homedir } from \"os\";\nimport { rmSync } from \"fs\";\nimport { execa } from \"execa\";\nimport { logError } from \"../utils/errors\";\nimport { deployHandler } from \"../utils/deployHandler\";\nimport { printMUD } from \"../utils/printMUD\";\n\ntype Options = {\n rpc?: string;\n configPath?: string;\n};\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"dev-contracts\",\n\n describe: \"Start a development server for MUD contracts\",\n\n builder(yargs) {\n return yargs.options({\n rpc: {\n type: \"string\",\n decs: \"RPC endpoint of the development node. If none is provided, an anvil instance is spawned in the background on port 8545.\",\n },\n configPath: {\n type: \"string\",\n decs: \"Path to MUD config\",\n },\n });\n },\n\n async handler(args) {\n // Initial cleanup\n await forge([\"clean\"]);\n\n const rpc = args.rpc ?? (await getRpcUrl());\n const configPath = args.configPath ?? (await resolveConfigPath(args.configPath));\n const srcDirectory = await getSrcDirectory();\n const scriptDirectory = await getScriptDirectory();\n const remappings = await getRemappings();\n const initialConfig = (await loadConfig(configPath)) as StoreConfig & WorldConfig;\n\n // Initial run of all codegen steps before starting anvil\n // (so clients can wait for everything to be ready before starting)\n await handleConfigChange(initialConfig);\n await handleContractsChange(initialConfig);\n\n // Start an anvil instance in the background if no RPC url is provided\n if (!args.rpc) {\n console.log(chalk.gray(\"Cleaning devnode cache\"));\n const userHomeDir = homedir();\n rmSync(path.join(userHomeDir, \".foundry\", \"anvil\", \"tmp\"), { recursive: true, force: true });\n\n const anvilArgs = [\"--block-time\", \"1\", \"--block-base-fee-per-gas\", \"0\"];\n anvil(anvilArgs);\n }\n\n const changedSinceLastHandled = {\n config: false,\n contracts: false,\n };\n\n const changeInProgress = {\n current: false,\n };\n\n // Watch for changes\n const configWatcher = chokidar.watch([configPath, srcDirectory]);\n configWatcher.on(\"all\", async (_, updatePath) => {\n if (updatePath.includes(configPath)) {\n changedSinceLastHandled.config = true;\n // We trigger contract changes if the config changed here instead of\n // listening to changes in the codegen directory to avoid an infinite loop\n changedSinceLastHandled.contracts = true;\n }\n\n if (updatePath.includes(srcDirectory) || updatePath.includes(scriptDirectory)) {\n // Ignore changes to codegen files to avoid an infinite loop\n if (updatePath.includes(initialConfig.codegenDirectory)) return;\n changedSinceLastHandled.contracts = true;\n }\n\n // Trigger debounced onChange\n handleChange();\n });\n\n const handleChange = debounce(100, async () => {\n // Avoid handling changes multiple times in parallel\n if (changeInProgress.current) return;\n changeInProgress.current = true;\n\n // Reset dirty flags\n const { config, contracts } = changedSinceLastHandled;\n changedSinceLastHandled.config = false;\n changedSinceLastHandled.contracts = false;\n\n try {\n // Load latest config\n const mudConfig = (await loadConfig(configPath)) as StoreConfig & WorldConfig;\n\n // Handle changes\n if (config) await handleConfigChange(mudConfig);\n if (contracts) await handleContractsChange(mudConfig);\n\n await deploy();\n } catch (error) {\n console.error(chalk.red(\"MUD dev-contracts watcher failed to deploy config or contracts changes\\n\"));\n logError(error);\n }\n\n changeInProgress.current = false;\n if (changedSinceLastHandled.config || changedSinceLastHandled.contracts) {\n console.log(\"Detected change while handling the previous change\");\n handleChange();\n }\n\n printMUD();\n console.log(\"MUD watching for changes...\");\n });\n\n /** Codegen to run if config changes */\n async function handleConfigChange(config: StoreConfig & WorldConfig) {\n console.log(chalk.blue(\"mud.config.ts changed - regenerating tables and recs types\"));\n // Run tablegen to generate tables based on the config\n const outPath = path.join(srcDirectory, config.codegenDirectory);\n await tablegen(config, outPath, remappings);\n }\n\n /** Codegen to run if contracts changed */\n async function handleContractsChange(config: StoreConfig & WorldConfig) {\n console.log(chalk.blue(\"contracts changed - regenerating interfaces and contract types\"));\n\n // Run worldgen to generate interfaces based on the systems\n await worldgenHandler({ config, clean: true, srcDir: srcDirectory });\n\n // Build the contracts\n await forge([\"build\", \"--skip\", \"test\", \"script\"]);\n\n // Generate TS type definitions for ABIs\n await execa(\"mud\", [\"abi-ts\"], { stdio: \"inherit\" });\n }\n\n /** Run after codegen if either mud config or contracts changed */\n async function deploy() {\n console.log(chalk.blue(\"redeploying World\"));\n await deployHandler({\n configPath,\n skipBuild: true,\n priorityFeeMultiplier: 1,\n disableTxWait: true,\n pollInterval: 1000,\n saveDeployment: true,\n srcDir: srcDirectory,\n rpc,\n });\n }\n },\n};\n\nexport default commandModule;\n","import chalk from \"chalk\";\n\nexport function printMUD() {\n console.log(\n chalk.yellow(`\n.------..------..------.\n|M.--. ||U.--. ||D.--. |\n| (\\\\/) || (\\\\/) || :/\\\\: |\n| :\\\\/: || :\\\\/: || (__) |\n| '--'M|| '--'U|| '--'D|\n'------''------''------'\n`)\n );\n}\n"],"mappings":"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","names":["yargs","hideBin","gasReport","abiTs","rmSync","homedir","path","execa","commandModule","yargs","blocktime","userHomeDir","anvilArgs","child","devnode_default","FaucetServiceDefinition","createChannel","createClient","chalk","NodeHttpTransport","createFaucetService","url","commandModule","yargs","dripDev","faucetUrl","address","faucet","faucet_default","commandModule","yargs","name","greeting","hello_default","path","loadConfig","tablegen","getRemappings","getSrcDirectory","commandModule","yargs","configPath","config","srcDir","remappings","tablegen_default","chalk","ZodError","fromZodError","ValidationError","NotInsideProjectError","MUDError","logError","error","validationError","yDeployOptions","commandModule","yargs","args","deployHandler","error","logError","deploy_default","loadConfig","worldgen","getSrcDirectory","path","rmSync","commandModule","yargs","args","worldgenHandler","srcDir","getSrcDirectory","existingContracts","getExistingContracts","mudConfig","loadConfig","outputBaseDirectory","path","rmSync","worldgen","worldgen_default","chalk","existsSync","readFileSync","rmSync","writeFileSync","path","MUDError","package_default","glob","BACKUP_FILE","MUD_PREFIX","commandModule","yargs","options","mutuallyExclusiveOptions","numMutuallyExclusiveOptions","acc","opt","MUDError","resolveVersion","packageJsons","p","packageJson","updatePackageJson","e","logError","npmResult","chalk","package_default","version","commit","v","filePath","restore","force","link","backup","mudVersion","backupFilePath","path","backupFileExists","existsSync","readPackageJson","backupJson","mudDependencies","key","mudDevDependencies","writeFileSync","resolveMudVersion","logComparison","rmSync","type","resolveLinkPath","jsonString","readFileSync","prev","curr","packageJsonPath","mudLinkPath","pkg","pkgName","packageJsonToRootPath","set_version_default","anvil","forge","getRpcUrl","chalk","rmSync","writeFileSync","WORLD_ADDRESS_FILE","commandModule","yargs","yDeployOptions","args","anvilArgs","anvil","forkRpc","getRpcUrl","worldAddress","deployHandler","chalk","writeFileSync","userOptions","testResult","forge","e","rmSync","test_default","existsSync","readFileSync","ethers","loadConfig","MUDError","cast","getRpcUrl","getSrcDirectory","resolveWorldConfig","IBaseWorldAbi","worldConfig","resourceIdToHex","systemsTableId","resourceIdToHex","worldConfig","commandModule","yargs","args","profile","getSrcDirectory","getRpcUrl","tx","configPath","srcDir","rpc","existingContracts","getExistingContracts","mudConfig","loadConfig","resolvedConfig","resolveWorldConfig","basename","worldAddress","getWorldAddress","provider","ethers","WorldContract","IBaseWorldAbi","namespace","names","name","systemTableFieldLayout","labels","systemSelector","address","result","cast","trace_default","worldsFile","existsSync","chainId","getChainId","deploys","readFileSync","MUDError","anvil","forge","getRemappings","getRpcUrl","getScriptDirectory","getSrcDirectory","chalk","chokidar","loadConfig","resolveConfigPath","tablegen","path","debounce","homedir","rmSync","execa","chalk","printMUD","commandModule","yargs","args","forge","rpc","getRpcUrl","configPath","resolveConfigPath","srcDirectory","getSrcDirectory","scriptDirectory","getScriptDirectory","remappings","getRemappings","initialConfig","loadConfig","handleConfigChange","handleContractsChange","chalk","userHomeDir","homedir","rmSync","path","anvil","changedSinceLastHandled","changeInProgress","chokidar","_","updatePath","handleChange","debounce","config","contracts","mudConfig","deploy","error","logError","printMUD","outPath","tablegen","worldgenHandler","execa","deployHandler","dev_contracts_default","commands","deploy_default","devnode_default","faucet_default","gasReport","hello_default","tablegen_default","worldgen_default","set_version_default","test_default","trace_default","dev_contracts_default","abiTs","dotenv","chalk","yargs","hideBin","commands","msg","err","logError"]}
1
+ {"version":3,"sources":["../src/mud.ts","../src/commands/index.ts","../src/commands/devnode.ts","../src/commands/faucet.ts","../src/commands/hello.ts","../src/commands/tablegen.ts","../src/utils/errors.ts","../src/commands/deploy.ts","../src/commands/worldgen.ts","../src/commands/set-version.ts","../package.json","../src/mudPackages.ts","../src/commands/test.ts","../src/commands/trace.ts","../src/commands/dev-contracts.ts","../src/utils/printMUD.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\nimport { commands } from \"./commands\";\nimport { logError } from \"./utils/errors\";\n\n// Load .env file into process.env\nimport * as dotenv from \"dotenv\";\nimport chalk from \"chalk\";\ndotenv.config();\n\nyargs(hideBin(process.argv))\n // Explicit name to display in help (by default it's the entry file, which may not be \"mud\" for e.g. ts-node)\n .scriptName(\"mud\")\n // Use the commands directory to scaffold\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- command array overload isn't typed, see https://github.com/yargs/yargs/blob/main/docs/advanced.md#esm-hierarchy\n .command(commands as any)\n // Enable strict mode.\n .strict()\n // Custom error handler\n .fail((msg, err) => {\n console.error(chalk.red(msg));\n if (msg.includes(\"Missing required argument\")) {\n console.log(\n chalk.yellow(`Run 'pnpm mud ${process.argv[2]} --help' for a list of available and required arguments.`)\n );\n }\n console.log(\"\");\n // Even though `.fail` type says we should get an `Error`, this can sometimes be undefined\n if (err != null) {\n logError(err);\n console.log(\"\");\n }\n\n process.exit(1);\n })\n // Useful aliases.\n .alias({ h: \"help\" }).argv;\n","import { CommandModule } from \"yargs\";\n\nimport gasReport from \"@latticexyz/gas-report\";\nimport abiTs from \"@latticexyz/abi-ts\";\n\nimport devnode from \"./devnode\";\nimport faucet from \"./faucet\";\nimport hello from \"./hello\";\nimport tablegen from \"./tablegen\";\nimport deploy from \"./deploy\";\nimport worldgen from \"./worldgen\";\nimport setVersion from \"./set-version\";\nimport test from \"./test\";\nimport trace from \"./trace\";\nimport devContracts from \"./dev-contracts\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Each command has different options\nexport const commands: CommandModule<any, any>[] = [\n deploy,\n devnode,\n faucet,\n gasReport as CommandModule,\n hello,\n tablegen,\n worldgen,\n setVersion,\n test,\n trace,\n devContracts,\n abiTs,\n];\n","import { rmSync } from \"fs\";\nimport { homedir } from \"os\";\nimport path from \"path\";\nimport type { CommandModule } from \"yargs\";\nimport { execa } from \"execa\";\n\ntype Options = {\n blocktime: number;\n};\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"devnode\",\n\n describe: \"Start a local Ethereum node for development\",\n\n builder(yargs) {\n return yargs.options({\n blocktime: { type: \"number\", default: 1, decs: \"Interval in which new blocks are produced\" },\n });\n },\n\n async handler({ blocktime }) {\n console.log(\"Clearing devnode history\");\n const userHomeDir = homedir();\n rmSync(path.join(userHomeDir, \".foundry\", \"anvil\", \"tmp\"), { recursive: true, force: true });\n\n const anvilArgs = [\"-b\", String(blocktime), \"--block-base-fee-per-gas\", \"0\"];\n console.log(`Running: anvil ${anvilArgs.join(\" \")}`);\n const child = execa(\"anvil\", anvilArgs, {\n stdio: [\"inherit\", \"inherit\", \"inherit\"],\n });\n\n process.on(\"SIGINT\", () => {\n console.log(\"\\ngracefully shutting down from SIGINT (Crtl-C)\");\n child.kill();\n process.exit();\n });\n await child;\n },\n};\n\nexport default commandModule;\n","import type { CommandModule } from \"yargs\";\nimport { FaucetServiceDefinition } from \"@latticexyz/services/faucet\";\nimport { createChannel, createClient } from \"nice-grpc-web\";\nimport chalk from \"chalk\";\nimport { NodeHttpTransport } from \"@improbable-eng/grpc-web-node-http-transport\";\n\ntype Options = {\n dripDev?: boolean;\n faucetUrl: string;\n address: string;\n};\n\n/**\n * Create a FaucetServiceClient\n * @param url FaucetService URL\n * @returns FaucetServiceClient\n */\nfunction createFaucetService(url: string) {\n return createClient(FaucetServiceDefinition, createChannel(url, NodeHttpTransport()));\n}\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"faucet\",\n\n describe: \"Interact with a MUD faucet\",\n\n builder(yargs) {\n return yargs.options({\n dripDev: {\n type: \"boolean\",\n desc: \"Request a drip from the dev endpoint (requires faucet to have dev mode enabled)\",\n default: true,\n },\n faucetUrl: {\n type: \"string\",\n desc: \"URL of the MUD faucet\",\n default: \"https://faucet.testnet-mud-services.linfra.xyz\",\n },\n address: {\n type: \"string\",\n desc: \"Ethereum address to fund\",\n required: true,\n },\n });\n },\n\n async handler({ dripDev, faucetUrl, address }) {\n const faucet = createFaucetService(faucetUrl);\n\n if (dripDev) {\n console.log(chalk.yellow(\"Dripping to\", address));\n await faucet.dripDev({ address });\n console.log(chalk.yellow(\"Success\"));\n }\n\n process.exit(0);\n },\n};\n\nexport default commandModule;\n","import type { CommandModule } from \"yargs\";\n\ntype Options = {\n name: string;\n upper: boolean | undefined;\n};\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"hello <name>\",\n\n describe: \"Greet <name> with Hello\",\n\n builder(yargs) {\n return yargs\n .options({\n upper: { type: \"boolean\" },\n })\n .positional(\"name\", { type: \"string\", demandOption: true });\n },\n\n handler({ name }) {\n const greeting = `Gm, ${name}!`;\n console.log(greeting);\n process.exit(0);\n },\n};\n\nexport default commandModule;\n","import path from \"path\";\nimport type { CommandModule } from \"yargs\";\nimport { loadConfig } from \"@latticexyz/config/node\";\nimport { StoreConfig } from \"@latticexyz/store\";\nimport { tablegen } from \"@latticexyz/store/codegen\";\nimport { getRemappings, getSrcDirectory } from \"@latticexyz/common/foundry\";\n\ntype Options = {\n configPath?: string;\n};\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"tablegen\",\n\n describe: \"Autogenerate MUD Store table libraries based on the config file\",\n\n builder(yargs) {\n return yargs.options({\n configPath: { type: \"string\", desc: \"Path to the config file\" },\n });\n },\n\n async handler({ configPath }) {\n const config = (await loadConfig(configPath)) as StoreConfig;\n const srcDir = await getSrcDirectory();\n const remappings = await getRemappings();\n\n await tablegen(config, path.join(srcDir, config.codegenDirectory), remappings);\n\n process.exit(0);\n },\n};\n\nexport default commandModule;\n","import chalk from \"chalk\";\nimport { ZodError } from \"zod\";\nimport { fromZodError, ValidationError } from \"zod-validation-error\";\nimport { NotInsideProjectError } from \"@latticexyz/config\";\nimport { MUDError } from \"@latticexyz/common/errors\";\n\nexport function logError(error: unknown) {\n if (error instanceof ValidationError) {\n console.log(chalk.redBright(error.message));\n } else if (error instanceof ZodError) {\n // TODO currently this error shouldn't happen, use `fromZodErrorCustom`\n // (see https://github.com/latticexyz/mud/issues/438)\n const validationError = fromZodError(error, {\n prefixSeparator: \"\\n- \",\n issueSeparator: \"\\n- \",\n });\n console.log(chalk.redBright(validationError.message));\n } else if (error instanceof NotInsideProjectError) {\n console.log(chalk.red(error.message));\n console.log(\"\");\n // TODO add docs to the website and update the link to the specific page\n // (see https://github.com/latticexyz/mud/issues/445)\n console.log(chalk.blue(`To learn more about MUD's configuration, please go to https://mud.dev/packages/cli/`));\n } else if (error instanceof MUDError) {\n console.log(chalk.red(error));\n } else {\n console.log(error);\n }\n}\n","import type { CommandModule, Options } from \"yargs\";\nimport { logError } from \"../utils/errors\";\nimport { DeployOptions, deployHandler } from \"../utils/deployHandler\";\n\nexport const yDeployOptions = {\n configPath: { type: \"string\", desc: \"Path to the config file\" },\n clean: { type: \"boolean\", desc: \"Remove the build forge artifacts and cache directories before building\" },\n printConfig: { type: \"boolean\", desc: \"Print the resolved config\" },\n profile: { type: \"string\", desc: \"The foundry profile to use\" },\n debug: { type: \"boolean\", desc: \"Print debug logs, like full error messages\" },\n priorityFeeMultiplier: {\n type: \"number\",\n desc: \"Multiply the estimated priority fee by the provided factor\",\n default: 1,\n },\n saveDeployment: { type: \"boolean\", desc: \"Save the deployment info to a file\", default: true },\n rpc: { type: \"string\", desc: \"The RPC URL to use. Defaults to the RPC url from the local foundry.toml\" },\n worldAddress: { type: \"string\", desc: \"Deploy to an existing World at the given address\" },\n srcDir: { type: \"string\", desc: \"Source directory. Defaults to foundry src directory.\" },\n disableTxWait: { type: \"boolean\", desc: \"Disable waiting for transactions to be confirmed.\", default: false },\n pollInterval: {\n type: \"number\",\n desc: \"Interval in miliseconds to use to poll for transaction receipts / block inclusion\",\n default: 1000,\n },\n skipBuild: { type: \"boolean\", desc: \"Skip rebuilding the contracts before deploying\" },\n} satisfies Record<keyof DeployOptions, Options>;\n\nconst commandModule: CommandModule<DeployOptions, DeployOptions> = {\n command: \"deploy\",\n\n describe: \"Deploy MUD contracts\",\n\n builder(yargs) {\n return yargs.options(yDeployOptions);\n },\n\n async handler(args) {\n try {\n await deployHandler(args);\n } catch (error: any) {\n logError(error);\n process.exit(1);\n }\n process.exit(0);\n },\n};\n\nexport default commandModule;\n","import type { CommandModule } from \"yargs\";\nimport { loadConfig } from \"@latticexyz/config/node\";\nimport { StoreConfig } from \"@latticexyz/store\";\nimport { WorldConfig } from \"@latticexyz/world\";\nimport { worldgen } from \"@latticexyz/world/node\";\nimport { getSrcDirectory } from \"@latticexyz/common/foundry\";\nimport path from \"path\";\nimport { rmSync } from \"fs\";\nimport { getExistingContracts } from \"../utils/getExistingContracts\";\n\ntype Options = {\n configPath?: string;\n clean?: boolean;\n srcDir?: string;\n config?: StoreConfig & WorldConfig;\n};\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"worldgen\",\n\n describe: \"Autogenerate interfaces for Systems and World based on existing contracts and the config file\",\n\n builder(yargs) {\n return yargs.options({\n configPath: { type: \"string\", desc: \"Path to the config file\" },\n clean: {\n type: \"boolean\",\n desc: \"Clear the worldgen directory before generating new interfaces (defaults to true)\",\n default: true,\n },\n });\n },\n\n async handler(args) {\n await worldgenHandler(args);\n process.exit(0);\n },\n};\n\nexport async function worldgenHandler(args: Options) {\n const srcDir = args.srcDir ?? (await getSrcDirectory());\n\n const existingContracts = getExistingContracts(srcDir);\n\n // Load the config\n const mudConfig = args.config ?? ((await loadConfig(args.configPath)) as StoreConfig & WorldConfig);\n\n const outputBaseDirectory = path.join(srcDir, mudConfig.codegenDirectory);\n\n // clear the worldgen directory\n if (args.clean) rmSync(path.join(outputBaseDirectory, mudConfig.worldgenDirectory), { recursive: true, force: true });\n\n // generate new interfaces\n await worldgen(mudConfig, existingContracts, outputBaseDirectory);\n}\n\nexport default commandModule;\n","import chalk from \"chalk\";\nimport { readFileSync, writeFileSync } from \"fs\";\nimport path from \"path\";\nimport type { CommandModule } from \"yargs\";\nimport { MUDError } from \"@latticexyz/common/errors\";\nimport { logError } from \"../utils/errors\";\nimport localPackageJson from \"../../package.json\" assert { type: \"json\" };\nimport glob from \"glob\";\nimport { mudPackages } from \"../mudPackages\";\n\ntype Options = {\n backup?: boolean;\n force?: boolean;\n restore?: boolean;\n mudVersion?: string;\n tag?: string;\n commit?: string;\n link?: string;\n};\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"set-version\",\n\n describe: \"Set MUD version in all package.json files and optionally backup the previously installed version\",\n\n builder(yargs) {\n return yargs.options({\n mudVersion: { alias: \"v\", type: \"string\", description: \"Set MUD to the given version\" },\n tag: {\n alias: \"t\",\n type: \"string\",\n description: \"Set MUD to the latest version with the given tag from npm\",\n },\n commit: {\n alias: \"c\",\n type: \"string\",\n description: \"Set MUD to the version based on a given git commit hash from npm\",\n },\n link: { alias: \"l\", type: \"string\", description: \"Relative path to the local MUD root directory to link\" },\n });\n },\n\n async handler(options) {\n try {\n const mutuallyExclusiveOptions = [\"mudVersion\", \"link\", \"tag\", \"commit\", \"restore\"];\n const numMutuallyExclusiveOptions = mutuallyExclusiveOptions.reduce(\n (acc, opt) => (options[opt] ? acc + 1 : acc),\n 0\n );\n\n if (numMutuallyExclusiveOptions === 0) {\n throw new MUDError(`You need to provide one these options: ${mutuallyExclusiveOptions.join(\", \")}`);\n }\n\n if (numMutuallyExclusiveOptions > 1) {\n throw new MUDError(`These options are mutually exclusive: ${mutuallyExclusiveOptions.join(\", \")}`);\n }\n\n // Resolve the version number from available options like `tag` or `commit`\n options.mudVersion = await resolveVersion(options);\n\n // Update all package.json below the current working directory (except in node_modules)\n const packageJsons = glob.sync(\"**/package.json\").filter((p) => !p.includes(\"node_modules\"));\n for (const packageJson of packageJsons) {\n updatePackageJson(packageJson, options);\n }\n } catch (e) {\n logError(e);\n } finally {\n process.exit(0);\n }\n },\n};\n\nasync function resolveVersion(options: Options) {\n // Backwards compatibility to previous behavior of this script where passing \"canary\" as the version resolved to the latest commit on main\n if (options.mudVersion === \"canary\") options.tag = \"main\";\n\n let npmResult;\n try {\n console.log(chalk.blue(`Fetching available versions`));\n npmResult = await (await fetch(`https://registry.npmjs.org/${localPackageJson.name}`)).json();\n } catch (e) {\n throw new MUDError(`Could not fetch available MUD versions`);\n }\n\n if (options.tag) {\n const version = npmResult[\"dist-tags\"][options.tag];\n if (!version) {\n throw new MUDError(`Could not find npm version with tag \"${options.tag}\"`);\n }\n console.log(chalk.green(`Latest version with tag ${options.tag}: ${version}`));\n return version;\n }\n\n if (options.commit) {\n // Find a version with this commit hash\n const commit = options.commit.substring(0, 8); // changesets uses the first 8 characters of the commit hash as version for prereleases/snapshot releases\n const version = Object.keys(npmResult[\"versions\"]).find((v) => (v as string).includes(commit));\n if (!version) {\n throw new MUDError(`Could not find npm version based on commit \"${options.commit}\"`);\n }\n console.log(chalk.green(`Version from commit ${options.commit}: ${version}`));\n return version;\n }\n\n // If neither a tag nor a commit option is given, return the `mudVersion`\n return options.mudVersion;\n}\n\nfunction updatePackageJson(filePath: string, options: Options): { workspaces?: string[] } {\n const { link } = options;\n let { mudVersion } = options;\n\n const packageJson = readPackageJson(filePath);\n const mudPackageNames = Object.keys(mudPackages);\n\n // Find all MUD dependencies\n const mudDependencies: Record<string, string> = {};\n for (const packageName in packageJson.dependencies) {\n if (mudPackageNames.includes(packageName)) {\n mudDependencies[packageName] = packageJson.dependencies[packageName];\n }\n }\n\n // Find all MUD devDependencies\n const mudDevDependencies: Record<string, string> = {};\n for (const packageName in packageJson.devDependencies) {\n if (mudPackageNames.includes(packageName)) {\n mudDevDependencies[packageName] = packageJson.devDependencies[packageName];\n }\n }\n\n // Update the dependencies\n for (const packageName in packageJson.dependencies) {\n if (mudPackageNames.includes(packageName)) {\n packageJson.dependencies[packageName] = resolveMudVersion(packageName, \"dependencies\");\n }\n }\n\n // Update the devDependencies\n for (const packageName in packageJson.devDependencies) {\n if (mudPackageNames.includes(packageName)) {\n packageJson.devDependencies[packageName] = resolveMudVersion(packageName, \"devDependencies\");\n }\n }\n\n // Write the updated package.json\n writeFileSync(filePath, JSON.stringify(packageJson, null, 2) + \"\\n\");\n\n console.log(`Updating ${filePath}`);\n logComparison(mudDependencies, packageJson.dependencies);\n logComparison(mudDevDependencies, packageJson.devDependencies);\n\n return packageJson;\n\n function resolveMudVersion(key: string, type: \"dependencies\" | \"devDependencies\") {\n if (link) mudVersion = resolveLinkPath(filePath, link, key);\n if (!mudVersion) return packageJson[type][key];\n return mudVersion;\n }\n}\n\nfunction readPackageJson(path: string): {\n workspaces?: string[];\n dependencies: Record<string, string>;\n devDependencies: Record<string, string>;\n} {\n try {\n const jsonString = readFileSync(path, \"utf8\");\n return JSON.parse(jsonString);\n } catch {\n throw new MUDError(\"Could not read JSON at \" + path);\n }\n}\n\nfunction logComparison(prev: Record<string, string>, curr: Record<string, string>) {\n for (const key in prev) {\n if (prev[key] !== curr[key]) {\n console.log(`${key}: ${chalk.red(prev[key])} -> ${chalk.green(curr[key])}`);\n }\n }\n}\n\n/**\n * Returns path of the package to link, given a path to a local MUD clone and a package\n */\nfunction resolveLinkPath(packageJsonPath: string, mudLinkPath: string, packageName: string) {\n const packageJsonToRootPath = path.relative(path.dirname(packageJsonPath), process.cwd());\n const linkPath = path.join(packageJsonToRootPath, mudLinkPath, mudPackages[packageName].localPath);\n return \"link:\" + linkPath;\n}\n\nexport default commandModule;\n","{\n \"name\": \"@latticexyz/cli\",\n \"version\": \"2.0.0-next.11\",\n \"description\": \"Command line interface for mud\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/latticexyz/mud.git\",\n \"directory\": \"packages/cli\"\n },\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"exports\": {\n \".\": \"./dist/index.js\"\n },\n \"types\": \"src/index.ts\",\n \"bin\": {\n \"mud\": \"./dist/mud.js\"\n },\n \"scripts\": {\n \"build\": \"pnpm run build:js && pnpm run build:test-tables\",\n \"build:js\": \"tsup && chmod +x ./dist/mud.js\",\n \"build:test-tables\": \"tsx ./scripts/generate-test-tables.ts\",\n \"clean\": \"pnpm run clean:js && pnpm run clean:test-tables\",\n \"clean:js\": \"rimraf dist\",\n \"clean:test-tables\": \"rimraf src/codegen\",\n \"dev\": \"tsup --watch\",\n \"lint\": \"eslint . --ext .ts\",\n \"prepare\": \"mkdir -p ./dist && touch ./dist/mud.js\",\n \"test\": \"tsc --noEmit && forge test\",\n \"test:ci\": \"pnpm run test\"\n },\n \"dependencies\": {\n \"@ethersproject/abi\": \"^5.7.0\",\n \"@ethersproject/providers\": \"^5.7.2\",\n \"@improbable-eng/grpc-web\": \"^0.15.0\",\n \"@improbable-eng/grpc-web-node-http-transport\": \"^0.15.0\",\n \"@latticexyz/abi-ts\": \"workspace:*\",\n \"@latticexyz/common\": \"workspace:*\",\n \"@latticexyz/config\": \"workspace:*\",\n \"@latticexyz/gas-report\": \"workspace:*\",\n \"@latticexyz/protocol-parser\": \"workspace:*\",\n \"@latticexyz/schema-type\": \"workspace:*\",\n \"@latticexyz/services\": \"workspace:*\",\n \"@latticexyz/store\": \"workspace:*\",\n \"@latticexyz/utils\": \"workspace:*\",\n \"@latticexyz/world\": \"workspace:*\",\n \"@latticexyz/world-modules\": \"workspace:*\",\n \"chalk\": \"^5.0.1\",\n \"chokidar\": \"^3.5.3\",\n \"dotenv\": \"^16.0.3\",\n \"ejs\": \"^3.1.8\",\n \"ethers\": \"^5.7.2\",\n \"execa\": \"^7.0.0\",\n \"glob\": \"^8.0.3\",\n \"nice-grpc-web\": \"^2.0.1\",\n \"openurl\": \"^1.1.1\",\n \"path\": \"^0.12.7\",\n \"throttle-debounce\": \"^5.0.0\",\n \"typescript\": \"5.1.6\",\n \"viem\": \"1.14.0\",\n \"yargs\": \"^17.7.1\",\n \"zod\": \"^3.21.4\",\n \"zod-validation-error\": \"^1.3.0\"\n },\n \"devDependencies\": {\n \"@types/ejs\": \"^3.1.1\",\n \"@types/glob\": \"^7.2.0\",\n \"@types/node\": \"^18.15.11\",\n \"@types/openurl\": \"^1.0.0\",\n \"@types/throttle-debounce\": \"^5.0.0\",\n \"@types/yargs\": \"^17.0.10\",\n \"ds-test\": \"https://github.com/dapphub/ds-test.git#e282159d5170298eb2455a6c05280ab5a73a4ef0\",\n \"forge-std\": \"https://github.com/foundry-rs/forge-std.git#74cfb77e308dd188d2f58864aaf44963ae6b88b1\",\n \"tsup\": \"^6.7.0\",\n \"tsx\": \"^3.12.6\",\n \"vitest\": \"0.31.4\"\n },\n \"gitHead\": \"914a1e0ae4a573d685841ca2ea921435057deb8f\"\n}\n","import { ZodError, z } from \"zod\";\nimport { MudPackages } from \"./common\";\n\nconst envSchema = z.object({\n MUD_PACKAGES: z.string().transform((value) => JSON.parse(value) as MudPackages),\n});\n\nfunction parseEnv(): z.infer<typeof envSchema> {\n try {\n return envSchema.parse({\n // tsup replaces the env vars with their values at compile time\n MUD_PACKAGES: process.env.MUD_PACKAGES,\n });\n } catch (error) {\n if (error instanceof ZodError) {\n const { _errors, ...invalidEnvVars } = error.format();\n console.error(`\\nMissing or invalid environment variables:\\n\\n ${Object.keys(invalidEnvVars).join(\"\\n \")}\\n`);\n process.exit(1);\n }\n throw error;\n }\n}\n\nexport const mudPackages = parseEnv().MUD_PACKAGES;\n","import type { CommandModule } from \"yargs\";\nimport { anvil, forge, getRpcUrl } from \"@latticexyz/common/foundry\";\nimport chalk from \"chalk\";\nimport { rmSync, writeFileSync } from \"fs\";\nimport { yDeployOptions } from \"./deploy\";\nimport { DeployOptions, deployHandler } from \"../utils/deployHandler\";\n\ntype Options = DeployOptions & { port?: number; worldAddress?: string; forgeOptions?: string };\n\nconst WORLD_ADDRESS_FILE = \".mudtest\";\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"test\",\n\n describe: \"Run tests in MUD contracts\",\n\n builder(yargs) {\n return yargs.options({\n ...yDeployOptions,\n port: { type: \"number\", description: \"Port to run internal node for fork testing on\", default: 4242 },\n worldAddress: {\n type: \"string\",\n description:\n \"Address of an existing world contract. If provided, deployment is skipped and the RPC provided in the foundry.toml is used for fork testing.\",\n },\n forgeOptions: { type: \"string\", description: \"Options to pass to forge test\" },\n });\n },\n\n async handler(args) {\n // Start an internal anvil process if no world address is provided\n if (!args.worldAddress) {\n const anvilArgs = [\"--block-base-fee-per-gas\", \"0\", \"--port\", String(args.port)];\n anvil(anvilArgs);\n }\n\n const forkRpc = args.worldAddress ? await getRpcUrl(args.profile) : `http://127.0.0.1:${args.port}`;\n\n const worldAddress =\n args.worldAddress ??\n (\n await deployHandler({\n ...args,\n saveDeployment: false,\n rpc: forkRpc,\n })\n ).worldAddress;\n\n console.log(chalk.blue(\"World address\", worldAddress));\n\n // Create a temporary file to pass the world address to the tests\n writeFileSync(WORLD_ADDRESS_FILE, worldAddress);\n\n const userOptions = args.forgeOptions?.replaceAll(\"\\\\\", \"\").split(\" \") ?? [];\n try {\n const testResult = await forge([\"test\", \"--fork-url\", forkRpc, ...userOptions], {\n profile: args.profile,\n });\n console.log(testResult);\n } catch (e) {\n console.error(e);\n rmSync(WORLD_ADDRESS_FILE);\n process.exit(1);\n }\n\n rmSync(WORLD_ADDRESS_FILE);\n process.exit(0);\n },\n};\n\nexport default commandModule;\n","import { existsSync, readFileSync } from \"fs\";\nimport type { CommandModule } from \"yargs\";\nimport { ethers } from \"ethers\";\n\nimport { loadConfig } from \"@latticexyz/config/node\";\nimport { MUDError } from \"@latticexyz/common/errors\";\nimport { cast, getRpcUrl, getSrcDirectory } from \"@latticexyz/common/foundry\";\nimport { StoreConfig } from \"@latticexyz/store\";\nimport { resolveWorldConfig, WorldConfig } from \"@latticexyz/world\";\nimport IBaseWorldAbi from \"@latticexyz/world/out/IBaseWorld.sol/IBaseWorld.abi.json\" assert { type: \"json\" };\nimport worldConfig from \"@latticexyz/world/mud.config.js\";\nimport { resourceIdToHex } from \"@latticexyz/common\";\nimport { getExistingContracts } from \"../utils/getExistingContracts\";\nimport { getChainId } from \"../utils/utils/getChainId\";\n\n// TODO account for multiple namespaces (https://github.com/latticexyz/mud/issues/994)\nconst systemsTableId = resourceIdToHex({\n type: \"system\",\n namespace: worldConfig.namespace,\n name: worldConfig.tables.Systems.name,\n});\n\ntype Options = {\n tx: string;\n worldAddress?: string;\n configPath?: string;\n profile?: string;\n srcDir?: string;\n rpc?: string;\n};\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"trace\",\n\n describe: \"Display the trace of a transaction\",\n\n builder(yargs) {\n return yargs.options({\n tx: { type: \"string\", required: true, description: \"Transaction hash to replay\" },\n worldAddress: {\n type: \"string\",\n description: \"World contract address. Defaults to the value from worlds.json, based on rpc's chainId\",\n },\n configPath: { type: \"string\", description: \"Path to the config file\" },\n profile: { type: \"string\", description: \"The foundry profile to use\" },\n srcDir: { type: \"string\", description: \"Source directory. Defaults to foundry src directory.\" },\n rpc: { type: \"string\", description: \"json rpc endpoint. Defaults to foundry's configured eth_rpc_url\" },\n });\n },\n\n async handler(args) {\n args.profile ??= process.env.FOUNDRY_PROFILE;\n const { profile } = args;\n args.srcDir ??= await getSrcDirectory(profile);\n args.rpc ??= await getRpcUrl(profile);\n const { tx, configPath, srcDir, rpc } = args;\n\n const existingContracts = getExistingContracts(srcDir);\n\n // Load the config\n const mudConfig = (await loadConfig(configPath)) as StoreConfig & WorldConfig;\n\n const resolvedConfig = resolveWorldConfig(\n mudConfig,\n existingContracts.map(({ basename }) => basename)\n );\n\n // Get worldAddress either from args or from worldsFile\n const worldAddress = args.worldAddress ?? (await getWorldAddress(mudConfig.worldsFile, rpc));\n\n // Create World contract instance from deployed address\n const provider = new ethers.providers.StaticJsonRpcProvider(rpc);\n const WorldContract = new ethers.Contract(worldAddress, IBaseWorldAbi, provider);\n\n // TODO account for multiple namespaces (https://github.com/latticexyz/mud/issues/994)\n const namespace = mudConfig.namespace;\n const names = Object.values(resolvedConfig.systems).map(({ name }) => name);\n\n // Fetch system table field layout from chain\n const systemTableFieldLayout = await WorldContract.getFieldLayout(systemsTableId);\n const labels: { name: string; address: string }[] = [];\n for (const name of names) {\n const systemSelector = resourceIdToHex({ type: \"system\", namespace, name });\n // Get the first field of `Systems` table (the table maps system name to its address and other data)\n const address = await WorldContract.getField(systemsTableId, [systemSelector], 0, systemTableFieldLayout);\n labels.push({ name, address });\n }\n\n const result = await cast([\n \"run\",\n \"--label\",\n `${worldAddress}:World`,\n ...labels.map(({ name, address }) => [\"--label\", `${address}:${name}`]).flat(),\n `${tx}`,\n ]);\n console.log(result);\n\n process.exit(0);\n },\n};\n\nexport default commandModule;\n\nasync function getWorldAddress(worldsFile: string, rpc: string) {\n if (existsSync(worldsFile)) {\n const chainId = await getChainId(rpc);\n const deploys = JSON.parse(readFileSync(worldsFile, \"utf-8\"));\n\n if (!deploys[chainId]) {\n throw new MUDError(`chainId ${chainId} is missing in worldsFile \"${worldsFile}\"`);\n }\n return deploys[chainId].address as string;\n } else {\n throw new MUDError(\"worldAddress is not specified and worldsFile is missing\");\n }\n}\n","import type { CommandModule } from \"yargs\";\nimport {\n anvil,\n forge,\n getRemappings,\n getRpcUrl,\n getScriptDirectory,\n getSrcDirectory,\n} from \"@latticexyz/common/foundry\";\nimport chalk from \"chalk\";\nimport chokidar from \"chokidar\";\nimport { loadConfig, resolveConfigPath } from \"@latticexyz/config/node\";\nimport { StoreConfig } from \"@latticexyz/store\";\nimport { tablegen } from \"@latticexyz/store/codegen\";\nimport path from \"path\";\nimport { debounce } from \"throttle-debounce\";\nimport { worldgenHandler } from \"./worldgen\";\nimport { WorldConfig } from \"@latticexyz/world\";\nimport { homedir } from \"os\";\nimport { rmSync } from \"fs\";\nimport { execa } from \"execa\";\nimport { logError } from \"../utils/errors\";\nimport { deployHandler } from \"../utils/deployHandler\";\nimport { printMUD } from \"../utils/printMUD\";\n\ntype Options = {\n rpc?: string;\n configPath?: string;\n};\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"dev-contracts\",\n\n describe: \"Start a development server for MUD contracts\",\n\n builder(yargs) {\n return yargs.options({\n rpc: {\n type: \"string\",\n decs: \"RPC endpoint of the development node. If none is provided, an anvil instance is spawned in the background on port 8545.\",\n },\n configPath: {\n type: \"string\",\n decs: \"Path to MUD config\",\n },\n });\n },\n\n async handler(args) {\n // Initial cleanup\n await forge([\"clean\"]);\n\n const rpc = args.rpc ?? (await getRpcUrl());\n const configPath = args.configPath ?? (await resolveConfigPath(args.configPath));\n const srcDirectory = await getSrcDirectory();\n const scriptDirectory = await getScriptDirectory();\n const remappings = await getRemappings();\n const initialConfig = (await loadConfig(configPath)) as StoreConfig & WorldConfig;\n\n // Initial run of all codegen steps before starting anvil\n // (so clients can wait for everything to be ready before starting)\n await handleConfigChange(initialConfig);\n await handleContractsChange(initialConfig);\n\n // Start an anvil instance in the background if no RPC url is provided\n if (!args.rpc) {\n console.log(chalk.gray(\"Cleaning devnode cache\"));\n const userHomeDir = homedir();\n rmSync(path.join(userHomeDir, \".foundry\", \"anvil\", \"tmp\"), { recursive: true, force: true });\n\n const anvilArgs = [\"--block-time\", \"1\", \"--block-base-fee-per-gas\", \"0\"];\n anvil(anvilArgs);\n }\n\n const changedSinceLastHandled = {\n config: false,\n contracts: false,\n };\n\n const changeInProgress = {\n current: false,\n };\n\n // Watch for changes\n const configWatcher = chokidar.watch([configPath, srcDirectory]);\n configWatcher.on(\"all\", async (_, updatePath) => {\n if (updatePath.includes(configPath)) {\n changedSinceLastHandled.config = true;\n // We trigger contract changes if the config changed here instead of\n // listening to changes in the codegen directory to avoid an infinite loop\n changedSinceLastHandled.contracts = true;\n }\n\n if (updatePath.includes(srcDirectory) || updatePath.includes(scriptDirectory)) {\n // Ignore changes to codegen files to avoid an infinite loop\n if (updatePath.includes(initialConfig.codegenDirectory)) return;\n changedSinceLastHandled.contracts = true;\n }\n\n // Trigger debounced onChange\n handleChange();\n });\n\n const handleChange = debounce(100, async () => {\n // Avoid handling changes multiple times in parallel\n if (changeInProgress.current) return;\n changeInProgress.current = true;\n\n // Reset dirty flags\n const { config, contracts } = changedSinceLastHandled;\n changedSinceLastHandled.config = false;\n changedSinceLastHandled.contracts = false;\n\n try {\n // Load latest config\n const mudConfig = (await loadConfig(configPath)) as StoreConfig & WorldConfig;\n\n // Handle changes\n if (config) await handleConfigChange(mudConfig);\n if (contracts) await handleContractsChange(mudConfig);\n\n await deploy();\n } catch (error) {\n console.error(chalk.red(\"MUD dev-contracts watcher failed to deploy config or contracts changes\\n\"));\n logError(error);\n }\n\n changeInProgress.current = false;\n if (changedSinceLastHandled.config || changedSinceLastHandled.contracts) {\n console.log(\"Detected change while handling the previous change\");\n handleChange();\n }\n\n printMUD();\n console.log(\"MUD watching for changes...\");\n });\n\n /** Codegen to run if config changes */\n async function handleConfigChange(config: StoreConfig & WorldConfig) {\n console.log(chalk.blue(\"mud.config.ts changed - regenerating tables and recs types\"));\n // Run tablegen to generate tables based on the config\n const outPath = path.join(srcDirectory, config.codegenDirectory);\n await tablegen(config, outPath, remappings);\n }\n\n /** Codegen to run if contracts changed */\n async function handleContractsChange(config: StoreConfig & WorldConfig) {\n console.log(chalk.blue(\"contracts changed - regenerating interfaces and contract types\"));\n\n // Run worldgen to generate interfaces based on the systems\n await worldgenHandler({ config, clean: true, srcDir: srcDirectory });\n\n // Build the contracts\n await forge([\"build\", \"--skip\", \"test\", \"script\"]);\n\n // Generate TS type definitions for ABIs\n await execa(\"mud\", [\"abi-ts\"], { stdio: \"inherit\" });\n }\n\n /** Run after codegen if either mud config or contracts changed */\n async function deploy() {\n console.log(chalk.blue(\"redeploying World\"));\n await deployHandler({\n configPath,\n skipBuild: true,\n priorityFeeMultiplier: 1,\n disableTxWait: true,\n pollInterval: 1000,\n saveDeployment: true,\n srcDir: srcDirectory,\n rpc,\n });\n }\n },\n};\n\nexport default commandModule;\n","import chalk from \"chalk\";\n\nexport function printMUD() {\n console.log(\n chalk.yellow(`\n.------..------..------.\n|M.--. ||U.--. ||D.--. |\n| (\\\\/) || (\\\\/) || :/\\\\: |\n| :\\\\/: || :\\\\/: || (__) |\n| '--'M|| '--'U|| '--'D|\n'------''------''------'\n`)\n );\n}\n"],"mappings":";sDAEA,OAAOA,OAAW,QAClB,OAAS,WAAAC,OAAe,gBCDxB,OAAOC,OAAe,yBACtB,OAAOC,OAAW,qBCHlB,OAAS,UAAAC,OAAc,KACvB,OAAS,WAAAC,OAAe,KACxB,OAAOC,OAAU,OAEjB,OAAS,SAAAC,OAAa,QAMtB,IAAMC,GAAiD,CACrD,QAAS,UAET,SAAU,8CAEV,QAAQC,EAAO,CACb,OAAOA,EAAM,QAAQ,CACnB,UAAW,CAAE,KAAM,SAAU,QAAS,EAAG,KAAM,2CAA4C,CAC7F,CAAC,CACH,EAEA,MAAM,QAAQ,CAAE,UAAAC,CAAU,EAAG,CAC3B,QAAQ,IAAI,0BAA0B,EACtC,IAAMC,EAAcN,GAAQ,EAC5BD,GAAOE,GAAK,KAAKK,EAAa,WAAY,QAAS,KAAK,EAAG,CAAE,UAAW,GAAM,MAAO,EAAK,CAAC,EAE3F,IAAMC,EAAY,CAAC,KAAM,OAAOF,CAAS,EAAG,2BAA4B,GAAG,EAC3E,QAAQ,IAAI,kBAAkBE,EAAU,KAAK,GAAG,GAAG,EACnD,IAAMC,EAAQN,GAAM,QAASK,EAAW,CACtC,MAAO,CAAC,UAAW,UAAW,SAAS,CACzC,CAAC,EAED,QAAQ,GAAG,SAAU,IAAM,CACzB,QAAQ,IAAI;AAAA,8CAAiD,EAC7DC,EAAM,KAAK,EACX,QAAQ,KAAK,CACf,CAAC,EACD,MAAMA,CACR,CACF,EAEOC,EAAQN,GCxCf,OAAS,2BAAAO,OAA+B,8BACxC,OAAS,iBAAAC,GAAe,gBAAAC,OAAoB,gBAC5C,OAAOC,MAAW,QAClB,OAAS,qBAAAC,OAAyB,+CAalC,SAASC,GAAoBC,EAAa,CACxC,OAAOJ,GAAaF,GAAyBC,GAAcK,EAAKF,GAAkB,CAAC,CAAC,CACtF,CAEA,IAAMG,GAAiD,CACrD,QAAS,SAET,SAAU,6BAEV,QAAQC,EAAO,CACb,OAAOA,EAAM,QAAQ,CACnB,QAAS,CACP,KAAM,UACN,KAAM,kFACN,QAAS,EACX,EACA,UAAW,CACT,KAAM,SACN,KAAM,wBACN,QAAS,gDACX,EACA,QAAS,CACP,KAAM,SACN,KAAM,2BACN,SAAU,EACZ,CACF,CAAC,CACH,EAEA,MAAM,QAAQ,CAAE,QAAAC,EAAS,UAAAC,EAAW,QAAAC,CAAQ,EAAG,CAC7C,IAAMC,EAASP,GAAoBK,CAAS,EAExCD,IACF,QAAQ,IAAIN,EAAM,OAAO,cAAeQ,CAAO,CAAC,EAChD,MAAMC,EAAO,QAAQ,CAAE,QAAAD,CAAQ,CAAC,EAChC,QAAQ,IAAIR,EAAM,OAAO,SAAS,CAAC,GAGrC,QAAQ,KAAK,CAAC,CAChB,CACF,EAEOU,EAAQN,GCpDf,IAAMO,GAAiD,CACrD,QAAS,eAET,SAAU,0BAEV,QAAQC,EAAO,CACb,OAAOA,EACJ,QAAQ,CACP,MAAO,CAAE,KAAM,SAAU,CAC3B,CAAC,EACA,WAAW,OAAQ,CAAE,KAAM,SAAU,aAAc,EAAK,CAAC,CAC9D,EAEA,QAAQ,CAAE,KAAAC,CAAK,EAAG,CAChB,IAAMC,EAAW,OAAOD,KACxB,QAAQ,IAAIC,CAAQ,EACpB,QAAQ,KAAK,CAAC,CAChB,CACF,EAEOC,EAAQJ,GC3Bf,OAAOK,OAAU,OAEjB,OAAS,cAAAC,OAAkB,0BAE3B,OAAS,YAAAC,OAAgB,4BACzB,OAAS,iBAAAC,GAAe,mBAAAC,OAAuB,6BAM/C,IAAMC,GAAiD,CACrD,QAAS,WAET,SAAU,kEAEV,QAAQC,EAAO,CACb,OAAOA,EAAM,QAAQ,CACnB,WAAY,CAAE,KAAM,SAAU,KAAM,yBAA0B,CAChE,CAAC,CACH,EAEA,MAAM,QAAQ,CAAE,WAAAC,CAAW,EAAG,CAC5B,IAAMC,EAAU,MAAMP,GAAWM,CAAU,EACrCE,EAAS,MAAML,GAAgB,EAC/BM,EAAa,MAAMP,GAAc,EAEvC,MAAMD,GAASM,EAAQR,GAAK,KAAKS,EAAQD,EAAO,gBAAgB,EAAGE,CAAU,EAE7E,QAAQ,KAAK,CAAC,CAChB,CACF,EAEOC,EAAQN,GCjCf,OAAOO,MAAW,QAClB,OAAS,YAAAC,OAAgB,MACzB,OAAS,gBAAAC,GAAc,mBAAAC,OAAuB,uBAC9C,OAAS,yBAAAC,OAA6B,qBACtC,OAAS,YAAAC,OAAgB,4BAElB,SAASC,EAASC,EAAgB,CACvC,GAAIA,aAAiBJ,GACnB,QAAQ,IAAIH,EAAM,UAAUO,EAAM,OAAO,CAAC,UACjCA,aAAiBN,GAAU,CAGpC,IAAMO,EAAkBN,GAAaK,EAAO,CAC1C,gBAAiB;AAAA,IACjB,eAAgB;AAAA,GAClB,CAAC,EACD,QAAQ,IAAIP,EAAM,UAAUQ,EAAgB,OAAO,CAAC,OAC3CD,aAAiBH,IAC1B,QAAQ,IAAIJ,EAAM,IAAIO,EAAM,OAAO,CAAC,EACpC,QAAQ,IAAI,EAAE,EAGd,QAAQ,IAAIP,EAAM,KAAK,qFAAqF,CAAC,GACpGO,aAAiBF,GAC1B,QAAQ,IAAIL,EAAM,IAAIO,CAAK,CAAC,EAE5B,QAAQ,IAAIA,CAAK,CAErB,CCxBO,IAAME,EAAiB,CAC5B,WAAY,CAAE,KAAM,SAAU,KAAM,yBAA0B,EAC9D,MAAO,CAAE,KAAM,UAAW,KAAM,wEAAyE,EACzG,YAAa,CAAE,KAAM,UAAW,KAAM,2BAA4B,EAClE,QAAS,CAAE,KAAM,SAAU,KAAM,4BAA6B,EAC9D,MAAO,CAAE,KAAM,UAAW,KAAM,4CAA6C,EAC7E,sBAAuB,CACrB,KAAM,SACN,KAAM,6DACN,QAAS,CACX,EACA,eAAgB,CAAE,KAAM,UAAW,KAAM,qCAAsC,QAAS,EAAK,EAC7F,IAAK,CAAE,KAAM,SAAU,KAAM,yEAA0E,EACvG,aAAc,CAAE,KAAM,SAAU,KAAM,kDAAmD,EACzF,OAAQ,CAAE,KAAM,SAAU,KAAM,sDAAuD,EACvF,cAAe,CAAE,KAAM,UAAW,KAAM,oDAAqD,QAAS,EAAM,EAC5G,aAAc,CACZ,KAAM,SACN,KAAM,oFACN,QAAS,GACX,EACA,UAAW,CAAE,KAAM,UAAW,KAAM,gDAAiD,CACvF,EAEMC,GAA6D,CACjE,QAAS,SAET,SAAU,uBAEV,QAAQC,EAAO,CACb,OAAOA,EAAM,QAAQF,CAAc,CACrC,EAEA,MAAM,QAAQG,EAAM,CAClB,GAAI,CACF,MAAMC,EAAcD,CAAI,CAC1B,OAASE,EAAP,CACAC,EAASD,CAAK,EACd,QAAQ,KAAK,CAAC,CAChB,CACA,QAAQ,KAAK,CAAC,CAChB,CACF,EAEOE,EAAQN,GC/Cf,OAAS,cAAAO,OAAkB,0BAG3B,OAAS,YAAAC,OAAgB,yBACzB,OAAS,mBAAAC,OAAuB,6BAChC,OAAOC,MAAU,OACjB,OAAS,UAAAC,OAAc,KAUvB,IAAMC,GAAiD,CACrD,QAAS,WAET,SAAU,gGAEV,QAAQC,EAAO,CACb,OAAOA,EAAM,QAAQ,CACnB,WAAY,CAAE,KAAM,SAAU,KAAM,yBAA0B,EAC9D,MAAO,CACL,KAAM,UACN,KAAM,mFACN,QAAS,EACX,CACF,CAAC,CACH,EAEA,MAAM,QAAQC,EAAM,CAClB,MAAMC,EAAgBD,CAAI,EAC1B,QAAQ,KAAK,CAAC,CAChB,CACF,EAEA,eAAsBC,EAAgBD,EAAe,CACnD,IAAME,EAASF,EAAK,QAAW,MAAMG,GAAgB,EAE/CC,EAAoBC,EAAqBH,CAAM,EAG/CI,EAAYN,EAAK,QAAY,MAAMO,GAAWP,EAAK,UAAU,EAE7DQ,EAAsBC,EAAK,KAAKP,EAAQI,EAAU,gBAAgB,EAGpEN,EAAK,OAAOU,GAAOD,EAAK,KAAKD,EAAqBF,EAAU,iBAAiB,EAAG,CAAE,UAAW,GAAM,MAAO,EAAK,CAAC,EAGpH,MAAMK,GAASL,EAAWF,EAAmBI,CAAmB,CAClE,CAEA,IAAOI,EAAQd,GCxDf,OAAOe,MAAW,QAClB,OAAS,gBAAAC,GAAc,iBAAAC,OAAqB,KAC5C,OAAOC,MAAU,OAEjB,OAAS,YAAAC,MAAgB,4BCJzB,IAAAC,EAAA,CACE,KAAQ,kBACR,QAAW,gBACX,YAAe,iCACf,WAAc,CACZ,KAAQ,MACR,IAAO,wCACP,UAAa,cACf,EACA,QAAW,MACX,KAAQ,SACR,QAAW,CACT,IAAK,iBACP,EACA,MAAS,eACT,IAAO,CACL,IAAO,eACT,EACA,QAAW,CACT,MAAS,kDACT,WAAY,iCACZ,oBAAqB,wCACrB,MAAS,kDACT,WAAY,cACZ,oBAAqB,qBACrB,IAAO,eACP,KAAQ,qBACR,QAAW,yCACX,KAAQ,6BACR,UAAW,eACb,EACA,aAAgB,CACd,qBAAsB,SACtB,2BAA4B,SAC5B,2BAA4B,UAC5B,+CAAgD,UAChD,qBAAsB,cACtB,qBAAsB,cACtB,qBAAsB,cACtB,yBAA0B,cAC1B,8BAA+B,cAC/B,0BAA2B,cAC3B,uBAAwB,cACxB,oBAAqB,cACrB,oBAAqB,cACrB,oBAAqB,cACrB,4BAA6B,cAC7B,MAAS,SACT,SAAY,SACZ,OAAU,UACV,IAAO,SACP,OAAU,SACV,MAAS,SACT,KAAQ,SACR,gBAAiB,SACjB,QAAW,SACX,KAAQ,UACR,oBAAqB,SACrB,WAAc,QACd,KAAQ,SACR,MAAS,UACT,IAAO,UACP,uBAAwB,QAC1B,EACA,gBAAmB,CACjB,aAAc,SACd,cAAe,SACf,cAAe,YACf,iBAAkB,SAClB,2BAA4B,SAC5B,eAAgB,WAChB,UAAW,kFACX,YAAa,uFACb,KAAQ,SACR,IAAO,UACP,OAAU,QACZ,EACA,QAAW,0CACb,EDvEA,OAAOC,OAAU,OEPjB,OAAS,YAAAC,GAAU,KAAAC,MAAS,MAG5B,IAAMC,GAAYD,EAAE,OAAO,CACzB,aAAcA,EAAE,OAAO,EAAE,UAAWE,GAAU,KAAK,MAAMA,CAAK,CAAgB,CAChF,CAAC,EAED,SAASC,IAAsC,CAC7C,GAAI,CACF,OAAOF,GAAU,MAAM,CAErB,aAAc,q2CAChB,CAAC,CACH,OAASG,EAAP,CACA,GAAIA,aAAiBL,GAAU,CAC7B,GAAM,CAAE,QAAAM,EAAS,GAAGC,CAAe,EAAIF,EAAM,OAAO,EACpD,QAAQ,MAAM;AAAA;AAAA;AAAA,IAAoD,OAAO,KAAKE,CAAc,EAAE,KAAK;AAAA,GAAM;AAAA,CAAK,EAC9G,QAAQ,KAAK,CAAC,EAEhB,MAAMF,CACR,CACF,CAEO,IAAMG,EAAcJ,GAAS,EAAE,aFHtC,IAAMK,GAAiD,CACrD,QAAS,cAET,SAAU,mGAEV,QAAQC,EAAO,CACb,OAAOA,EAAM,QAAQ,CACnB,WAAY,CAAE,MAAO,IAAK,KAAM,SAAU,YAAa,8BAA+B,EACtF,IAAK,CACH,MAAO,IACP,KAAM,SACN,YAAa,2DACf,EACA,OAAQ,CACN,MAAO,IACP,KAAM,SACN,YAAa,kEACf,EACA,KAAM,CAAE,MAAO,IAAK,KAAM,SAAU,YAAa,uDAAwD,CAC3G,CAAC,CACH,EAEA,MAAM,QAAQC,EAAS,CACrB,GAAI,CACF,IAAMC,EAA2B,CAAC,aAAc,OAAQ,MAAO,SAAU,SAAS,EAC5EC,EAA8BD,EAAyB,OAC3D,CAACE,EAAKC,IAASJ,EAAQI,CAAG,EAAID,EAAM,EAAIA,EACxC,CACF,EAEA,GAAID,IAAgC,EAClC,MAAM,IAAIG,EAAS,0CAA0CJ,EAAyB,KAAK,IAAI,GAAG,EAGpG,GAAIC,EAA8B,EAChC,MAAM,IAAIG,EAAS,yCAAyCJ,EAAyB,KAAK,IAAI,GAAG,EAInGD,EAAQ,WAAa,MAAMM,GAAeN,CAAO,EAGjD,IAAMO,EAAeC,GAAK,KAAK,iBAAiB,EAAE,OAAQC,GAAM,CAACA,EAAE,SAAS,cAAc,CAAC,EAC3F,QAAWC,KAAeH,EACxBI,GAAkBD,EAAaV,CAAO,CAE1C,OAASY,EAAP,CACAC,EAASD,CAAC,CACZ,QAAE,CACA,QAAQ,KAAK,CAAC,CAChB,CACF,CACF,EAEA,eAAeN,GAAeN,EAAkB,CAE1CA,EAAQ,aAAe,WAAUA,EAAQ,IAAM,QAEnD,IAAIc,EACJ,GAAI,CACF,QAAQ,IAAIC,EAAM,KAAK,6BAA6B,CAAC,EACrDD,EAAY,MAAO,MAAM,MAAM,8BAA8BE,EAAiB,MAAM,GAAG,KAAK,CAC9F,MAAE,CACA,MAAM,IAAIX,EAAS,wCAAwC,CAC7D,CAEA,GAAIL,EAAQ,IAAK,CACf,IAAMiB,EAAUH,EAAU,WAAW,EAAEd,EAAQ,GAAG,EAClD,GAAI,CAACiB,EACH,MAAM,IAAIZ,EAAS,wCAAwCL,EAAQ,MAAM,EAE3E,eAAQ,IAAIe,EAAM,MAAM,2BAA2Bf,EAAQ,QAAQiB,GAAS,CAAC,EACtEA,EAGT,GAAIjB,EAAQ,OAAQ,CAElB,IAAMkB,EAASlB,EAAQ,OAAO,UAAU,EAAG,CAAC,EACtCiB,EAAU,OAAO,KAAKH,EAAU,QAAW,EAAE,KAAMK,GAAOA,EAAa,SAASD,CAAM,CAAC,EAC7F,GAAI,CAACD,EACH,MAAM,IAAIZ,EAAS,+CAA+CL,EAAQ,SAAS,EAErF,eAAQ,IAAIe,EAAM,MAAM,uBAAuBf,EAAQ,WAAWiB,GAAS,CAAC,EACrEA,EAIT,OAAOjB,EAAQ,UACjB,CAEA,SAASW,GAAkBS,EAAkBpB,EAA6C,CACxF,GAAM,CAAE,KAAAqB,CAAK,EAAIrB,EACb,CAAE,WAAAsB,CAAW,EAAItB,EAEfU,EAAca,GAAgBH,CAAQ,EACtCI,EAAkB,OAAO,KAAKC,CAAW,EAGzCC,EAA0C,CAAC,EACjD,QAAWC,KAAejB,EAAY,aAChCc,EAAgB,SAASG,CAAW,IACtCD,EAAgBC,CAAW,EAAIjB,EAAY,aAAaiB,CAAW,GAKvE,IAAMC,EAA6C,CAAC,EACpD,QAAWD,KAAejB,EAAY,gBAChCc,EAAgB,SAASG,CAAW,IACtCC,EAAmBD,CAAW,EAAIjB,EAAY,gBAAgBiB,CAAW,GAK7E,QAAWA,KAAejB,EAAY,aAChCc,EAAgB,SAASG,CAAW,IACtCjB,EAAY,aAAaiB,CAAW,EAAIE,EAAkBF,EAAa,cAAc,GAKzF,QAAWA,KAAejB,EAAY,gBAChCc,EAAgB,SAASG,CAAW,IACtCjB,EAAY,gBAAgBiB,CAAW,EAAIE,EAAkBF,EAAa,iBAAiB,GAK/F,OAAAG,GAAcV,EAAU,KAAK,UAAUV,EAAa,KAAM,CAAC,EAAI;AAAA,CAAI,EAEnE,QAAQ,IAAI,YAAYU,GAAU,EAClCW,EAAcL,EAAiBhB,EAAY,YAAY,EACvDqB,EAAcH,EAAoBlB,EAAY,eAAe,EAEtDA,EAEP,SAASmB,EAAkBG,EAAaC,EAA0C,CAEhF,OADIZ,IAAMC,EAAaY,GAAgBd,EAAUC,EAAMW,CAAG,GACrDV,GAAmBZ,EAAYuB,CAAI,EAAED,CAAG,CAE/C,CACF,CAEA,SAAST,GAAgBY,EAIvB,CACA,GAAI,CACF,IAAMC,EAAaC,GAAaF,EAAM,MAAM,EAC5C,OAAO,KAAK,MAAMC,CAAU,CAC9B,MAAE,CACA,MAAM,IAAI/B,EAAS,0BAA4B8B,CAAI,CACrD,CACF,CAEA,SAASJ,EAAcO,EAA8BC,EAA8B,CACjF,QAAWP,KAAOM,EACZA,EAAKN,CAAG,IAAMO,EAAKP,CAAG,GACxB,QAAQ,IAAI,GAAGA,MAAQjB,EAAM,IAAIuB,EAAKN,CAAG,CAAC,QAAQjB,EAAM,MAAMwB,EAAKP,CAAG,CAAC,GAAG,CAGhF,CAKA,SAASE,GAAgBM,EAAyBC,EAAqBd,EAAqB,CAC1F,IAAMe,EAAwBP,EAAK,SAASA,EAAK,QAAQK,CAAe,EAAG,QAAQ,IAAI,CAAC,EAExF,MAAO,QADUL,EAAK,KAAKO,EAAuBD,EAAahB,EAAYE,CAAW,EAAE,SAAS,CAEnG,CAEA,IAAOgB,EAAQ7C,GGhMf,OAAS,SAAA8C,GAAO,SAAAC,GAAO,aAAAC,OAAiB,6BACxC,OAAOC,OAAW,QAClB,OAAS,UAAAC,EAAQ,iBAAAC,OAAqB,KAMtC,IAAMC,EAAqB,WAErBC,GAAiD,CACrD,QAAS,OAET,SAAU,6BAEV,QAAQC,EAAO,CACb,OAAOA,EAAM,QAAQ,CACnB,GAAGC,EACH,KAAM,CAAE,KAAM,SAAU,YAAa,gDAAiD,QAAS,IAAK,EACpG,aAAc,CACZ,KAAM,SACN,YACE,8IACJ,EACA,aAAc,CAAE,KAAM,SAAU,YAAa,+BAAgC,CAC/E,CAAC,CACH,EAEA,MAAM,QAAQC,EAAM,CAElB,GAAI,CAACA,EAAK,aAAc,CACtB,IAAMC,EAAY,CAAC,2BAA4B,IAAK,SAAU,OAAOD,EAAK,IAAI,CAAC,EAC/EE,GAAMD,CAAS,EAGjB,IAAME,EAAUH,EAAK,aAAe,MAAMI,GAAUJ,EAAK,OAAO,EAAI,oBAAoBA,EAAK,OAEvFK,EACJL,EAAK,eAEH,MAAMM,EAAc,CAClB,GAAGN,EACH,eAAgB,GAChB,IAAKG,CACP,CAAC,GACD,aAEJ,QAAQ,IAAII,GAAM,KAAK,gBAAiBF,CAAY,CAAC,EAGrDG,GAAcZ,EAAoBS,CAAY,EAE9C,IAAMI,EAAcT,EAAK,cAAc,WAAW,KAAM,EAAE,EAAE,MAAM,GAAG,GAAK,CAAC,EAC3E,GAAI,CACF,IAAMU,EAAa,MAAMC,GAAM,CAAC,OAAQ,aAAcR,EAAS,GAAGM,CAAW,EAAG,CAC9E,QAAST,EAAK,OAChB,CAAC,EACD,QAAQ,IAAIU,CAAU,CACxB,OAASE,EAAP,CACA,QAAQ,MAAMA,CAAC,EACfC,EAAOjB,CAAkB,EACzB,QAAQ,KAAK,CAAC,CAChB,CAEAiB,EAAOjB,CAAkB,EACzB,QAAQ,KAAK,CAAC,CAChB,CACF,EAEOkB,EAAQjB,GCtEf,OAAS,cAAAkB,GAAY,gBAAAC,OAAoB,KAEzC,OAAS,UAAAC,MAAc,SAEvB,OAAS,cAAAC,OAAkB,0BAC3B,OAAS,YAAAC,MAAgB,4BACzB,OAAS,QAAAC,GAAM,aAAAC,GAAW,mBAAAC,OAAuB,6BAEjD,OAAS,sBAAAC,OAAuC,oBAChD,OAAOC,OAAmB,0DAA2D,MAAO,CAAE,KAAM,MAAO,EAC3G,OAAOC,MAAiB,kCACxB,OAAS,mBAAAC,MAAuB,qBAKhC,IAAMC,EAAiBC,EAAgB,CACrC,KAAM,SACN,UAAWC,EAAY,UACvB,KAAMA,EAAY,OAAO,QAAQ,IACnC,CAAC,EAWKC,GAAiD,CACrD,QAAS,QAET,SAAU,qCAEV,QAAQC,EAAO,CACb,OAAOA,EAAM,QAAQ,CACnB,GAAI,CAAE,KAAM,SAAU,SAAU,GAAM,YAAa,4BAA6B,EAChF,aAAc,CACZ,KAAM,SACN,YAAa,wFACf,EACA,WAAY,CAAE,KAAM,SAAU,YAAa,yBAA0B,EACrE,QAAS,CAAE,KAAM,SAAU,YAAa,4BAA6B,EACrE,OAAQ,CAAE,KAAM,SAAU,YAAa,sDAAuD,EAC9F,IAAK,CAAE,KAAM,SAAU,YAAa,iEAAkE,CACxG,CAAC,CACH,EAEA,MAAM,QAAQC,EAAM,CAClBA,EAAK,UAAY,QAAQ,IAAI,gBAC7B,GAAM,CAAE,QAAAC,CAAQ,EAAID,EACpBA,EAAK,SAAW,MAAME,GAAgBD,CAAO,EAC7CD,EAAK,MAAQ,MAAMG,GAAUF,CAAO,EACpC,GAAM,CAAE,GAAAG,EAAI,WAAAC,EAAY,OAAAC,EAAQ,IAAAC,CAAI,EAAIP,EAElCQ,EAAoBC,EAAqBH,CAAM,EAG/CI,EAAa,MAAMC,GAAWN,CAAU,EAExCO,EAAiBC,GACrBH,EACAF,EAAkB,IAAI,CAAC,CAAE,SAAAM,CAAS,IAAMA,CAAQ,CAClD,EAGMC,EAAef,EAAK,cAAiB,MAAMgB,GAAgBN,EAAU,WAAYH,CAAG,EAGpFU,EAAW,IAAIC,EAAO,UAAU,sBAAsBX,CAAG,EACzDY,EAAgB,IAAID,EAAO,SAASH,EAAcK,GAAeH,CAAQ,EAGzEI,EAAYX,EAAU,UACtBY,EAAQ,OAAO,OAAOV,EAAe,OAAO,EAAE,IAAI,CAAC,CAAE,KAAAW,CAAK,IAAMA,CAAI,EAGpEC,EAAyB,MAAML,EAAc,eAAexB,CAAc,EAC1E8B,EAA8C,CAAC,EACrD,QAAWF,KAAQD,EAAO,CACxB,IAAMI,EAAiB9B,EAAgB,CAAE,KAAM,SAAU,UAAAyB,EAAW,KAAAE,CAAK,CAAC,EAEpEI,GAAU,MAAMR,EAAc,SAASxB,EAAgB,CAAC+B,CAAc,EAAG,EAAGF,CAAsB,EACxGC,EAAO,KAAK,CAAE,KAAAF,EAAM,QAAAI,EAAQ,CAAC,EAG/B,IAAMC,EAAS,MAAMC,GAAK,CACxB,MACA,UACA,GAAGd,UACH,GAAGU,EAAO,IAAI,CAAC,CAAE,KAAAF,EAAM,QAAAI,CAAQ,IAAM,CAAC,UAAW,GAAGA,KAAWJ,GAAM,CAAC,EAAE,KAAK,EAC7E,GAAGnB,GACL,CAAC,EACD,QAAQ,IAAIwB,CAAM,EAElB,QAAQ,KAAK,CAAC,CAChB,CACF,EAEOE,EAAQhC,GAEf,eAAekB,GAAgBe,EAAoBxB,EAAa,CAC9D,GAAIyB,GAAWD,CAAU,EAAG,CAC1B,IAAME,EAAU,MAAMC,EAAW3B,CAAG,EAC9B4B,EAAU,KAAK,MAAMC,GAAaL,EAAY,OAAO,CAAC,EAE5D,GAAI,CAACI,EAAQF,CAAO,EAClB,MAAM,IAAII,EAAS,WAAWJ,+BAAqCF,IAAa,EAElF,OAAOI,EAAQF,CAAO,EAAE,YAExB,OAAM,IAAII,EAAS,yDAAyD,CAEhF,CClHA,OACE,SAAAC,GACA,SAAAC,EACA,iBAAAC,GACA,aAAAC,GACA,sBAAAC,GACA,mBAAAC,OACK,6BACP,OAAOC,MAAW,QAClB,OAAOC,OAAc,WACrB,OAAS,cAAAC,GAAY,qBAAAC,OAAyB,0BAE9C,OAAS,YAAAC,OAAgB,4BACzB,OAAOC,OAAU,OACjB,OAAS,YAAAC,OAAgB,oBAGzB,OAAS,WAAAC,OAAe,KACxB,OAAS,UAAAC,OAAc,KACvB,OAAS,SAAAC,OAAa,QCpBtB,OAAOC,OAAW,QAEX,SAASC,GAAW,CACzB,QAAQ,IACND,GAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAOhB,CACC,CACF,CDiBA,IAAME,GAAiD,CACrD,QAAS,gBAET,SAAU,+CAEV,QAAQC,EAAO,CACb,OAAOA,EAAM,QAAQ,CACnB,IAAK,CACH,KAAM,SACN,KAAM,yHACR,EACA,WAAY,CACV,KAAM,SACN,KAAM,oBACR,CACF,CAAC,CACH,EAEA,MAAM,QAAQC,EAAM,CAElB,MAAMC,EAAM,CAAC,OAAO,CAAC,EAErB,IAAMC,EAAMF,EAAK,KAAQ,MAAMG,GAAU,EACnCC,EAAaJ,EAAK,YAAe,MAAMK,GAAkBL,EAAK,UAAU,EACxEM,EAAe,MAAMC,GAAgB,EACrCC,EAAkB,MAAMC,GAAmB,EAC3CC,EAAa,MAAMC,GAAc,EACjCC,EAAiB,MAAMC,GAAWT,CAAU,EAQlD,GAJA,MAAMU,EAAmBF,CAAa,EACtC,MAAMG,EAAsBH,CAAa,EAGrC,CAACZ,EAAK,IAAK,CACb,QAAQ,IAAIgB,EAAM,KAAK,wBAAwB,CAAC,EAChD,IAAMC,EAAcC,GAAQ,EAC5BC,GAAOC,GAAK,KAAKH,EAAa,WAAY,QAAS,KAAK,EAAG,CAAE,UAAW,GAAM,MAAO,EAAK,CAAC,EAG3FI,GADkB,CAAC,eAAgB,IAAK,2BAA4B,GAAG,CACxD,EAGjB,IAAMC,EAA0B,CAC9B,OAAQ,GACR,UAAW,EACb,EAEMC,EAAmB,CACvB,QAAS,EACX,EAGsBC,GAAS,MAAM,CAACpB,EAAYE,CAAY,CAAC,EACjD,GAAG,MAAO,MAAOmB,EAAGC,IAAe,CAQ/C,GAPIA,EAAW,SAAStB,CAAU,IAChCkB,EAAwB,OAAS,GAGjCA,EAAwB,UAAY,IAGlCI,EAAW,SAASpB,CAAY,GAAKoB,EAAW,SAASlB,CAAe,EAAG,CAE7E,GAAIkB,EAAW,SAASd,EAAc,gBAAgB,EAAG,OACzDU,EAAwB,UAAY,GAItCK,EAAa,CACf,CAAC,EAED,IAAMA,EAAeC,GAAS,IAAK,SAAY,CAE7C,GAAIL,EAAiB,QAAS,OAC9BA,EAAiB,QAAU,GAG3B,GAAM,CAAE,OAAAM,EAAQ,UAAAC,CAAU,EAAIR,EAC9BA,EAAwB,OAAS,GACjCA,EAAwB,UAAY,GAEpC,GAAI,CAEF,IAAMS,EAAa,MAAMlB,GAAWT,CAAU,EAG1CyB,GAAQ,MAAMf,EAAmBiB,CAAS,EAC1CD,GAAW,MAAMf,EAAsBgB,CAAS,EAEpD,MAAMC,EAAO,CACf,OAASC,EAAP,CACA,QAAQ,MAAMjB,EAAM,IAAI;AAAA,CAA0E,CAAC,EACnGkB,EAASD,CAAK,CAChB,CAEAV,EAAiB,QAAU,IACvBD,EAAwB,QAAUA,EAAwB,aAC5D,QAAQ,IAAI,oDAAoD,EAChEK,EAAa,GAGfQ,EAAS,EACT,QAAQ,IAAI,6BAA6B,CAC3C,CAAC,EAGD,eAAerB,EAAmBe,EAAmC,CACnE,QAAQ,IAAIb,EAAM,KAAK,4DAA4D,CAAC,EAEpF,IAAMoB,EAAUhB,GAAK,KAAKd,EAAcuB,EAAO,gBAAgB,EAC/D,MAAMQ,GAASR,EAAQO,EAAS1B,CAAU,CAC5C,CAGA,eAAeK,EAAsBc,EAAmC,CACtE,QAAQ,IAAIb,EAAM,KAAK,gEAAgE,CAAC,EAGxF,MAAMsB,EAAgB,CAAE,OAAAT,EAAQ,MAAO,GAAM,OAAQvB,CAAa,CAAC,EAGnE,MAAML,EAAM,CAAC,QAAS,SAAU,OAAQ,QAAQ,CAAC,EAGjD,MAAMsC,GAAM,MAAO,CAAC,QAAQ,EAAG,CAAE,MAAO,SAAU,CAAC,CACrD,CAGA,eAAeP,GAAS,CACtB,QAAQ,IAAIhB,EAAM,KAAK,mBAAmB,CAAC,EAC3C,MAAMwB,EAAc,CAClB,WAAApC,EACA,UAAW,GACX,sBAAuB,EACvB,cAAe,GACf,aAAc,IACd,eAAgB,GAChB,OAAQE,EACR,IAAAJ,CACF,CAAC,CACH,CACF,CACF,EAEOuC,GAAQ3C,Gb/JR,IAAM4C,GAAsC,CACjDC,EACAC,EACAC,EACAC,GACAC,EACAC,EACAC,EACAC,EACAC,EACAC,EACAC,GACAC,EACF,EDtBA,UAAYC,OAAY,SACxB,OAAOC,OAAW,QACX,UAAO,EAEdC,GAAMC,GAAQ,QAAQ,IAAI,CAAC,EAExB,WAAW,KAAK,EAGhB,QAAQC,EAAe,EAEvB,OAAO,EAEP,KAAK,CAACC,EAAKC,IAAQ,CAClB,QAAQ,MAAML,GAAM,IAAII,CAAG,CAAC,EACxBA,EAAI,SAAS,2BAA2B,GAC1C,QAAQ,IACNJ,GAAM,OAAO,iBAAiB,QAAQ,KAAK,CAAC,2DAA2D,CACzG,EAEF,QAAQ,IAAI,EAAE,EAEVK,GAAO,OACTC,EAASD,CAAG,EACZ,QAAQ,IAAI,EAAE,GAGhB,QAAQ,KAAK,CAAC,CAChB,CAAC,EAEA,MAAM,CAAE,EAAG,MAAO,CAAC,EAAE","names":["yargs","hideBin","gasReport","abiTs","rmSync","homedir","path","execa","commandModule","yargs","blocktime","userHomeDir","anvilArgs","child","devnode_default","FaucetServiceDefinition","createChannel","createClient","chalk","NodeHttpTransport","createFaucetService","url","commandModule","yargs","dripDev","faucetUrl","address","faucet","faucet_default","commandModule","yargs","name","greeting","hello_default","path","loadConfig","tablegen","getRemappings","getSrcDirectory","commandModule","yargs","configPath","config","srcDir","remappings","tablegen_default","chalk","ZodError","fromZodError","ValidationError","NotInsideProjectError","MUDError","logError","error","validationError","yDeployOptions","commandModule","yargs","args","deployHandler","error","logError","deploy_default","loadConfig","worldgen","getSrcDirectory","path","rmSync","commandModule","yargs","args","worldgenHandler","srcDir","getSrcDirectory","existingContracts","getExistingContracts","mudConfig","loadConfig","outputBaseDirectory","path","rmSync","worldgen","worldgen_default","chalk","readFileSync","writeFileSync","path","MUDError","package_default","glob","ZodError","z","envSchema","value","parseEnv","error","_errors","invalidEnvVars","mudPackages","commandModule","yargs","options","mutuallyExclusiveOptions","numMutuallyExclusiveOptions","acc","opt","MUDError","resolveVersion","packageJsons","glob","p","packageJson","updatePackageJson","e","logError","npmResult","chalk","package_default","version","commit","v","filePath","link","mudVersion","readPackageJson","mudPackageNames","mudPackages","mudDependencies","packageName","mudDevDependencies","resolveMudVersion","writeFileSync","logComparison","key","type","resolveLinkPath","path","jsonString","readFileSync","prev","curr","packageJsonPath","mudLinkPath","packageJsonToRootPath","set_version_default","anvil","forge","getRpcUrl","chalk","rmSync","writeFileSync","WORLD_ADDRESS_FILE","commandModule","yargs","yDeployOptions","args","anvilArgs","anvil","forkRpc","getRpcUrl","worldAddress","deployHandler","chalk","writeFileSync","userOptions","testResult","forge","e","rmSync","test_default","existsSync","readFileSync","ethers","loadConfig","MUDError","cast","getRpcUrl","getSrcDirectory","resolveWorldConfig","IBaseWorldAbi","worldConfig","resourceIdToHex","systemsTableId","resourceIdToHex","worldConfig","commandModule","yargs","args","profile","getSrcDirectory","getRpcUrl","tx","configPath","srcDir","rpc","existingContracts","getExistingContracts","mudConfig","loadConfig","resolvedConfig","resolveWorldConfig","basename","worldAddress","getWorldAddress","provider","ethers","WorldContract","IBaseWorldAbi","namespace","names","name","systemTableFieldLayout","labels","systemSelector","address","result","cast","trace_default","worldsFile","existsSync","chainId","getChainId","deploys","readFileSync","MUDError","anvil","forge","getRemappings","getRpcUrl","getScriptDirectory","getSrcDirectory","chalk","chokidar","loadConfig","resolveConfigPath","tablegen","path","debounce","homedir","rmSync","execa","chalk","printMUD","commandModule","yargs","args","forge","rpc","getRpcUrl","configPath","resolveConfigPath","srcDirectory","getSrcDirectory","scriptDirectory","getScriptDirectory","remappings","getRemappings","initialConfig","loadConfig","handleConfigChange","handleContractsChange","chalk","userHomeDir","homedir","rmSync","path","anvil","changedSinceLastHandled","changeInProgress","chokidar","_","updatePath","handleChange","debounce","config","contracts","mudConfig","deploy","error","logError","printMUD","outPath","tablegen","worldgenHandler","execa","deployHandler","dev_contracts_default","commands","deploy_default","devnode_default","faucet_default","gasReport","hello_default","tablegen_default","worldgen_default","set_version_default","test_default","trace_default","dev_contracts_default","abiTs","dotenv","chalk","yargs","hideBin","commands","msg","err","logError"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@latticexyz/cli",
3
- "version": "2.0.0-next.10",
3
+ "version": "2.0.0-next.11",
4
4
  "description": "Command line interface for mud",
5
5
  "repository": {
6
6
  "type": "git",
@@ -33,21 +33,21 @@
33
33
  "path": "^0.12.7",
34
34
  "throttle-debounce": "^5.0.0",
35
35
  "typescript": "5.1.6",
36
- "viem": "1.6.0",
36
+ "viem": "1.14.0",
37
37
  "yargs": "^17.7.1",
38
38
  "zod": "^3.21.4",
39
39
  "zod-validation-error": "^1.3.0",
40
- "@latticexyz/abi-ts": "2.0.0-next.10",
41
- "@latticexyz/common": "2.0.0-next.10",
42
- "@latticexyz/config": "2.0.0-next.10",
43
- "@latticexyz/gas-report": "2.0.0-next.10",
44
- "@latticexyz/protocol-parser": "2.0.0-next.10",
45
- "@latticexyz/schema-type": "2.0.0-next.10",
46
- "@latticexyz/services": "2.0.0-next.10",
47
- "@latticexyz/store": "2.0.0-next.10",
48
- "@latticexyz/utils": "2.0.0-next.10",
49
- "@latticexyz/world": "2.0.0-next.10",
50
- "@latticexyz/world-modules": "2.0.0-next.10"
40
+ "@latticexyz/abi-ts": "2.0.0-next.11",
41
+ "@latticexyz/common": "2.0.0-next.11",
42
+ "@latticexyz/config": "2.0.0-next.11",
43
+ "@latticexyz/gas-report": "2.0.0-next.11",
44
+ "@latticexyz/protocol-parser": "2.0.0-next.11",
45
+ "@latticexyz/schema-type": "2.0.0-next.11",
46
+ "@latticexyz/services": "2.0.0-next.11",
47
+ "@latticexyz/store": "2.0.0-next.11",
48
+ "@latticexyz/utils": "2.0.0-next.11",
49
+ "@latticexyz/world": "2.0.0-next.11",
50
+ "@latticexyz/world-modules": "2.0.0-next.11"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@types/ejs": "^3.1.1",
@@ -1,11 +1,12 @@
1
1
  import chalk from "chalk";
2
- import { existsSync, readFileSync, rmSync, writeFileSync } from "fs";
2
+ import { readFileSync, writeFileSync } from "fs";
3
3
  import path from "path";
4
4
  import type { CommandModule } from "yargs";
5
5
  import { MUDError } from "@latticexyz/common/errors";
6
6
  import { logError } from "../utils/errors";
7
7
  import localPackageJson from "../../package.json" assert { type: "json" };
8
8
  import glob from "glob";
9
+ import { mudPackages } from "../mudPackages";
9
10
 
10
11
  type Options = {
11
12
  backup?: boolean;
@@ -17,9 +18,6 @@ type Options = {
17
18
  link?: string;
18
19
  };
19
20
 
20
- const BACKUP_FILE = ".mudbackup";
21
- const MUD_PREFIX = "@latticexyz";
22
-
23
21
  const commandModule: CommandModule<Options, Options> = {
24
22
  command: "set-version",
25
23
 
@@ -27,12 +25,6 @@ const commandModule: CommandModule<Options, Options> = {
27
25
 
28
26
  builder(yargs) {
29
27
  return yargs.options({
30
- backup: { type: "boolean", description: `Back up the current MUD versions to "${BACKUP_FILE}"` },
31
- force: {
32
- type: "boolean",
33
- description: `Backup fails if a "${BACKUP_FILE}" file is found, unless --force is provided`,
34
- },
35
- restore: { type: "boolean", description: `Restore the previous MUD versions from "${BACKUP_FILE}"` },
36
28
  mudVersion: { alias: "v", type: "string", description: "Set MUD to the given version" },
37
29
  tag: {
38
30
  alias: "t",
@@ -117,63 +109,39 @@ async function resolveVersion(options: Options) {
117
109
  }
118
110
 
119
111
  function updatePackageJson(filePath: string, options: Options): { workspaces?: string[] } {
120
- const { restore, force, link } = options;
121
- let { backup, mudVersion } = options;
122
-
123
- const backupFilePath = path.join(path.dirname(filePath), BACKUP_FILE);
124
- const backupFileExists = existsSync(backupFilePath);
125
-
126
- // Create a backup file for previous MUD versions by default if linking to local MUD
127
- if (link && !backupFileExists) backup = true;
128
-
129
- // If `backup` is true and force not set, check if a backup file already exists and throw an error if it does
130
- if (backup && !force && backupFileExists) {
131
- throw new MUDError(
132
- `A backup file already exists at ${backupFilePath}.\nUse --force to overwrite it or --restore to restore it.`
133
- );
134
- }
112
+ const { link } = options;
113
+ let { mudVersion } = options;
135
114
 
136
115
  const packageJson = readPackageJson(filePath);
137
-
138
- // Load .mudbackup if `restore` is true
139
- const backupJson = restore ? readPackageJson(backupFilePath) : undefined;
116
+ const mudPackageNames = Object.keys(mudPackages);
140
117
 
141
118
  // Find all MUD dependencies
142
119
  const mudDependencies: Record<string, string> = {};
143
- for (const key in packageJson.dependencies) {
144
- if (key.startsWith(MUD_PREFIX)) {
145
- mudDependencies[key] = packageJson.dependencies[key];
120
+ for (const packageName in packageJson.dependencies) {
121
+ if (mudPackageNames.includes(packageName)) {
122
+ mudDependencies[packageName] = packageJson.dependencies[packageName];
146
123
  }
147
124
  }
148
125
 
149
126
  // Find all MUD devDependencies
150
127
  const mudDevDependencies: Record<string, string> = {};
151
- for (const key in packageJson.devDependencies) {
152
- if (key.startsWith(MUD_PREFIX)) {
153
- mudDevDependencies[key] = packageJson.devDependencies[key];
128
+ for (const packageName in packageJson.devDependencies) {
129
+ if (mudPackageNames.includes(packageName)) {
130
+ mudDevDependencies[packageName] = packageJson.devDependencies[packageName];
154
131
  }
155
132
  }
156
133
 
157
- // Back up the current dependencies if `backup` is true
158
- if (backup) {
159
- writeFileSync(
160
- backupFilePath,
161
- JSON.stringify({ dependencies: mudDependencies, devDependencies: mudDevDependencies }, null, 2)
162
- );
163
- console.log(chalk.green(`Backed up MUD dependencies from ${filePath} to ${backupFilePath}`));
164
- }
165
-
166
134
  // Update the dependencies
167
- for (const key in packageJson.dependencies) {
168
- if (key.startsWith(MUD_PREFIX)) {
169
- packageJson.dependencies[key] = resolveMudVersion(key, "dependencies");
135
+ for (const packageName in packageJson.dependencies) {
136
+ if (mudPackageNames.includes(packageName)) {
137
+ packageJson.dependencies[packageName] = resolveMudVersion(packageName, "dependencies");
170
138
  }
171
139
  }
172
140
 
173
141
  // Update the devDependencies
174
- for (const key in packageJson.devDependencies) {
175
- if (key.startsWith(MUD_PREFIX)) {
176
- packageJson.devDependencies[key] = resolveMudVersion(key, "devDependencies");
142
+ for (const packageName in packageJson.devDependencies) {
143
+ if (mudPackageNames.includes(packageName)) {
144
+ packageJson.devDependencies[packageName] = resolveMudVersion(packageName, "devDependencies");
177
145
  }
178
146
  }
179
147
 
@@ -184,17 +152,9 @@ function updatePackageJson(filePath: string, options: Options): { workspaces?: s
184
152
  logComparison(mudDependencies, packageJson.dependencies);
185
153
  logComparison(mudDevDependencies, packageJson.devDependencies);
186
154
 
187
- // Remove the backup file if `restore` is true and `backup` is false
188
- // because the old backup file is no longer needed
189
- if (restore && !backup) {
190
- rmSync(backupFilePath);
191
- console.log(chalk.green(`Cleaned up ${backupFilePath}`));
192
- }
193
-
194
155
  return packageJson;
195
156
 
196
157
  function resolveMudVersion(key: string, type: "dependencies" | "devDependencies") {
197
- if (restore && backupJson) return backupJson[type][key];
198
158
  if (link) mudVersion = resolveLinkPath(filePath, link, key);
199
159
  if (!mudVersion) return packageJson[type][key];
200
160
  return mudVersion;
@@ -225,10 +185,9 @@ function logComparison(prev: Record<string, string>, curr: Record<string, string
225
185
  /**
226
186
  * Returns path of the package to link, given a path to a local MUD clone and a package
227
187
  */
228
- function resolveLinkPath(packageJsonPath: string, mudLinkPath: string, pkg: string) {
229
- const pkgName = pkg.replace(MUD_PREFIX, "");
188
+ function resolveLinkPath(packageJsonPath: string, mudLinkPath: string, packageName: string) {
230
189
  const packageJsonToRootPath = path.relative(path.dirname(packageJsonPath), process.cwd());
231
- const linkPath = path.join(packageJsonToRootPath, mudLinkPath, "packages", pkgName);
190
+ const linkPath = path.join(packageJsonToRootPath, mudLinkPath, mudPackages[packageName].localPath);
232
191
  return "link:" + linkPath;
233
192
  }
234
193
 
package/src/common.ts ADDED
@@ -0,0 +1 @@
1
+ export type MudPackages = Record<string, { localPath: string }>;
@@ -0,0 +1,24 @@
1
+ import { ZodError, z } from "zod";
2
+ import { MudPackages } from "./common";
3
+
4
+ const envSchema = z.object({
5
+ MUD_PACKAGES: z.string().transform((value) => JSON.parse(value) as MudPackages),
6
+ });
7
+
8
+ function parseEnv(): z.infer<typeof envSchema> {
9
+ try {
10
+ return envSchema.parse({
11
+ // tsup replaces the env vars with their values at compile time
12
+ MUD_PACKAGES: process.env.MUD_PACKAGES,
13
+ });
14
+ } catch (error) {
15
+ if (error instanceof ZodError) {
16
+ const { _errors, ...invalidEnvVars } = error.format();
17
+ console.error(`\nMissing or invalid environment variables:\n\n ${Object.keys(invalidEnvVars).join("\n ")}\n`);
18
+ process.exit(1);
19
+ }
20
+ throw error;
21
+ }
22
+ }
23
+
24
+ export const mudPackages = parseEnv().MUD_PACKAGES;