@latticexyz/cli 2.0.0-alpha.1.179 → 2.0.0-alpha.1.181
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 +10 -10
- package/dist/mud.js.map +1 -1
- package/package.json +10 -10
- package/src/commands/dev-contracts.ts +6 -0
package/dist/mud.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{d as
|
|
3
|
-
gracefully shutting down from SIGINT (Crtl-C)`),n.kill(),process.exit()}),await n}},U=
|
|
4
|
-
uint256 _gasreport;`)}let i=new RegExp(/\/\/ !gasreport (.*)\n(.*)/g),r;for(;(r=i.exec(o))!==null;){let
|
|
2
|
+
import{d as M,e as u}from"./chunk-3GOC5VHR.js";import Co from"yargs";import{hideBin as ko}from"yargs/helpers";import{rmSync as ie}from"fs";import{homedir as ae}from"os";import ce from"path";import{execa as le}from"execa";var de={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=ae();ie(ce.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}},U=de;import{FaucetServiceDefinition as pe}from"@latticexyz/services/faucet";import{createChannel as me,createClient as fe}from"nice-grpc-web";import P from"chalk";import{NodeHttpTransport as ge}from"@improbable-eng/grpc-web-node-http-transport";function ue(e){return fe(pe,me(e,ge()))}var ye={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=ue(o);e&&(console.log(P.yellow("Dripping to",t)),await n.dripDev({address:t}),console.log(P.yellow("Success"))),process.exit(0)}},E=ye;import{readFileSync as G,writeFileSync as j,rmSync as $}from"fs";import{execa as he}from"execa";import d from"chalk";import{table as be,getBorderCharacters as we}from"table";var W="MudGasReport",ve={command:"gas-report",describe:"Create a gas report",builder(e){return e.options({path:{type:"array",string:!0,default:["Gas.t.sol"],desc:"File containing the gas tests"},save:{type:"string",desc:"Save the gas report to a file"},compare:{type:"string",desc:"Compare to an existing gas report"}})},async handler({path:e,save:o,compare:t}){let n=e.filter(r=>r.endsWith(".t.sol")),s=await Promise.all(n.map(r=>De(r)));process.once("SIGINT",()=>{console.log("caught sigint, deleting temp files"),s.forEach(r=>$(r))});let i;try{i=await Ce()}catch{setTimeout(()=>process.exit());return}finally{s.forEach(r=>$(r))}if(t)try{let r=JSON.parse(G(t,"utf8"));i=i.map(l=>{let m=r.find(c=>c.name===l.name&&c.functionCall===l.functionCall);return{...l,prevGasUsed:m?.gasUsed}})}catch{console.log(d.red(`Gas report to compare not found: ${t}`)),t=void 0}ke(i,t),o&&xe(i,o),process.exit(0)}},I=ve;async function De(e){console.log("Creating gas report for",d.bold(e));let o=G(e,"utf8"),t=o,n=new RegExp(/function (.*){/g),s;for(;(s=n.exec(o))!==null;){let m=s[0];t=t.replace(m,`${m}
|
|
4
|
+
uint256 _gasreport;`)}let i=new RegExp(/\/\/ !gasreport (.*)\n(.*)/g),r;for(;(r=i.exec(o))!==null;){let m=r[1],c=r[2].trim();t=t.replace(r[0],`
|
|
5
5
|
_gasreport = gasleft();
|
|
6
6
|
${c}
|
|
7
7
|
_gasreport = _gasreport - gasleft();
|
|
8
|
-
console.log("GAS REPORT(${e}): ${
|
|
8
|
+
console.log("GAS REPORT(${e}): ${m} [${c.replaceAll('"','\\"')}]:", _gasreport);`)}t=t.replace(/pure/g,"view");let l=e.replace(/\.t\.sol$/,`${W}.t.sol`);return j(l,t),l}async function Ce(){console.log("Running gas report");let e=[],o="";try{o=(await he("forge",["test","--match-path",`*${W}*`,"-vvv"],{stdio:["inherit","pipe","inherit"]})).stdout}catch(s){throw console.log(s.stdout??s),console.log(d.red(`
|
|
9
9
|
-----------
|
|
10
|
-
Error while running the gas report (see above)`)),s}let t=new RegExp(/GAS REPORT\((.*)\): (.*) \[(.*)\]: (.*)/g),n;for(;(n=t.exec(o))!==null;){let s=n[1],i=n[2],r=n[3].replace(";",""),l=parseInt(n[4]);e.push({source:s,name:i,functionCall:r,gasUsed:l})}return e.sort((s,i)=>s.source.localeCompare(i.source)),e}function
|
|
11
|
-
`)}var
|
|
10
|
+
Error while running the gas report (see above)`)),s}let t=new RegExp(/GAS REPORT\((.*)\): (.*) \[(.*)\]: (.*)/g),n;for(;(n=t.exec(o))!==null;){let s=n[1],i=n[2],r=n[3].replace(";",""),l=parseInt(n[4]);e.push({source:s,name:i,functionCall:r,gasUsed:l})}return e.sort((s,i)=>s.source.localeCompare(i.source)),e}function ke(e,o){o&&console.log(d.bold(`Gas report compared to ${o}`));let t=[d.bold("Source"),d.bold("Name"),d.bold("Function call"),d.bold("Gas used"),...o?[d.bold("Prev gas used"),d.bold("Difference")]:[]],n=e.map(i=>{let r=i.prevGasUsed?i.gasUsed-i.prevGasUsed:0,l=r>0?d.red(`+${r}`):r<0?d.green(`${r}`):r,m=o?[i.prevGasUsed??"n/a",l]:[],c=r>0?d.red(i.gasUsed):r<0?d.green(i.gasUsed):i.gasUsed;return[i.source,i.name,i.functionCall,c,...m]}),s=[t,...n];console.log(be(s,{border:we("norc")}))}function xe(e,o){console.log(d.bold(`Saving gas report to ${o}`)),j(o,`${JSON.stringify(e,null,2)}
|
|
11
|
+
`)}var Me={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)}},A=Me;import Oe from"path";import{loadConfig as Se}from"@latticexyz/config/node";import{tablegen as Re}from"@latticexyz/store";import{getSrcDirectory as Ue}from"@latticexyz/common/foundry";var Pe={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 Se(e),t=await Ue();await Re(o,Oe.join(t,o.codegenDirectory)),process.exit(0)}},F=Pe;import{loadConfig as Ee}from"@latticexyz/config/node";var $e={command:"tsgen",describe:"Autogenerate MUD typescript definitions based on the config file",builder(e){return e.options({configPath:{type:"string",demandOption:!0,desc:"Path to the config file"},out:{type:"string",demandOption:!0,desc:"Directory to output MUD typescript definition files"}})},async handler(e){let{configPath:o,out:t}=e,n=await Ee(o);await M(n,t),process.exit(0)}},T=$e;import D from"chalk";import{ZodError as Ge}from"zod";import{fromZodError as je,ValidationError as We}from"zod-validation-error";import{NotInsideProjectError as Ie}from"@latticexyz/config";import{MUDError as Ae}from"@latticexyz/common/errors";function y(e){if(e instanceof We)console.log(D.redBright(e.message));else if(e instanceof Ge){let o=je(e,{prefixSeparator:`
|
|
12
12
|
- `,issueSeparator:`
|
|
13
|
-
- `});console.log(D.redBright(o.message))}else e instanceof
|
|
13
|
+
- `});console.log(D.redBright(o.message))}else e instanceof Ie?(console.log(D.red(e.message)),console.log(""),console.log(D.blue("To learn more about MUD's configuration, please go to https://mud.dev/packages/cli/"))):e instanceof Ae?console.log(D.red(e)):console.log(e)}import{getOutDirectory as Fe}from"@latticexyz/common/foundry";import Te from"path";import{runTypeChain as Ne}from"typechain";async function N(){let e=process.cwd(),o=await Fe(),t=Te.join(process.cwd(),o,"IWorld.sol/IWorld.json");await Ne({cwd:e,filesToProcess:[t],allFiles:[t],target:"ethers-v5"}),console.log("Typechain generated IWorld interface")}import ze from"chalk";function z(){console.log(ze.yellow(`
|
|
14
14
|
.------..------..------.
|
|
15
15
|
|M.--. ||U.--. ||D.--. |
|
|
16
16
|
| (\\/) || (\\/) || :/\\: |
|
|
17
17
|
| :\\/: || :\\/: || (__) |
|
|
18
18
|
| '--'M|| '--'U|| '--'D|
|
|
19
19
|
'------''------''------'
|
|
20
|
-
`))}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"}},
|
|
21
|
-
Use --force to overwrite it or --restore to restore it.`);let c=q(e),w=t?q(l):void 0,g={};for(let a in c.dependencies)a.startsWith(C)&&(g[a]=c.dependencies[a]);let v={};for(let a in c.devDependencies)a.startsWith(C)&&(v[a]=c.devDependencies[a]);i&&(H(l,JSON.stringify({dependencies:g,devDependencies:v},null,2)),console.log(b.green(`Backed up MUD dependencies from ${e} to ${l}`)));for(let a in c.dependencies)a.startsWith(C)&&(c.dependencies[a]=
|
|
22
|
-
`),console.log(`Updating ${e}`),Z(g,c.dependencies),Z(v,c.devDependencies),t&&!i&&(
|
|
20
|
+
`))}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"}},Ve={command:"deploy",describe:"Deploy MUD contracts",builder(e){return e.options(S)},async handler(e){try{await u(e)}catch(o){y(o),process.exit(1)}process.exit(0)}},V=Ve;import{loadConfig as Je}from"@latticexyz/config/node";import{worldgen as _e}from"@latticexyz/world/node";import{getSrcDirectory as Be}from"@latticexyz/common/foundry";import He from"glob";import J,{basename as Le}from"path";import{rmSync as qe}from"fs";var Ze={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"}})},async handler(e){await R(e),process.exit(0)}};async function R(e){let o=e.srcDir??await Be(),t=He.sync(`${o}/**/*.sol`).map(i=>({path:i,basename:Le(i,".sol")})),n=e.config??await Je(e.configPath),s=J.join(o,n.codegenDirectory);e.clean&&qe(J.join(s,n.worldgenDirectory),{recursive:!0,force:!0}),await _e(n,t,s)}var _=Ze;import b from"chalk";import{existsSync as Xe,readFileSync as Qe,rmSync as Ye,writeFileSync as H}from"fs";import h from"path";import{MUDError as k}from"@latticexyz/common/errors";var B={name:"@latticexyz/cli",version:"1.42.0",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","build:js":"tsup && chmod +x ./dist/mud.js",clean:"pnpm run clean:js","clean:js":"rimraf dist",dev:"tsup --watch","generate-test-tables":"tsx ./scripts/generate-test-tables.ts",lint:"eslint . --ext .ts",test:"tsc --noEmit && pnpm run generate-test-tables && forge 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/common":"workspace:*","@latticexyz/config":"workspace:*","@latticexyz/schema-type":"workspace:*","@latticexyz/services":"workspace:*","@latticexyz/solecs":"workspace:*","@latticexyz/std-contracts":"workspace:*","@latticexyz/store":"workspace:*","@latticexyz/world":"workspace:*","@typechain/ethers-v5":"^10.2.0",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",table:"^6.8.1","throttle-debounce":"^5.0.0",typechain:"^8.1.1",typescript:"^4.9.5",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#c9ce3f25bde29fc5eb9901842bf02850dfd2d084","forge-std":"https://github.com/foundry-rs/forge-std.git#b4f121555729b3afb3c5ffccb62ff4b6e2818fd3",tsup:"^6.7.0",tsx:"^3.12.6",vitest:"0.30.1"},gitHead:"914a1e0ae4a573d685841ca2ea921435057deb8f"};var O=".mudbackup",C="@latticexyz",eo={command:"set-version",describe:"Install a custom MUD version 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:"The MUD version to install"},link:{alias:"l",type:"string",description:"Relative path to the local MUD root directory to link"}})},async handler(e){try{if(!e.mudVersion&&!e.link&&!e.restore)throw new k("`--mudVersion` or `--link` is required unless --restore is provided.");if(e.link&&e.mudVersion)throw new k("Options `--link` and `--mudVersion` are mutually exclusive");e.mudVersion=e.mudVersion==="canary"?await oo(B.name):e.mudVersion;let o="./package.json",{workspaces:t}=L(o,e);if(t)for(let n of t){let s=h.join(n,"/package.json");L(s,e)}}catch(o){y(o)}finally{process.exit(0)}}};function L(e,o){let{restore:t,force:n,link:s}=o,{backup:i,mudVersion:r}=o,l=h.join(h.dirname(e),O),m=Xe(l);if(s&&!m&&(i=!0),i&&!n&&m)throw new k(`A backup file already exists at ${l}.
|
|
21
|
+
Use --force to overwrite it or --restore to restore it.`);let c=q(e),w=t?q(l):void 0,g={};for(let a in c.dependencies)a.startsWith(C)&&(g[a]=c.dependencies[a]);let v={};for(let a in c.devDependencies)a.startsWith(C)&&(v[a]=c.devDependencies[a]);i&&(H(l,JSON.stringify({dependencies:g,devDependencies:v},null,2)),console.log(b.green(`Backed up MUD dependencies from ${e} to ${l}`)));for(let a in c.dependencies)a.startsWith(C)&&(c.dependencies[a]=p(a,"dependencies"));for(let a in c.devDependencies)a.startsWith(C)&&(c.devDependencies[a]=p(a,"devDependencies"));return H(e,JSON.stringify(c,null,2)+`
|
|
22
|
+
`),console.log(`Updating ${e}`),Z(g,c.dependencies),Z(v,c.devDependencies),t&&!i&&(Ye(l),console.log(b.green(`Cleaned up ${l}`))),c;function p(a,f){return t&&w?w[f][a]:(s&&(r=to(e,s,a)),r||c[f][a])}}function q(e){try{let o=Qe(e,"utf8");return JSON.parse(o)}catch{throw new k("Could not read JSON at "+e)}}async function oo(e){try{console.log(b.blue("fetching MUD canary version..."));let t=(await(await fetch(`https://registry.npmjs.org/${e}`)).json())["dist-tags"].canary;return console.log(b.green("MUD canary version:",t)),t}catch{throw new k(`Could not fetch canary version of ${e}`)}}function Z(e,o){for(let t in e)e[t]!==o[t]&&console.log(`${t}: ${b.red(e[t])} -> ${b.green(o[t])}`)}function to(e,o,t){let n=t.replace(C,""),s=h.relative(h.dirname(e),process.cwd());return"link:"+h.join(s,o,"packages",n)}var K=eo;import{anvil as ro,forge as no,getRpcUrl as so}from"@latticexyz/common/foundry";import io from"chalk";import{rmSync as ao,writeFileSync as co}from"fs";var X=".mudtest",lo={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 s=["--block-base-fee-per-gas","0","--port",String(e.port)];ro(s)}let o=e.worldAddress?await so(e.profile):`http://127.0.0.1:${e.port}`,t=e.worldAddress??(await u({...e,saveDeployment:!1,rpc:o})).worldAddress;console.log(io.blue("World address",t)),co(X,t);let n=e.forgeOptions?.replaceAll("\\","").split(" ")??[];try{let s=await no(["test","--fork-url",o,...n],{profile:e.profile});console.log(s)}catch(s){console.error(s)}ao(X),process.exit(0)}},Q=lo;import{anvil as po,forge as Y,getRpcUrl as mo,getScriptDirectory as fo,getSrcDirectory as go}from"@latticexyz/common/foundry";import x from"chalk";import uo from"chokidar";import{loadConfig as ee,resolveConfigPath as yo}from"@latticexyz/config/node";import{tablegen as ho}from"@latticexyz/store";import oe from"path";import{debounce as bo}from"throttle-debounce";import{homedir as wo}from"os";import{rmSync as vo}from"fs";var Do={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"},tsgenOutput:{type:"string",demandOption:!0,desc:"Directory to output MUD typescript definition files"}})},async handler(e){e.tsgenOutputDir||console.error("No output provided"),await Y(["clean"]);let o=e.rpc??await mo(),t=e.configPath??await yo(e.configPath),n=await go(),s=await fo(),i=await ee(t);if(await w(i),await g(i),!e.rpc){console.log(x.gray("Cleaning devnode cache"));let p=wo();vo(oe.join(p,".foundry","anvil","tmp"),{recursive:!0,force:!0}),po(["--block-time","1","--block-base-fee-per-gas","0"])}let r={config:!1,contracts:!1},l={current:!1};uo.watch([t,n]).on("all",async(p,a)=>{if(a.includes(t)&&(r.config=!0,r.contracts=!0),a.includes(n)||a.includes(s)){if(a.includes(i.codegenDirectory))return;r.contracts=!0}c()});let c=bo(100,async()=>{if(l.current)return;l.current=!0;let{config:p,contracts:a}=r;r.config=!1,r.contracts=!1;try{let f=await ee(t);p&&await w(f),a&&await g(f),await v()}catch(f){console.error(x.red("MUD dev-contracts watcher failed to deploy config or contracts changes"),f)}l.current=!1,(r.config||r.contracts)&&(console.log("Detected change while handling the previous change"),c()),z(),console.log("MUD watching for changes...")});async function w(p){console.log(x.blue("mud.config.ts changed - regenerating tables and recs types"));let a=oe.join(n,p.codegenDirectory);await ho(p,a),await M(p,e.tsgenOutput)}async function g(p){console.log(x.blue("contracts changed - regenerating interfaces and contract types")),await R({config:p,clean:!0,srcDir:n}),await Y(["build"]),await N()}async function v(){console.log(x.blue("redeploying World")),await u({configPath:t,skipBuild:!0,priorityFeeMultiplier:1,disableTxWait:!0,pollInterval:1e3,saveDeployment:!0,srcDir:n,rpc:o})}}},te=Do;var re=[V,U,E,I,A,F,T,_,K,Q,te];import*as se from"dotenv";import ne from"chalk";se.config();Co(ko(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(""),y(o),console.log(""),process.exit(1)}).alias({h:"help"}).argv;
|
|
23
23
|
//# sourceMappingURL=mud.js.map
|
package/dist/mud.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mud.ts","../src/commands/devnode.ts","../src/commands/faucet.ts","../src/commands/gas-report.ts","../src/commands/hello.ts","../src/commands/tablegen.ts","../src/commands/tsgen.ts","../src/utils/errors.ts","../src/utils/worldtypes.ts","../src/utils/printMUD.ts","../src/commands/deploy.ts","../src/commands/worldgen.ts","../src/commands/set-version.ts","../package.json","../src/commands/test.ts","../src/commands/dev-contracts.ts","../src/commands/index.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 logError(err);\n console.log(\"\");\n\n process.exit(1);\n })\n // Useful aliases.\n .alias({ h: \"help\" }).argv;\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\";\nimport { readFileSync, writeFileSync, rmSync } from \"fs\";\nimport { execa } from \"execa\";\nimport chalk from \"chalk\";\nimport { table, getBorderCharacters } from \"table\";\n\n/**\n * Print the gas report to the console, save it to a file and compare it to a previous gas report if provided.\n * Requires forge to be installed, and gas test files including `// !gasreport` comments, like this:\n *\n * ```solidity\n * contract GasTest is DSTestPlus {\n * function testBuffer() public pure {\n * // !gasreport allocate a buffer\n * Buffer buffer = Buffer_.allocate(32);\n *\n * bytes32 value = keccak256(\"some data\");\n *\n * // !gasreport append 32 bytes to a buffer\n * buffer.append(value);\n * }\n * }\n * ```\n */\n\ntype Options = {\n path: string[];\n save?: string;\n compare?: string;\n};\n\ntype GasReportEntry = {\n source: string;\n name: string;\n functionCall: string;\n gasUsed: number;\n prevGasUsed?: number;\n};\n\ntype GasReport = GasReportEntry[];\n\nconst tempFileSuffix = \"MudGasReport\";\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"gas-report\",\n\n describe: \"Create a gas report\",\n\n builder(yargs) {\n return yargs.options({\n path: { type: \"array\", string: true, default: [\"Gas.t.sol\"], desc: \"File containing the gas tests\" },\n save: { type: \"string\", desc: \"Save the gas report to a file\" },\n compare: { type: \"string\", desc: \"Compare to an existing gas report\" },\n });\n },\n\n async handler({ path: files, save, compare }) {\n const validFiles = files.filter((file) => file.endsWith(\".t.sol\"));\n const tempFiles = await Promise.all(validFiles.map((file) => createGasReport(file)));\n\n process.once(\"SIGINT\", () => {\n console.log(\"caught sigint, deleting temp files\");\n tempFiles.forEach((file) => rmSync(file));\n });\n\n let gasReport: GasReport;\n try {\n gasReport = await runGasReport();\n } catch {\n setTimeout(() => process.exit());\n return;\n } finally {\n // Delete the temporary files\n tempFiles.forEach((file) => rmSync(file));\n }\n\n // If this gas report should be compared to an existing one, load the existing one\n if (compare) {\n try {\n const compareGasReport: GasReport = JSON.parse(readFileSync(compare, \"utf8\"));\n // Merge the previous gas report with the new one\n gasReport = gasReport.map((entry) => {\n const prevEntry = compareGasReport.find(\n (e) => e.name === entry.name && e.functionCall === entry.functionCall\n );\n return { ...entry, prevGasUsed: prevEntry?.gasUsed };\n });\n } catch {\n console.log(chalk.red(`Gas report to compare not found: ${compare}`));\n compare = undefined;\n }\n }\n\n // Print gas report\n printGasReport(gasReport, compare);\n\n // Save gas report to file if requested\n if (save) saveGasReport(gasReport, save);\n\n process.exit(0);\n },\n};\n\nexport default commandModule;\n\nasync function createGasReport(filename: string): Promise<string> {\n console.log(\"Creating gas report for\", chalk.bold(filename));\n\n // Parse the given test file, and add gas reporting wherever requested by a `// !gasreport` comment\n const fileContents = readFileSync(filename, \"utf8\");\n let newFile = fileContents;\n\n // Use a regex to find first line of each function\n const functionRegex = new RegExp(/function (.*){/g);\n // Insert a line to declare the _gasreport variable at the start of each function\n let functionMatch;\n while ((functionMatch = functionRegex.exec(fileContents)) !== null) {\n const functionSignature = functionMatch[0];\n newFile = newFile.replace(functionSignature, `${functionSignature}\\nuint256 _gasreport;`);\n }\n\n // A gasreport comment has a name (written after the comment) and a function call (written on the next line)\n // Create a regex to extract both the name and the function call\n const regex = new RegExp(/\\/\\/ !gasreport (.*)\\n(.*)/g);\n\n // Apply the regex and loop through the matches,\n // and create a new file with the gasreport comments replaced by the gas report\n let match;\n while ((match = regex.exec(fileContents)) !== null) {\n const name = match[1];\n const functionCall = match[2].trim();\n\n newFile = newFile.replace(\n match[0],\n `\n_gasreport = gasleft();\n${functionCall}\n_gasreport = _gasreport - gasleft();\nconsole.log(\"GAS REPORT(${filename}): ${name} [${functionCall.replaceAll('\"', '\\\\\"')}]:\", _gasreport);`\n );\n }\n\n // Remove all occurrences of `pure` with `view`\n newFile = newFile.replace(/pure/g, \"view\");\n\n // Write the new file to disk (temporarily)\n // Create the temp file by replacing the previous file name with MudGasReport\n const tempFileName = filename.replace(/\\.t\\.sol$/, `${tempFileSuffix}.t.sol`);\n writeFileSync(tempFileName, newFile);\n\n return tempFileName;\n}\n\nasync function runGasReport(): Promise<GasReport> {\n console.log(\"Running gas report\");\n const gasReport: GasReport = [];\n\n // Extract the logs from the child process\n let logs = \"\";\n try {\n // Run the generated file using forge\n const child = execa(\"forge\", [\"test\", \"--match-path\", `*${tempFileSuffix}*`, \"-vvv\"], {\n stdio: [\"inherit\", \"pipe\", \"inherit\"],\n });\n logs = (await child).stdout;\n } catch (error: any) {\n console.log(error.stdout ?? error);\n console.log(chalk.red(\"\\n-----------\\nError while running the gas report (see above)\"));\n throw error;\n }\n\n // Extract the gas reports from the logs\n\n // Create a regex to find all lines starting with `GAS REPORT:` and extract the name, function call and gas used\n const gasReportRegex = new RegExp(/GAS REPORT\\((.*)\\): (.*) \\[(.*)\\]: (.*)/g);\n\n // Loop through the matches and print the gas report\n let gasReportMatch;\n while ((gasReportMatch = gasReportRegex.exec(logs)) !== null) {\n const source = gasReportMatch[1];\n const name = gasReportMatch[2];\n const functionCall = gasReportMatch[3].replace(\";\", \"\");\n const gasUsed = parseInt(gasReportMatch[4]);\n gasReport.push({ source, name, functionCall, gasUsed });\n }\n\n gasReport.sort((a, b) => a.source.localeCompare(b.source));\n\n return gasReport;\n}\n\nfunction printGasReport(gasReport: GasReport, compare?: string) {\n if (compare) console.log(chalk.bold(`Gas report compared to ${compare}`));\n\n const headers = [\n chalk.bold(\"Source\"),\n chalk.bold(\"Name\"),\n chalk.bold(\"Function call\"),\n chalk.bold(\"Gas used\"),\n ...(compare ? [chalk.bold(\"Prev gas used\"), chalk.bold(\"Difference\")] : []),\n ];\n\n const values = gasReport.map((entry) => {\n const diff = entry.prevGasUsed ? entry.gasUsed - entry.prevGasUsed : 0;\n const diffEntry = diff > 0 ? chalk.red(`+${diff}`) : diff < 0 ? chalk.green(`${diff}`) : diff;\n const compareColumns = compare ? [entry.prevGasUsed ?? \"n/a\", diffEntry] : [];\n const gasUsedEntry = diff > 0 ? chalk.red(entry.gasUsed) : diff < 0 ? chalk.green(entry.gasUsed) : entry.gasUsed;\n return [entry.source, entry.name, entry.functionCall, gasUsedEntry, ...compareColumns];\n });\n\n const rows = [headers, ...values];\n\n console.log(table(rows, { border: getBorderCharacters(\"norc\") }));\n}\n\nfunction saveGasReport(gasReport: GasReport, path: string) {\n console.log(chalk.bold(`Saving gas report to ${path}`));\n writeFileSync(path, `${JSON.stringify(gasReport, null, 2)}\\n`);\n}\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, tablegen } from \"@latticexyz/store\";\nimport { 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\n await tablegen(config, path.join(srcDir, config.codegenDirectory));\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 { tsgen } from \"../render-ts/tsgen\";\n\ntype Options = {\n configPath: string;\n out: string;\n};\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"tsgen\",\n\n describe: \"Autogenerate MUD typescript definitions based on the config file\",\n\n builder(yargs) {\n return yargs.options({\n configPath: { type: \"string\", demandOption: true, desc: \"Path to the config file\" },\n out: { type: \"string\", demandOption: true, desc: \"Directory to output MUD typescript definition files\" },\n });\n },\n\n async handler(args) {\n const { configPath, out } = args;\n\n const config = (await loadConfig(configPath)) as StoreConfig;\n\n await tsgen(config, out);\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 { getOutDirectory } from \"@latticexyz/common/foundry\";\nimport path from \"path\";\nimport { runTypeChain } from \"typechain\";\n\n/**\n * Generate IWorld typescript bindings\n */\nexport async function worldtypes() {\n const cwd = process.cwd();\n const forgeOurDir = await getOutDirectory();\n const IWorldPath = path.join(process.cwd(), forgeOurDir, \"IWorld.sol/IWorld.json\");\n\n await runTypeChain({\n cwd,\n filesToProcess: [IWorldPath],\n allFiles: [IWorldPath],\n target: \"ethers-v5\",\n });\n\n console.log(\"Typechain generated IWorld interface\");\n}\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","import type { CommandModule, Options } from \"yargs\";\nimport { logError } from \"../utils/errors\";\nimport { deployHandler, DeployOptions } from \"../utils\";\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 glob from \"glob\";\nimport path, { basename } from \"path\";\nimport { rmSync } from \"fs\";\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: { type: \"boolean\", desc: \"Clear the worldgen directory before generating new interfaces\" },\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 // Get a list of all contract names\n const existingContracts = glob.sync(`${srcDir}/**/*.sol`).map((path) => ({\n path,\n basename: basename(path, \".sol\"),\n }));\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\" };\n\ntype Options = {\n backup?: boolean;\n force?: boolean;\n restore?: boolean;\n mudVersion?: 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: \"Install a custom MUD version 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: \"The MUD version to install\" },\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 if (!options.mudVersion && !options.link && !options.restore) {\n throw new MUDError(\"`--mudVersion` or `--link` is required unless --restore is provided.\");\n }\n\n // `link` and `mudVersion` are mutually exclusive\n if (options.link && options.mudVersion) {\n throw new MUDError(\"Options `--link` and `--mudVersion` are mutually exclusive\");\n }\n\n // Resolve the `canary` version number if needed\n options.mudVersion =\n options.mudVersion === \"canary\" ? await getCanaryVersion(localPackageJson.name) : options.mudVersion;\n\n // Read the current package.json\n const rootPath = \"./package.json\";\n const { workspaces } = updatePackageJson(rootPath, options);\n\n // Load the package.json of each workspace\n if (workspaces) {\n for (const workspace of workspaces) {\n const filePath = path.join(workspace, \"/package.json\");\n updatePackageJson(filePath, options);\n }\n }\n } catch (e) {\n logError(e);\n } finally {\n process.exit(0);\n }\n },\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\nasync function getCanaryVersion(pkg: string) {\n try {\n console.log(chalk.blue(\"fetching MUD canary version...\"));\n const result = await (await fetch(`https://registry.npmjs.org/${pkg}`)).json();\n const canary = result[\"dist-tags\"].canary;\n console.log(chalk.green(\"MUD canary version:\", canary));\n return canary;\n } catch (e) {\n throw new MUDError(`Could not fetch canary version of ${pkg}`);\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\": \"1.42.0\",\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\",\n \"build:js\": \"tsup && chmod +x ./dist/mud.js\",\n \"clean\": \"pnpm run clean:js\",\n \"clean:js\": \"rimraf dist\",\n \"dev\": \"tsup --watch\",\n \"generate-test-tables\": \"tsx ./scripts/generate-test-tables.ts\",\n \"lint\": \"eslint . --ext .ts\",\n \"test\": \"tsc --noEmit && pnpm run generate-test-tables && forge 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/common\": \"workspace:*\",\n \"@latticexyz/config\": \"workspace:*\",\n \"@latticexyz/schema-type\": \"workspace:*\",\n \"@latticexyz/services\": \"workspace:*\",\n \"@latticexyz/solecs\": \"workspace:*\",\n \"@latticexyz/std-contracts\": \"workspace:*\",\n \"@latticexyz/store\": \"workspace:*\",\n \"@latticexyz/world\": \"workspace:*\",\n \"@typechain/ethers-v5\": \"^10.2.0\",\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 \"table\": \"^6.8.1\",\n \"throttle-debounce\": \"^5.0.0\",\n \"typechain\": \"^8.1.1\",\n \"typescript\": \"^4.9.5\",\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#c9ce3f25bde29fc5eb9901842bf02850dfd2d084\",\n \"forge-std\": \"https://github.com/foundry-rs/forge-std.git#b4f121555729b3afb3c5ffccb62ff4b6e2818fd3\",\n \"tsup\": \"^6.7.0\",\n \"tsx\": \"^3.12.6\",\n \"vitest\": \"0.30.1\"\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 { deployHandler, DeployOptions } from \"../utils\";\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 }\n\n rmSync(WORLD_ADDRESS_FILE);\n\n process.exit(0);\n },\n};\n\nexport default commandModule;\n","import type { CommandModule } from \"yargs\";\nimport { anvil, forge, getRpcUrl, getScriptDirectory, getSrcDirectory } from \"@latticexyz/common/foundry\";\nimport chalk from \"chalk\";\nimport chokidar from \"chokidar\";\nimport { loadConfig, resolveConfigPath } from \"@latticexyz/config/node\";\nimport { StoreConfig, tablegen } from \"@latticexyz/store\";\nimport path from \"path\";\nimport { tsgen } from \"../render-ts\";\nimport { debounce } from \"throttle-debounce\";\nimport { worldgenHandler } from \"./worldgen\";\nimport { WorldConfig } from \"@latticexyz/world\";\nimport { deployHandler, printMUD, worldtypes } from \"../utils\";\n\ntype Options = {\n rpc?: string;\n configPath?: string;\n tsgenOutput: 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 tsgenOutput: { type: \"string\", demandOption: true, desc: \"Directory to output MUD typescript definition files\" },\n });\n },\n\n async handler(args) {\n if (!args.tsgenOutputDir) {\n console.error(\"No output provided\");\n }\n\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 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 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\"), 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);\n\n // Run tsgen to regenerate recs types based on the mud config\n await tsgen(config, args.tsgenOutput);\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\"]);\n\n // Run typechain to rebuild typescript types for the contracts\n await worldtypes();\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 { CommandModule } from \"yargs\";\n\nimport devnode from \"./devnode\";\nimport faucet from \"./faucet\";\nimport gasReport from \"./gas-report\";\nimport hello from \"./hello\";\nimport tablegen from \"./tablegen\";\nimport tsgen from \"./tsgen\";\nimport deploy from \"./deploy\";\nimport worldgen from \"./worldgen\";\nimport setVersion from \"./set-version\";\nimport test from \"./test\";\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,\n hello,\n tablegen,\n tsgen,\n worldgen,\n setVersion,\n test,\n devContracts,\n];\n"],"mappings":"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","names":["yargs","hideBin","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","readFileSync","writeFileSync","rmSync","execa","chalk","table","getBorderCharacters","tempFileSuffix","commandModule","yargs","files","save","compare","validFiles","file","tempFiles","createGasReport","gasReport","runGasReport","compareGasReport","entry","prevEntry","e","printGasReport","saveGasReport","gas_report_default","filename","fileContents","newFile","functionRegex","functionMatch","functionSignature","regex","match","name","functionCall","tempFileName","logs","error","gasReportRegex","gasReportMatch","source","gasUsed","a","b","headers","values","diff","diffEntry","compareColumns","gasUsedEntry","rows","path","commandModule","yargs","name","greeting","hello_default","path","loadConfig","tablegen","getSrcDirectory","commandModule","yargs","configPath","config","srcDir","tablegen_default","loadConfig","commandModule","yargs","args","configPath","out","config","loadConfig","tsgen","tsgen_default","chalk","ZodError","fromZodError","ValidationError","NotInsideProjectError","MUDError","logError","error","validationError","getOutDirectory","path","runTypeChain","worldtypes","cwd","forgeOurDir","IWorldPath","chalk","printMUD","yDeployOptions","commandModule","yargs","args","deployHandler","error","logError","deploy_default","loadConfig","worldgen","getSrcDirectory","glob","path","basename","rmSync","commandModule","yargs","args","worldgenHandler","srcDir","existingContracts","mudConfig","outputBaseDirectory","worldgen_default","chalk","existsSync","readFileSync","rmSync","writeFileSync","path","MUDError","package_default","BACKUP_FILE","MUD_PREFIX","commandModule","yargs","options","MUDError","getCanaryVersion","package_default","rootPath","workspaces","updatePackageJson","workspace","filePath","path","e","logError","restore","force","link","backup","mudVersion","backupFilePath","backupFileExists","existsSync","packageJson","readPackageJson","backupJson","mudDependencies","key","mudDevDependencies","writeFileSync","chalk","resolveMudVersion","logComparison","rmSync","type","resolveLinkPath","jsonString","readFileSync","pkg","canary","prev","curr","packageJsonPath","mudLinkPath","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","anvil","forge","getRpcUrl","getScriptDirectory","getSrcDirectory","chalk","chokidar","loadConfig","resolveConfigPath","tablegen","path","debounce","commandModule","yargs","args","forge","rpc","getRpcUrl","configPath","resolveConfigPath","srcDirectory","getSrcDirectory","scriptDirectory","getScriptDirectory","initialConfig","loadConfig","handleConfigChange","handleContractsChange","anvil","changedSinceLastHandled","changeInProgress","chokidar","_","updatePath","handleChange","debounce","config","contracts","mudConfig","deploy","error","chalk","printMUD","outPath","path","tablegen","tsgen","worldgenHandler","worldtypes","deployHandler","dev_contracts_default","commands","deploy_default","devnode_default","faucet_default","gas_report_default","hello_default","tablegen_default","tsgen_default","worldgen_default","set_version_default","test_default","dev_contracts_default","dotenv","chalk","yargs","hideBin","commands","msg","err","logError"]}
|
|
1
|
+
{"version":3,"sources":["../src/mud.ts","../src/commands/devnode.ts","../src/commands/faucet.ts","../src/commands/gas-report.ts","../src/commands/hello.ts","../src/commands/tablegen.ts","../src/commands/tsgen.ts","../src/utils/errors.ts","../src/utils/worldtypes.ts","../src/utils/printMUD.ts","../src/commands/deploy.ts","../src/commands/worldgen.ts","../src/commands/set-version.ts","../package.json","../src/commands/test.ts","../src/commands/dev-contracts.ts","../src/commands/index.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 logError(err);\n console.log(\"\");\n\n process.exit(1);\n })\n // Useful aliases.\n .alias({ h: \"help\" }).argv;\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\";\nimport { readFileSync, writeFileSync, rmSync } from \"fs\";\nimport { execa } from \"execa\";\nimport chalk from \"chalk\";\nimport { table, getBorderCharacters } from \"table\";\n\n/**\n * Print the gas report to the console, save it to a file and compare it to a previous gas report if provided.\n * Requires forge to be installed, and gas test files including `// !gasreport` comments, like this:\n *\n * ```solidity\n * contract GasTest is DSTestPlus {\n * function testBuffer() public pure {\n * // !gasreport allocate a buffer\n * Buffer buffer = Buffer_.allocate(32);\n *\n * bytes32 value = keccak256(\"some data\");\n *\n * // !gasreport append 32 bytes to a buffer\n * buffer.append(value);\n * }\n * }\n * ```\n */\n\ntype Options = {\n path: string[];\n save?: string;\n compare?: string;\n};\n\ntype GasReportEntry = {\n source: string;\n name: string;\n functionCall: string;\n gasUsed: number;\n prevGasUsed?: number;\n};\n\ntype GasReport = GasReportEntry[];\n\nconst tempFileSuffix = \"MudGasReport\";\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"gas-report\",\n\n describe: \"Create a gas report\",\n\n builder(yargs) {\n return yargs.options({\n path: { type: \"array\", string: true, default: [\"Gas.t.sol\"], desc: \"File containing the gas tests\" },\n save: { type: \"string\", desc: \"Save the gas report to a file\" },\n compare: { type: \"string\", desc: \"Compare to an existing gas report\" },\n });\n },\n\n async handler({ path: files, save, compare }) {\n const validFiles = files.filter((file) => file.endsWith(\".t.sol\"));\n const tempFiles = await Promise.all(validFiles.map((file) => createGasReport(file)));\n\n process.once(\"SIGINT\", () => {\n console.log(\"caught sigint, deleting temp files\");\n tempFiles.forEach((file) => rmSync(file));\n });\n\n let gasReport: GasReport;\n try {\n gasReport = await runGasReport();\n } catch {\n setTimeout(() => process.exit());\n return;\n } finally {\n // Delete the temporary files\n tempFiles.forEach((file) => rmSync(file));\n }\n\n // If this gas report should be compared to an existing one, load the existing one\n if (compare) {\n try {\n const compareGasReport: GasReport = JSON.parse(readFileSync(compare, \"utf8\"));\n // Merge the previous gas report with the new one\n gasReport = gasReport.map((entry) => {\n const prevEntry = compareGasReport.find(\n (e) => e.name === entry.name && e.functionCall === entry.functionCall\n );\n return { ...entry, prevGasUsed: prevEntry?.gasUsed };\n });\n } catch {\n console.log(chalk.red(`Gas report to compare not found: ${compare}`));\n compare = undefined;\n }\n }\n\n // Print gas report\n printGasReport(gasReport, compare);\n\n // Save gas report to file if requested\n if (save) saveGasReport(gasReport, save);\n\n process.exit(0);\n },\n};\n\nexport default commandModule;\n\nasync function createGasReport(filename: string): Promise<string> {\n console.log(\"Creating gas report for\", chalk.bold(filename));\n\n // Parse the given test file, and add gas reporting wherever requested by a `// !gasreport` comment\n const fileContents = readFileSync(filename, \"utf8\");\n let newFile = fileContents;\n\n // Use a regex to find first line of each function\n const functionRegex = new RegExp(/function (.*){/g);\n // Insert a line to declare the _gasreport variable at the start of each function\n let functionMatch;\n while ((functionMatch = functionRegex.exec(fileContents)) !== null) {\n const functionSignature = functionMatch[0];\n newFile = newFile.replace(functionSignature, `${functionSignature}\\nuint256 _gasreport;`);\n }\n\n // A gasreport comment has a name (written after the comment) and a function call (written on the next line)\n // Create a regex to extract both the name and the function call\n const regex = new RegExp(/\\/\\/ !gasreport (.*)\\n(.*)/g);\n\n // Apply the regex and loop through the matches,\n // and create a new file with the gasreport comments replaced by the gas report\n let match;\n while ((match = regex.exec(fileContents)) !== null) {\n const name = match[1];\n const functionCall = match[2].trim();\n\n newFile = newFile.replace(\n match[0],\n `\n_gasreport = gasleft();\n${functionCall}\n_gasreport = _gasreport - gasleft();\nconsole.log(\"GAS REPORT(${filename}): ${name} [${functionCall.replaceAll('\"', '\\\\\"')}]:\", _gasreport);`\n );\n }\n\n // Remove all occurrences of `pure` with `view`\n newFile = newFile.replace(/pure/g, \"view\");\n\n // Write the new file to disk (temporarily)\n // Create the temp file by replacing the previous file name with MudGasReport\n const tempFileName = filename.replace(/\\.t\\.sol$/, `${tempFileSuffix}.t.sol`);\n writeFileSync(tempFileName, newFile);\n\n return tempFileName;\n}\n\nasync function runGasReport(): Promise<GasReport> {\n console.log(\"Running gas report\");\n const gasReport: GasReport = [];\n\n // Extract the logs from the child process\n let logs = \"\";\n try {\n // Run the generated file using forge\n const child = execa(\"forge\", [\"test\", \"--match-path\", `*${tempFileSuffix}*`, \"-vvv\"], {\n stdio: [\"inherit\", \"pipe\", \"inherit\"],\n });\n logs = (await child).stdout;\n } catch (error: any) {\n console.log(error.stdout ?? error);\n console.log(chalk.red(\"\\n-----------\\nError while running the gas report (see above)\"));\n throw error;\n }\n\n // Extract the gas reports from the logs\n\n // Create a regex to find all lines starting with `GAS REPORT:` and extract the name, function call and gas used\n const gasReportRegex = new RegExp(/GAS REPORT\\((.*)\\): (.*) \\[(.*)\\]: (.*)/g);\n\n // Loop through the matches and print the gas report\n let gasReportMatch;\n while ((gasReportMatch = gasReportRegex.exec(logs)) !== null) {\n const source = gasReportMatch[1];\n const name = gasReportMatch[2];\n const functionCall = gasReportMatch[3].replace(\";\", \"\");\n const gasUsed = parseInt(gasReportMatch[4]);\n gasReport.push({ source, name, functionCall, gasUsed });\n }\n\n gasReport.sort((a, b) => a.source.localeCompare(b.source));\n\n return gasReport;\n}\n\nfunction printGasReport(gasReport: GasReport, compare?: string) {\n if (compare) console.log(chalk.bold(`Gas report compared to ${compare}`));\n\n const headers = [\n chalk.bold(\"Source\"),\n chalk.bold(\"Name\"),\n chalk.bold(\"Function call\"),\n chalk.bold(\"Gas used\"),\n ...(compare ? [chalk.bold(\"Prev gas used\"), chalk.bold(\"Difference\")] : []),\n ];\n\n const values = gasReport.map((entry) => {\n const diff = entry.prevGasUsed ? entry.gasUsed - entry.prevGasUsed : 0;\n const diffEntry = diff > 0 ? chalk.red(`+${diff}`) : diff < 0 ? chalk.green(`${diff}`) : diff;\n const compareColumns = compare ? [entry.prevGasUsed ?? \"n/a\", diffEntry] : [];\n const gasUsedEntry = diff > 0 ? chalk.red(entry.gasUsed) : diff < 0 ? chalk.green(entry.gasUsed) : entry.gasUsed;\n return [entry.source, entry.name, entry.functionCall, gasUsedEntry, ...compareColumns];\n });\n\n const rows = [headers, ...values];\n\n console.log(table(rows, { border: getBorderCharacters(\"norc\") }));\n}\n\nfunction saveGasReport(gasReport: GasReport, path: string) {\n console.log(chalk.bold(`Saving gas report to ${path}`));\n writeFileSync(path, `${JSON.stringify(gasReport, null, 2)}\\n`);\n}\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, tablegen } from \"@latticexyz/store\";\nimport { 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\n await tablegen(config, path.join(srcDir, config.codegenDirectory));\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 { tsgen } from \"../render-ts/tsgen\";\n\ntype Options = {\n configPath: string;\n out: string;\n};\n\nconst commandModule: CommandModule<Options, Options> = {\n command: \"tsgen\",\n\n describe: \"Autogenerate MUD typescript definitions based on the config file\",\n\n builder(yargs) {\n return yargs.options({\n configPath: { type: \"string\", demandOption: true, desc: \"Path to the config file\" },\n out: { type: \"string\", demandOption: true, desc: \"Directory to output MUD typescript definition files\" },\n });\n },\n\n async handler(args) {\n const { configPath, out } = args;\n\n const config = (await loadConfig(configPath)) as StoreConfig;\n\n await tsgen(config, out);\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 { getOutDirectory } from \"@latticexyz/common/foundry\";\nimport path from \"path\";\nimport { runTypeChain } from \"typechain\";\n\n/**\n * Generate IWorld typescript bindings\n */\nexport async function worldtypes() {\n const cwd = process.cwd();\n const forgeOurDir = await getOutDirectory();\n const IWorldPath = path.join(process.cwd(), forgeOurDir, \"IWorld.sol/IWorld.json\");\n\n await runTypeChain({\n cwd,\n filesToProcess: [IWorldPath],\n allFiles: [IWorldPath],\n target: \"ethers-v5\",\n });\n\n console.log(\"Typechain generated IWorld interface\");\n}\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","import type { CommandModule, Options } from \"yargs\";\nimport { logError } from \"../utils/errors\";\nimport { deployHandler, DeployOptions } from \"../utils\";\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 glob from \"glob\";\nimport path, { basename } from \"path\";\nimport { rmSync } from \"fs\";\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: { type: \"boolean\", desc: \"Clear the worldgen directory before generating new interfaces\" },\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 // Get a list of all contract names\n const existingContracts = glob.sync(`${srcDir}/**/*.sol`).map((path) => ({\n path,\n basename: basename(path, \".sol\"),\n }));\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\" };\n\ntype Options = {\n backup?: boolean;\n force?: boolean;\n restore?: boolean;\n mudVersion?: 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: \"Install a custom MUD version 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: \"The MUD version to install\" },\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 if (!options.mudVersion && !options.link && !options.restore) {\n throw new MUDError(\"`--mudVersion` or `--link` is required unless --restore is provided.\");\n }\n\n // `link` and `mudVersion` are mutually exclusive\n if (options.link && options.mudVersion) {\n throw new MUDError(\"Options `--link` and `--mudVersion` are mutually exclusive\");\n }\n\n // Resolve the `canary` version number if needed\n options.mudVersion =\n options.mudVersion === \"canary\" ? await getCanaryVersion(localPackageJson.name) : options.mudVersion;\n\n // Read the current package.json\n const rootPath = \"./package.json\";\n const { workspaces } = updatePackageJson(rootPath, options);\n\n // Load the package.json of each workspace\n if (workspaces) {\n for (const workspace of workspaces) {\n const filePath = path.join(workspace, \"/package.json\");\n updatePackageJson(filePath, options);\n }\n }\n } catch (e) {\n logError(e);\n } finally {\n process.exit(0);\n }\n },\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\nasync function getCanaryVersion(pkg: string) {\n try {\n console.log(chalk.blue(\"fetching MUD canary version...\"));\n const result = await (await fetch(`https://registry.npmjs.org/${pkg}`)).json();\n const canary = result[\"dist-tags\"].canary;\n console.log(chalk.green(\"MUD canary version:\", canary));\n return canary;\n } catch (e) {\n throw new MUDError(`Could not fetch canary version of ${pkg}`);\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\": \"1.42.0\",\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\",\n \"build:js\": \"tsup && chmod +x ./dist/mud.js\",\n \"clean\": \"pnpm run clean:js\",\n \"clean:js\": \"rimraf dist\",\n \"dev\": \"tsup --watch\",\n \"generate-test-tables\": \"tsx ./scripts/generate-test-tables.ts\",\n \"lint\": \"eslint . --ext .ts\",\n \"test\": \"tsc --noEmit && pnpm run generate-test-tables && forge 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/common\": \"workspace:*\",\n \"@latticexyz/config\": \"workspace:*\",\n \"@latticexyz/schema-type\": \"workspace:*\",\n \"@latticexyz/services\": \"workspace:*\",\n \"@latticexyz/solecs\": \"workspace:*\",\n \"@latticexyz/std-contracts\": \"workspace:*\",\n \"@latticexyz/store\": \"workspace:*\",\n \"@latticexyz/world\": \"workspace:*\",\n \"@typechain/ethers-v5\": \"^10.2.0\",\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 \"table\": \"^6.8.1\",\n \"throttle-debounce\": \"^5.0.0\",\n \"typechain\": \"^8.1.1\",\n \"typescript\": \"^4.9.5\",\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#c9ce3f25bde29fc5eb9901842bf02850dfd2d084\",\n \"forge-std\": \"https://github.com/foundry-rs/forge-std.git#b4f121555729b3afb3c5ffccb62ff4b6e2818fd3\",\n \"tsup\": \"^6.7.0\",\n \"tsx\": \"^3.12.6\",\n \"vitest\": \"0.30.1\"\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 { deployHandler, DeployOptions } from \"../utils\";\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 }\n\n rmSync(WORLD_ADDRESS_FILE);\n\n process.exit(0);\n },\n};\n\nexport default commandModule;\n","import type { CommandModule } from \"yargs\";\nimport { anvil, forge, getRpcUrl, getScriptDirectory, getSrcDirectory } from \"@latticexyz/common/foundry\";\nimport chalk from \"chalk\";\nimport chokidar from \"chokidar\";\nimport { loadConfig, resolveConfigPath } from \"@latticexyz/config/node\";\nimport { StoreConfig, tablegen } from \"@latticexyz/store\";\nimport path from \"path\";\nimport { tsgen } from \"../render-ts\";\nimport { debounce } from \"throttle-debounce\";\nimport { worldgenHandler } from \"./worldgen\";\nimport { WorldConfig } from \"@latticexyz/world\";\nimport { deployHandler, printMUD, worldtypes } from \"../utils\";\nimport { homedir } from \"os\";\nimport { rmSync } from \"fs\";\n\ntype Options = {\n rpc?: string;\n configPath?: string;\n tsgenOutput: 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 tsgenOutput: { type: \"string\", demandOption: true, desc: \"Directory to output MUD typescript definition files\" },\n });\n },\n\n async handler(args) {\n if (!args.tsgenOutputDir) {\n console.error(\"No output provided\");\n }\n\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 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\"), 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);\n\n // Run tsgen to regenerate recs types based on the mud config\n await tsgen(config, args.tsgenOutput);\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\"]);\n\n // Run typechain to rebuild typescript types for the contracts\n await worldtypes();\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 { CommandModule } from \"yargs\";\n\nimport devnode from \"./devnode\";\nimport faucet from \"./faucet\";\nimport gasReport from \"./gas-report\";\nimport hello from \"./hello\";\nimport tablegen from \"./tablegen\";\nimport tsgen from \"./tsgen\";\nimport deploy from \"./deploy\";\nimport worldgen from \"./worldgen\";\nimport setVersion from \"./set-version\";\nimport test from \"./test\";\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,\n hello,\n tablegen,\n tsgen,\n worldgen,\n setVersion,\n test,\n devContracts,\n];\n"],"mappings":"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","names":["yargs","hideBin","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","readFileSync","writeFileSync","rmSync","execa","chalk","table","getBorderCharacters","tempFileSuffix","commandModule","yargs","files","save","compare","validFiles","file","tempFiles","createGasReport","gasReport","runGasReport","compareGasReport","entry","prevEntry","e","printGasReport","saveGasReport","gas_report_default","filename","fileContents","newFile","functionRegex","functionMatch","functionSignature","regex","match","name","functionCall","tempFileName","logs","error","gasReportRegex","gasReportMatch","source","gasUsed","a","b","headers","values","diff","diffEntry","compareColumns","gasUsedEntry","rows","path","commandModule","yargs","name","greeting","hello_default","path","loadConfig","tablegen","getSrcDirectory","commandModule","yargs","configPath","config","srcDir","tablegen_default","loadConfig","commandModule","yargs","args","configPath","out","config","loadConfig","tsgen","tsgen_default","chalk","ZodError","fromZodError","ValidationError","NotInsideProjectError","MUDError","logError","error","validationError","getOutDirectory","path","runTypeChain","worldtypes","cwd","forgeOurDir","IWorldPath","chalk","printMUD","yDeployOptions","commandModule","yargs","args","deployHandler","error","logError","deploy_default","loadConfig","worldgen","getSrcDirectory","glob","path","basename","rmSync","commandModule","yargs","args","worldgenHandler","srcDir","existingContracts","mudConfig","outputBaseDirectory","worldgen_default","chalk","existsSync","readFileSync","rmSync","writeFileSync","path","MUDError","package_default","BACKUP_FILE","MUD_PREFIX","commandModule","yargs","options","MUDError","getCanaryVersion","package_default","rootPath","workspaces","updatePackageJson","workspace","filePath","path","e","logError","restore","force","link","backup","mudVersion","backupFilePath","backupFileExists","existsSync","packageJson","readPackageJson","backupJson","mudDependencies","key","mudDevDependencies","writeFileSync","chalk","resolveMudVersion","logComparison","rmSync","type","resolveLinkPath","jsonString","readFileSync","pkg","canary","prev","curr","packageJsonPath","mudLinkPath","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","anvil","forge","getRpcUrl","getScriptDirectory","getSrcDirectory","chalk","chokidar","loadConfig","resolveConfigPath","tablegen","path","debounce","homedir","rmSync","commandModule","yargs","args","forge","rpc","getRpcUrl","configPath","resolveConfigPath","srcDirectory","getSrcDirectory","scriptDirectory","getScriptDirectory","initialConfig","loadConfig","handleConfigChange","handleContractsChange","chalk","userHomeDir","path","anvil","changedSinceLastHandled","changeInProgress","chokidar","_","updatePath","handleChange","debounce","config","contracts","mudConfig","deploy","error","printMUD","outPath","tablegen","tsgen","worldgenHandler","worldtypes","deployHandler","dev_contracts_default","commands","deploy_default","devnode_default","faucet_default","gas_report_default","hello_default","tablegen_default","tsgen_default","worldgen_default","set_version_default","test_default","dev_contracts_default","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-alpha.1.
|
|
3
|
+
"version": "2.0.0-alpha.1.181+e80def85",
|
|
4
4
|
"description": "Command line interface for mud",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -31,14 +31,14 @@
|
|
|
31
31
|
"@ethersproject/providers": "^5.7.2",
|
|
32
32
|
"@improbable-eng/grpc-web": "^0.15.0",
|
|
33
33
|
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
|
|
34
|
-
"@latticexyz/common": "2.0.0-alpha.1.
|
|
35
|
-
"@latticexyz/config": "2.0.0-alpha.1.
|
|
36
|
-
"@latticexyz/schema-type": "2.0.0-alpha.1.
|
|
37
|
-
"@latticexyz/services": "2.0.0-alpha.1.
|
|
38
|
-
"@latticexyz/solecs": "2.0.0-alpha.1.
|
|
39
|
-
"@latticexyz/std-contracts": "2.0.0-alpha.1.
|
|
40
|
-
"@latticexyz/store": "2.0.0-alpha.1.
|
|
41
|
-
"@latticexyz/world": "2.0.0-alpha.1.
|
|
34
|
+
"@latticexyz/common": "2.0.0-alpha.1.181+e80def85",
|
|
35
|
+
"@latticexyz/config": "2.0.0-alpha.1.181+e80def85",
|
|
36
|
+
"@latticexyz/schema-type": "2.0.0-alpha.1.181+e80def85",
|
|
37
|
+
"@latticexyz/services": "2.0.0-alpha.1.181+e80def85",
|
|
38
|
+
"@latticexyz/solecs": "2.0.0-alpha.1.181+e80def85",
|
|
39
|
+
"@latticexyz/std-contracts": "2.0.0-alpha.1.181+e80def85",
|
|
40
|
+
"@latticexyz/store": "2.0.0-alpha.1.181+e80def85",
|
|
41
|
+
"@latticexyz/world": "2.0.0-alpha.1.181+e80def85",
|
|
42
42
|
"@typechain/ethers-v5": "^10.2.0",
|
|
43
43
|
"chalk": "^5.0.1",
|
|
44
44
|
"chokidar": "^3.5.3",
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"tsx": "^3.12.6",
|
|
72
72
|
"vitest": "0.30.1"
|
|
73
73
|
},
|
|
74
|
-
"gitHead": "
|
|
74
|
+
"gitHead": "e80def85d358f41990c2da63fec35c1fb2da1a64"
|
|
75
75
|
}
|
|
@@ -10,6 +10,8 @@ import { debounce } from "throttle-debounce";
|
|
|
10
10
|
import { worldgenHandler } from "./worldgen";
|
|
11
11
|
import { WorldConfig } from "@latticexyz/world";
|
|
12
12
|
import { deployHandler, printMUD, worldtypes } from "../utils";
|
|
13
|
+
import { homedir } from "os";
|
|
14
|
+
import { rmSync } from "fs";
|
|
13
15
|
|
|
14
16
|
type Options = {
|
|
15
17
|
rpc?: string;
|
|
@@ -57,6 +59,10 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
57
59
|
|
|
58
60
|
// Start an anvil instance in the background if no RPC url is provided
|
|
59
61
|
if (!args.rpc) {
|
|
62
|
+
console.log(chalk.gray("Cleaning devnode cache"));
|
|
63
|
+
const userHomeDir = homedir();
|
|
64
|
+
rmSync(path.join(userHomeDir, ".foundry", "anvil", "tmp"), { recursive: true, force: true });
|
|
65
|
+
|
|
60
66
|
const anvilArgs = ["--block-time", "1", "--block-base-fee-per-gas", "0"];
|
|
61
67
|
anvil(anvilArgs);
|
|
62
68
|
}
|