@latticexyz/cli 1.41.0 → 1.41.1-alpha.41
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/{chunk-GR245KYP.js → chunk-J4DJQNIC.js} +679 -133
- package/dist/chunk-O57QENJ6.js +23039 -0
- package/dist/config/index.d.ts +610 -296
- package/dist/config/index.js +49 -26
- package/dist/index.d.ts +2 -110
- package/dist/index.js +9 -50
- package/dist/mud.js +937 -57
- package/dist/utils/index.d.ts +92 -4
- package/dist/utils/index.js +2 -3
- package/package.json +10 -9
- package/src/commands/deploy-v2.ts +11 -15
- package/src/commands/index.ts +2 -0
- package/src/commands/worldgen.ts +55 -0
- package/src/config/commonSchemas.ts +11 -13
- package/src/config/dynamicResolution.ts +49 -0
- package/src/config/index.ts +15 -3
- package/src/config/loadStoreConfig.ts +1 -1
- package/src/config/parseStoreConfig.test-d.ts +31 -5
- package/src/config/parseStoreConfig.ts +218 -78
- package/src/config/validation.ts +25 -0
- package/src/config/world/index.ts +4 -0
- package/src/config/{loadWorldConfig.test-d.ts → world/loadWorldConfig.test-d.ts} +3 -3
- package/src/config/world/loadWorldConfig.ts +26 -0
- package/src/config/world/parseWorldConfig.ts +55 -0
- package/src/config/world/resolveWorldConfig.ts +80 -0
- package/src/config/world/userTypes.ts +72 -0
- package/src/index.ts +4 -6
- package/src/render-solidity/common.ts +51 -6
- package/src/render-solidity/field.ts +40 -44
- package/src/render-solidity/index.ts +5 -1
- package/src/render-solidity/record.ts +56 -73
- package/src/render-solidity/renderSystemInterface.ts +31 -0
- package/src/render-solidity/renderTable.ts +98 -70
- package/src/render-solidity/renderTypeHelpers.ts +99 -0
- package/src/render-solidity/renderTypesFromConfig.ts +2 -2
- package/src/render-solidity/renderWorld.ts +24 -0
- package/src/render-solidity/{renderTablesFromConfig.ts → tableOptions.ts} +28 -30
- package/src/render-solidity/tablegen.ts +20 -22
- package/src/render-solidity/types.ts +39 -5
- package/src/render-solidity/userType.ts +80 -48
- package/src/render-solidity/worldgen.ts +60 -0
- package/src/utils/contractToInterface.ts +130 -0
- package/src/utils/deploy-v2.ts +268 -101
- package/src/utils/formatAndWrite.ts +12 -0
- package/src/utils/getChainId.ts +10 -0
- package/src/utils/typeUtils.ts +17 -0
- package/dist/chunk-AER7UDD4.js +0 -0
- package/dist/chunk-XRS7KWBZ.js +0 -547
- package/dist/chunk-YZATC2M3.js +0 -397
- package/dist/chunk-ZYDMYSTH.js +0 -1178
- package/dist/deploy-v2-b7b3207d.d.ts +0 -92
- package/src/config/loadWorldConfig.ts +0 -178
- package/src/constants.ts +0 -1
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,5 +1,93 @@
|
|
|
1
|
-
|
|
2
|
-
import 'zod';
|
|
3
|
-
import '
|
|
4
|
-
import '../config/index.js';
|
|
1
|
+
import { ZodError, z } from 'zod';
|
|
2
|
+
import { ValidationError } from 'zod-validation-error';
|
|
3
|
+
import { MUDConfig } from '../config/index.js';
|
|
5
4
|
import '@latticexyz/schema-type';
|
|
5
|
+
|
|
6
|
+
declare function fromZodErrorCustom(error: ZodError, prefix: string): ValidationError;
|
|
7
|
+
declare class NotInsideProjectError extends Error {
|
|
8
|
+
name: string;
|
|
9
|
+
message: string;
|
|
10
|
+
}
|
|
11
|
+
declare class NotESMConfigError extends Error {
|
|
12
|
+
name: string;
|
|
13
|
+
message: string;
|
|
14
|
+
}
|
|
15
|
+
declare class MUDError extends Error {
|
|
16
|
+
name: string;
|
|
17
|
+
}
|
|
18
|
+
declare function UnrecognizedSystemErrorFactory(path: string[], systemName: string): z.ZodError<any>;
|
|
19
|
+
declare function logError(error: unknown): void;
|
|
20
|
+
|
|
21
|
+
interface ForgeConfig {
|
|
22
|
+
src: string;
|
|
23
|
+
test: string;
|
|
24
|
+
script: string;
|
|
25
|
+
out: string;
|
|
26
|
+
libs: string[];
|
|
27
|
+
eth_rpc_url: string | null;
|
|
28
|
+
[key: string]: unknown;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get forge config as a parsed json object.
|
|
32
|
+
*/
|
|
33
|
+
declare function getForgeConfig(profile?: string): Promise<ForgeConfig>;
|
|
34
|
+
/**
|
|
35
|
+
* Get the value of "src" from forge config.
|
|
36
|
+
* The path to the contract sources relative to the root of the project.
|
|
37
|
+
*/
|
|
38
|
+
declare function getSrcDirectory(profile?: string): Promise<string>;
|
|
39
|
+
/**
|
|
40
|
+
* Get the value of "script" from forge config.
|
|
41
|
+
* The path to the contract sources relative to the root of the project.
|
|
42
|
+
*/
|
|
43
|
+
declare function getScriptDirectory(profile?: string): Promise<string>;
|
|
44
|
+
/**
|
|
45
|
+
* Get the value of "test" from forge config.
|
|
46
|
+
* The path to the test contract sources relative to the root of the project.
|
|
47
|
+
*/
|
|
48
|
+
declare function getTestDirectory(profile?: string): Promise<string>;
|
|
49
|
+
/**
|
|
50
|
+
* Get the value of "out" from forge config.
|
|
51
|
+
* The path to put contract artifacts in, relative to the root of the project.
|
|
52
|
+
*/
|
|
53
|
+
declare function getOutDirectory(profile?: string): Promise<string>;
|
|
54
|
+
/**
|
|
55
|
+
* Get the value of "eth_rpc_url" from forge config, default to "http://127.0.0.1:8545"
|
|
56
|
+
* @param profile The foundry profile to use
|
|
57
|
+
* @returns The rpc url
|
|
58
|
+
*/
|
|
59
|
+
declare function getRpcUrl(profile?: string): Promise<string>;
|
|
60
|
+
/**
|
|
61
|
+
* Execute a forge command
|
|
62
|
+
* @param args The arguments to pass to forge
|
|
63
|
+
* @param options { profile?: The foundry profile to use; silent?: If true, nothing will be logged to the console }
|
|
64
|
+
*/
|
|
65
|
+
declare function forge(args: string[], options?: {
|
|
66
|
+
profile?: string;
|
|
67
|
+
silent?: boolean;
|
|
68
|
+
}): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Execute a cast command
|
|
71
|
+
* @param args The arguments to pass to cast
|
|
72
|
+
* @returns Stdout of the command
|
|
73
|
+
*/
|
|
74
|
+
declare function cast(args: string[], options?: {
|
|
75
|
+
profile?: string;
|
|
76
|
+
}): Promise<string>;
|
|
77
|
+
|
|
78
|
+
declare function formatSolidity(content: string, prettierConfigPath?: string): Promise<string>;
|
|
79
|
+
|
|
80
|
+
interface DeployConfig {
|
|
81
|
+
profile?: string;
|
|
82
|
+
rpc: string;
|
|
83
|
+
privateKey: string;
|
|
84
|
+
priorityFeeMultiplier: number;
|
|
85
|
+
debug?: boolean;
|
|
86
|
+
}
|
|
87
|
+
interface DeploymentInfo {
|
|
88
|
+
blockNumber: number;
|
|
89
|
+
worldAddress: string;
|
|
90
|
+
}
|
|
91
|
+
declare function deploy(mudConfig: MUDConfig, deployConfig: DeployConfig): Promise<DeploymentInfo>;
|
|
92
|
+
|
|
93
|
+
export { DeployConfig, DeploymentInfo, ForgeConfig, MUDError, NotESMConfigError, NotInsideProjectError, UnrecognizedSystemErrorFactory, cast, deploy, forge, formatSolidity, fromZodErrorCustom, getForgeConfig, getOutDirectory, getRpcUrl, getScriptDirectory, getSrcDirectory, getTestDirectory, logError };
|
package/dist/utils/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import "../chunk-AER7UDD4.js";
|
|
2
1
|
import {
|
|
3
2
|
deploy,
|
|
4
3
|
formatSolidity
|
|
5
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-O57QENJ6.js";
|
|
6
5
|
import {
|
|
7
6
|
MUDError,
|
|
8
7
|
NotESMConfigError,
|
|
@@ -10,7 +9,7 @@ import {
|
|
|
10
9
|
UnrecognizedSystemErrorFactory,
|
|
11
10
|
fromZodErrorCustom,
|
|
12
11
|
logError
|
|
13
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-J4DJQNIC.js";
|
|
14
13
|
import {
|
|
15
14
|
cast,
|
|
16
15
|
forge,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@latticexyz/cli",
|
|
3
|
-
"version": "1.41.
|
|
3
|
+
"version": "1.41.1-alpha.41+efdfeb310",
|
|
4
4
|
"description": "Command line interface for mud",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"release": "npm publish --access=public"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@latticexyz/store": "^1.41.
|
|
30
|
+
"@latticexyz/store": "^1.41.1-alpha.41+efdfeb310",
|
|
31
31
|
"@types/ejs": "^3.1.1",
|
|
32
32
|
"@types/glob": "^7.2.0",
|
|
33
33
|
"@types/node": "^17.0.34",
|
|
@@ -40,10 +40,11 @@
|
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@improbable-eng/grpc-web": "^0.15.0",
|
|
42
42
|
"@improbable-eng/grpc-web-node-http-transport": "^0.15.0",
|
|
43
|
-
"@latticexyz/schema-type": "^1.41.
|
|
44
|
-
"@latticexyz/services": "^1.41.
|
|
45
|
-
"@latticexyz/solecs": "^1.41.
|
|
46
|
-
"@latticexyz/std-contracts": "^1.41.
|
|
43
|
+
"@latticexyz/schema-type": "^1.41.1-alpha.41+efdfeb310",
|
|
44
|
+
"@latticexyz/services": "^1.41.1-alpha.41+efdfeb310",
|
|
45
|
+
"@latticexyz/solecs": "^1.41.1-alpha.41+efdfeb310",
|
|
46
|
+
"@latticexyz/std-contracts": "^1.41.1-alpha.41+efdfeb310",
|
|
47
|
+
"@solidity-parser/parser": "^0.16.0",
|
|
47
48
|
"@typechain/ethers-v5": "^10.1.1",
|
|
48
49
|
"chalk": "^5.0.1",
|
|
49
50
|
"chokidar": "^3.5.3",
|
|
@@ -66,8 +67,8 @@
|
|
|
66
67
|
"typechain": "^8.1.1",
|
|
67
68
|
"typescript": "^4.9.5",
|
|
68
69
|
"yargs": "^17.7.1",
|
|
69
|
-
"zod": "^3.
|
|
70
|
-
"zod-validation-error": "^0.
|
|
70
|
+
"zod": "^3.21.4",
|
|
71
|
+
"zod-validation-error": "^1.0.1"
|
|
71
72
|
},
|
|
72
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "efdfeb3102429e76ed87352cf69465990004957b"
|
|
73
74
|
}
|
|
@@ -2,14 +2,13 @@ import chalk from "chalk";
|
|
|
2
2
|
import glob from "glob";
|
|
3
3
|
import path, { basename } from "path";
|
|
4
4
|
import type { CommandModule } from "yargs";
|
|
5
|
-
import { loadWorldConfig } from "../config/
|
|
5
|
+
import { loadWorldConfig } from "../config/world/index.js";
|
|
6
6
|
import { deploy } from "../utils/deploy-v2.js";
|
|
7
7
|
import { logError, MUDError } from "../utils/errors.js";
|
|
8
|
-
import { forge, getRpcUrl } from "../utils/foundry.js";
|
|
9
|
-
import { getOutDirectory } from "../utils/foundry.js";
|
|
8
|
+
import { forge, getRpcUrl, getSrcDirectory } from "../utils/foundry.js";
|
|
10
9
|
import { mkdirSync, writeFileSync } from "fs";
|
|
11
10
|
import { loadStoreConfig } from "../config/loadStoreConfig.js";
|
|
12
|
-
import {
|
|
11
|
+
import { getChainId } from "../utils/getChainId.js";
|
|
13
12
|
|
|
14
13
|
type Options = {
|
|
15
14
|
configPath?: string;
|
|
@@ -18,6 +17,7 @@ type Options = {
|
|
|
18
17
|
privateKey: string;
|
|
19
18
|
priorityFeeMultiplier: number;
|
|
20
19
|
clean?: boolean;
|
|
20
|
+
debug?: boolean;
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
const commandModule: CommandModule<Options, Options> = {
|
|
@@ -31,6 +31,7 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
31
31
|
clean: { type: "boolean", desc: "Remove the build forge artifacts and cache directories before building" },
|
|
32
32
|
printConfig: { type: "boolean", desc: "Print the resolved config" },
|
|
33
33
|
profile: { type: "string", desc: "The foundry profile to use" },
|
|
34
|
+
debug: { type: "boolean", desc: "Print debug logs, like full error messages" },
|
|
34
35
|
priorityFeeMultiplier: {
|
|
35
36
|
type: "number",
|
|
36
37
|
desc: "Multiply the estimated priority fee by the provided factor",
|
|
@@ -56,9 +57,9 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
56
57
|
await forge(["build"], { profile });
|
|
57
58
|
|
|
58
59
|
// Get a list of all contract names
|
|
59
|
-
const
|
|
60
|
+
const srcDir = await getSrcDirectory();
|
|
60
61
|
const existingContracts = glob
|
|
61
|
-
.sync(`${
|
|
62
|
+
.sync(`${srcDir}/**/*.sol`)
|
|
62
63
|
// Get the basename of the file
|
|
63
64
|
.map((path) => basename(path, ".sol"));
|
|
64
65
|
|
|
@@ -75,16 +76,11 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
75
76
|
const deploymentInfo = await deploy(mudConfig, { ...args, rpc, privateKey });
|
|
76
77
|
|
|
77
78
|
// Write deployment result to file (latest and timestamp)
|
|
78
|
-
const
|
|
79
|
+
const chainId = await getChainId(rpc);
|
|
80
|
+
const outputDir = path.join(mudConfig.deploysDirectory, chainId.toString());
|
|
79
81
|
mkdirSync(outputDir, { recursive: true });
|
|
80
|
-
writeFileSync(
|
|
81
|
-
|
|
82
|
-
JSON.stringify(deploymentInfo, null, 2)
|
|
83
|
-
);
|
|
84
|
-
writeFileSync(
|
|
85
|
-
path.join(outputDir, deploymentInfoFilenamePrefix + Date.now() + ".json"),
|
|
86
|
-
JSON.stringify(deploymentInfo, null, 2)
|
|
87
|
-
);
|
|
82
|
+
writeFileSync(path.join(outputDir, "latest.json"), JSON.stringify(deploymentInfo, null, 2));
|
|
83
|
+
writeFileSync(path.join(outputDir, Date.now() + ".json"), JSON.stringify(deploymentInfo, null, 2));
|
|
88
84
|
|
|
89
85
|
console.log(chalk.bgGreen(chalk.whiteBright(`\n Deployment result (written to ${outputDir}): \n`)));
|
|
90
86
|
console.log(deploymentInfo);
|
package/src/commands/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ import gasReport from "./gas-report.js";
|
|
|
15
15
|
import hello from "./hello.js";
|
|
16
16
|
import tablegen from "./tablegen.js";
|
|
17
17
|
import deployV2 from "./deploy-v2.js";
|
|
18
|
+
import worldgen from "./worldgen.js";
|
|
18
19
|
|
|
19
20
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Each command has different options
|
|
20
21
|
export const commands: CommandModule<any, any>[] = [
|
|
@@ -32,4 +33,5 @@ export const commands: CommandModule<any, any>[] = [
|
|
|
32
33
|
test,
|
|
33
34
|
trace,
|
|
34
35
|
types,
|
|
36
|
+
worldgen,
|
|
35
37
|
];
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { CommandModule } from "yargs";
|
|
2
|
+
import { loadStoreConfig } from "../config/loadStoreConfig.js";
|
|
3
|
+
import { loadWorldConfig } from "../config/index.js";
|
|
4
|
+
import { getSrcDirectory } from "../utils/foundry.js";
|
|
5
|
+
import glob from "glob";
|
|
6
|
+
import path, { basename } from "path";
|
|
7
|
+
import { worldgen } from "../render-solidity/worldgen.js";
|
|
8
|
+
import { rmSync } from "fs";
|
|
9
|
+
|
|
10
|
+
type Options = {
|
|
11
|
+
configPath?: string;
|
|
12
|
+
clean?: boolean;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const commandModule: CommandModule<Options, Options> = {
|
|
16
|
+
command: "worldgen",
|
|
17
|
+
|
|
18
|
+
describe: "Autogenerate interfaces for Systems and World based on existing contracts and the config file",
|
|
19
|
+
|
|
20
|
+
builder(yargs) {
|
|
21
|
+
return yargs.options({
|
|
22
|
+
configPath: { type: "string", desc: "Path to the config file" },
|
|
23
|
+
clean: { type: "boolean", desc: "Clear the worldgen directory before generating new interfaces" },
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
async handler(args) {
|
|
28
|
+
const { configPath, clean } = args;
|
|
29
|
+
const srcDir = await getSrcDirectory();
|
|
30
|
+
|
|
31
|
+
// Get a list of all contract names
|
|
32
|
+
const existingContracts = glob.sync(`${srcDir}/**/*.sol`).map((path) => ({
|
|
33
|
+
path,
|
|
34
|
+
basename: basename(path, ".sol"),
|
|
35
|
+
}));
|
|
36
|
+
|
|
37
|
+
// Load and resolve the config
|
|
38
|
+
const worldConfig = await loadWorldConfig(
|
|
39
|
+
configPath,
|
|
40
|
+
existingContracts.map(({ basename }) => basename)
|
|
41
|
+
);
|
|
42
|
+
const storeConfig = await loadStoreConfig(configPath);
|
|
43
|
+
const mudConfig = { ...worldConfig, ...storeConfig };
|
|
44
|
+
|
|
45
|
+
// clear the worldgen directory
|
|
46
|
+
if (clean) rmSync(path.join(srcDir, worldConfig.worldgenDirectory), { recursive: true, force: true });
|
|
47
|
+
|
|
48
|
+
// generate new interfaces
|
|
49
|
+
await worldgen(mudConfig, existingContracts, srcDir);
|
|
50
|
+
|
|
51
|
+
process.exit(0);
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default commandModule;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { getStaticByteLength, SchemaType } from "@latticexyz/schema-type";
|
|
2
1
|
import { z } from "zod";
|
|
3
2
|
import {
|
|
4
3
|
validateBaseRoute,
|
|
@@ -9,28 +8,27 @@ import {
|
|
|
9
8
|
validateRoute,
|
|
10
9
|
validateSingleLevelRoute,
|
|
11
10
|
validateUncapitalizedName,
|
|
11
|
+
validateSelector,
|
|
12
12
|
} from "./validation.js";
|
|
13
13
|
|
|
14
14
|
/** Capitalized names of objects, like tables and systems */
|
|
15
|
-
export const
|
|
15
|
+
export const zObjectName = z.string().superRefine(validateCapitalizedName);
|
|
16
16
|
/** Uncapitalized names of values, like keys and columns */
|
|
17
|
-
export const
|
|
17
|
+
export const zValueName = z.string().superRefine(validateUncapitalizedName);
|
|
18
18
|
/** Name that can start with any case */
|
|
19
|
-
export const
|
|
19
|
+
export const zAnyCaseName = z.string().superRefine(validateName);
|
|
20
20
|
/** List of unique enum member names and 0 < length < 256 */
|
|
21
|
-
export const
|
|
21
|
+
export const zUserEnum = z.array(zObjectName).superRefine(validateEnum);
|
|
22
22
|
|
|
23
23
|
/** Ordinary routes */
|
|
24
|
-
export const
|
|
24
|
+
export const zOrdinaryRoute = z.string().superRefine(validateRoute);
|
|
25
25
|
/** Routes with exactly 1 non-empty level */
|
|
26
|
-
export const
|
|
26
|
+
export const zSingleLevelRoute = z.string().superRefine(validateSingleLevelRoute);
|
|
27
27
|
/** Base routes (can be an empty string) */
|
|
28
|
-
export const
|
|
28
|
+
export const zBaseRoute = z.string().superRefine(validateBaseRoute);
|
|
29
29
|
|
|
30
30
|
/** A valid Ethereum address */
|
|
31
|
-
export const
|
|
31
|
+
export const zEthereumAddress = z.string().superRefine(validateEthereumAddress);
|
|
32
32
|
|
|
33
|
-
/**
|
|
34
|
-
export const
|
|
35
|
-
.nativeEnum(SchemaType)
|
|
36
|
-
.refine((arg) => getStaticByteLength(arg) > 0, "SchemaType must be static");
|
|
33
|
+
/** A selector for namespace/file/resource */
|
|
34
|
+
export const zSelector = z.string().superRefine(validateSelector);
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { MUDError } from "../utils/errors.js";
|
|
2
|
+
import { ValueWithType } from "./world/userTypes.js";
|
|
3
|
+
|
|
4
|
+
export enum DynamicResolutionType {
|
|
5
|
+
TABLE_ID,
|
|
6
|
+
SYSTEM_ADDRESS,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type DynamicResolution = {
|
|
10
|
+
type: DynamicResolutionType;
|
|
11
|
+
input: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Dynamically resolve a table name to a table id at deploy time
|
|
16
|
+
*/
|
|
17
|
+
export function resolveTableId(tableName: string) {
|
|
18
|
+
return {
|
|
19
|
+
type: DynamicResolutionType.TABLE_ID,
|
|
20
|
+
input: tableName,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Type guard for DynamicResolution */
|
|
25
|
+
export function isDynamicResolution(value: unknown): value is DynamicResolution {
|
|
26
|
+
return typeof value === "object" && value !== null && "type" in value && "input" in value;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Turn a DynamicResolution object into a ValueWithType based on the provided context
|
|
31
|
+
*/
|
|
32
|
+
export async function resolveWithContext(
|
|
33
|
+
unresolved: any,
|
|
34
|
+
context: { systemAddresses?: Record<string, Promise<string>>; tableIds?: Record<string, Uint8Array> }
|
|
35
|
+
): Promise<ValueWithType> {
|
|
36
|
+
if (!isDynamicResolution(unresolved)) return unresolved;
|
|
37
|
+
let resolved: ValueWithType | undefined = undefined;
|
|
38
|
+
|
|
39
|
+
if (unresolved.type === DynamicResolutionType.TABLE_ID) {
|
|
40
|
+
const tableId = context.tableIds?.[unresolved.input];
|
|
41
|
+
resolved = tableId && { value: tableId, type: "bytes32" };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (resolved === undefined) {
|
|
45
|
+
throw new MUDError(`Could not resolve dynamic resolution: \n${JSON.stringify(unresolved, null, 2)}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return resolved;
|
|
49
|
+
}
|
package/src/config/index.ts
CHANGED
|
@@ -1,12 +1,24 @@
|
|
|
1
|
+
import { ExtractUserTypes, StringForUnion } from "../utils/typeUtils.js";
|
|
1
2
|
import { StoreUserConfig, StoreConfig } from "./parseStoreConfig.js";
|
|
2
|
-
import { WorldUserConfig, ResolvedWorldConfig } from "./
|
|
3
|
+
import { WorldUserConfig, ResolvedWorldConfig } from "./world/index.js";
|
|
3
4
|
|
|
4
|
-
export type MUDUserConfig
|
|
5
|
+
export type MUDUserConfig<
|
|
6
|
+
EnumNames extends StringForUnion = StringForUnion,
|
|
7
|
+
StaticUserTypes extends ExtractUserTypes<EnumNames> = ExtractUserTypes<EnumNames>
|
|
8
|
+
> = StoreUserConfig<EnumNames, StaticUserTypes> & WorldUserConfig;
|
|
5
9
|
export type MUDConfig = StoreConfig & ResolvedWorldConfig;
|
|
6
10
|
|
|
11
|
+
export function mudConfig<
|
|
12
|
+
EnumNames extends StringForUnion = never,
|
|
13
|
+
StaticUserTypes extends ExtractUserTypes<EnumNames> = ExtractUserTypes<EnumNames>
|
|
14
|
+
>(config: MUDUserConfig<EnumNames, StaticUserTypes>) {
|
|
15
|
+
return config;
|
|
16
|
+
}
|
|
17
|
+
|
|
7
18
|
export * from "./commonSchemas.js";
|
|
8
19
|
export * from "./loadConfig.js";
|
|
9
20
|
export * from "./loadStoreConfig.js";
|
|
10
21
|
export * from "./parseStoreConfig.js";
|
|
11
|
-
export * from "./
|
|
22
|
+
export * from "./world/index.js";
|
|
12
23
|
export * from "./validation.js";
|
|
24
|
+
export * from "./dynamicResolution.js";
|
|
@@ -7,7 +7,7 @@ export async function loadStoreConfig(configPath?: string) {
|
|
|
7
7
|
const config = await loadConfig(configPath);
|
|
8
8
|
|
|
9
9
|
try {
|
|
10
|
-
return parseStoreConfig(config);
|
|
10
|
+
return parseStoreConfig(config as any);
|
|
11
11
|
} catch (error) {
|
|
12
12
|
if (error instanceof ZodError) {
|
|
13
13
|
throw fromZodErrorCustom(error, "StoreConfig Validation Error");
|
|
@@ -1,14 +1,40 @@
|
|
|
1
1
|
import { describe, expectTypeOf } from "vitest";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import {
|
|
3
|
+
import { storeConfig, zStoreConfig, StoreUserConfig } from "./parseStoreConfig.js";
|
|
4
4
|
|
|
5
5
|
describe("StoreUserConfig", () => {
|
|
6
6
|
// Typecheck manual interfaces against zod
|
|
7
|
-
expectTypeOf<StoreUserConfig>().toEqualTypeOf<z.input<typeof
|
|
7
|
+
expectTypeOf<StoreUserConfig>().toEqualTypeOf<z.input<typeof zStoreConfig>>();
|
|
8
8
|
// type equality isn't deep for optionals
|
|
9
|
-
expectTypeOf<StoreUserConfig["tables"][string]>().toEqualTypeOf<z.input<typeof
|
|
10
|
-
expectTypeOf<NonNullable<
|
|
11
|
-
NonNullable<NonNullable<z.input<typeof
|
|
9
|
+
expectTypeOf<StoreUserConfig["tables"][string]>().toEqualTypeOf<z.input<typeof zStoreConfig>["tables"][string]>();
|
|
10
|
+
expectTypeOf<NonNullable<StoreUserConfig["enums"]>[string]>().toEqualTypeOf<
|
|
11
|
+
NonNullable<NonNullable<z.input<typeof zStoreConfig>>["enums"]>[string]
|
|
12
12
|
>();
|
|
13
13
|
// TODO If more nested schemas are added, provide separate tests for them
|
|
14
|
+
|
|
15
|
+
// Test possible inference confusion.
|
|
16
|
+
// This would fail if you remove `AsDependent` from `StoreUserConfig`
|
|
17
|
+
expectTypeOf(
|
|
18
|
+
storeConfig({
|
|
19
|
+
tables: {
|
|
20
|
+
Table1: {
|
|
21
|
+
primaryKeys: {
|
|
22
|
+
a: "Enum1",
|
|
23
|
+
},
|
|
24
|
+
schema: {
|
|
25
|
+
b: "Enum2",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
Table2: {
|
|
29
|
+
schema: {
|
|
30
|
+
a: "uint32",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
enums: {
|
|
35
|
+
Enum1: ["E1"],
|
|
36
|
+
Enum2: ["E1"],
|
|
37
|
+
},
|
|
38
|
+
})
|
|
39
|
+
).toEqualTypeOf<StoreUserConfig<"Enum1" | "Enum2", "Enum1" | "Enum2">>();
|
|
14
40
|
});
|