@latticexyz/cli 1.40.0 → 1.41.0

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.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/dist/chunk-AER7UDD4.js +0 -0
  3. package/dist/chunk-ATAWDHWC.js +67 -0
  4. package/dist/{chunk-6AQ6LFVZ.js → chunk-GR245KYP.js} +95 -1
  5. package/dist/{chunk-S3V3XX7N.js → chunk-SLIMIO4Z.js} +1 -1
  6. package/dist/{chunk-JNGSW4AP.js → chunk-XRS7KWBZ.js} +139 -85
  7. package/dist/chunk-YZATC2M3.js +397 -0
  8. package/dist/chunk-ZYDMYSTH.js +1178 -0
  9. package/dist/config/index.d.ts +427 -3
  10. package/dist/config/index.js +26 -3
  11. package/dist/deploy-v2-b7b3207d.d.ts +92 -0
  12. package/dist/index.d.ts +110 -3
  13. package/dist/index.js +53 -8
  14. package/dist/mud.js +172 -46
  15. package/dist/utils/deprecated/index.js +2 -2
  16. package/dist/utils/index.d.ts +5 -44
  17. package/dist/utils/index.js +18 -3
  18. package/package.json +13 -9
  19. package/src/commands/deploy-v2.ts +100 -0
  20. package/src/commands/deprecated/call-system.ts +1 -1
  21. package/src/commands/deprecated/deploy-contracts.ts +1 -1
  22. package/src/commands/deprecated/test.ts +9 -6
  23. package/src/commands/deprecated/trace.ts +1 -1
  24. package/src/commands/gas-report.ts +1 -1
  25. package/src/commands/index.ts +2 -0
  26. package/src/commands/tablegen.ts +4 -18
  27. package/src/config/commonSchemas.ts +16 -0
  28. package/src/config/index.ts +8 -0
  29. package/src/config/loadStoreConfig.ts +2 -88
  30. package/src/config/loadWorldConfig.test-d.ts +11 -0
  31. package/src/config/loadWorldConfig.ts +178 -0
  32. package/src/config/{loadStoreConfig.test-d.ts → parseStoreConfig.test-d.ts} +5 -2
  33. package/src/config/parseStoreConfig.ts +174 -0
  34. package/src/config/validation.ts +46 -0
  35. package/src/constants.ts +1 -0
  36. package/src/index.ts +15 -5
  37. package/src/mud.ts +4 -0
  38. package/src/{render-table → render-solidity}/common.ts +37 -11
  39. package/src/{render-table → render-solidity}/field.ts +29 -20
  40. package/src/{render-table → render-solidity}/record.ts +3 -8
  41. package/src/{render-table → render-solidity}/renderTable.ts +38 -11
  42. package/src/{render-table → render-solidity}/renderTablesFromConfig.ts +37 -27
  43. package/src/render-solidity/renderTypes.ts +19 -0
  44. package/src/render-solidity/renderTypesFromConfig.ts +13 -0
  45. package/src/render-solidity/tablegen.ts +35 -0
  46. package/src/{render-table → render-solidity}/types.ts +25 -0
  47. package/src/render-solidity/userType.ts +100 -0
  48. package/src/utils/deploy-v2.ts +345 -0
  49. package/src/utils/deprecated/build.ts +1 -1
  50. package/src/utils/deprecated/typegen.ts +1 -1
  51. package/src/utils/errors.ts +12 -2
  52. package/src/utils/execLog.ts +22 -0
  53. package/src/utils/foundry.ts +94 -0
  54. package/src/utils/index.ts +2 -1
  55. package/dist/chunk-B6VWCGHZ.js +0 -199
  56. package/dist/chunk-JKAA3WMC.js +0 -55
  57. package/dist/chunk-PJ6GS2R4.js +0 -22
  58. package/dist/chunk-UC3QPOON.js +0 -35
  59. package/dist/loadStoreConfig-37f99136.d.ts +0 -164
  60. package/dist/render-table/index.d.ts +0 -29
  61. package/dist/render-table/index.js +0 -24
  62. package/dist/renderTable-9e6410c5.d.ts +0 -72
  63. package/src/utils/forgeConfig.ts +0 -45
  64. /package/src/{render-table → render-solidity}/index.ts +0 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022-present Lattice Labs Ltd.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
File without changes
@@ -0,0 +1,67 @@
1
+ // src/utils/foundry.ts
2
+ import { execa as execa2 } from "execa";
3
+
4
+ // src/utils/execLog.ts
5
+ import chalk from "chalk";
6
+ import { execa } from "execa";
7
+ async function execLog(command, args, options) {
8
+ const commandString = `${command} ${args.join(" ")}`;
9
+ try {
10
+ console.log(chalk.gray(`running "${commandString}"`));
11
+ const { stdout } = await execa(command, args, { stdout: "pipe", stderr: "pipe", ...options });
12
+ return stdout;
13
+ } catch (error) {
14
+ let errorMessage = error?.stderr || error?.message || "";
15
+ errorMessage += chalk.red(`
16
+ Error running "${commandString}"`);
17
+ throw new Error(errorMessage);
18
+ }
19
+ }
20
+
21
+ // src/utils/foundry.ts
22
+ async function getForgeConfig(profile) {
23
+ const { stdout } = await execa2("forge", ["config", "--json"], {
24
+ stdio: ["inherit", "pipe", "pipe"],
25
+ env: { FOUNDRY_PROFILE: profile }
26
+ });
27
+ return JSON.parse(stdout);
28
+ }
29
+ async function getSrcDirectory(profile) {
30
+ return (await getForgeConfig(profile)).src;
31
+ }
32
+ async function getScriptDirectory(profile) {
33
+ return (await getForgeConfig(profile)).script;
34
+ }
35
+ async function getTestDirectory(profile) {
36
+ return (await getForgeConfig(profile)).test;
37
+ }
38
+ async function getOutDirectory(profile) {
39
+ return (await getForgeConfig(profile)).out;
40
+ }
41
+ async function getRpcUrl(profile) {
42
+ return (await getForgeConfig(profile)).eth_rpc_url || "http://127.0.0.1:8545";
43
+ }
44
+ async function forge(args, options) {
45
+ const execOptions = {
46
+ env: { FOUNDRY_PROFILE: options?.profile },
47
+ stdout: "inherit",
48
+ stderr: "pipe"
49
+ };
50
+ await (options?.silent ? execa2("forge", args, execOptions) : execLog("forge", args, execOptions));
51
+ }
52
+ async function cast(args, options) {
53
+ return execLog("cast", args, {
54
+ env: { FOUNDRY_PROFILE: options?.profile }
55
+ });
56
+ }
57
+
58
+ export {
59
+ getForgeConfig,
60
+ getSrcDirectory,
61
+ getScriptDirectory,
62
+ getTestDirectory,
63
+ getOutDirectory,
64
+ getRpcUrl,
65
+ forge,
66
+ cast
67
+ };
@@ -1,3 +1,63 @@
1
+ // src/utils/errors.ts
2
+ import chalk from "chalk";
3
+ import { z, ZodError, ZodIssueCode } from "zod";
4
+ import { fromZodError, ValidationError } from "zod-validation-error";
5
+ function fromZodErrorCustom(error, prefix) {
6
+ return fromZodError(error, {
7
+ prefix: chalk.red(prefix),
8
+ prefixSeparator: "\n- ",
9
+ issueSeparator: "\n- "
10
+ });
11
+ }
12
+ var NotInsideProjectError = class extends Error {
13
+ constructor() {
14
+ super(...arguments);
15
+ this.name = "NotInsideProjectError";
16
+ this.message = "You are not inside a MUD project";
17
+ }
18
+ };
19
+ var NotESMConfigError = class extends Error {
20
+ constructor() {
21
+ super(...arguments);
22
+ this.name = "NotESMConfigError";
23
+ this.message = "MUD config must be an ES module";
24
+ }
25
+ };
26
+ var MUDError = class extends Error {
27
+ constructor() {
28
+ super(...arguments);
29
+ this.name = "MUDError";
30
+ }
31
+ };
32
+ function UnrecognizedSystemErrorFactory(path, systemName) {
33
+ return new z.ZodError([{ code: ZodIssueCode.custom, path, message: `Unrecognized system: "${systemName}"` }]);
34
+ }
35
+ function logError(error) {
36
+ if (error instanceof ValidationError) {
37
+ console.log(chalk.redBright(error.message));
38
+ } else if (error instanceof ZodError) {
39
+ const validationError = fromZodError(error, {
40
+ prefixSeparator: "\n- ",
41
+ issueSeparator: "\n- "
42
+ });
43
+ console.log(chalk.redBright(validationError.message));
44
+ } else if (error instanceof NotInsideProjectError) {
45
+ console.log(chalk.red(error.message));
46
+ console.log("");
47
+ console.log(chalk.blue(`To learn more about MUD's configuration, please go to https://mud.dev/packages/cli/`));
48
+ } else if (error instanceof NotESMConfigError) {
49
+ console.log(chalk.red(error.message));
50
+ console.log("");
51
+ console.log(
52
+ chalk.blue(`Please name your config file \`mud.config.mts\`, or use \`type: "module"\` in package.json`)
53
+ );
54
+ } else if (error instanceof MUDError) {
55
+ console.log(chalk.red(error));
56
+ } else {
57
+ console.log(error);
58
+ }
59
+ }
60
+
1
61
  // ../schema-type/src/typescript/SchemaType.ts
2
62
  var SchemaType = /* @__PURE__ */ ((SchemaType2) => {
3
63
  SchemaType2[SchemaType2["UINT8"] = 0] = "UINT8";
@@ -516,10 +576,44 @@ var SchemaTypeArrayToElement = {
516
576
  [194 /* BOOL_ARRAY */]: 96 /* BOOL */,
517
577
  [195 /* ADDRESS_ARRAY */]: 97 /* ADDRESS */
518
578
  };
579
+ function encodeSchema(schema) {
580
+ if (schema.length > 28)
581
+ throw new Error("Schema can only have up to 28 fields");
582
+ const encodedSchema = new Uint8Array(32);
583
+ let length = 0;
584
+ let staticFields = 0;
585
+ let hasDynamicFields = false;
586
+ for (let i = 0; i < schema.length; i++) {
587
+ const staticByteLength = getStaticByteLength(schema[i]);
588
+ if (staticByteLength > 0) {
589
+ if (hasDynamicFields)
590
+ throw new Error("Static fields must come before dynamic fields in the schema");
591
+ staticFields++;
592
+ } else {
593
+ hasDynamicFields = true;
594
+ }
595
+ length += staticByteLength;
596
+ encodedSchema[i + 4] = schema[i];
597
+ }
598
+ const dynamicFields = schema.length - staticFields;
599
+ if (dynamicFields > 14)
600
+ throw new Error("Schema can only have up to 14 dynamic fields");
601
+ new DataView(encodedSchema.buffer).setUint16(0, length);
602
+ encodedSchema[2] = staticFields;
603
+ encodedSchema[3] = dynamicFields;
604
+ return encodedSchema;
605
+ }
519
606
 
520
607
  export {
521
608
  SchemaType,
522
609
  getStaticByteLength,
523
610
  SchemaTypeId,
524
- SchemaTypeArrayToElement
611
+ SchemaTypeArrayToElement,
612
+ encodeSchema,
613
+ fromZodErrorCustom,
614
+ NotInsideProjectError,
615
+ NotESMConfigError,
616
+ MUDError,
617
+ UnrecognizedSystemErrorFactory,
618
+ logError
525
619
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getOutDirectory,
3
3
  getSrcDirectory
4
- } from "./chunk-PJ6GS2R4.js";
4
+ } from "./chunk-ATAWDHWC.js";
5
5
  import {
6
6
  __commonJS,
7
7
  __require,
@@ -1,11 +1,16 @@
1
1
  import {
2
- SchemaType,
3
- SchemaTypeArrayToElement,
4
- SchemaTypeId,
5
- getStaticByteLength
6
- } from "./chunk-6AQ6LFVZ.js";
2
+ getSchemaTypeInfo,
3
+ resolveSchemaOrUserType
4
+ } from "./chunk-ZYDMYSTH.js";
5
+ import {
6
+ SchemaTypeArrayToElement
7
+ } from "./chunk-GR245KYP.js";
8
+
9
+ // src/render-solidity/common.ts
10
+ var renderedSolidityHeader = `// SPDX-License-Identifier: MIT
11
+ pragma solidity >=0.8.0;
7
12
 
8
- // src/render-table/common.ts
13
+ /* Autogenerated file. Do not edit manually. */`;
9
14
  function renderList(list, renderItem) {
10
15
  return internalRenderList("", list, renderItem);
11
16
  }
@@ -22,9 +27,7 @@ function renderCommonData({ staticRouteData, primaryKeys }) {
22
27
  bytes32[] memory _primaryKeys = new bytes32[](${primaryKeys.length});
23
28
  ${renderList(
24
29
  primaryKeys,
25
- ({ name, typeId, staticByteLength }, index) => `
26
- _primaryKeys[${index}] = ${renderValueTypeToBytes32(name, typeId, staticByteLength)};
27
- `
30
+ (primaryKey, index) => `_primaryKeys[${index}] = ${renderValueTypeToBytes32(primaryKey.name, primaryKey)};`
28
31
  )}
29
32
  `;
30
33
  return {
@@ -35,27 +38,43 @@ function renderCommonData({ staticRouteData, primaryKeys }) {
35
38
  _primaryKeysDefinition
36
39
  };
37
40
  }
38
- function renderValueTypeToBytes32(innerText, typeId, staticByteLength) {
41
+ function renderImports(imports) {
42
+ const aggregatedImports = /* @__PURE__ */ new Map();
43
+ for (const { symbol, path: path2 } of imports) {
44
+ if (!aggregatedImports.has(path2)) {
45
+ aggregatedImports.set(path2, /* @__PURE__ */ new Set());
46
+ }
47
+ aggregatedImports.get(path2)?.add(symbol);
48
+ }
49
+ const renderedImports = [];
50
+ for (const [path2, symbols] of aggregatedImports) {
51
+ const renderedSymbols = [...symbols].join(", ");
52
+ renderedImports.push(`import { ${renderedSymbols} } from "${path2}";`);
53
+ }
54
+ return renderedImports.join("\n");
55
+ }
56
+ function renderValueTypeToBytes32(name, { staticByteLength, typeUnwrap, internalTypeId }) {
39
57
  const bits = staticByteLength * 8;
40
- if (typeId.match(/^uint\d{1,3}$/)) {
58
+ const innerText = `${typeUnwrap}(${name})`;
59
+ if (internalTypeId.match(/^uint\d{1,3}$/)) {
41
60
  return `bytes32(uint256(${innerText}))`;
42
- } else if (typeId.match(/^int\d{1,3}$/)) {
61
+ } else if (internalTypeId.match(/^int\d{1,3}$/)) {
43
62
  return `bytes32(uint256(uint${bits}(${innerText})))`;
44
- } else if (typeId.match(/^bytes\d{1,2}$/)) {
63
+ } else if (internalTypeId.match(/^bytes\d{1,2}$/)) {
45
64
  return `bytes32(${innerText})`;
46
- } else if (typeId === "address") {
65
+ } else if (internalTypeId === "address") {
47
66
  return `bytes32(bytes20(${innerText}))`;
48
- } else if (typeId === "bool") {
67
+ } else if (internalTypeId === "bool") {
49
68
  return `_boolToBytes32(${innerText})`;
50
69
  } else {
51
- throw new Error(`Unknown value type id ${typeId}`);
70
+ throw new Error(`Unknown value type id ${internalTypeId}`);
52
71
  }
53
72
  }
54
73
  function internalRenderList(lineTerminator, list, renderItem) {
55
74
  return list.map((item, index) => renderItem(item, index) + (index === list.length - 1 ? "" : lineTerminator)).join("\n");
56
75
  }
57
76
 
58
- // src/render-table/field.ts
77
+ // src/render-solidity/field.ts
59
78
  function renderFieldMethods(options) {
60
79
  const { _typedTableId, _typedKeyArgs, _primaryKeysDefinition } = renderCommonData(options);
61
80
  let result = "";
@@ -108,7 +127,7 @@ function renderFieldMethods(options) {
108
127
  ])}) internal {
109
128
  ${_primaryKeysDefinition}
110
129
  bytes memory _blob = StoreSwitch.getField(_tableId, _primaryKeys, ${index});
111
- bytes memory _newBlob = abi.encodePacked(_blob, ${portionData.encodeFunc}(${portionData.name}));
130
+ bytes memory _newBlob = abi.encodePacked(_blob, ${portionData.encoded});
112
131
  StoreSwitch.setField(_tableId, _primaryKeys, ${index}, _newBlob);
113
132
  }
114
133
  `;
@@ -125,52 +144,60 @@ function renderEncodeField(field) {
125
144
  } else {
126
145
  func = "abi.encodePacked";
127
146
  }
128
- return `${func}(${field.name})`;
147
+ return `${func}(${field.typeUnwrap}(${field.name}))`;
129
148
  }
130
- function renderDecodeValueType(typeId, staticByteLength, offset) {
149
+ function renderDecodeValueType(field, offset) {
150
+ const { staticByteLength, internalTypeId } = field;
131
151
  const innerSlice = `Bytes.slice${staticByteLength}(_blob, ${offset})`;
132
152
  const bits = staticByteLength * 8;
133
- if (typeId.match(/^uint\d{1,3}$/) || typeId === "address") {
134
- return `${typeId}(${innerSlice})`;
135
- } else if (typeId.match(/^int\d{1,3}$/)) {
136
- return `${typeId}(uint${bits}(${innerSlice}))`;
137
- } else if (typeId.match(/^bytes\d{1,2}$/)) {
138
- return innerSlice;
139
- } else if (typeId === "bool") {
140
- return `_toBool(uint8(${innerSlice}))`;
153
+ let result;
154
+ if (internalTypeId.match(/^uint\d{1,3}$/) || internalTypeId === "address") {
155
+ result = `${internalTypeId}(${innerSlice})`;
156
+ } else if (internalTypeId.match(/^int\d{1,3}$/)) {
157
+ result = `${internalTypeId}(uint${bits}(${innerSlice}))`;
158
+ } else if (internalTypeId.match(/^bytes\d{1,2}$/)) {
159
+ result = innerSlice;
160
+ } else if (internalTypeId === "bool") {
161
+ result = `_toBool(uint8(${innerSlice}))`;
141
162
  } else {
142
- throw new Error(`Unknown value type id ${typeId}`);
163
+ throw new Error(`Unknown value type id ${internalTypeId}`);
143
164
  }
165
+ return `${field.typeWrap}(${result})`;
144
166
  }
145
167
  function fieldPortionData(field) {
168
+ const methodNameSuffix = "";
146
169
  if (field.arrayElement) {
170
+ const name = "_element";
147
171
  return {
148
172
  typeWithLocation: field.arrayElement.typeWithLocation,
149
173
  name: "_element",
150
- encodeFunc: "abi.encodePacked",
174
+ encoded: renderEncodeField({ ...field.arrayElement, arrayElement: void 0, name, methodNameSuffix }),
151
175
  title: "an element"
152
176
  };
153
177
  } else {
178
+ const name = "_slice";
154
179
  return {
155
180
  typeWithLocation: `${field.typeId} memory`,
156
- name: "_slice",
157
- encodeFunc: "bytes",
181
+ name,
182
+ encoded: renderEncodeField({ ...field, name, methodNameSuffix }),
158
183
  title: "a slice"
159
184
  };
160
185
  }
161
186
  }
162
187
  function renderDecodeFieldSingle(field) {
163
- const { typeId, isDynamic, arrayElement } = field;
188
+ const { isDynamic, arrayElement } = field;
164
189
  if (arrayElement) {
165
- return `SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_${arrayElement.typeId}()`;
190
+ return `${field.typeWrap}(
191
+ SliceLib.getSubslice(_blob, 0, _blob.length).decodeArray_${arrayElement.internalTypeId}()
192
+ )`;
166
193
  } else if (isDynamic) {
167
- return `${typeId}(_blob)`;
194
+ return `${field.typeWrap}(${field.internalTypeId}(_blob))`;
168
195
  } else {
169
- return renderDecodeValueType(typeId, field.staticByteLength, 0);
196
+ return renderDecodeValueType(field, 0);
170
197
  }
171
198
  }
172
199
 
173
- // src/render-table/record.ts
200
+ // src/render-solidity/record.ts
174
201
  function renderRecordMethods(options) {
175
202
  const { staticFields, dynamicFields, structName, storeArgument } = options;
176
203
  const { _tableId, _typedTableId, _keyArgs, _typedKeyArgs, _primaryKeysDefinition } = renderCommonData(options);
@@ -253,7 +280,7 @@ function renderDecodeFunction({ structName, fields, staticFields, dynamicFields
253
280
  ${renderList(
254
281
  staticFields,
255
282
  (field, index) => `
256
- ${fieldNamePrefix}${field.name} = ${renderDecodeStaticFieldPartial(field, staticOffsets[index])};
283
+ ${fieldNamePrefix}${field.name} = ${renderDecodeValueType(field, staticOffsets[index])};
257
284
  `
258
285
  )}
259
286
  uint256 _start;
@@ -275,7 +302,7 @@ function renderDecodeFunction({ structName, fields, staticFields, dynamicFields
275
302
  ${renderList(
276
303
  staticFields,
277
304
  (field, index) => `
278
- ${fieldNamePrefix}${field.name} = ${renderDecodeStaticFieldPartial(field, staticOffsets[index])};
305
+ ${fieldNamePrefix}${field.name} = ${renderDecodeValueType(field, staticOffsets[index])};
279
306
  `
280
307
  )}
281
308
  }
@@ -297,10 +324,6 @@ function renderDecodeDynamicFieldPartial(field) {
297
324
  return `${typeId}(SliceLib.getSubslice(_blob, _start, _end).toBytes())`;
298
325
  }
299
326
  }
300
- function renderDecodeStaticFieldPartial(field, start) {
301
- const { typeId, staticByteLength } = field;
302
- return renderDecodeValueType(typeId, staticByteLength, start);
303
- }
304
327
  function renderEncodedLengths(dynamicFields) {
305
328
  if (dynamicFields.length > 0) {
306
329
  return `
@@ -319,17 +342,16 @@ function renderEncodedLengths(dynamicFields) {
319
342
  }
320
343
  }
321
344
 
322
- // src/render-table/renderTable.ts
345
+ // src/render-solidity/renderTable.ts
323
346
  function renderTable(options) {
324
- const { libraryName, structName, staticRouteData, storeImportPath, fields, withRecordMethods } = options;
347
+ const { imports, libraryName, structName, staticRouteData, storeImportPath, fields, withRecordMethods } = options;
325
348
  const { _typedTableId, _typedKeyArgs, _primaryKeysDefinition } = renderCommonData(options);
326
- return `// SPDX-License-Identifier: MIT
327
- pragma solidity >=0.8.0;
328
-
329
- /* Autogenerated file. Do not edit manually. */
349
+ return `${renderedSolidityHeader}
330
350
 
351
+ // Import schema type
331
352
  import { SchemaType } from "@latticexyz/schema-type/src/solidity/SchemaType.sol";
332
353
 
354
+ // Import store internals
333
355
  import { IStore } from "${storeImportPath}IStore.sol";
334
356
  import { StoreSwitch } from "${storeImportPath}StoreSwitch.sol";
335
357
  import { StoreCore } from "${storeImportPath}StoreCore.sol";
@@ -339,15 +361,20 @@ import { EncodeArray } from "${storeImportPath}tightcoder/EncodeArray.sol";
339
361
  import { Schema, SchemaLib } from "${storeImportPath}Schema.sol";
340
362
  import { PackedCounter, PackedCounterLib } from "${storeImportPath}PackedCounter.sol";
341
363
 
364
+ ${imports.length > 0 ? `
365
+ // Import user types
366
+ ${renderImports(imports)}
367
+ ` : ""}
368
+
342
369
  ${!staticRouteData ? "" : `
343
- uint256 constant _tableId = uint256(keccak256("${staticRouteData.baseRoute + staticRouteData.subRoute}"));
344
- uint256 constant ${staticRouteData.tableIdName} = _tableId;
370
+ uint256 constant _tableId = uint256(keccak256("${staticRouteData.baseRoute + staticRouteData.subRoute}"));
371
+ uint256 constant ${staticRouteData.tableIdName} = _tableId;
345
372
  `}
346
373
 
347
374
  ${!structName ? "" : `
348
- struct ${structName} {
349
- ${renderList(fields, ({ name, typeId }) => `${typeId} ${name};`)}
350
- }
375
+ struct ${structName} {
376
+ ${renderList(fields, ({ name, typeId }) => `${typeId} ${name};`)}
377
+ }
351
378
  `}
352
379
 
353
380
  library ${libraryName} {
@@ -359,16 +386,35 @@ library ${libraryName} {
359
386
  return SchemaLib.encode(_schema);
360
387
  }
361
388
 
389
+ /** Get the table's metadata */
390
+ function getMetadata() internal pure returns (string memory, string[] memory) {
391
+ string[] memory _fieldNames = new string[](${fields.length});
392
+ ${renderList(fields, (field, index) => `_fieldNames[${index}] = "${field.name}";`)}
393
+ return ("${libraryName}", _fieldNames);
394
+ }
395
+
362
396
  /** Register the table's schema */
363
397
  function registerSchema(${_typedTableId}) internal {
364
398
  StoreSwitch.registerSchema(_tableId, getSchema());
365
399
  }
366
400
 
401
+ /** Set the table's metadata */
402
+ function setMetadata(${_typedTableId}) internal {
403
+ (string memory _tableName, string[] memory _fieldNames) = getMetadata();
404
+ StoreSwitch.setMetadata(_tableId, _tableName, _fieldNames);
405
+ }
406
+
367
407
  ${!options.storeArgument ? "" : `
368
408
  /** Register the table's schema for the specified store */
369
409
  function registerSchema(${renderArguments([_typedTableId, "IStore _store"])}) internal {
370
410
  _store.registerSchema(_tableId, getSchema());
371
411
  }
412
+
413
+ /** Set the table's metadata for the specified store */
414
+ function setMetadata(${renderArguments([_typedTableId, "IStore _store"])}) internal {
415
+ (string memory _tableName, string[] memory _fieldNames) = getMetadata();
416
+ _store.setMetadata(_tableId, _tableName, _fieldNames);
417
+ }
372
418
  `}
373
419
 
374
420
  ${renderFieldMethods(options)}
@@ -403,33 +449,51 @@ ${// nothing can be cast from bool, so an assembly helper is required
403
449
  `;
404
450
  }
405
451
 
406
- // src/render-table/renderTablesFromConfig.ts
407
- function renderTablesFromConfig(config) {
452
+ // src/render-solidity/renderTablesFromConfig.ts
453
+ import path from "path";
454
+ function renderTablesFromConfig(config, srcDirectory) {
408
455
  const storeImportPath = config.storeImportPath;
409
456
  const renderedTables = [];
410
457
  for (const tableName of Object.keys(config.tables)) {
411
458
  const tableData = config.tables[tableName];
459
+ const outputDirectory = path.join(srcDirectory, tableData.directory);
412
460
  const withStruct = tableData.dataStruct;
413
461
  const withRecordMethods = withStruct || Object.keys(tableData.schema).length > 1;
414
462
  const noFieldMethodSuffix = !withRecordMethods && Object.keys(tableData.schema).length === 1;
463
+ const imports = [];
415
464
  const primaryKeys = Object.keys(tableData.primaryKeys).map((name) => {
416
- const type = tableData.primaryKeys[name];
417
- const typeInfo = getSchemaTypeInfo(type);
418
- if (typeInfo.isDynamic)
419
- throw new Error("Parsing error: found dynamic primary key");
465
+ const schemaOrUserType = tableData.primaryKeys[name];
466
+ const { renderTableType, importDatum } = resolveSchemaOrUserType(
467
+ schemaOrUserType,
468
+ srcDirectory,
469
+ outputDirectory,
470
+ config.userTypes
471
+ );
472
+ if (importDatum)
473
+ imports.push(importDatum);
474
+ if (renderTableType.isDynamic)
475
+ throw new Error(`Parsing error: found dynamic primary key ${name} in table ${tableName}`);
420
476
  const primaryKey = {
421
- ...typeInfo,
477
+ ...renderTableType,
422
478
  name,
423
479
  isDynamic: false
424
480
  };
425
481
  return primaryKey;
426
482
  });
427
483
  const fields = Object.keys(tableData.schema).map((name) => {
428
- const type = tableData.schema[name];
429
- const elementType = SchemaTypeArrayToElement[type];
484
+ const schemaOrUserType = tableData.schema[name];
485
+ const { renderTableType, importDatum, schemaType } = resolveSchemaOrUserType(
486
+ schemaOrUserType,
487
+ srcDirectory,
488
+ outputDirectory,
489
+ config.userTypes
490
+ );
491
+ if (importDatum)
492
+ imports.push(importDatum);
493
+ const elementType = SchemaTypeArrayToElement[schemaType];
430
494
  const field = {
431
- ...getSchemaTypeInfo(type),
432
- arrayElement: elementType ? getSchemaTypeInfo(elementType) : void 0,
495
+ ...renderTableType,
496
+ arrayElement: elementType !== void 0 ? getSchemaTypeInfo(elementType) : void 0,
433
497
  name,
434
498
  methodNameSuffix: noFieldMethodSuffix ? "" : `${name[0].toUpperCase()}${name.slice(1)}`
435
499
  };
@@ -443,15 +507,17 @@ function renderTablesFromConfig(config) {
443
507
  } else {
444
508
  return {
445
509
  tableIdName: tableName + "TableId",
446
- baseRoute: config.baseRoute + tableData.route,
447
- subRoute: `/${tableName}`
510
+ baseRoute: config.baseRoute,
511
+ subRoute: tableData.route
448
512
  };
449
513
  }
450
514
  })();
451
515
  renderedTables.push({
516
+ outputDirectory,
452
517
  tableName,
453
518
  tableData,
454
519
  output: renderTable({
520
+ imports,
455
521
  libraryName: tableName,
456
522
  structName: withStruct ? tableName + "Data" : void 0,
457
523
  staticRouteData,
@@ -467,27 +533,15 @@ function renderTablesFromConfig(config) {
467
533
  }
468
534
  return renderedTables;
469
535
  }
470
- function getSchemaTypeInfo(schemaType) {
471
- const staticByteLength = getStaticByteLength(schemaType);
472
- const isDynamic = staticByteLength === 0;
473
- const typeId = SchemaTypeId[schemaType];
474
- return {
475
- typeId,
476
- typeWithLocation: isDynamic ? typeId + " memory" : typeId,
477
- enumName: SchemaType[schemaType],
478
- staticByteLength,
479
- isDynamic
480
- };
481
- }
536
+
537
+ // src/constants.ts
538
+ var deploymentInfoFilenamePrefix = "mud-deployment-";
482
539
 
483
540
  export {
541
+ renderedSolidityHeader,
484
542
  renderList,
485
543
  renderArguments,
486
- renderCommonData,
487
- renderFieldMethods,
488
- renderEncodeField,
489
- renderDecodeValueType,
490
- renderRecordMethods,
491
544
  renderTable,
492
- renderTablesFromConfig
545
+ renderTablesFromConfig,
546
+ deploymentInfoFilenamePrefix
493
547
  };