@latticexyz/common 2.0.0-next.15 → 2.0.0-next.17

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.
@@ -0,0 +1,83 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { getLeftPaddingBits, isLeftAligned, renderTableId, renderValueTypeToBytes32 } from "./common";
3
+
4
+ describe("isLeftAligned", () => {
5
+ it("returns true when a Solidity type's bytes should be left aligned", () => {
6
+ expect(isLeftAligned({ internalTypeId: "bytes32" })).toBe(true);
7
+ expect(isLeftAligned({ internalTypeId: "uint256" })).toBe(false);
8
+ expect(isLeftAligned({ internalTypeId: "bool" })).toBe(false);
9
+ });
10
+ });
11
+
12
+ describe("getLeftPaddingBits", () => {
13
+ it("returns number of bits to left pad the bytes representation", () => {
14
+ expect(getLeftPaddingBits({ internalTypeId: "bytes32", staticByteLength: 32 })).toBe(0);
15
+ expect(getLeftPaddingBits({ internalTypeId: "bytes16", staticByteLength: 16 })).toBe(0);
16
+ expect(getLeftPaddingBits({ internalTypeId: "uint32", staticByteLength: 4 })).toBe(224);
17
+ expect(getLeftPaddingBits({ internalTypeId: "uint64", staticByteLength: 8 })).toBe(192);
18
+ expect(getLeftPaddingBits({ internalTypeId: "uint128", staticByteLength: 16 })).toBe(128);
19
+ });
20
+ });
21
+
22
+ describe("renderValueTypeToBytes32", () => {
23
+ it("returns Solidity code to cast native type to bytes32", () => {
24
+ expect(renderValueTypeToBytes32("someField", { typeUnwrap: "", internalTypeId: "bytes32" })).toMatchInlineSnapshot(
25
+ '"someField"'
26
+ );
27
+ expect(
28
+ renderValueTypeToBytes32("someField", { typeUnwrap: "SomeStruct.unwrap", internalTypeId: "bytes32" })
29
+ ).toMatchInlineSnapshot('"SomeStruct.unwrap(someField)"');
30
+
31
+ expect(renderValueTypeToBytes32("someField", { typeUnwrap: "", internalTypeId: "bytes16" })).toMatchInlineSnapshot(
32
+ '"bytes32(someField)"'
33
+ );
34
+ expect(
35
+ renderValueTypeToBytes32("someField", { typeUnwrap: "SomeStruct.unwrap", internalTypeId: "bytes16" })
36
+ ).toMatchInlineSnapshot('"bytes32(SomeStruct.unwrap(someField))"');
37
+
38
+ expect(renderValueTypeToBytes32("someField", { typeUnwrap: "", internalTypeId: "uint8" })).toMatchInlineSnapshot(
39
+ '"bytes32(uint256(someField))"'
40
+ );
41
+ expect(
42
+ renderValueTypeToBytes32("someField", { typeUnwrap: "SomeStruct.unwrap", internalTypeId: "uint8" })
43
+ ).toMatchInlineSnapshot('"bytes32(uint256(SomeStruct.unwrap(someField)))"');
44
+
45
+ expect(renderValueTypeToBytes32("someField", { typeUnwrap: "", internalTypeId: "bool" })).toMatchInlineSnapshot(
46
+ '"_boolToBytes32(someField)"'
47
+ );
48
+ expect(
49
+ renderValueTypeToBytes32("someField", { typeUnwrap: "SomeStruct.unwrap", internalTypeId: "bool" })
50
+ ).toMatchInlineSnapshot('"_boolToBytes32(SomeStruct.unwrap(someField))"');
51
+
52
+ expect(renderValueTypeToBytes32("someField", { typeUnwrap: "", internalTypeId: "address" })).toMatchInlineSnapshot(
53
+ '"bytes32(uint256(uint160(someField)))"'
54
+ );
55
+ expect(
56
+ renderValueTypeToBytes32("someField", { typeUnwrap: "SomeStruct.unwrap", internalTypeId: "address" })
57
+ ).toMatchInlineSnapshot('"bytes32(uint256(uint160(SomeStruct.unwrap(someField))))"');
58
+ });
59
+ });
60
+
61
+ describe("renderTableId", () => {
62
+ it("returns Solidity code to compute table ID", () => {
63
+ expect(renderTableId({ namespace: "somewhere", name: "Player", offchainOnly: false, tableIdName: "PlayerTableId" }))
64
+ .toMatchInlineSnapshot(`
65
+ "
66
+ // Hex below is the result of \`WorldResourceIdLib.encode({ namespace: \\"somewhere\\", name: \\"Player\\", typeId: RESOURCE_TABLE });\`
67
+ ResourceId constant _tableId = ResourceId.wrap(0x7462736f6d6577686572650000000000506c6179657200000000000000000000);
68
+ ResourceId constant PlayerTableId = _tableId;
69
+ "
70
+ `);
71
+ });
72
+
73
+ it("returns Solidity code to compute offchain table ID", () => {
74
+ expect(renderTableId({ namespace: "somewhere", name: "Player", offchainOnly: true, tableIdName: "PlayerTableId" }))
75
+ .toMatchInlineSnapshot(`
76
+ "
77
+ // Hex below is the result of \`WorldResourceIdLib.encode({ namespace: \\"somewhere\\", name: \\"Player\\", typeId: RESOURCE_OFFCHAIN_TABLE });\`
78
+ ResourceId constant _tableId = ResourceId.wrap(0x6f74736f6d6577686572650000000000506c6179657200000000000000000000);
79
+ ResourceId constant PlayerTableId = _tableId;
80
+ "
81
+ `);
82
+ });
83
+ });
@@ -8,9 +8,13 @@ import {
8
8
  RenderType,
9
9
  } from "./types";
10
10
  import { posixPath } from "../utils";
11
+ import { resourceToHex } from "../../resourceToHex";
11
12
 
13
+ /**
14
+ * Common header for all codegenerated solidity files
15
+ */
12
16
  export const renderedSolidityHeader = `// SPDX-License-Identifier: MIT
13
- pragma solidity >=0.8.21;
17
+ pragma solidity >=0.8.24;
14
18
 
15
19
  /* Autogenerated file. Do not edit manually. */`;
16
20
 
@@ -29,24 +33,30 @@ export function renderArguments(args: (string | undefined)[]): string {
29
33
  return internalRenderList(",", filteredArgs, (arg) => arg);
30
34
  }
31
35
 
36
+ interface RenderedCommonData {
37
+ /** `_tableId` variable prefixed with its type (empty string if absent) */
38
+ _typedTableId: string;
39
+ /** Comma-separated table key names prefixed with their types (empty string if 0 keys) */
40
+ _typedKeyArgs: string;
41
+ /** Definition and initialization of the dynamic `_keyTuple` bytes32 array */
42
+ _keyTupleDefinition: string;
43
+ }
44
+
45
+ /**
46
+ * Renders some solidity statements commonly used within table libraries
47
+ * @param param0.staticResourceData static data about the table library
48
+ * @param param0.keyTuple key tuple of the table library
49
+ * @returns Rendered statement strings
50
+ */
32
51
  export function renderCommonData({
33
52
  staticResourceData,
34
53
  keyTuple,
35
54
  }: {
36
55
  staticResourceData?: StaticResourceData;
37
56
  keyTuple: RenderKeyTuple[];
38
- }): {
39
- _tableId: string;
40
- _typedTableId: string;
41
- _keyArgs: string;
42
- _typedKeyArgs: string;
43
- _keyTupleDefinition: string;
44
- } {
57
+ }): RenderedCommonData {
45
58
  // static resource means static tableId as well, and no tableId arguments
46
- const _tableId = staticResourceData ? "" : "_tableId";
47
59
  const _typedTableId = staticResourceData ? "" : "ResourceId _tableId";
48
-
49
- const _keyArgs = renderArguments(keyTuple.map(({ name }) => name));
50
60
  const _typedKeyArgs = renderArguments(keyTuple.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`));
51
61
 
52
62
  const _keyTupleDefinition = `
@@ -55,9 +65,7 @@ export function renderCommonData({
55
65
  `;
56
66
 
57
67
  return {
58
- _tableId,
59
68
  _typedTableId,
60
- _keyArgs,
61
69
  _typedKeyArgs,
62
70
  _keyTupleDefinition,
63
71
  };
@@ -125,28 +133,60 @@ export function renderAbsoluteImports(imports: AbsoluteImportDatum[]): string {
125
133
  return renderedImports.join("\n");
126
134
  }
127
135
 
136
+ interface RenderWithStoreCallbackData {
137
+ /** `_store` variable prefixed with its type (undefined if library name) */
138
+ _typedStore: string | undefined;
139
+ /** `_store` variable (undefined if library name) */
140
+ _store: string;
141
+ /** Empty string if storeArgument is false, otherwise `" (using the specified store)"` */
142
+ _commentSuffix: string;
143
+ /** Prefix to differentiate different kinds of store usage within methods */
144
+ _methodNamePrefix: string;
145
+ /** Whether FieldLayout variable should be passed to store methods */
146
+ _useExplicitFieldLayout?: boolean;
147
+ }
148
+
149
+ /**
150
+ * Renders several versions of the callback's result, which access Store in different ways
151
+ * @param storeArgument whether to render a version with `IStore _store` as an argument
152
+ * @param callback renderer for a method which uses store
153
+ * @returns Concatenated results of all callback calls
154
+ */
128
155
  export function renderWithStore(
129
156
  storeArgument: boolean,
130
- callback: (
131
- _typedStore: string | undefined,
132
- _store: string,
133
- _commentSuffix: string,
134
- _untypedStore: string | undefined,
135
- _methodPrefix: string,
136
- _internal?: boolean
137
- ) => string
157
+ callback: (data: RenderWithStoreCallbackData) => string
138
158
  ): string {
139
159
  let result = "";
140
- result += callback(undefined, "StoreSwitch", "", undefined, "");
141
- result += callback(undefined, "StoreCore", "", undefined, "_", true);
160
+ result += callback({ _typedStore: undefined, _store: "StoreSwitch", _commentSuffix: "", _methodNamePrefix: "" });
161
+ result += callback({
162
+ _typedStore: undefined,
163
+ _store: "StoreCore",
164
+ _commentSuffix: "",
165
+ _methodNamePrefix: "_",
166
+ _useExplicitFieldLayout: true,
167
+ });
142
168
 
143
169
  if (storeArgument) {
144
- result += "\n" + callback("IStore _store", "_store", " (using the specified store)", "_store", "");
170
+ result +=
171
+ "\n" +
172
+ callback({
173
+ _typedStore: "IStore _store",
174
+ _store: "_store",
175
+ _commentSuffix: " (using the specified store)",
176
+ _methodNamePrefix: "",
177
+ });
145
178
  }
146
179
 
147
180
  return result;
148
181
  }
149
182
 
183
+ /**
184
+ * Renders several versions of the callback's result, which have different method name suffixes
185
+ * @param withSuffixlessFieldMethods whether to render methods with an empty suffix
186
+ * @param fieldName name of the field which the methods access, used for a suffix
187
+ * @param callback renderer for a method to be suffixed
188
+ * @returns Concatenated results of all callback calls
189
+ */
150
190
  export function renderWithFieldSuffix(
151
191
  withSuffixlessFieldMethods: boolean,
152
192
  fieldName: string,
@@ -163,42 +203,47 @@ export function renderWithFieldSuffix(
163
203
  return result;
164
204
  }
165
205
 
166
- export function renderTableId({ namespace, name, offchainOnly, tableIdName }: StaticResourceData): {
167
- hardcodedTableId: string;
168
- tableIdDefinition: string;
169
- } {
170
- const hardcodedTableId = `
171
- ResourceId.wrap(
172
- bytes32(
173
- abi.encodePacked(
174
- ${offchainOnly ? "RESOURCE_OFFCHAIN_TABLE" : "RESOURCE_TABLE"},
175
- bytes14("${namespace}"),
176
- bytes16("${name}")
177
- )
178
- )
179
- )
180
- `;
181
-
182
- const tableIdDefinition = `
183
- ResourceId constant _tableId = ${hardcodedTableId};
206
+ /**
207
+ * Renders `_tableId` variable definition and initialization, and its alias which uses the provided `tableIdName`.
208
+ * @param param0 static resource data needed to construct the table id
209
+ */
210
+ export function renderTableId({
211
+ namespace,
212
+ name,
213
+ offchainOnly,
214
+ tableIdName,
215
+ }: Pick<StaticResourceData, "namespace" | "name" | "offchainOnly" | "tableIdName">): string {
216
+ return `
217
+ // Hex below is the result of \`WorldResourceIdLib.encode({ namespace: ${JSON.stringify(
218
+ namespace
219
+ )}, name: ${JSON.stringify(name)}, typeId: ${offchainOnly ? "RESOURCE_OFFCHAIN_TABLE" : "RESOURCE_TABLE"} });\`
220
+ ResourceId constant _tableId = ResourceId.wrap(${resourceToHex({
221
+ type: offchainOnly ? "offchainTable" : "table",
222
+ namespace,
223
+ name,
224
+ })});
184
225
  ResourceId constant ${tableIdName} = _tableId;
185
226
  `;
186
- return {
187
- hardcodedTableId,
188
- tableIdDefinition,
189
- };
190
227
  }
191
228
 
192
- export function renderValueTypeToBytes32(name: string, { typeUnwrap, internalTypeId }: RenderType): string {
229
+ /**
230
+ * Renders solidity typecasts to get from the given type to `bytes32`
231
+ * @param name variable name to be typecasted
232
+ * @param param1 type data
233
+ */
234
+ export function renderValueTypeToBytes32(
235
+ name: string,
236
+ { typeUnwrap, internalTypeId }: Pick<RenderType, "typeUnwrap" | "internalTypeId">
237
+ ): string {
193
238
  const innerText = typeUnwrap.length ? `${typeUnwrap}(${name})` : name;
194
239
 
195
240
  if (internalTypeId === "bytes32") {
196
241
  return innerText;
197
- } else if (internalTypeId.match(/^bytes\d{1,2}$/)) {
242
+ } else if (/^bytes\d{1,2}$/.test(internalTypeId)) {
198
243
  return `bytes32(${innerText})`;
199
- } else if (internalTypeId.match(/^uint\d{1,3}$/)) {
244
+ } else if (/^uint\d{1,3}$/.test(internalTypeId)) {
200
245
  return `bytes32(uint256(${innerText}))`;
201
- } else if (internalTypeId.match(/^int\d{1,3}$/)) {
246
+ } else if (/^int\d{1,3}$/.test(internalTypeId)) {
202
247
  return `bytes32(uint256(int256(${innerText})))`;
203
248
  } else if (internalTypeId === "address") {
204
249
  return `bytes32(uint256(uint160(${innerText})))`;
@@ -209,10 +254,16 @@ export function renderValueTypeToBytes32(name: string, { typeUnwrap, internalTyp
209
254
  }
210
255
  }
211
256
 
257
+ /**
258
+ * Whether the storage representation of the given solidity type is left aligned
259
+ */
212
260
  export function isLeftAligned(field: Pick<RenderType, "internalTypeId">): boolean {
213
- return field.internalTypeId.match(/^bytes\d{1,2}$/) !== null;
261
+ return /^bytes\d{1,2}$/.test(field.internalTypeId);
214
262
  }
215
263
 
264
+ /**
265
+ * The number of padding bits in the storage representation of a right-aligned solidity type
266
+ */
216
267
  export function getLeftPaddingBits(field: Pick<RenderType, "internalTypeId" | "staticByteLength">): number {
217
268
  if (isLeftAligned(field)) {
218
269
  return 0;
@@ -221,6 +272,9 @@ export function getLeftPaddingBits(field: Pick<RenderType, "internalTypeId" | "s
221
272
  }
222
273
  }
223
274
 
275
+ /**
276
+ * Internal helper to render `lineTerminator`-separated list of items mapped by `renderItem`
277
+ */
224
278
  function internalRenderList<T>(
225
279
  lineTerminator: string,
226
280
  list: T[],
@@ -1,6 +1,9 @@
1
1
  import { renderArguments, renderList, renderedSolidityHeader } from "./common";
2
2
  import { RenderEnum } from "./types";
3
3
 
4
+ /**
5
+ * Render a list of enum data as solidity enum definitions
6
+ */
4
7
  export function renderEnums(enums: RenderEnum[]): string {
5
8
  let result = renderedSolidityHeader;
6
9
 
@@ -1,5 +1,8 @@
1
1
  import { RenderField, RenderKeyTuple, RenderType } from "./types";
2
2
 
3
+ /**
4
+ * Renders the necessary helper functions to typecast to/from the types of given fields and keys
5
+ */
3
6
  export function renderTypeHelpers(options: { fields: RenderField[]; keyTuple: RenderKeyTuple[] }): string {
4
7
  const { fields, keyTuple } = options;
5
8
 
@@ -59,6 +62,14 @@ function getWrappingHelpers(array: RenderType[]): string[] {
59
62
  return [...wrappers.values(), ...unwrappers.values()];
60
63
  }
61
64
 
65
+ /**
66
+ * Renders a function to cast a dynamic array to a static array.
67
+ * @param functionName name of the function to be rendered
68
+ * @param elementType type of the array's element
69
+ * @param staticLength length of the static array
70
+ * @param internalTypeId solidity type name of the dynamic array
71
+ * @returns
72
+ */
62
73
  function renderWrapperStaticArray(
63
74
  functionName: string,
64
75
  elementType: string,
@@ -96,6 +107,14 @@ function renderWrapperStaticArray(
96
107
  `;
97
108
  }
98
109
 
110
+ /**
111
+ * Renders a function to cast a static array to a dynamic array.
112
+ * @param functionName name of the function to be rendered
113
+ * @param elementType type of the array's element
114
+ * @param staticLength length of the static array
115
+ * @param internalTypeId solidity type name of the dynamic array
116
+ * @returns
117
+ */
99
118
  function renderUnwrapperStaticArray(
100
119
  functionName: string,
101
120
  elementType: string,
@@ -14,13 +14,18 @@ export type ImportDatum = AbsoluteImportDatum | RelativeImportDatum;
14
14
  export interface StaticResourceData {
15
15
  /** Name of the table id constant to render. */
16
16
  tableIdName: string;
17
+ /** Table namespace string */
17
18
  namespace: string;
19
+ /** Table name string */
18
20
  name: string;
21
+ /** Whether the table is offchain only (does not use storage) */
19
22
  offchainOnly: boolean;
20
23
  }
21
24
 
22
25
  export interface RenderType {
26
+ /** Fully-qualified name of the user-defined type (may include a library name as prefix) */
23
27
  typeId: string;
28
+ /** Fully-qualified name of the user-defined type (may include a library name as prefix), followed by location (none/memory/storage) */
24
29
  typeWithLocation: string;
25
30
  /** The name of the enum element in SchemaType to use for schema registration (e.g. "UINT256_ARRAY") */
26
31
  enumName: string;
@@ -1,5 +1,10 @@
1
1
  import { parse, visit } from "@solidity-parser/parser";
2
- import type { SourceUnit, TypeName, VariableDeclaration } from "@solidity-parser/parser/dist/src/ast-types";
2
+ import type {
3
+ ContractDefinition,
4
+ SourceUnit,
5
+ TypeName,
6
+ VariableDeclaration,
7
+ } from "@solidity-parser/parser/dist/src/ast-types";
3
8
  import { MUDError } from "../../errors";
4
9
 
5
10
  export interface ContractInterfaceFunction {
@@ -36,52 +41,55 @@ export function contractToInterface(
36
41
  } {
37
42
  const ast = parse(data);
38
43
 
39
- let withContract = false;
44
+ const contractNode = findContractNode(parse(data), contractName);
40
45
  let symbolImports: SymbolImport[] = [];
41
46
  const functions: ContractInterfaceFunction[] = [];
42
47
  const errors: ContractInterfaceError[] = [];
43
48
 
44
- visit(ast, {
45
- ContractDefinition({ name }) {
46
- if (name === contractName) {
47
- withContract = true;
48
- }
49
- },
50
- FunctionDefinition(
51
- { name, visibility, parameters, stateMutability, returnParameters, isConstructor, isFallback, isReceiveEther },
52
- parent
53
- ) {
54
- if (parent !== undefined && parent.type === "ContractDefinition" && parent.name === contractName) {
55
- try {
56
- // skip constructor and fallbacks
57
- if (isConstructor || isFallback || isReceiveEther) return;
58
- // forbid default visibility (this check might be unnecessary, modern solidity already disallows this)
59
- if (visibility === "default") throw new MUDError(`Visibility is not specified`);
60
-
61
- if (visibility === "external" || visibility === "public") {
62
- functions.push({
63
- name: name === null ? "" : name,
64
- parameters: parameters.map(parseParameter),
65
- stateMutability: stateMutability || "",
66
- returnParameters: returnParameters === null ? [] : returnParameters.map(parseParameter),
67
- });
68
-
69
- for (const { typeName } of parameters.concat(returnParameters ?? [])) {
70
- const symbols = typeNameToSymbols(typeName);
71
- symbolImports = symbolImports.concat(symbolsToImports(ast, symbols));
72
- }
73
- }
74
- } catch (error: unknown) {
75
- if (error instanceof MUDError) {
76
- error.message = `Function "${name}" in contract "${contractName}": ${error.message}`;
49
+ if (!contractNode) {
50
+ throw new MUDError(`Contract not found: ${contractName}`);
51
+ }
52
+
53
+ visit(contractNode, {
54
+ FunctionDefinition({
55
+ name,
56
+ visibility,
57
+ parameters,
58
+ stateMutability,
59
+ returnParameters,
60
+ isConstructor,
61
+ isFallback,
62
+ isReceiveEther,
63
+ }) {
64
+ try {
65
+ // skip constructor and fallbacks
66
+ if (isConstructor || isFallback || isReceiveEther) return;
67
+ // forbid default visibility (this check might be unnecessary, modern solidity already disallows this)
68
+ if (visibility === "default") throw new MUDError(`Visibility is not specified`);
69
+
70
+ if (visibility === "external" || visibility === "public") {
71
+ functions.push({
72
+ name: name === null ? "" : name,
73
+ parameters: parameters.map(parseParameter),
74
+ stateMutability: stateMutability || "",
75
+ returnParameters: returnParameters === null ? [] : returnParameters.map(parseParameter),
76
+ });
77
+
78
+ for (const { typeName } of parameters.concat(returnParameters ?? [])) {
79
+ const symbols = typeNameToSymbols(typeName);
80
+ symbolImports = symbolImports.concat(symbolsToImports(ast, symbols));
77
81
  }
78
- throw error;
79
82
  }
83
+ } catch (error: unknown) {
84
+ if (error instanceof MUDError) {
85
+ error.message = `Function "${name}" in contract "${contractName}": ${error.message}`;
86
+ }
87
+ throw error;
80
88
  }
81
89
  },
82
90
  CustomErrorDefinition({ name, parameters }) {
83
91
  errors.push({
84
- name: name === null ? "" : name,
92
+ name,
85
93
  parameters: parameters.map(parseParameter),
86
94
  });
87
95
 
@@ -92,10 +100,6 @@ export function contractToInterface(
92
100
  },
93
101
  });
94
102
 
95
- if (!withContract) {
96
- throw new MUDError(`Contract not found: ${contractName}`);
97
- }
98
-
99
103
  return {
100
104
  functions,
101
105
  errors,
@@ -103,6 +107,20 @@ export function contractToInterface(
103
107
  };
104
108
  }
105
109
 
110
+ function findContractNode(ast: SourceUnit, contractName: string): ContractDefinition | undefined {
111
+ let contract = undefined;
112
+
113
+ visit(ast, {
114
+ ContractDefinition(node) {
115
+ if (node.name === contractName) {
116
+ contract = node;
117
+ }
118
+ },
119
+ });
120
+
121
+ return contract;
122
+ }
123
+
106
124
  function parseParameter({ name, typeName, storageLocation }: VariableDeclaration): string {
107
125
  let typedNameWithLocation = "";
108
126
 
@@ -2,10 +2,15 @@ import { parse, visit } from "@solidity-parser/parser";
2
2
  import { MUDError } from "../../errors";
3
3
 
4
4
  export interface SolidityUserDefinedType {
5
+ /** Fully-qualified name of the user-defined type (may include a library name as prefix) */
5
6
  typeId: string;
7
+ /** Name of the wrapped primitive type */
6
8
  internalTypeId: string;
9
+ /** Symbol which must be imported to use the type (either the type name, or the library name where the type is defined) */
7
10
  importSymbol: string;
11
+ /** Path to the solidity file which contains the user type */
8
12
  fromPath: string;
13
+ /** Whether `fromPath` is relative */
9
14
  isRelativePath: boolean;
10
15
  }
11
16
 
@@ -13,6 +18,8 @@ export interface SolidityUserDefinedType {
13
18
  * Parse the solidity data to extract user-defined type information.
14
19
  * @param data contents of a solidity file with the user types declarations
15
20
  * @param userTypeNames names of the user types to extract
21
+ * @param fromPath path to the solidity file from which the user types are extracted
22
+ * @returns record of type names mapped to the extracted type information
16
23
  */
17
24
  export function extractUserTypes(
18
25
  data: string,
@@ -1,6 +1,12 @@
1
1
  import prettier from "prettier";
2
2
  import prettierPluginSolidity from "prettier-plugin-solidity";
3
3
 
4
+ /**
5
+ * Formats solidity code using prettier
6
+ * @param content solidity code
7
+ * @param prettierConfigPath optional path to a prettier config
8
+ * @returns formatted solidity code
9
+ */
4
10
  export async function formatSolidity(content: string, prettierConfigPath?: string): Promise<string> {
5
11
  let config;
6
12
  if (prettierConfigPath) {
@@ -31,6 +37,11 @@ export async function formatSolidity(content: string, prettierConfigPath?: strin
31
37
  }
32
38
  }
33
39
 
40
+ /**
41
+ * Formats typescript code using prettier
42
+ * @param content typescript code
43
+ * @returns formatted typescript code
44
+ */
34
45
  export async function formatTypescript(content: string): Promise<string> {
35
46
  return prettier.format(content, {
36
47
  parser: "typescript",
@@ -3,6 +3,12 @@ import { dirname } from "path";
3
3
  import { formatSolidity, formatTypescript } from "./format";
4
4
  import { debug } from "../debug";
5
5
 
6
+ /**
7
+ * Formats solidity code using prettier and write it to a file
8
+ * @param output solidity code
9
+ * @param fullOutputPath full path to the output file
10
+ * @param logPrefix prefix for debug logs
11
+ */
6
12
  export async function formatAndWriteSolidity(output: string, fullOutputPath: string, logPrefix: string): Promise<void> {
7
13
  const formattedOutput = await formatSolidity(output);
8
14
 
@@ -12,6 +18,12 @@ export async function formatAndWriteSolidity(output: string, fullOutputPath: str
12
18
  debug(`${logPrefix}: ${fullOutputPath}`);
13
19
  }
14
20
 
21
+ /**
22
+ * Formats typescript code using prettier and write it to a file
23
+ * @param output typescript code
24
+ * @param fullOutputPath full path to the output file
25
+ * @param logPrefix prefix for debug logs
26
+ */
15
27
  export async function formatAndWriteTypescript(
16
28
  output: string,
17
29
  fullOutputPath: string,
@@ -9,6 +9,13 @@ export type UserType = {
9
9
  internalType: SchemaAbiType;
10
10
  };
11
11
 
12
+ /**
13
+ * Load the user type files and extract type information from them.
14
+ * @param userTypes record of user type data mapped by type names
15
+ * @param outputBaseDirectory base path to the output directory
16
+ * @param remappings solc remappings
17
+ * @returns record of the user type information mapped by type names
18
+ */
12
19
  export function loadAndExtractUserTypes(
13
20
  userTypes: Record<string, UserType>,
14
21
  outputBaseDirectory: string,
@@ -35,7 +42,7 @@ export function loadAndExtractUserTypes(
35
42
  }
36
43
  }
37
44
 
38
- extractedUserTypes = Object.assign(extractedUserTypes, userTypesInFile);
45
+ extractedUserTypes = { ...extractedUserTypes, ...userTypesInFile };
39
46
  }
40
47
  return extractedUserTypes;
41
48
  }
@@ -1,2 +0,0 @@
1
- import o from"debug";var e=o("mud:common"),r=o("mud:common");e.log=console.debug.bind(console);r.log=console.error.bind(console);export{e as a};
2
- //# sourceMappingURL=chunk-TCWGPC6G.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/debug.ts"],"sourcesContent":["import createDebug from \"debug\";\n\nexport const debug = createDebug(\"mud:common\");\nexport const error = createDebug(\"mud:common\");\n\n// Pipe debug output to stdout instead of stderr\ndebug.log = console.debug.bind(console);\n\n// Pipe error output to stderr\nerror.log = console.error.bind(console);\n"],"mappings":"AAAA,OAAOA,MAAiB,QAEjB,IAAMC,EAAQD,EAAY,YAAY,EAChCE,EAAQF,EAAY,YAAY,EAG7CC,EAAM,IAAM,QAAQ,MAAM,KAAK,OAAO,EAGtCC,EAAM,IAAM,QAAQ,MAAM,KAAK,OAAO","names":["createDebug","debug","error"]}