From 1124267afa17dff2217dcf63c6beb18d5fd89fbf Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Wed, 24 Jul 2024 20:22:12 +0100 Subject: [PATCH 01/16] replace use of renderList with .map --- .../src/codegen/render-solidity/common.ts | 9 +----- packages/store/ts/codegen/record.ts | 28 ++++++------------- packages/store/ts/codegen/renderTable.ts | 13 ++++----- packages/store/ts/codegen/renderTableIndex.ts | 14 +++++----- .../render-solidity/renderSystemInterface.ts | 21 +++++++------- 5 files changed, 33 insertions(+), 52 deletions(-) diff --git a/packages/common/src/codegen/render-solidity/common.ts b/packages/common/src/codegen/render-solidity/common.ts index f0b284d169..1f4b2e5bad 100644 --- a/packages/common/src/codegen/render-solidity/common.ts +++ b/packages/common/src/codegen/render-solidity/common.ts @@ -19,13 +19,6 @@ pragma solidity >=0.8.24; /* Autogenerated file. Do not edit manually. */`; -/** - * Renders a list of lines - */ -export function renderList(list: T[], renderItem: (item: T, index: number) => string): string { - return internalRenderList("", list, renderItem); -} - /** * Renders a comma-separated list of arguments for solidity functions, ignoring empty and undefined ones */ @@ -62,7 +55,7 @@ export function renderCommonData({ const _keyTupleDefinition = ` bytes32[] memory _keyTuple = new bytes32[](${keyTuple.length}); - ${renderList(keyTuple, (key, index) => `_keyTuple[${index}] = ${renderValueTypeToBytes32(key.name, key)};`)} + ${keyTuple.map((key, index) => `_keyTuple[${index}] = ${renderValueTypeToBytes32(key.name, key)};`).join("\n")} `; return { diff --git a/packages/store/ts/codegen/record.ts b/packages/store/ts/codegen/record.ts index 09766b21cc..a98f2abf39 100644 --- a/packages/store/ts/codegen/record.ts +++ b/packages/store/ts/codegen/record.ts @@ -1,10 +1,4 @@ -import { - RenderDynamicField, - renderArguments, - renderCommonData, - renderList, - renderWithStore, -} from "@latticexyz/common/codegen"; +import { RenderDynamicField, renderArguments, renderCommonData, renderWithStore } from "@latticexyz/common/codegen"; import { renderDecodeValueType } from "./field"; import { RenderTableOptions } from "./types"; @@ -204,12 +198,7 @@ function renderDecodeFunctions({ structName, fields, staticFields, dynamicFields function decodeStatic(bytes memory _blob) internal pure returns (${renderArguments( staticFields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`), )}) { - ${renderList( - staticFields, - (field, index) => ` - ${field.name} = ${renderDecodeValueType(field, staticOffsets[index])}; - `, - )} + ${staticFields.map((field, index) => `${field.name} = ${renderDecodeValueType(field, staticOffsets[index])};`).join(" ")} } `; } @@ -222,11 +211,10 @@ function renderDecodeFunctions({ structName, fields, staticFields, dynamicFields function decodeDynamic(EncodedLengths _encodedLengths, bytes memory _blob) internal pure returns (${renderArguments( dynamicFields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`), )}) { - ${renderList( - dynamicFields, - // unchecked is only dangerous if _encodedLengths (and _blob) is invalid, - // but it's assumed to be valid, and this function is meant to be mostly used internally - (field, index) => { + ${dynamicFields + .map((field, index) => { + // unchecked is only dangerous if _encodedLengths (and _blob) is invalid, + // but it's assumed to be valid, and this function is meant to be mostly used internally if (index === 0) { return ` uint256 _start; @@ -245,8 +233,8 @@ function renderDecodeFunctions({ structName, fields, staticFields, dynamicFields ${field.name} = ${renderDecodeDynamicFieldPartial(field)}; `; } - }, - )} + }) + .join("\n")} } `; } diff --git a/packages/store/ts/codegen/renderTable.ts b/packages/store/ts/codegen/renderTable.ts index 91b7036dd3..a93c53e79e 100644 --- a/packages/store/ts/codegen/renderTable.ts +++ b/packages/store/ts/codegen/renderTable.ts @@ -2,7 +2,6 @@ import { RenderDynamicField, renderArguments, renderCommonData, - renderList, renderImports, renderTableId, renderTypeHelpers, @@ -64,13 +63,13 @@ export function renderTable(options: RenderTableOptions) { } ${ - !structName - ? "" - : ` + structName + ? ` struct ${structName} { - ${renderList(fields, ({ name, typeId }) => `${typeId} ${name};`)} + ${fields.map(({ name, typeId }) => `${typeId} ${name};`).join(" ")} } ` + : "" } library ${libraryName} { @@ -93,7 +92,7 @@ export function renderTable(options: RenderTableOptions) { */ function getKeyNames() internal pure returns (string[] memory keyNames) { keyNames = new string[](${keyTuple.length}); - ${renderList(keyTuple, (keyElement, index) => `keyNames[${index}] = "${keyElement.name}";`)} + ${keyTuple.map((element, index) => `keyNames[${index}] = "${element.name}";`).join(" ")} } /** @@ -102,7 +101,7 @@ export function renderTable(options: RenderTableOptions) { */ function getFieldNames() internal pure returns (string[] memory fieldNames) { fieldNames = new string[](${fields.length}); - ${renderList(fields, (field, index) => `fieldNames[${index}] = "${field.name}";`)} + ${fields.map((field, index) => `fieldNames[${index}] = "${field.name}";`).join(" ")} } ${renderWithStore( diff --git a/packages/store/ts/codegen/renderTableIndex.ts b/packages/store/ts/codegen/renderTableIndex.ts index 1bb5a990f5..92584596d6 100644 --- a/packages/store/ts/codegen/renderTableIndex.ts +++ b/packages/store/ts/codegen/renderTableIndex.ts @@ -1,4 +1,4 @@ -import { posixPath, renderList, renderedSolidityHeader } from "@latticexyz/common/codegen"; +import { posixPath, renderedSolidityHeader } from "@latticexyz/common/codegen"; import { TableOptions } from "./tableOptions"; /** @@ -10,11 +10,11 @@ export function renderTableIndex(options: TableOptions[]) { return ` ${renderedSolidityHeader} - ${renderList(options, ({ outputPath, tableName, renderOptions: { structName } }) => { - const imports = [tableName]; - if (structName) imports.push(structName); - - return `import { ${imports.join(", ")} } from "./${posixPath(outputPath)}";`; - })} + ${options + .map(({ outputPath, tableName, renderOptions: { structName } }) => { + const imports = [tableName, ...(structName ? [structName] : [])]; + return `import { ${imports.join(", ")} } from "./${posixPath(outputPath)}";`; + }) + .join("\n")} `; } diff --git a/packages/world/ts/node/render-solidity/renderSystemInterface.ts b/packages/world/ts/node/render-solidity/renderSystemInterface.ts index ceb3be23da..c0058f733f 100644 --- a/packages/world/ts/node/render-solidity/renderSystemInterface.ts +++ b/packages/world/ts/node/render-solidity/renderSystemInterface.ts @@ -1,4 +1,4 @@ -import { renderArguments, renderList, renderedSolidityHeader, renderImports } from "@latticexyz/common/codegen"; +import { renderArguments, renderedSolidityHeader, renderImports } from "@latticexyz/common/codegen"; import { RenderSystemInterfaceOptions } from "./types"; export function renderSystemInterface(options: RenderSystemInterfaceOptions) { @@ -15,16 +15,17 @@ export function renderSystemInterface(options: RenderSystemInterfaceOptions) { * @dev This interface is automatically generated from the corresponding system contract. Do not edit manually. */ interface ${name} { - ${renderList(errors, ({ name, parameters }) => `error ${name}(${renderArguments(parameters)});`)} + ${errors.map(({ name, parameters }) => `error ${name}(${renderArguments(parameters)});`).join("\n")} - ${renderList( - functions, - ({ name, parameters, stateMutability, returnParameters }) => ` - function ${functionPrefix}${name}( - ${renderArguments(parameters)} - ) external ${stateMutability} ${renderReturnParameters(returnParameters)}; - `, - )} + ${functions + .map( + ({ name, parameters, stateMutability, returnParameters }) => ` + function ${functionPrefix}${name}( + ${renderArguments(parameters)} + ) external ${stateMutability} ${renderReturnParameters(returnParameters)}; + `, + ) + .join("\n")} } `; } From f6ba539fff32d30f89b866b0f6c12cf85ebfd7ac Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Wed, 24 Jul 2024 20:22:16 +0100 Subject: [PATCH 02/16] Revert "replace use of renderList with .map" This reverts commit 1124267afa17dff2217dcf63c6beb18d5fd89fbf. --- .../src/codegen/render-solidity/common.ts | 9 +++++- packages/store/ts/codegen/record.ts | 28 +++++++++++++------ packages/store/ts/codegen/renderTable.ts | 13 +++++---- packages/store/ts/codegen/renderTableIndex.ts | 14 +++++----- .../render-solidity/renderSystemInterface.ts | 21 +++++++------- 5 files changed, 52 insertions(+), 33 deletions(-) diff --git a/packages/common/src/codegen/render-solidity/common.ts b/packages/common/src/codegen/render-solidity/common.ts index 1f4b2e5bad..f0b284d169 100644 --- a/packages/common/src/codegen/render-solidity/common.ts +++ b/packages/common/src/codegen/render-solidity/common.ts @@ -19,6 +19,13 @@ pragma solidity >=0.8.24; /* Autogenerated file. Do not edit manually. */`; +/** + * Renders a list of lines + */ +export function renderList(list: T[], renderItem: (item: T, index: number) => string): string { + return internalRenderList("", list, renderItem); +} + /** * Renders a comma-separated list of arguments for solidity functions, ignoring empty and undefined ones */ @@ -55,7 +62,7 @@ export function renderCommonData({ const _keyTupleDefinition = ` bytes32[] memory _keyTuple = new bytes32[](${keyTuple.length}); - ${keyTuple.map((key, index) => `_keyTuple[${index}] = ${renderValueTypeToBytes32(key.name, key)};`).join("\n")} + ${renderList(keyTuple, (key, index) => `_keyTuple[${index}] = ${renderValueTypeToBytes32(key.name, key)};`)} `; return { diff --git a/packages/store/ts/codegen/record.ts b/packages/store/ts/codegen/record.ts index a98f2abf39..09766b21cc 100644 --- a/packages/store/ts/codegen/record.ts +++ b/packages/store/ts/codegen/record.ts @@ -1,4 +1,10 @@ -import { RenderDynamicField, renderArguments, renderCommonData, renderWithStore } from "@latticexyz/common/codegen"; +import { + RenderDynamicField, + renderArguments, + renderCommonData, + renderList, + renderWithStore, +} from "@latticexyz/common/codegen"; import { renderDecodeValueType } from "./field"; import { RenderTableOptions } from "./types"; @@ -198,7 +204,12 @@ function renderDecodeFunctions({ structName, fields, staticFields, dynamicFields function decodeStatic(bytes memory _blob) internal pure returns (${renderArguments( staticFields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`), )}) { - ${staticFields.map((field, index) => `${field.name} = ${renderDecodeValueType(field, staticOffsets[index])};`).join(" ")} + ${renderList( + staticFields, + (field, index) => ` + ${field.name} = ${renderDecodeValueType(field, staticOffsets[index])}; + `, + )} } `; } @@ -211,10 +222,11 @@ function renderDecodeFunctions({ structName, fields, staticFields, dynamicFields function decodeDynamic(EncodedLengths _encodedLengths, bytes memory _blob) internal pure returns (${renderArguments( dynamicFields.map(({ name, typeWithLocation }) => `${typeWithLocation} ${name}`), )}) { - ${dynamicFields - .map((field, index) => { - // unchecked is only dangerous if _encodedLengths (and _blob) is invalid, - // but it's assumed to be valid, and this function is meant to be mostly used internally + ${renderList( + dynamicFields, + // unchecked is only dangerous if _encodedLengths (and _blob) is invalid, + // but it's assumed to be valid, and this function is meant to be mostly used internally + (field, index) => { if (index === 0) { return ` uint256 _start; @@ -233,8 +245,8 @@ function renderDecodeFunctions({ structName, fields, staticFields, dynamicFields ${field.name} = ${renderDecodeDynamicFieldPartial(field)}; `; } - }) - .join("\n")} + }, + )} } `; } diff --git a/packages/store/ts/codegen/renderTable.ts b/packages/store/ts/codegen/renderTable.ts index a93c53e79e..91b7036dd3 100644 --- a/packages/store/ts/codegen/renderTable.ts +++ b/packages/store/ts/codegen/renderTable.ts @@ -2,6 +2,7 @@ import { RenderDynamicField, renderArguments, renderCommonData, + renderList, renderImports, renderTableId, renderTypeHelpers, @@ -63,13 +64,13 @@ export function renderTable(options: RenderTableOptions) { } ${ - structName - ? ` + !structName + ? "" + : ` struct ${structName} { - ${fields.map(({ name, typeId }) => `${typeId} ${name};`).join(" ")} + ${renderList(fields, ({ name, typeId }) => `${typeId} ${name};`)} } ` - : "" } library ${libraryName} { @@ -92,7 +93,7 @@ export function renderTable(options: RenderTableOptions) { */ function getKeyNames() internal pure returns (string[] memory keyNames) { keyNames = new string[](${keyTuple.length}); - ${keyTuple.map((element, index) => `keyNames[${index}] = "${element.name}";`).join(" ")} + ${renderList(keyTuple, (keyElement, index) => `keyNames[${index}] = "${keyElement.name}";`)} } /** @@ -101,7 +102,7 @@ export function renderTable(options: RenderTableOptions) { */ function getFieldNames() internal pure returns (string[] memory fieldNames) { fieldNames = new string[](${fields.length}); - ${fields.map((field, index) => `fieldNames[${index}] = "${field.name}";`).join(" ")} + ${renderList(fields, (field, index) => `fieldNames[${index}] = "${field.name}";`)} } ${renderWithStore( diff --git a/packages/store/ts/codegen/renderTableIndex.ts b/packages/store/ts/codegen/renderTableIndex.ts index 92584596d6..1bb5a990f5 100644 --- a/packages/store/ts/codegen/renderTableIndex.ts +++ b/packages/store/ts/codegen/renderTableIndex.ts @@ -1,4 +1,4 @@ -import { posixPath, renderedSolidityHeader } from "@latticexyz/common/codegen"; +import { posixPath, renderList, renderedSolidityHeader } from "@latticexyz/common/codegen"; import { TableOptions } from "./tableOptions"; /** @@ -10,11 +10,11 @@ export function renderTableIndex(options: TableOptions[]) { return ` ${renderedSolidityHeader} - ${options - .map(({ outputPath, tableName, renderOptions: { structName } }) => { - const imports = [tableName, ...(structName ? [structName] : [])]; - return `import { ${imports.join(", ")} } from "./${posixPath(outputPath)}";`; - }) - .join("\n")} + ${renderList(options, ({ outputPath, tableName, renderOptions: { structName } }) => { + const imports = [tableName]; + if (structName) imports.push(structName); + + return `import { ${imports.join(", ")} } from "./${posixPath(outputPath)}";`; + })} `; } diff --git a/packages/world/ts/node/render-solidity/renderSystemInterface.ts b/packages/world/ts/node/render-solidity/renderSystemInterface.ts index c0058f733f..ceb3be23da 100644 --- a/packages/world/ts/node/render-solidity/renderSystemInterface.ts +++ b/packages/world/ts/node/render-solidity/renderSystemInterface.ts @@ -1,4 +1,4 @@ -import { renderArguments, renderedSolidityHeader, renderImports } from "@latticexyz/common/codegen"; +import { renderArguments, renderList, renderedSolidityHeader, renderImports } from "@latticexyz/common/codegen"; import { RenderSystemInterfaceOptions } from "./types"; export function renderSystemInterface(options: RenderSystemInterfaceOptions) { @@ -15,17 +15,16 @@ export function renderSystemInterface(options: RenderSystemInterfaceOptions) { * @dev This interface is automatically generated from the corresponding system contract. Do not edit manually. */ interface ${name} { - ${errors.map(({ name, parameters }) => `error ${name}(${renderArguments(parameters)});`).join("\n")} + ${renderList(errors, ({ name, parameters }) => `error ${name}(${renderArguments(parameters)});`)} - ${functions - .map( - ({ name, parameters, stateMutability, returnParameters }) => ` - function ${functionPrefix}${name}( - ${renderArguments(parameters)} - ) external ${stateMutability} ${renderReturnParameters(returnParameters)}; - `, - ) - .join("\n")} + ${renderList( + functions, + ({ name, parameters, stateMutability, returnParameters }) => ` + function ${functionPrefix}${name}( + ${renderArguments(parameters)} + ) external ${stateMutability} ${renderReturnParameters(returnParameters)}; + `, + )} } `; } From 154778c611e74378b43681896a264d87b04f5f26 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 25 Jul 2024 14:22:40 +0100 Subject: [PATCH 03/16] start migrating tablegen with new imports --- packages/store/ts/codegen/getTableOptions.ts | 138 ++++++++++++++++++ .../store/ts/codegen/getUserTypes.test.ts | 14 ++ packages/store/ts/codegen/getUserTypes.ts | 48 ++++++ .../store/ts/codegen/getUserTypesFilename.ts | 9 ++ packages/store/ts/codegen/renderTableIndex.ts | 7 +- packages/store/ts/codegen/tablegen.ts | 88 +++++++---- packages/store/ts/config/v2/output.ts | 4 +- 7 files changed, 272 insertions(+), 36 deletions(-) create mode 100644 packages/store/ts/codegen/getTableOptions.ts create mode 100644 packages/store/ts/codegen/getUserTypes.test.ts create mode 100644 packages/store/ts/codegen/getUserTypes.ts create mode 100644 packages/store/ts/codegen/getUserTypesFilename.ts diff --git a/packages/store/ts/codegen/getTableOptions.ts b/packages/store/ts/codegen/getTableOptions.ts new file mode 100644 index 0000000000..dfc5646174 --- /dev/null +++ b/packages/store/ts/codegen/getTableOptions.ts @@ -0,0 +1,138 @@ +import path from "path"; +import { SchemaTypeArrayToElement } from "@latticexyz/schema-type/deprecated"; +import { + ImportDatum, + RenderDynamicField, + RenderField, + RenderKeyTuple, + RenderStaticField, + SolidityUserDefinedType, +} from "@latticexyz/common/codegen"; +import { RenderTableOptions } from "./types"; +import { getSchemaTypeInfo, resolveAbiOrUserType } from "./userType"; +import { Store, Table } from "../config/v2/output"; +import { getKeySchema, getValueSchema } from "@latticexyz/protocol-parser/internal"; +import { UserType } from "./getUserTypes"; + +export interface TableOptions { + /** Path where the file is expected to be written (relative to project root) */ + outputPath: string; + /** Name of the table, as used in filename and library name */ + tableName: string; + /** Options for `renderTable` function */ + renderOptions: RenderTableOptions; +} + +/** + * Transforms store config and available solidity user types into useful options for `tablegen` and `renderTable` + */ +export function getTableOptions({ + tables, + rootDir, + codegenDir, + userTypes, + storeImportPath, + config, + solidityUserTypes, +}: { + readonly tables: Table[]; + readonly rootDir: string; + /** Absolute path to base codegen dir */ + readonly codegenDir: string; + readonly userTypes: readonly UserType[]; + readonly storeImportPath: string; + /** @deprecated */ + readonly config: Store; + /** @deprecated */ + readonly solidityUserTypes: Record; +}): TableOptions[] { + const options = tables.map((table): TableOptions => { + const outputPath = path.join(rootDir, codegenDir, table.codegen.outputDirectory, `${table.label}.sol`); + + const keySchema = getKeySchema(table); + const valueSchema = getValueSchema(table); + + // struct adds methods to get/set all values at once + const withStruct = table.codegen.dataStruct; + // operate on all fields at once; always render for offchain tables; for only 1 field keep them if struct is also kept + const withRecordMethods = withStruct || table.type === "offchainTable" || Object.keys(valueSchema).length > 1; + // field methods can include simply get/set if there's only 1 field and no record methods + const withSuffixlessFieldMethods = !withRecordMethods && Object.keys(valueSchema).length === 1; + // list of any symbols that need to be imported + const imports = Object.entries(table.schema) + .filter(([, field]) => field.type !== field.internalType) + .map(([fieldName, field]): ImportDatum => { + const userType = userTypes.find((userType) => userType.name === field.internalType); + if (!userType) { + throw new Error( + `Table "${table.label}" schema with field "${fieldName}" had no corresponding user type for "${field.internalType}".`, + ); + } + return { + symbol: userType.name, + path: userType.importPath.startsWith(".") + ? "./" + path.relative(path.dirname(outputPath), path.join(rootDir, userType.importPath)) + : userType.importPath, + }; + }); + + const keyTuple = Object.entries(keySchema).map(([name, field]): RenderKeyTuple => { + const abiOrUserType = field.internalType; + const { renderType } = resolveAbiOrUserType(abiOrUserType, config, solidityUserTypes); + + return { + ...renderType, + name, + isDynamic: false, + }; + }); + + const fields = Object.entries(valueSchema).map(([name, field]): RenderField => { + const abiOrUserType = field.internalType; + const { renderType, schemaType } = resolveAbiOrUserType(abiOrUserType, config, solidityUserTypes); + + const elementType = SchemaTypeArrayToElement[schemaType]; + return { + ...renderType, + arrayElement: elementType !== undefined ? getSchemaTypeInfo(elementType) : undefined, + name, + }; + }); + + const staticFields = fields.filter(({ isDynamic }) => !isDynamic) as RenderStaticField[]; + const dynamicFields = fields.filter(({ isDynamic }) => isDynamic) as RenderDynamicField[]; + + // With tableIdArgument: tableId is a dynamic argument for each method + // Without tableIdArgument: tableId is a file-level constant generated from `staticResourceData` + const staticResourceData = table.codegen.tableIdArgument + ? undefined + : { + namespace: table.namespace, + name: table.name, + offchainOnly: table.type === "offchainTable", + }; + + return { + outputPath, + tableName: table.label, + renderOptions: { + imports, + libraryName: table.label, + structName: withStruct ? table.label + "Data" : undefined, + staticResourceData, + storeImportPath, + keyTuple, + fields, + staticFields, + dynamicFields, + withGetters: table.type === "table", + withRecordMethods, + withDynamicFieldMethods: table.type === "table", + withSuffixlessFieldMethods, + storeArgument: table.codegen.storeArgument, + }, + }; + }); + + return options; +} diff --git a/packages/store/ts/codegen/getUserTypes.test.ts b/packages/store/ts/codegen/getUserTypes.test.ts new file mode 100644 index 0000000000..10ffd9ea7f --- /dev/null +++ b/packages/store/ts/codegen/getUserTypes.test.ts @@ -0,0 +1,14 @@ +import path from "node:path"; +import { describe, expect, it } from "vitest"; + +describe("getUserTypes", () => { + it("should resolve relative import path", () => { + const rootDir = process.cwd(); + const filePath = "./src/MyUserType.sol"; + const tableFilename = "src/codegen/tables/Table.sol"; + + const importPath = path.relative(path.dirname(path.join(rootDir, tableFilename)), path.join(rootDir, filePath)); + + expect(importPath).toMatchInlineSnapshot('"../../MyUserType.sol"'); + }); +}); diff --git a/packages/store/ts/codegen/getUserTypes.ts b/packages/store/ts/codegen/getUserTypes.ts new file mode 100644 index 0000000000..46e1f1b77e --- /dev/null +++ b/packages/store/ts/codegen/getUserTypes.ts @@ -0,0 +1,48 @@ +import { Store } from "../config/v2"; +import { AbiType } from "@latticexyz/config"; +import { getUserTypesFilename } from "./getUserTypesFilename"; +import { groupBy } from "@latticexyz/common/utils"; + +export type UserType = { + readonly type: "enum" | "userType"; + readonly name: string; + readonly abiType: AbiType; + /** + * Import path relative to the root dir or absolute path if importing from a package. + * Relative paths must start with a `.` to be treated as a relative path. + */ + readonly importPath: string; +}; + +export function getUserTypes({ config }: { readonly config: Store }): readonly UserType[] { + const enums = Object.keys(config.enums).map( + (name): UserType => ({ + type: "enum", + name, + abiType: "uint8", + importPath: "./" + getUserTypesFilename({ config }), + }), + ); + + const userTypes = Object.entries(config.userTypes).map( + ([name, userType]): UserType => ({ + type: "userType", + name, + abiType: userType.type, + // If `userType.filePath` starts with a `.`, it's relative to the root dir + importPath: userType.filePath, + }), + ); + + const result = [...enums, ...userTypes]; + + // TODO: move this to config validation step? + const duplicates = Array.from(groupBy(result, (userType) => userType.name).entries()) + .filter(([, entries]) => entries.length > 1) + .map(([name]) => name); + if (duplicates.length > 0) { + throw new Error(`Found enums and user types sharing the same name: ${duplicates.join(", ")}`); + } + + return result; +} diff --git a/packages/store/ts/codegen/getUserTypesFilename.ts b/packages/store/ts/codegen/getUserTypesFilename.ts new file mode 100644 index 0000000000..70a4ecf3ec --- /dev/null +++ b/packages/store/ts/codegen/getUserTypesFilename.ts @@ -0,0 +1,9 @@ +import path from "node:path"; +import { Store } from "../config/v2"; + +/** + * @returns File path for codegen'ed user types, relative to source dir + */ +export function getUserTypesFilename({ config }: { config: Store }): string { + return path.join(config.sourceDirectory, config.codegen.outputDirectory, config.codegen.userTypesFilename); +} diff --git a/packages/store/ts/codegen/renderTableIndex.ts b/packages/store/ts/codegen/renderTableIndex.ts index 1bb5a990f5..1217bad2f7 100644 --- a/packages/store/ts/codegen/renderTableIndex.ts +++ b/packages/store/ts/codegen/renderTableIndex.ts @@ -1,12 +1,13 @@ -import { posixPath, renderList, renderedSolidityHeader } from "@latticexyz/common/codegen"; +import { renderList, renderedSolidityHeader } from "@latticexyz/common/codegen"; import { TableOptions } from "./tableOptions"; +import path from "node:path/posix"; /** * Returns Solidity code for table index file that imports all codegen tables * @param options table definitions * @returns string of Solidity code */ -export function renderTableIndex(options: TableOptions[]) { +export function renderTableIndex(codegenIndexPath: string, options: TableOptions[]) { return ` ${renderedSolidityHeader} @@ -14,7 +15,7 @@ export function renderTableIndex(options: TableOptions[]) { const imports = [tableName]; if (structName) imports.push(structName); - return `import { ${imports.join(", ")} } from "./${posixPath(outputPath)}";`; + return `import { ${imports.join(", ")} } from "./${path.relative(path.dirname(codegenIndexPath), outputPath)}";`; })} `; } diff --git a/packages/store/ts/codegen/tablegen.ts b/packages/store/ts/codegen/tablegen.ts index af9c7aa1a7..4d2cd2bf34 100644 --- a/packages/store/ts/codegen/tablegen.ts +++ b/packages/store/ts/codegen/tablegen.ts @@ -1,12 +1,13 @@ import fs from "node:fs/promises"; import path from "node:path"; -import { formatAndWriteSolidity, loadAndExtractUserTypes } from "@latticexyz/common/codegen"; -import { getTableOptions } from "./tableOptions"; +import { formatAndWriteSolidity, loadAndExtractUserTypes, renderEnums } from "@latticexyz/common/codegen"; import { renderTable } from "./renderTable"; -import { renderTypesFromConfig } from "./renderTypesFromConfig"; import { renderTableIndex } from "./renderTableIndex"; import { Store as StoreConfig } from "../config/v2/output"; -import { mapObject } from "@latticexyz/common/utils"; +import { mapObject, uniqueBy } from "@latticexyz/common/utils"; +import { getUserTypes } from "./getUserTypes"; +import { getUserTypesFilename } from "./getUserTypesFilename"; +import { getTableOptions } from "./getTableOptions"; export type TablegenOptions = { /** @@ -18,41 +19,64 @@ export type TablegenOptions = { }; export async function tablegen({ rootDir, config, remappings }: TablegenOptions) { - const outputDirectory = path.join(rootDir, config.sourceDirectory, config.codegen.outputDirectory); + const userTypes = getUserTypes({ config }); + const solidityUserTypes = loadAndExtractUserTypes( mapObject(config.userTypes, (type) => ({ ...type, internalType: type.type })), - outputDirectory, + path.join(rootDir, config.sourceDirectory, config.codegen.outputDirectory), remappings, ); - const allTableOptions = getTableOptions(config, solidityUserTypes); - const uniqueTableDirectories = Array.from(new Set(allTableOptions.map(({ outputPath }) => path.dirname(outputPath)))); - await Promise.all( - uniqueTableDirectories.map(async (tableDir) => { - await fs.rm(path.join(outputDirectory, tableDir), { recursive: true, force: true }); - }), - ); + // Write enums to user types file + if (Object.keys(config.enums).length > 0) { + await formatAndWriteSolidity( + renderEnums(config.enums), + path.join(rootDir, getUserTypesFilename({ config })), + "Generated types file with enums", + ); + } - // write tables to files await Promise.all( - allTableOptions.map(async ({ outputPath, renderOptions }) => { - const fullOutputPath = path.join(outputDirectory, outputPath); - const output = renderTable(renderOptions); - await formatAndWriteSolidity(output, fullOutputPath, "Generated table"); - }), - ); + Object.values(config.namespaces).map(async (namespace) => { + // TODO: get this value from config once multiple namespaces are supported + const multipleNamespaces = false; + const sourceDir = multipleNamespaces + ? path.join(config.sourceDirectory, "namespaces", namespace.label) + : config.sourceDirectory; + const codegenDir = path.join(sourceDir, config.codegen.outputDirectory); - // write table index - if (allTableOptions.length > 0) { - const fullOutputPath = path.join(outputDirectory, config.codegen.indexFilename); - const output = renderTableIndex(allTableOptions); - await formatAndWriteSolidity(output, fullOutputPath, "Generated table index"); - } + const tables = Object.values(namespace.tables); + if (tables.length === 0) return; - // write types to file - if (Object.keys(config.enums).length > 0) { - const fullOutputPath = path.join(outputDirectory, config.codegen.userTypesFilename); - const output = renderTypesFromConfig(config); - await formatAndWriteSolidity(output, fullOutputPath, "Generated types file"); - } + const tableOptions = getTableOptions({ + tables, + rootDir, + codegenDir, + userTypes, + storeImportPath: config.codegen.storeImportPath, + // TODO: remove + config, + solidityUserTypes, + }); + + const tableDirs = uniqueBy( + tableOptions.map(({ outputPath }) => path.dirname(outputPath)), + (dir) => dir, + ); + await Promise.all(tableDirs.map((dir) => fs.rm(dir, { recursive: true, force: true }))); + + await Promise.all( + tableOptions.map(({ outputPath, renderOptions }) => + formatAndWriteSolidity(renderTable(renderOptions), outputPath, "Generated table"), + ), + ); + + const codegenIndexPath = path.join(rootDir, codegenDir, config.codegen.indexFilename); + await formatAndWriteSolidity( + renderTableIndex(codegenIndexPath, tableOptions), + codegenIndexPath, + "Generated table index", + ); + }), + ); } diff --git a/packages/store/ts/config/v2/output.ts b/packages/store/ts/config/v2/output.ts index 4d10e71a71..3b4fd1d464 100644 --- a/packages/store/ts/config/v2/output.ts +++ b/packages/store/ts/config/v2/output.ts @@ -11,6 +11,8 @@ export type UserTypes = { }; }; +export type Enums = EnumsInput; + export type EnumValues = { readonly [enumName: string]: { readonly [enumElement: string]: number; @@ -92,7 +94,7 @@ export type Store = Omit & { */ readonly sourceDirectory: string; readonly userTypes: UserTypes; - readonly enums: EnumsInput; + readonly enums: Enums; readonly enumValues: EnumValues; readonly codegen: Codegen; readonly namespaces: Namespaces; From f074cbdb1b41890e3c0ff59704278c673f49bc17 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 25 Jul 2024 14:26:27 +0100 Subject: [PATCH 04/16] clean up --- packages/store/ts/codegen/renderTableIndex.ts | 2 +- packages/store/ts/codegen/tableOptions.ts | 121 ------------------ 2 files changed, 1 insertion(+), 122 deletions(-) delete mode 100644 packages/store/ts/codegen/tableOptions.ts diff --git a/packages/store/ts/codegen/renderTableIndex.ts b/packages/store/ts/codegen/renderTableIndex.ts index 1217bad2f7..69f14f5432 100644 --- a/packages/store/ts/codegen/renderTableIndex.ts +++ b/packages/store/ts/codegen/renderTableIndex.ts @@ -1,5 +1,5 @@ import { renderList, renderedSolidityHeader } from "@latticexyz/common/codegen"; -import { TableOptions } from "./tableOptions"; +import { TableOptions } from "./getTableOptions"; import path from "node:path/posix"; /** diff --git a/packages/store/ts/codegen/tableOptions.ts b/packages/store/ts/codegen/tableOptions.ts deleted file mode 100644 index d0959361c1..0000000000 --- a/packages/store/ts/codegen/tableOptions.ts +++ /dev/null @@ -1,121 +0,0 @@ -import path from "path"; -import { SchemaTypeArrayToElement } from "@latticexyz/schema-type/deprecated"; -import { - ImportDatum, - RenderDynamicField, - RenderField, - RenderKeyTuple, - RenderStaticField, - SolidityUserDefinedType, -} from "@latticexyz/common/codegen"; -import { RenderTableOptions } from "./types"; -import { getSchemaTypeInfo, importForAbiOrUserType, resolveAbiOrUserType } from "./userType"; -import { Store as StoreConfig } from "../config/v2/output"; -import { getKeySchema, getValueSchema } from "@latticexyz/protocol-parser/internal"; - -export interface TableOptions { - /** Path where the file is expected to be written (relative to project root) */ - outputPath: string; - /** Name of the table, as used in filename and library name */ - tableName: string; - /** Options for `renderTable` function */ - renderOptions: RenderTableOptions; -} - -/** - * Transforms store config and available solidity user types into useful options for `tablegen` and `renderTable` - */ -export function getTableOptions( - config: StoreConfig, - solidityUserTypes: Record, -): TableOptions[] { - const tables = Object.values(config.namespaces).flatMap((namespace) => Object.values(namespace.tables)); - const options = tables.map((table): TableOptions => { - const keySchema = getKeySchema(table); - const valueSchema = getValueSchema(table); - - // struct adds methods to get/set all values at once - const withStruct = table.codegen.dataStruct; - // operate on all fields at once; always render for offchain tables; for only 1 field keep them if struct is also kept - const withRecordMethods = withStruct || table.type === "offchainTable" || Object.keys(valueSchema).length > 1; - // field methods can include simply get/set if there's only 1 field and no record methods - const withSuffixlessFieldMethods = !withRecordMethods && Object.keys(valueSchema).length === 1; - // list of any symbols that need to be imported - const imports: ImportDatum[] = []; - - const keyTuple = Object.entries(keySchema).map(([name, field]): RenderKeyTuple => { - const abiOrUserType = field.internalType; - const { renderType } = resolveAbiOrUserType(abiOrUserType, config, solidityUserTypes); - - const importDatum = importForAbiOrUserType( - abiOrUserType, - table.codegen.outputDirectory, - config, - solidityUserTypes, - ); - if (importDatum) imports.push(importDatum); - - return { - ...renderType, - name, - isDynamic: false, - }; - }); - - const fields = Object.entries(valueSchema).map(([name, field]): RenderField => { - const abiOrUserType = field.internalType; - const { renderType, schemaType } = resolveAbiOrUserType(abiOrUserType, config, solidityUserTypes); - - const importDatum = importForAbiOrUserType( - abiOrUserType, - table.codegen.outputDirectory, - config, - solidityUserTypes, - ); - if (importDatum) imports.push(importDatum); - - const elementType = SchemaTypeArrayToElement[schemaType]; - return { - ...renderType, - arrayElement: elementType !== undefined ? getSchemaTypeInfo(elementType) : undefined, - name, - }; - }); - - const staticFields = fields.filter(({ isDynamic }) => !isDynamic) as RenderStaticField[]; - const dynamicFields = fields.filter(({ isDynamic }) => isDynamic) as RenderDynamicField[]; - - // With tableIdArgument: tableId is a dynamic argument for each method - // Without tableIdArgument: tableId is a file-level constant generated from `staticResourceData` - const staticResourceData = table.codegen.tableIdArgument - ? undefined - : { - namespace: table.namespace, - name: table.name, - offchainOnly: table.type === "offchainTable", - }; - - return { - outputPath: path.join(table.codegen.outputDirectory, `${table.label}.sol`), - tableName: table.label, - renderOptions: { - imports, - libraryName: table.label, - structName: withStruct ? table.label + "Data" : undefined, - staticResourceData, - storeImportPath: config.codegen.storeImportPath, - keyTuple, - fields, - staticFields, - dynamicFields, - withGetters: table.type === "table", - withRecordMethods, - withDynamicFieldMethods: table.type === "table", - withSuffixlessFieldMethods, - storeArgument: table.codegen.storeArgument, - }, - }; - }); - - return options; -} From 52749bd66680ee192fdec09c28cfe20c99c441c4 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 25 Jul 2024 15:26:38 +0100 Subject: [PATCH 05/16] refactor user type handling --- packages/store/ts/codegen/getTableOptions.ts | 16 +--- packages/store/ts/codegen/index.ts | 2 +- packages/store/ts/codegen/tablegen.ts | 16 +--- packages/store/ts/codegen/userType.ts | 93 +++++++++----------- 4 files changed, 51 insertions(+), 76 deletions(-) diff --git a/packages/store/ts/codegen/getTableOptions.ts b/packages/store/ts/codegen/getTableOptions.ts index dfc5646174..58ec291d75 100644 --- a/packages/store/ts/codegen/getTableOptions.ts +++ b/packages/store/ts/codegen/getTableOptions.ts @@ -6,11 +6,10 @@ import { RenderField, RenderKeyTuple, RenderStaticField, - SolidityUserDefinedType, } from "@latticexyz/common/codegen"; import { RenderTableOptions } from "./types"; import { getSchemaTypeInfo, resolveAbiOrUserType } from "./userType"; -import { Store, Table } from "../config/v2/output"; +import { Table } from "../config/v2/output"; import { getKeySchema, getValueSchema } from "@latticexyz/protocol-parser/internal"; import { UserType } from "./getUserTypes"; @@ -32,8 +31,6 @@ export function getTableOptions({ codegenDir, userTypes, storeImportPath, - config, - solidityUserTypes, }: { readonly tables: Table[]; readonly rootDir: string; @@ -41,10 +38,6 @@ export function getTableOptions({ readonly codegenDir: string; readonly userTypes: readonly UserType[]; readonly storeImportPath: string; - /** @deprecated */ - readonly config: Store; - /** @deprecated */ - readonly solidityUserTypes: Record; }): TableOptions[] { const options = tables.map((table): TableOptions => { const outputPath = path.join(rootDir, codegenDir, table.codegen.outputDirectory, `${table.label}.sol`); @@ -60,6 +53,7 @@ export function getTableOptions({ const withSuffixlessFieldMethods = !withRecordMethods && Object.keys(valueSchema).length === 1; // list of any symbols that need to be imported const imports = Object.entries(table.schema) + // TODO: refactor this to support static-length array types (where type and internalType won't match) .filter(([, field]) => field.type !== field.internalType) .map(([fieldName, field]): ImportDatum => { const userType = userTypes.find((userType) => userType.name === field.internalType); @@ -77,8 +71,7 @@ export function getTableOptions({ }); const keyTuple = Object.entries(keySchema).map(([name, field]): RenderKeyTuple => { - const abiOrUserType = field.internalType; - const { renderType } = resolveAbiOrUserType(abiOrUserType, config, solidityUserTypes); + const { renderType } = resolveAbiOrUserType(field.internalType, userTypes); return { ...renderType, @@ -88,8 +81,7 @@ export function getTableOptions({ }); const fields = Object.entries(valueSchema).map(([name, field]): RenderField => { - const abiOrUserType = field.internalType; - const { renderType, schemaType } = resolveAbiOrUserType(abiOrUserType, config, solidityUserTypes); + const { renderType, schemaType } = resolveAbiOrUserType(field.internalType, userTypes); const elementType = SchemaTypeArrayToElement[schemaType]; return { diff --git a/packages/store/ts/codegen/index.ts b/packages/store/ts/codegen/index.ts index d5dfbf0f96..112468cd58 100644 --- a/packages/store/ts/codegen/index.ts +++ b/packages/store/ts/codegen/index.ts @@ -3,7 +3,7 @@ export * from "./record"; export * from "./renderTable"; export * from "./renderTypesFromConfig"; export * from "./tablegen"; -export * from "./tableOptions"; +export * from "./getTableOptions"; export * from "./tightcoder"; export * from "./types"; export * from "./userType"; diff --git a/packages/store/ts/codegen/tablegen.ts b/packages/store/ts/codegen/tablegen.ts index 4d2cd2bf34..fcaaaa3966 100644 --- a/packages/store/ts/codegen/tablegen.ts +++ b/packages/store/ts/codegen/tablegen.ts @@ -1,10 +1,10 @@ import fs from "node:fs/promises"; import path from "node:path"; -import { formatAndWriteSolidity, loadAndExtractUserTypes, renderEnums } from "@latticexyz/common/codegen"; +import { formatAndWriteSolidity, renderEnums } from "@latticexyz/common/codegen"; import { renderTable } from "./renderTable"; import { renderTableIndex } from "./renderTableIndex"; import { Store as StoreConfig } from "../config/v2/output"; -import { mapObject, uniqueBy } from "@latticexyz/common/utils"; +import { uniqueBy } from "@latticexyz/common/utils"; import { getUserTypes } from "./getUserTypes"; import { getUserTypesFilename } from "./getUserTypesFilename"; import { getTableOptions } from "./getTableOptions"; @@ -15,18 +15,11 @@ export type TablegenOptions = { */ rootDir: string; config: StoreConfig; - remappings: [string, string][]; }; -export async function tablegen({ rootDir, config, remappings }: TablegenOptions) { +export async function tablegen({ rootDir, config }: TablegenOptions) { const userTypes = getUserTypes({ config }); - const solidityUserTypes = loadAndExtractUserTypes( - mapObject(config.userTypes, (type) => ({ ...type, internalType: type.type })), - path.join(rootDir, config.sourceDirectory, config.codegen.outputDirectory), - remappings, - ); - // Write enums to user types file if (Object.keys(config.enums).length > 0) { await formatAndWriteSolidity( @@ -54,9 +47,6 @@ export async function tablegen({ rootDir, config, remappings }: TablegenOptions) codegenDir, userTypes, storeImportPath: config.codegen.storeImportPath, - // TODO: remove - config, - solidityUserTypes, }); const tableDirs = uniqueBy( diff --git a/packages/store/ts/codegen/userType.ts b/packages/store/ts/codegen/userType.ts index 395b542cfa..257f40c7cd 100644 --- a/packages/store/ts/codegen/userType.ts +++ b/packages/store/ts/codegen/userType.ts @@ -6,6 +6,7 @@ import { } from "@latticexyz/schema-type/deprecated"; import { ImportDatum, RenderType, SolidityUserDefinedType } from "@latticexyz/common/codegen"; import { Store as StoreConfig } from "../config/v2/output"; +import { UserType } from "./getUserTypes"; function parseStaticArray(abiType: string) { const matches = abiType.match(/^(\w+)\[(\d+)\]$/); @@ -21,8 +22,7 @@ function parseStaticArray(abiType: string) { */ export function resolveAbiOrUserType( abiOrUserType: string, - config: StoreConfig, - solidityUserTypes: Record, + userTypes: readonly UserType[], ): { schemaType: SchemaType; renderType: RenderType; @@ -44,8 +44,13 @@ export function resolveAbiOrUserType( throw new Error("Static arrays of user types are not supported"); } } + // user types - return getUserTypeInfo(abiOrUserType, config, solidityUserTypes); + const userType = userTypes.find((type) => type.name === abiOrUserType); + if (!userType) { + throw new Error(`User type "${abiOrUserType}" not found`); + } + return getUserTypeInfo(userType); } /** @@ -108,58 +113,46 @@ export function getSchemaTypeInfo(schemaType: SchemaType): RenderType { }; } -export function getUserTypeInfo( - userType: string, - config: StoreConfig, - solidityUserTypes: Record, -): { +export function getUserTypeInfo(userType: UserType): { schemaType: SchemaType; renderType: RenderType; } { - // enums - if (userType in config.enums) { - const schemaType = SchemaType.UINT8; - const staticByteLength = getStaticByteLength(schemaType); - const isDynamic = staticByteLength === 0; - const typeId = userType; - return { - schemaType, - renderType: { - typeId, - typeWithLocation: typeId, - enumName: SchemaType[schemaType], - staticByteLength, - isDynamic, - typeWrap: `${userType}`, - typeUnwrap: `uint8`, - internalTypeId: `${SchemaTypeToAbiType[schemaType]}`, - }, - }; - } - // user-defined types - if (userType in solidityUserTypes) { - if (!(userType in solidityUserTypes)) { - throw new Error(`User type "${userType}" not found in MUD config`); + switch (userType.type) { + case "enum": { + const schemaType = SchemaType.UINT8; + const staticByteLength = getStaticByteLength(schemaType); + const isDynamic = staticByteLength === 0; + return { + schemaType, + renderType: { + typeId: userType.name, + typeWithLocation: userType.name, + enumName: SchemaType[schemaType], + staticByteLength, + isDynamic, + typeWrap: userType.name, + typeUnwrap: userType.abiType, + internalTypeId: userType.abiType, + }, + }; + } + case "userType": { + const schemaType = AbiTypeToSchemaType[userType.abiType]; + return { + schemaType, + renderType: { + typeId: userType.name, + typeWithLocation: userType.name, + enumName: SchemaType[schemaType], + staticByteLength: getStaticByteLength(schemaType), + isDynamic: false, + typeWrap: `${userType.name}.wrap`, + typeUnwrap: `${userType.name}.unwrap`, + internalTypeId: userType.abiType, + }, + }; } - const solidityUserType = solidityUserTypes[userType]; - const typeId = solidityUserType.typeId; - const schemaType = AbiTypeToSchemaType[solidityUserType.internalTypeId]; - return { - schemaType, - renderType: { - typeId, - typeWithLocation: typeId, - enumName: SchemaType[schemaType], - staticByteLength: getStaticByteLength(schemaType), - isDynamic: false, - typeWrap: `${typeId}.wrap`, - typeUnwrap: `${typeId}.unwrap`, - internalTypeId: solidityUserType.internalTypeId, - }, - }; } - // invalid - throw new Error(`User type "${userType}" does not exist`); } function getStaticArrayTypeInfo(abiType: string, elementType: string, staticLength: number) { From 5114b262840728c8ef684b78f184488a576ad75b Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 25 Jul 2024 15:27:32 +0100 Subject: [PATCH 06/16] no longer need remappings --- packages/common/src/foundry/index.ts | 9 --------- packages/store/ts/scripts/build.ts | 4 +--- packages/store/ts/scripts/generate-test-tables.ts | 5 +---- packages/world/ts/scripts/build.ts | 4 +--- packages/world/ts/scripts/generate-test-tables.ts | 5 +---- 5 files changed, 4 insertions(+), 23 deletions(-) diff --git a/packages/common/src/foundry/index.ts b/packages/common/src/foundry/index.ts index 628a98deea..b14d4548b2 100644 --- a/packages/common/src/foundry/index.ts +++ b/packages/common/src/foundry/index.ts @@ -71,15 +71,6 @@ export async function getRpcUrl(profile?: string): Promise { return (await getForgeConfig(profile)).eth_rpc_url || "http://127.0.0.1:8545"; } -/** - * Get the value of "remappings" from forge config - * @param profile The foundry profile to use - * @returns The array of remapping tuples `[from, to]` - */ -export async function getRemappings(profile?: string): Promise<[string, string][]> { - return (await getForgeConfig(profile)).remappings.map((line) => line.trim().split("=")) as [string, string][]; -} - /** * Execute a forge command * @param args The arguments to pass to forge diff --git a/packages/store/ts/scripts/build.ts b/packages/store/ts/scripts/build.ts index b207284106..ad74d9828e 100644 --- a/packages/store/ts/scripts/build.ts +++ b/packages/store/ts/scripts/build.ts @@ -1,11 +1,9 @@ import { loadConfig, resolveConfigPath } from "@latticexyz/config/node"; -import { getRemappings } from "@latticexyz/common/foundry"; import { tablegen } from "../codegen"; import { Store as StoreConfig } from "../config/v2/output"; import path from "node:path"; const configPath = await resolveConfigPath(undefined); const config = (await loadConfig(configPath)) as StoreConfig; -const remappings = await getRemappings(); -await tablegen({ rootDir: path.dirname(configPath), config, remappings }); +await tablegen({ rootDir: path.dirname(configPath), config }); diff --git a/packages/store/ts/scripts/generate-test-tables.ts b/packages/store/ts/scripts/generate-test-tables.ts index 0a61b15d24..2e2f142e5d 100644 --- a/packages/store/ts/scripts/generate-test-tables.ts +++ b/packages/store/ts/scripts/generate-test-tables.ts @@ -1,4 +1,3 @@ -import { getRemappings } from "@latticexyz/common/foundry"; import { tablegen } from "../codegen"; import { defineStore } from "../config/v2/store"; import { fileURLToPath } from "node:url"; @@ -52,6 +51,4 @@ const config = defineStore({ }, }); -const remappings = await getRemappings(); - -await tablegen({ rootDir: path.dirname(configPath), config, remappings }); +await tablegen({ rootDir: path.dirname(configPath), config }); diff --git a/packages/world/ts/scripts/build.ts b/packages/world/ts/scripts/build.ts index 8a44243225..75e5630967 100644 --- a/packages/world/ts/scripts/build.ts +++ b/packages/world/ts/scripts/build.ts @@ -1,6 +1,5 @@ import path from "node:path"; import { loadConfig, resolveConfigPath } from "@latticexyz/config/node"; -import { getRemappings } from "@latticexyz/common/foundry"; import { tablegen } from "@latticexyz/store/codegen"; import { World } from "../config/v2"; import { worldgen } from "../node"; @@ -15,10 +14,9 @@ import { worldgen } from "../node"; const configPath = await resolveConfigPath(); const rootDir = path.dirname(configPath); const config = (await loadConfig(configPath)) as World; -const remappings = await getRemappings(); await Promise.all([ - tablegen({ rootDir, config, remappings }), + tablegen({ rootDir, config }), worldgen({ rootDir, config: { diff --git a/packages/world/ts/scripts/generate-test-tables.ts b/packages/world/ts/scripts/generate-test-tables.ts index 392596fd96..eb382c1c82 100644 --- a/packages/world/ts/scripts/generate-test-tables.ts +++ b/packages/world/ts/scripts/generate-test-tables.ts @@ -1,4 +1,3 @@ -import { getRemappings } from "@latticexyz/common/foundry"; import { tablegen } from "@latticexyz/store/codegen"; import { defineWorld } from "../config/v2/world"; import { fileURLToPath } from "node:url"; @@ -41,6 +40,4 @@ const config = defineWorld({ }, }); -const remappings = await getRemappings(); - -await tablegen({ rootDir: path.dirname(configPath), config, remappings }); +await tablegen({ rootDir: path.dirname(configPath), config }); From 0f41a0358dbc7e5b9849690d155829ae0ecb0365 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 25 Jul 2024 15:29:56 +0100 Subject: [PATCH 07/16] fix for static length arrays --- packages/store/ts/codegen/getTableOptions.ts | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/packages/store/ts/codegen/getTableOptions.ts b/packages/store/ts/codegen/getTableOptions.ts index 58ec291d75..ce00478ec7 100644 --- a/packages/store/ts/codegen/getTableOptions.ts +++ b/packages/store/ts/codegen/getTableOptions.ts @@ -12,6 +12,7 @@ import { getSchemaTypeInfo, resolveAbiOrUserType } from "./userType"; import { Table } from "../config/v2/output"; import { getKeySchema, getValueSchema } from "@latticexyz/protocol-parser/internal"; import { UserType } from "./getUserTypes"; +import { isDefined } from "@latticexyz/common/utils"; export interface TableOptions { /** Path where the file is expected to be written (relative to project root) */ @@ -52,16 +53,10 @@ export function getTableOptions({ // field methods can include simply get/set if there's only 1 field and no record methods const withSuffixlessFieldMethods = !withRecordMethods && Object.keys(valueSchema).length === 1; // list of any symbols that need to be imported - const imports = Object.entries(table.schema) - // TODO: refactor this to support static-length array types (where type and internalType won't match) - .filter(([, field]) => field.type !== field.internalType) - .map(([fieldName, field]): ImportDatum => { - const userType = userTypes.find((userType) => userType.name === field.internalType); - if (!userType) { - throw new Error( - `Table "${table.label}" schema with field "${fieldName}" had no corresponding user type for "${field.internalType}".`, - ); - } + const imports = Object.values(table.schema) + .map((field) => userTypes.find((type) => type.name === field.internalType)) + .filter(isDefined) + .map((userType): ImportDatum => { return { symbol: userType.name, path: userType.importPath.startsWith(".") From 68ec8635173cbc2805892c3b0ed76c0411fa6eaf Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 25 Jul 2024 15:31:56 +0100 Subject: [PATCH 08/16] missed some spots --- packages/cli/scripts/generate-test-tables.ts | 5 +---- packages/cli/src/build.ts | 6 ++---- packages/cli/src/commands/tablegen.ts | 4 +--- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/cli/scripts/generate-test-tables.ts b/packages/cli/scripts/generate-test-tables.ts index a564fdfdf1..34f7e22951 100644 --- a/packages/cli/scripts/generate-test-tables.ts +++ b/packages/cli/scripts/generate-test-tables.ts @@ -1,6 +1,5 @@ import { tablegen } from "@latticexyz/store/codegen"; import { defineStore } from "@latticexyz/store"; -import { getRemappings } from "@latticexyz/common/foundry"; import { fileURLToPath } from "node:url"; import path from "node:path"; @@ -96,6 +95,4 @@ const config = defineStore({ }, }); -const remappings = await getRemappings(); - -await tablegen({ rootDir: path.dirname(configPath), config, remappings }); +await tablegen({ rootDir: path.dirname(configPath), config }); diff --git a/packages/cli/src/build.ts b/packages/cli/src/build.ts index 849558b7c1..1413aae58c 100644 --- a/packages/cli/src/build.ts +++ b/packages/cli/src/build.ts @@ -1,7 +1,7 @@ import { tablegen } from "@latticexyz/store/codegen"; import { worldgen } from "@latticexyz/world/node"; import { World as WorldConfig } from "@latticexyz/world"; -import { forge, getRemappings } from "@latticexyz/common/foundry"; +import { forge } from "@latticexyz/common/foundry"; import { execa } from "execa"; type BuildOptions = { @@ -20,9 +20,7 @@ export async function build({ config, foundryProfile = process.env.FOUNDRY_PROFILE, }: BuildOptions): Promise { - const remappings = await getRemappings(foundryProfile); - - await Promise.all([tablegen({ rootDir, config, remappings }), worldgen({ rootDir, config })]); + await Promise.all([tablegen({ rootDir, config }), worldgen({ rootDir, config })]); await forge(["build"], { profile: foundryProfile }); await execa("mud", ["abi-ts"], { stdio: "inherit" }); diff --git a/packages/cli/src/commands/tablegen.ts b/packages/cli/src/commands/tablegen.ts index cc406dc1bd..d0030b6283 100644 --- a/packages/cli/src/commands/tablegen.ts +++ b/packages/cli/src/commands/tablegen.ts @@ -2,7 +2,6 @@ import type { CommandModule } from "yargs"; import { loadConfig, resolveConfigPath } from "@latticexyz/config/node"; import { Store as StoreConfig } from "@latticexyz/store"; import { tablegen } from "@latticexyz/store/codegen"; -import { getRemappings } from "@latticexyz/common/foundry"; import path from "node:path"; type Options = { @@ -23,9 +22,8 @@ const commandModule: CommandModule = { async handler(opts) { const configPath = await resolveConfigPath(opts.configPath); const config = (await loadConfig(configPath)) as StoreConfig; - const remappings = await getRemappings(); - await tablegen({ rootDir: path.dirname(configPath), config, remappings }); + await tablegen({ rootDir: path.dirname(configPath), config }); process.exit(0); }, From a6f9179e4461426573183ed7e7a2d3e8d2809022 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 25 Jul 2024 16:11:02 +0100 Subject: [PATCH 09/16] try fully qualified type name --- .../src/codegen/tables/UserTyped.sol | 2 +- packages/cli/scripts/generate-test-tables.ts | 12 +++++----- packages/store/ts/codegen/getTableOptions.ts | 4 +++- packages/store/ts/codegen/tablegen.ts | 22 ++++++++----------- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/packages/cli/contracts/src/codegen/tables/UserTyped.sol b/packages/cli/contracts/src/codegen/tables/UserTyped.sol index 5e05f4d1a9..692a0ad135 100644 --- a/packages/cli/contracts/src/codegen/tables/UserTyped.sol +++ b/packages/cli/contracts/src/codegen/tables/UserTyped.sol @@ -17,7 +17,7 @@ import { EncodedLengths, EncodedLengthsLib } from "@latticexyz/store/src/Encoded import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; // Import user types -import { TestTypeAddress, TestTypeInt64, TestTypeLibrary } from "./../../types.sol"; +import { TestTypeAddress, TestTypeInt64, TestTypeLibrary } from "./../../../../scripts/contracts/src/types.sol"; import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; struct UserTypedData { diff --git a/packages/cli/scripts/generate-test-tables.ts b/packages/cli/scripts/generate-test-tables.ts index 34f7e22951..4515b59d3b 100644 --- a/packages/cli/scripts/generate-test-tables.ts +++ b/packages/cli/scripts/generate-test-tables.ts @@ -17,8 +17,8 @@ const config = defineStore({ userTypes: { TestTypeAddress: { filePath: "./contracts/src/types.sol", type: "address" }, TestTypeInt64: { filePath: "./contracts/src/types.sol", type: "int64" }, - TestTypeBool: { filePath: "./contracts/src/types.sol", type: "bool" }, - TestTypeUint128: { filePath: "./contracts/src/types.sol", type: "uint128" }, + "TestTypeLibrary.TestTypeBool": { filePath: "./contracts/src/types.sol", type: "bool" }, + "TestTypeLibrary.TestTypeUint128": { filePath: "./contracts/src/types.sol", type: "uint128" }, ResourceId: { filePath: "@latticexyz/store/src/ResourceId.sol", type: "bytes32" }, }, tables: { @@ -81,13 +81,13 @@ const config = defineStore({ schema: { k1: "TestTypeAddress", k2: "TestTypeInt64", - k3: "TestTypeBool", - k4: "TestTypeUint128", + k3: "TestTypeLibrary.TestTypeBool", + k4: "TestTypeLibrary.TestTypeUint128", k5: "ResourceId", v1: "TestTypeAddress", v2: "TestTypeInt64", - v3: "TestTypeBool", - v4: "TestTypeUint128", + v3: "TestTypeLibrary.TestTypeBool", + v4: "TestTypeLibrary.TestTypeUint128", v5: "ResourceId", }, key: ["k1", "k2", "k3", "k4", "k5"], diff --git a/packages/store/ts/codegen/getTableOptions.ts b/packages/store/ts/codegen/getTableOptions.ts index ce00478ec7..69fff9bc33 100644 --- a/packages/store/ts/codegen/getTableOptions.ts +++ b/packages/store/ts/codegen/getTableOptions.ts @@ -58,7 +58,9 @@ export function getTableOptions({ .filter(isDefined) .map((userType): ImportDatum => { return { - symbol: userType.name, + // If it's a fully qualified name, remove trailing references + // This enables support for user types inside libraries + symbol: userType.name.replace(/\..*$/, ""), path: userType.importPath.startsWith(".") ? "./" + path.relative(path.dirname(outputPath), path.join(rootDir, userType.importPath)) : userType.importPath, diff --git a/packages/store/ts/codegen/tablegen.ts b/packages/store/ts/codegen/tablegen.ts index fcaaaa3966..a31cb3e899 100644 --- a/packages/store/ts/codegen/tablegen.ts +++ b/packages/store/ts/codegen/tablegen.ts @@ -22,11 +22,9 @@ export async function tablegen({ rootDir, config }: TablegenOptions) { // Write enums to user types file if (Object.keys(config.enums).length > 0) { - await formatAndWriteSolidity( - renderEnums(config.enums), - path.join(rootDir, getUserTypesFilename({ config })), - "Generated types file with enums", - ); + const userTypesFilename = path.join(rootDir, getUserTypesFilename({ config })); + const source = renderEnums(config.enums); + await formatAndWriteSolidity(source, userTypesFilename, "Generated types file with enums"); } await Promise.all( @@ -56,17 +54,15 @@ export async function tablegen({ rootDir, config }: TablegenOptions) { await Promise.all(tableDirs.map((dir) => fs.rm(dir, { recursive: true, force: true }))); await Promise.all( - tableOptions.map(({ outputPath, renderOptions }) => - formatAndWriteSolidity(renderTable(renderOptions), outputPath, "Generated table"), - ), + tableOptions.map(async ({ outputPath, renderOptions }) => { + const source = renderTable(renderOptions); + return await formatAndWriteSolidity(source, outputPath, "Generated table"); + }), ); const codegenIndexPath = path.join(rootDir, codegenDir, config.codegen.indexFilename); - await formatAndWriteSolidity( - renderTableIndex(codegenIndexPath, tableOptions), - codegenIndexPath, - "Generated table index", - ); + const source = renderTableIndex(codegenIndexPath, tableOptions); + await formatAndWriteSolidity(source, codegenIndexPath, "Generated table index"); }), ); } From 71ed19d3466de63a4f67f1b1999d6eb6d56a6597 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 25 Jul 2024 16:42:27 +0100 Subject: [PATCH 10/16] user types file path should be relative to project root not cwd --- packages/cli/contracts/src/codegen/tables/UserTyped.sol | 2 +- packages/cli/scripts/generate-test-tables.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/cli/contracts/src/codegen/tables/UserTyped.sol b/packages/cli/contracts/src/codegen/tables/UserTyped.sol index 692a0ad135..5e05f4d1a9 100644 --- a/packages/cli/contracts/src/codegen/tables/UserTyped.sol +++ b/packages/cli/contracts/src/codegen/tables/UserTyped.sol @@ -17,7 +17,7 @@ import { EncodedLengths, EncodedLengthsLib } from "@latticexyz/store/src/Encoded import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; // Import user types -import { TestTypeAddress, TestTypeInt64, TestTypeLibrary } from "./../../../../scripts/contracts/src/types.sol"; +import { TestTypeAddress, TestTypeInt64, TestTypeLibrary } from "./../../types.sol"; import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; struct UserTypedData { diff --git a/packages/cli/scripts/generate-test-tables.ts b/packages/cli/scripts/generate-test-tables.ts index 4515b59d3b..15d1df9cfd 100644 --- a/packages/cli/scripts/generate-test-tables.ts +++ b/packages/cli/scripts/generate-test-tables.ts @@ -15,10 +15,10 @@ const config = defineStore({ Enum2: ["E1"], }, userTypes: { - TestTypeAddress: { filePath: "./contracts/src/types.sol", type: "address" }, - TestTypeInt64: { filePath: "./contracts/src/types.sol", type: "int64" }, - "TestTypeLibrary.TestTypeBool": { filePath: "./contracts/src/types.sol", type: "bool" }, - "TestTypeLibrary.TestTypeUint128": { filePath: "./contracts/src/types.sol", type: "uint128" }, + TestTypeAddress: { filePath: "../contracts/src/types.sol", type: "address" }, + TestTypeInt64: { filePath: "../contracts/src/types.sol", type: "int64" }, + "TestTypeLibrary.TestTypeBool": { filePath: "../contracts/src/types.sol", type: "bool" }, + "TestTypeLibrary.TestTypeUint128": { filePath: "../contracts/src/types.sol", type: "uint128" }, ResourceId: { filePath: "@latticexyz/store/src/ResourceId.sol", type: "bytes32" }, }, tables: { From ec3c21495921343aa5c0ad3a591bf94da14df175 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 25 Jul 2024 17:06:47 +0100 Subject: [PATCH 11/16] update comment --- packages/store/ts/codegen/getTableOptions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/store/ts/codegen/getTableOptions.ts b/packages/store/ts/codegen/getTableOptions.ts index 69fff9bc33..fbe1fc052d 100644 --- a/packages/store/ts/codegen/getTableOptions.ts +++ b/packages/store/ts/codegen/getTableOptions.ts @@ -35,7 +35,7 @@ export function getTableOptions({ }: { readonly tables: Table[]; readonly rootDir: string; - /** Absolute path to base codegen dir */ + /** namespace codegen output dir, relative to project root dir */ readonly codegenDir: string; readonly userTypes: readonly UserType[]; readonly storeImportPath: string; From d85934ee28c8ad719bd4c4cd72271da64543d3bd Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Thu, 25 Jul 2024 09:12:01 -0700 Subject: [PATCH 12/16] Create shaggy-weeks-grab.md --- .changeset/shaggy-weeks-grab.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .changeset/shaggy-weeks-grab.md diff --git a/.changeset/shaggy-weeks-grab.md b/.changeset/shaggy-weeks-grab.md new file mode 100644 index 0000000000..c55bc884f2 --- /dev/null +++ b/.changeset/shaggy-weeks-grab.md @@ -0,0 +1,8 @@ +--- +"@latticexyz/store": patch +--- + +Refactored tablegen in preparation for multiple namespaces and addressed a few edge cases: + +- User types configured with a relative `filePath` are now resolved relative to the project root (where the `mud.config.ts` lives) rather than the current working directory. +- User types inside libraries now need to be referenced with their fully-qualified code path (e.g. `LibraryName.UserTypeName`). From 82e900464681d21f5e61508c938ab9ad9b9c0f85 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Fri, 26 Jul 2024 11:31:34 +0100 Subject: [PATCH 13/16] add renderImportPath helper --- .../src/codegen/render-solidity/common.ts | 5 +- .../src/codegen/render-solidity/index.ts | 1 + .../render-solidity/renderImportPath.test.ts | 74 +++++++++++++++++++ .../render-solidity/renderImportPath.ts | 18 +++++ 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 packages/common/src/codegen/render-solidity/renderImportPath.test.ts create mode 100644 packages/common/src/codegen/render-solidity/renderImportPath.ts diff --git a/packages/common/src/codegen/render-solidity/common.ts b/packages/common/src/codegen/render-solidity/common.ts index f0b284d169..a1b7558a8b 100644 --- a/packages/common/src/codegen/render-solidity/common.ts +++ b/packages/common/src/codegen/render-solidity/common.ts @@ -72,7 +72,10 @@ export function renderCommonData({ }; } -/** For 2 paths which are relative to a common root, create a relative import path from one to another */ +/** + * For 2 paths which are relative to a common root, create a relative import path from one to another + * @deprecated Use `renderImportPath` instead. + */ export function solidityRelativeImportPath(fromPath: string, usedInPath: string): string { // 1st "./" must be added because path strips it, // but solidity expects it unless there's "../" ("./../" is fine). diff --git a/packages/common/src/codegen/render-solidity/index.ts b/packages/common/src/codegen/render-solidity/index.ts index 126d991c28..1a9c63f824 100644 --- a/packages/common/src/codegen/render-solidity/index.ts +++ b/packages/common/src/codegen/render-solidity/index.ts @@ -1,4 +1,5 @@ export * from "./common"; export * from "./renderEnums"; +export * from "./renderImportPath"; export * from "./renderTypeHelpers"; export * from "./types"; diff --git a/packages/common/src/codegen/render-solidity/renderImportPath.test.ts b/packages/common/src/codegen/render-solidity/renderImportPath.test.ts new file mode 100644 index 0000000000..8504e92500 --- /dev/null +++ b/packages/common/src/codegen/render-solidity/renderImportPath.test.ts @@ -0,0 +1,74 @@ +import { describe, expect, it } from "vitest"; +import { renderImportPath } from "./renderImportPath"; + +describe("renderImportPath", () => { + it("returns valid path for package imports", () => { + expect(renderImportPath("@latticexyz/store/src")).toMatchInlineSnapshot('"@latticexyz/store/src"'); + expect(renderImportPath("@latticexyz/store/src/")).toMatchInlineSnapshot('"@latticexyz/store/src"'); + expect(renderImportPath("@latticexyz/store/src", "IStore.sol")).toMatchInlineSnapshot( + '"@latticexyz/store/src/IStore.sol"', + ); + expect(renderImportPath("@latticexyz/store/src/", "IStore.sol")).toMatchInlineSnapshot( + '"@latticexyz/store/src/IStore.sol"', + ); + expect(renderImportPath("@latticexyz/store/src", "codegen/tables/Tables.sol")).toMatchInlineSnapshot( + '"@latticexyz/store/src/codegen/tables/Tables.sol"', + ); + expect(renderImportPath("@latticexyz/store/src/", "codegen/tables/Tables.sol")).toMatchInlineSnapshot( + '"@latticexyz/store/src/codegen/tables/Tables.sol"', + ); + expect(renderImportPath("@latticexyz/store/src", "./codegen/tables/Tables.sol")).toMatchInlineSnapshot( + '"@latticexyz/store/src/codegen/tables/Tables.sol"', + ); + expect(renderImportPath("@latticexyz/store/src/", "./codegen/tables/Tables.sol")).toMatchInlineSnapshot( + '"@latticexyz/store/src/codegen/tables/Tables.sol"', + ); + expect(renderImportPath("@latticexyz/store/src", "../test/codegen/common.sol")).toMatchInlineSnapshot( + '"@latticexyz/store/test/codegen/common.sol"', + ); + expect(renderImportPath("@latticexyz/store/src/", "../test/codegen/common.sol")).toMatchInlineSnapshot( + '"@latticexyz/store/test/codegen/common.sol"', + ); + }); + + it("returns valid path for relative imports", () => { + expect(renderImportPath(".")).toMatchInlineSnapshot('"."'); + expect(renderImportPath("./")).toMatchInlineSnapshot('"."'); + expect(renderImportPath(".", "IStore.sol")).toMatchInlineSnapshot('"./IStore.sol"'); + expect(renderImportPath("./", "IStore.sol")).toMatchInlineSnapshot('"./IStore.sol"'); + expect(renderImportPath("./src")).toMatchInlineSnapshot('"./src"'); + expect(renderImportPath("./src/")).toMatchInlineSnapshot('"./src"'); + expect(renderImportPath("./src", "IStore.sol")).toMatchInlineSnapshot('"./src/IStore.sol"'); + expect(renderImportPath("../test/", "IStore.sol")).toMatchInlineSnapshot('"../test/IStore.sol"'); + expect(renderImportPath("../test")).toMatchInlineSnapshot('"../test"'); + expect(renderImportPath("../test/")).toMatchInlineSnapshot('"../test"'); + expect(renderImportPath("../test", "IStore.sol")).toMatchInlineSnapshot('"../test/IStore.sol"'); + expect(renderImportPath("../test/", "IStore.sol")).toMatchInlineSnapshot('"../test/IStore.sol"'); + expect(renderImportPath(".", "codegen/tables/Tables.sol")).toMatchInlineSnapshot('"./codegen/tables/Tables.sol"'); + expect(renderImportPath("./", "codegen/tables/Tables.sol")).toMatchInlineSnapshot('"./codegen/tables/Tables.sol"'); + expect(renderImportPath(".", "./codegen/tables/Tables.sol")).toMatchInlineSnapshot('"./codegen/tables/Tables.sol"'); + expect(renderImportPath("./", "./codegen/tables/Tables.sol")).toMatchInlineSnapshot( + '"./codegen/tables/Tables.sol"', + ); + expect(renderImportPath(".", "../test/codegen/common.sol")).toMatchInlineSnapshot('"../test/codegen/common.sol"'); + expect(renderImportPath("./", "../test/codegen/common.sol")).toMatchInlineSnapshot('"../test/codegen/common.sol"'); + expect(renderImportPath("./src", "codegen/tables/Tables.sol")).toMatchInlineSnapshot( + '"./src/codegen/tables/Tables.sol"', + ); + expect(renderImportPath("./src/", "codegen/tables/Tables.sol")).toMatchInlineSnapshot( + '"./src/codegen/tables/Tables.sol"', + ); + expect(renderImportPath("./src", "./codegen/tables/Tables.sol")).toMatchInlineSnapshot( + '"./src/codegen/tables/Tables.sol"', + ); + expect(renderImportPath("./src/", "./codegen/tables/Tables.sol")).toMatchInlineSnapshot( + '"./src/codegen/tables/Tables.sol"', + ); + expect(renderImportPath("./src", "../test/codegen/common.sol")).toMatchInlineSnapshot( + '"./test/codegen/common.sol"', + ); + expect(renderImportPath("./src/", "../test/codegen/common.sol")).toMatchInlineSnapshot( + '"./test/codegen/common.sol"', + ); + }); +}); diff --git a/packages/common/src/codegen/render-solidity/renderImportPath.ts b/packages/common/src/codegen/render-solidity/renderImportPath.ts new file mode 100644 index 0000000000..0c503df87c --- /dev/null +++ b/packages/common/src/codegen/render-solidity/renderImportPath.ts @@ -0,0 +1,18 @@ +// Solidity compiler expects POSIX paths +import path from "node:path/posix"; + +export function renderImportPath(basePath: string, ...segments: readonly string[]): string { + const fullPath = path + .join(basePath, ...segments) + // remove trailing slash + .replace(/\/$/, ""); + + // `path.join` strips the leading `./` + // so if we started with a relative path, make it relative again + if (basePath.startsWith(".")) { + const relativePath = "./" + fullPath; + return relativePath.replace(/^(\.\/)+\./, "."); + } + + return fullPath; +} From dcd6bc6320bf44e65e43a5ac787ed0ccfb1b54d1 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Fri, 26 Jul 2024 12:01:23 +0100 Subject: [PATCH 14/16] normalize to posix paths --- .../render-solidity/renderImportPath.test.ts | 9 +++++++++ .../codegen/render-solidity/renderImportPath.ts | 14 ++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/packages/common/src/codegen/render-solidity/renderImportPath.test.ts b/packages/common/src/codegen/render-solidity/renderImportPath.test.ts index 8504e92500..1dc0ae4125 100644 --- a/packages/common/src/codegen/render-solidity/renderImportPath.test.ts +++ b/packages/common/src/codegen/render-solidity/renderImportPath.test.ts @@ -71,4 +71,13 @@ describe("renderImportPath", () => { '"./test/codegen/common.sol"', ); }); + + it("normalizes to POSIX paths", () => { + expect(renderImportPath("C:\\src")).toMatchInlineSnapshot('"C:/src"'); + expect(renderImportPath("C:\\src\\")).toMatchInlineSnapshot('"C:/src"'); + expect(renderImportPath("C:\\src", "./IStore.sol")).toMatchInlineSnapshot('"C:/src/IStore.sol"'); + expect(renderImportPath("C:\\src\\", "./IStore.sol")).toMatchInlineSnapshot('"C:/src/IStore.sol"'); + expect(renderImportPath("./src", ".\\IStore.sol")).toMatchInlineSnapshot('"./src/IStore.sol"'); + expect(renderImportPath("./src", ".\\IStore.sol")).toMatchInlineSnapshot('"./src/IStore.sol"'); + }); }); diff --git a/packages/common/src/codegen/render-solidity/renderImportPath.ts b/packages/common/src/codegen/render-solidity/renderImportPath.ts index 0c503df87c..39eb138c4b 100644 --- a/packages/common/src/codegen/render-solidity/renderImportPath.ts +++ b/packages/common/src/codegen/render-solidity/renderImportPath.ts @@ -1,9 +1,15 @@ -// Solidity compiler expects POSIX paths -import path from "node:path/posix"; +import path from "node:path"; + +// This will probably break for backslash-escaped POSIX paths, +// but we'll worry about that later. +function winToPosix(segment: string): string { + return segment.replaceAll(path.win32.sep, path.posix.sep); +} export function renderImportPath(basePath: string, ...segments: readonly string[]): string { - const fullPath = path - .join(basePath, ...segments) + // Solidity compiler expects POSIX paths + const fullPath = path.posix + .join(winToPosix(basePath), ...segments.map(winToPosix)) // remove trailing slash .replace(/\/$/, ""); From 07b024712b173ad6f281fa7bd767190a10a66d39 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Fri, 26 Jul 2024 12:08:35 +0100 Subject: [PATCH 15/16] improve import path handling --- .../contracts/src/codegen/tables/Statics.sol | 2 +- .../src/codegen/tables/UserTyped.sol | 2 +- .../src/codegen/render-solidity/common.ts | 3 +- packages/store/mud.config.ts | 2 +- packages/store/src/codegen/tables/Hooks.sol | 2 +- .../store/src/codegen/tables/ResourceIds.sol | 2 +- .../store/src/codegen/tables/StoreHooks.sol | 2 +- packages/store/src/codegen/tables/Tables.sol | 6 +-- .../store/test/codegen/tables/KeyEncoding.sol | 2 +- packages/store/ts/codegen/getTableOptions.ts | 5 +- packages/store/ts/codegen/renderTable.ts | 23 ++++----- packages/store/ts/codegen/userType.ts | 47 +------------------ packages/store/ts/config/v2/defaults.ts | 2 +- packages/store/ts/config/v2/output.ts | 7 ++- .../store/ts/scripts/generate-test-tables.ts | 8 ++-- .../interfaces/IAccessManagementSystem.sol | 2 +- .../codegen/interfaces/IBatchCallSystem.sol | 2 +- .../interfaces/IModuleInstallationSystem.sol | 2 +- .../interfaces/IWorldRegistrationSystem.sol | 4 +- .../render-solidity/renderWorldInterface.ts | 2 +- .../src/codegen/tables/Terrain.sol | 2 +- 21 files changed, 47 insertions(+), 82 deletions(-) diff --git a/packages/cli/contracts/src/codegen/tables/Statics.sol b/packages/cli/contracts/src/codegen/tables/Statics.sol index 83b959c491..ebba037d3f 100644 --- a/packages/cli/contracts/src/codegen/tables/Statics.sol +++ b/packages/cli/contracts/src/codegen/tables/Statics.sol @@ -17,7 +17,7 @@ import { EncodedLengths, EncodedLengthsLib } from "@latticexyz/store/src/Encoded import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; // Import user types -import { Enum2, Enum1 } from "./../common.sol"; +import { Enum2, Enum1 } from "../common.sol"; struct StaticsData { uint256 v1; diff --git a/packages/cli/contracts/src/codegen/tables/UserTyped.sol b/packages/cli/contracts/src/codegen/tables/UserTyped.sol index 5e05f4d1a9..bf0f26ef18 100644 --- a/packages/cli/contracts/src/codegen/tables/UserTyped.sol +++ b/packages/cli/contracts/src/codegen/tables/UserTyped.sol @@ -17,7 +17,7 @@ import { EncodedLengths, EncodedLengthsLib } from "@latticexyz/store/src/Encoded import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; // Import user types -import { TestTypeAddress, TestTypeInt64, TestTypeLibrary } from "./../../types.sol"; +import { TestTypeAddress, TestTypeInt64, TestTypeLibrary } from "../../types.sol"; import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; struct UserTypedData { diff --git a/packages/common/src/codegen/render-solidity/common.ts b/packages/common/src/codegen/render-solidity/common.ts index a1b7558a8b..f73a5162d7 100644 --- a/packages/common/src/codegen/render-solidity/common.ts +++ b/packages/common/src/codegen/render-solidity/common.ts @@ -10,6 +10,7 @@ import { import { posixPath } from "../utils"; import { resourceToHex } from "../../resourceToHex"; import { hexToResource } from "../../hexToResource"; +import { renderImportPath } from "./renderImportPath"; /** * Common header for all codegenerated solidity files @@ -132,7 +133,7 @@ export function renderAbsoluteImports(imports: AbsoluteImportDatum[]): string { const renderedImports = []; for (const [path, symbols] of aggregatedImports) { const renderedSymbols = [...symbols].join(", "); - renderedImports.push(`import { ${renderedSymbols} } from "${posixPath(path)}";`); + renderedImports.push(`import { ${renderedSymbols} } from "${renderImportPath(path)}";`); } return renderedImports.join("\n"); } diff --git a/packages/store/mud.config.ts b/packages/store/mud.config.ts index 5c779cd700..f9e958c98f 100644 --- a/packages/store/mud.config.ts +++ b/packages/store/mud.config.ts @@ -2,7 +2,7 @@ import { defineStore } from "./ts/config/v2/store"; export default defineStore({ codegen: { - storeImportPath: "../../", + storeImportPath: "./src", }, namespace: "store", userTypes: { diff --git a/packages/store/src/codegen/tables/Hooks.sol b/packages/store/src/codegen/tables/Hooks.sol index e815dd892d..a0bbf36faf 100644 --- a/packages/store/src/codegen/tables/Hooks.sol +++ b/packages/store/src/codegen/tables/Hooks.sol @@ -17,7 +17,7 @@ import { EncodedLengths, EncodedLengthsLib } from "../../EncodedLengths.sol"; import { ResourceId } from "../../ResourceId.sol"; // Import user types -import { ResourceId } from "./../../ResourceId.sol"; +import { ResourceId } from "../../ResourceId.sol"; library Hooks { FieldLayout constant _fieldLayout = diff --git a/packages/store/src/codegen/tables/ResourceIds.sol b/packages/store/src/codegen/tables/ResourceIds.sol index 0caf3ecac7..0e04073444 100644 --- a/packages/store/src/codegen/tables/ResourceIds.sol +++ b/packages/store/src/codegen/tables/ResourceIds.sol @@ -17,7 +17,7 @@ import { EncodedLengths, EncodedLengthsLib } from "../../EncodedLengths.sol"; import { ResourceId } from "../../ResourceId.sol"; // Import user types -import { ResourceId } from "./../../ResourceId.sol"; +import { ResourceId } from "../../ResourceId.sol"; library ResourceIds { // Hex below is the result of `WorldResourceIdLib.encode({ namespace: "store", name: "ResourceIds", typeId: RESOURCE_TABLE });` diff --git a/packages/store/src/codegen/tables/StoreHooks.sol b/packages/store/src/codegen/tables/StoreHooks.sol index c5c474768e..4aac606501 100644 --- a/packages/store/src/codegen/tables/StoreHooks.sol +++ b/packages/store/src/codegen/tables/StoreHooks.sol @@ -17,7 +17,7 @@ import { EncodedLengths, EncodedLengthsLib } from "../../EncodedLengths.sol"; import { ResourceId } from "../../ResourceId.sol"; // Import user types -import { ResourceId } from "./../../ResourceId.sol"; +import { ResourceId } from "../../ResourceId.sol"; library StoreHooks { // Hex below is the result of `WorldResourceIdLib.encode({ namespace: "store", name: "StoreHooks", typeId: RESOURCE_TABLE });` diff --git a/packages/store/src/codegen/tables/Tables.sol b/packages/store/src/codegen/tables/Tables.sol index d034310006..9cbe48f824 100644 --- a/packages/store/src/codegen/tables/Tables.sol +++ b/packages/store/src/codegen/tables/Tables.sol @@ -17,9 +17,9 @@ import { EncodedLengths, EncodedLengthsLib } from "../../EncodedLengths.sol"; import { ResourceId } from "../../ResourceId.sol"; // Import user types -import { ResourceId } from "./../../ResourceId.sol"; -import { FieldLayout } from "./../../FieldLayout.sol"; -import { Schema } from "./../../Schema.sol"; +import { ResourceId } from "../../ResourceId.sol"; +import { FieldLayout } from "../../FieldLayout.sol"; +import { Schema } from "../../Schema.sol"; struct TablesData { FieldLayout fieldLayout; diff --git a/packages/store/test/codegen/tables/KeyEncoding.sol b/packages/store/test/codegen/tables/KeyEncoding.sol index 6252ff5200..8004179b40 100644 --- a/packages/store/test/codegen/tables/KeyEncoding.sol +++ b/packages/store/test/codegen/tables/KeyEncoding.sol @@ -17,7 +17,7 @@ import { EncodedLengths, EncodedLengthsLib } from "../../../src/EncodedLengths.s import { ResourceId } from "../../../src/ResourceId.sol"; // Import user types -import { ExampleEnum } from "./../common.sol"; +import { ExampleEnum } from "../common.sol"; library KeyEncoding { // Hex below is the result of `WorldResourceIdLib.encode({ namespace: "", name: "KeyEncoding", typeId: RESOURCE_TABLE });` diff --git a/packages/store/ts/codegen/getTableOptions.ts b/packages/store/ts/codegen/getTableOptions.ts index fbe1fc052d..b8c4f66158 100644 --- a/packages/store/ts/codegen/getTableOptions.ts +++ b/packages/store/ts/codegen/getTableOptions.ts @@ -38,6 +38,7 @@ export function getTableOptions({ /** namespace codegen output dir, relative to project root dir */ readonly codegenDir: string; readonly userTypes: readonly UserType[]; + /** absolute import path or, if starting with `.`, relative to project root dir */ readonly storeImportPath: string; }): TableOptions[] { const options = tables.map((table): TableOptions => { @@ -109,7 +110,9 @@ export function getTableOptions({ libraryName: table.label, structName: withStruct ? table.label + "Data" : undefined, staticResourceData, - storeImportPath, + storeImportPath: storeImportPath.startsWith(".") + ? "./" + path.relative(path.dirname(outputPath), path.join(rootDir, storeImportPath)) + : storeImportPath, keyTuple, fields, staticFields, diff --git a/packages/store/ts/codegen/renderTable.ts b/packages/store/ts/codegen/renderTable.ts index 91b7036dd3..9d65b34052 100644 --- a/packages/store/ts/codegen/renderTable.ts +++ b/packages/store/ts/codegen/renderTable.ts @@ -9,6 +9,7 @@ import { renderWithStore, renderedSolidityHeader, RenderStaticField, + renderImportPath, } from "@latticexyz/common/codegen"; import { renderEncodeFieldSingle, renderFieldMethods } from "./field"; import { renderDeleteRecordMethods, renderRecordData, renderRecordMethods } from "./record"; @@ -42,17 +43,17 @@ export function renderTable(options: RenderTableOptions) { ${renderedSolidityHeader} // Import store internals - import { IStore } from "${storeImportPath}IStore.sol"; - import { StoreSwitch } from "${storeImportPath}StoreSwitch.sol"; - import { StoreCore } from "${storeImportPath}StoreCore.sol"; - import { Bytes } from "${storeImportPath}Bytes.sol"; - import { Memory } from "${storeImportPath}Memory.sol"; - import { SliceLib } from "${storeImportPath}Slice.sol"; - import { EncodeArray } from "${storeImportPath}tightcoder/EncodeArray.sol"; - import { FieldLayout } from "${storeImportPath}FieldLayout.sol"; - import { Schema } from "${storeImportPath}Schema.sol"; - import { EncodedLengths, EncodedLengthsLib } from "${storeImportPath}EncodedLengths.sol"; - import { ResourceId } from "${storeImportPath}ResourceId.sol"; + import { IStore } from "${renderImportPath(storeImportPath, "IStore.sol")}"; + import { StoreSwitch } from "${renderImportPath(storeImportPath, "StoreSwitch.sol")}"; + import { StoreCore } from "${renderImportPath(storeImportPath, "StoreCore.sol")}"; + import { Bytes } from "${renderImportPath(storeImportPath, "Bytes.sol")}"; + import { Memory } from "${renderImportPath(storeImportPath, "Memory.sol")}"; + import { SliceLib } from "${renderImportPath(storeImportPath, "Slice.sol")}"; + import { EncodeArray } from "${renderImportPath(storeImportPath, "tightcoder/EncodeArray.sol")}"; + import { FieldLayout } from "${renderImportPath(storeImportPath, "FieldLayout.sol")}"; + import { Schema } from "${renderImportPath(storeImportPath, "Schema.sol")}"; + import { EncodedLengths, EncodedLengthsLib } from "${renderImportPath(storeImportPath, "EncodedLengths.sol")}"; + import { ResourceId } from "${renderImportPath(storeImportPath, "ResourceId.sol")}"; ${ imports.length > 0 diff --git a/packages/store/ts/codegen/userType.ts b/packages/store/ts/codegen/userType.ts index 257f40c7cd..3748d8b387 100644 --- a/packages/store/ts/codegen/userType.ts +++ b/packages/store/ts/codegen/userType.ts @@ -4,8 +4,7 @@ import { SchemaType, SchemaTypeToAbiType, } from "@latticexyz/schema-type/deprecated"; -import { ImportDatum, RenderType, SolidityUserDefinedType } from "@latticexyz/common/codegen"; -import { Store as StoreConfig } from "../config/v2/output"; +import { RenderType } from "@latticexyz/common/codegen"; import { UserType } from "./getUserTypes"; function parseStaticArray(abiType: string) { @@ -53,50 +52,6 @@ export function resolveAbiOrUserType( return getUserTypeInfo(userType); } -/** - * Get the required import for SchemaType|userType (`undefined` means that no import is required) - */ -export function importForAbiOrUserType( - abiOrUserType: string, - usedInDirectory: string, - config: StoreConfig, - solidityUserTypes: Record, -): ImportDatum | undefined { - // abi types which directly mirror a SchemaType - if (abiOrUserType in AbiTypeToSchemaType) { - return undefined; - } - // static arrays - const staticArray = parseStaticArray(abiOrUserType); - if (staticArray) { - return undefined; - } - // user-defined types in a user-provided file - if (abiOrUserType in solidityUserTypes) { - // these types can have a library name as their import symbol - const solidityUserType = solidityUserTypes[abiOrUserType]; - const symbol = solidityUserType.importSymbol; - if (solidityUserType.isRelativePath) { - return { - symbol, - fromPath: solidityUserType.fromPath, - usedInPath: usedInDirectory, - }; - } else { - return { - symbol, - path: solidityUserType.fromPath, - }; - } - } - // other user types - return { - symbol: abiOrUserType, - fromPath: config.codegen.userTypesFilename, - usedInPath: usedInDirectory, - }; -} - export function getSchemaTypeInfo(schemaType: SchemaType): RenderType { const staticByteLength = getStaticByteLength(schemaType); const isDynamic = staticByteLength === 0; diff --git a/packages/store/ts/config/v2/defaults.ts b/packages/store/ts/config/v2/defaults.ts index 9c1899f343..eb5e0cb957 100644 --- a/packages/store/ts/config/v2/defaults.ts +++ b/packages/store/ts/config/v2/defaults.ts @@ -1,7 +1,7 @@ import { CodegenInput, StoreInput, TableCodegenInput, TableDeployInput, TableInput } from "./input"; export const CODEGEN_DEFAULTS = { - storeImportPath: "@latticexyz/store/src/", + storeImportPath: "@latticexyz/store/src", userTypesFilename: "common.sol", outputDirectory: "codegen", // TODO: default to true if using top-level `namespaces` key (once its migrated to store) diff --git a/packages/store/ts/config/v2/output.ts b/packages/store/ts/config/v2/output.ts index 3b4fd1d464..f882e7a470 100644 --- a/packages/store/ts/config/v2/output.ts +++ b/packages/store/ts/config/v2/output.ts @@ -47,7 +47,12 @@ export type Tables = { }; export type Codegen = { - /** @internal */ + /** + * @internal + * Absolute import path for a package import or starting with `.` for an import relative to project root dir. + * + * Defaults to `@latticexyz/store/src` if not set. + */ readonly storeImportPath: string; readonly userTypesFilename: string; /** diff --git a/packages/store/ts/scripts/generate-test-tables.ts b/packages/store/ts/scripts/generate-test-tables.ts index 2e2f142e5d..8d659a03e0 100644 --- a/packages/store/ts/scripts/generate-test-tables.ts +++ b/packages/store/ts/scripts/generate-test-tables.ts @@ -3,12 +3,12 @@ import { defineStore } from "../config/v2/store"; import { fileURLToPath } from "node:url"; import path from "node:path"; -const configPath = fileURLToPath(import.meta.url); +const rootDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); const config = defineStore({ - sourceDirectory: "../../test", + sourceDirectory: "test", codegen: { - storeImportPath: "../../../src/", + storeImportPath: "./src", }, enums: { ExampleEnum: ["None", "First", "Second", "Third"], @@ -51,4 +51,4 @@ const config = defineStore({ }, }); -await tablegen({ rootDir: path.dirname(configPath), config }); +await tablegen({ rootDir, config }); diff --git a/packages/world/src/codegen/interfaces/IAccessManagementSystem.sol b/packages/world/src/codegen/interfaces/IAccessManagementSystem.sol index fac3eb1116..cc7284c71d 100644 --- a/packages/world/src/codegen/interfaces/IAccessManagementSystem.sol +++ b/packages/world/src/codegen/interfaces/IAccessManagementSystem.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.24; /* Autogenerated file. Do not edit manually. */ -import { ResourceId } from "./../../WorldResourceId.sol"; +import { ResourceId } from "../../WorldResourceId.sol"; /** * @title IAccessManagementSystem diff --git a/packages/world/src/codegen/interfaces/IBatchCallSystem.sol b/packages/world/src/codegen/interfaces/IBatchCallSystem.sol index c6f95b5489..6555140871 100644 --- a/packages/world/src/codegen/interfaces/IBatchCallSystem.sol +++ b/packages/world/src/codegen/interfaces/IBatchCallSystem.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.24; /* Autogenerated file. Do not edit manually. */ -import { SystemCallData, SystemCallFromData } from "./../../modules/init/types.sol"; +import { SystemCallData, SystemCallFromData } from "../../modules/init/types.sol"; /** * @title IBatchCallSystem diff --git a/packages/world/src/codegen/interfaces/IModuleInstallationSystem.sol b/packages/world/src/codegen/interfaces/IModuleInstallationSystem.sol index 80fb477ecf..cb4504bd49 100644 --- a/packages/world/src/codegen/interfaces/IModuleInstallationSystem.sol +++ b/packages/world/src/codegen/interfaces/IModuleInstallationSystem.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.24; /* Autogenerated file. Do not edit manually. */ -import { IModule } from "./../../IModule.sol"; +import { IModule } from "../../IModule.sol"; /** * @title IModuleInstallationSystem diff --git a/packages/world/src/codegen/interfaces/IWorldRegistrationSystem.sol b/packages/world/src/codegen/interfaces/IWorldRegistrationSystem.sol index 7db5058421..276f3ea674 100644 --- a/packages/world/src/codegen/interfaces/IWorldRegistrationSystem.sol +++ b/packages/world/src/codegen/interfaces/IWorldRegistrationSystem.sol @@ -4,8 +4,8 @@ pragma solidity >=0.8.24; /* Autogenerated file. Do not edit manually. */ import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; -import { ISystemHook } from "./../../ISystemHook.sol"; -import { System } from "./../../System.sol"; +import { ISystemHook } from "../../ISystemHook.sol"; +import { System } from "../../System.sol"; /** * @title IWorldRegistrationSystem diff --git a/packages/world/ts/node/render-solidity/renderWorldInterface.ts b/packages/world/ts/node/render-solidity/renderWorldInterface.ts index 3391bec587..92b3980325 100644 --- a/packages/world/ts/node/render-solidity/renderWorldInterface.ts +++ b/packages/world/ts/node/render-solidity/renderWorldInterface.ts @@ -12,7 +12,7 @@ export function renderWorldInterface(options: RenderWorldOptions) { const baseImports: AbsoluteImportDatum[] = interfaceName === "IBaseWorld" ? [ - { symbol: "IStore", path: `${storeImportPath}IStore.sol` }, + { symbol: "IStore", path: `${storeImportPath}/IStore.sol` }, { symbol: "IWorldKernel", path: `${worldImportPath}IWorldKernel.sol` }, ] : [ diff --git a/test/mock-game-contracts/src/codegen/tables/Terrain.sol b/test/mock-game-contracts/src/codegen/tables/Terrain.sol index 3476bc100a..bc4bb03c23 100644 --- a/test/mock-game-contracts/src/codegen/tables/Terrain.sol +++ b/test/mock-game-contracts/src/codegen/tables/Terrain.sol @@ -17,7 +17,7 @@ import { EncodedLengths, EncodedLengthsLib } from "@latticexyz/store/src/Encoded import { ResourceId } from "@latticexyz/store/src/ResourceId.sol"; // Import user types -import { TerrainType } from "./../common.sol"; +import { TerrainType } from "../common.sol"; library Terrain { // Hex below is the result of `WorldResourceIdLib.encode({ namespace: "", name: "Terrain", typeId: RESOURCE_TABLE });` From e9071c77488da2ca0c1f734b3df3fb5adf9aff75 Mon Sep 17 00:00:00 2001 From: Kevin Ingersoll Date: Fri, 26 Jul 2024 12:17:22 +0100 Subject: [PATCH 16/16] build all the things --- .../contracts/src/codegen/world/ICustomErrorsSystem.sol | 2 +- .../packages/contracts/src/codegen/world/IStructSystem.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/packages/contracts/src/codegen/world/ICustomErrorsSystem.sol b/e2e/packages/contracts/src/codegen/world/ICustomErrorsSystem.sol index ce3085beda..47e672d4d9 100644 --- a/e2e/packages/contracts/src/codegen/world/ICustomErrorsSystem.sol +++ b/e2e/packages/contracts/src/codegen/world/ICustomErrorsSystem.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.24; /* Autogenerated file. Do not edit manually. */ -import { Position } from "./../../CustomTypes.sol"; +import { Position } from "../../CustomTypes.sol"; /** * @title ICustomErrorsSystem diff --git a/examples/minimal/packages/contracts/src/codegen/world/IStructSystem.sol b/examples/minimal/packages/contracts/src/codegen/world/IStructSystem.sol index a95d9eb919..e25284fbfe 100644 --- a/examples/minimal/packages/contracts/src/codegen/world/IStructSystem.sol +++ b/examples/minimal/packages/contracts/src/codegen/world/IStructSystem.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.24; /* Autogenerated file. Do not edit manually. */ -import { BytesStruct, StringStruct } from "./../../systems/structs.sol"; +import { BytesStruct, StringStruct } from "../../systems/structs.sol"; /** * @title IStructSystem