Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): user types and route/path separation #454

Merged
merged 22 commits into from
Mar 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
fb98e48
feat(cli): add enums to store config
dk1a Mar 1, 2023
6419618
chore(cli): add export for possibly useful function
dk1a Mar 1, 2023
8eb8eb7
refactor(cli): rename render-table to render-solidity
dk1a Mar 1, 2023
557b75f
feat(cli): add renderTypes
dk1a Mar 1, 2023
a9b7041
feat(cli): separate route and output directory
dk1a Mar 1, 2023
aab33cf
refactor(store): use new config
dk1a Mar 1, 2023
6bca6e9
refactor(world): use new config
dk1a Mar 1, 2023
e504b45
feat(cli): finish userType parsing
dk1a Mar 1, 2023
d3a6137
feat(cli): support generalized wrapped types in rendering
dk1a Mar 1, 2023
cef5a38
refactor(cli): wrap tablegen logic into a standalone function
dk1a Mar 1, 2023
803f68b
fix(cli): crosscheck local table variable name uniqueness
dk1a Mar 1, 2023
4329f29
test(cli): add tablegen tests
dk1a Mar 1, 2023
a83cc30
fix(cli): add userTypeNames to globalNames
dk1a Mar 8, 2023
dd65bd2
refactor(cli): reorganize contracts folders
dk1a Mar 8, 2023
57f85e0
fix(cli): fix StaticSchemaType error message
dk1a Mar 8, 2023
7e5504f
chore(cli): rename RequireKeys type
dk1a Mar 8, 2023
fad2c00
chore(cli): better error description for dynamic primary key in renderer
dk1a Mar 8, 2023
d80c4a5
chore(cli): reformat Table1
dk1a Mar 8, 2023
2720ea3
refactor(cli): render _primaryKeys more compactly
dk1a Mar 8, 2023
9c30b06
fix(cli): fix indirect merge conflicts
dk1a Mar 8, 2023
a004926
fix(cli): use StoreView in contract test
dk1a Mar 8, 2023
3206bbd
refactor(cli): capitalize TablegenTest
dk1a Mar 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
443 changes: 443 additions & 0 deletions packages/cli/contracts/src/tables/Table1.sol

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions packages/cli/contracts/src/types.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/* Autogenerated file. Do not edit manually. */

enum Enum1 {
E1,
E2,
E3
}

enum Enum2 {
E1
}
28 changes: 28 additions & 0 deletions packages/cli/contracts/test/Tablegen.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import "forge-std/Test.sol";
import {StoreView} from "@latticexyz/store/src/StoreView.sol";
import {Table1, Table1Data} from "../src/tables/Table1.sol";
import {Enum1, Enum2} from "../src/types.sol";

contract TablegenTest is Test, StoreView {
function testTable1SetAndGet() public {
Table1.registerSchema();

uint256 k1 = 1;
int32 k2 = -1;
bytes16 k3 = hex"02";
address k4 = address(123);
bool k5 = true;
Enum1 k6 = Enum1.E3;
Enum2 k7 = Enum2.E1;

Table1.setV1(k1, k2, k3, k4, k5, k6, k7, 4);
assertEq(Table1.getV1(k1, k2, k3, k4, k5, k6, k7), 4);

Table1Data memory data = Table1Data(4, -5, hex"06", address(456), false, Enum1.E2, Enum2.E1);
Table1.set(k1, k2, k3, k4, k5, k6, k7, data);
assertEq(abi.encode(Table1.get(k1, k2, k3, k4, k5, k6, k7)), abi.encode(data));
}
}
7 changes: 4 additions & 3 deletions packages/cli/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ fuzz_runs = 256
optimizer = true
optimizer_runs = 3000
verbosity = 1
libs = ["../../node_modules", "../solecs", "../std-contracts"]
src = "src"
out = "out"
libs = ["../../node_modules", "../solecs", "../std-contracts", "../store"]
src = "contracts/src"
out = "contracts/out"
test = "contracts/test"
5 changes: 4 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,18 @@
},
"scripts": {
"prepare": "yarn build && chmod u+x git-install.sh",
"codegen": "ts-node --esm --files ./scripts/codegen.ts",
"lint": "eslint . --ext .ts",
"dev": "tsup --watch",
"build": "tsup",
"link": "yarn link",
"test": "vitest typecheck --run && echo 'todo: add tests'",
"test": "vitest typecheck --run && yarn test:contracts",
"test:contracts": "yarn codegen && forge test",
"git:install": "bash git-install.sh",
"release": "npm publish --access=public"
},
"devDependencies": {
"@latticexyz/store": "^1.34.0",
"@types/ejs": "^3.1.1",
"@types/glob": "^7.2.0",
"@types/node": "^17.0.34",
Expand Down
4 changes: 3 additions & 1 deletion packages/cli/remappings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ ds-test/=../../node_modules/ds-test/src/
forge-std/=../../node_modules/forge-std/src/
solmate/=../../node_modules/@rari-capital/solmate/src
std-contracts/=../../node_modules/@latticexyz/std-contracts/src/
solecs/=../../node_modules/@latticexyz/solecs/src/
solecs/=../../node_modules/@latticexyz/solecs/src/
@solidstate/=../../node_modules/@solidstate/
alvrs marked this conversation as resolved.
Show resolved Hide resolved
@latticexyz/=../../node_modules/@latticexyz/
55 changes: 55 additions & 0 deletions packages/cli/scripts/codegen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { SchemaType } from "@latticexyz/schema-type";
import { parseStoreConfig, StoreUserConfig } from "../src/config/index.js";
import { tablegen } from "../src/render-solidity/tablegen.js";
import { logError } from "../src/utils/errors.js";
import { getSrcDirectory } from "../src/utils/foundry.js";

// This config is used only for tests
const config: StoreUserConfig = {
tables: {
Table1: {
primaryKeys: {
k1: SchemaType.UINT256,
k2: SchemaType.INT32,
k3: SchemaType.BYTES16,
k4: SchemaType.ADDRESS,
k5: SchemaType.BOOL,
k6: "Enum1",
k7: "Enum2",
},
schema: {
v1: SchemaType.UINT256,
v2: SchemaType.INT32,
v3: SchemaType.BYTES16,
v4: SchemaType.ADDRESS,
v5: SchemaType.BOOL,
v6: "Enum1",
v7: "Enum2",
},
},
},

userTypes: {
enums: {
Enum1: ["E1", "E2", "E3"],
Enum2: ["E1"],
},
},
};

// Aside from avoiding `mud.config.mts` in cli package (could cause issues),
// this also tests that tablegen can work as a standalone function
const parsedConfig = await (async () => {
try {
return await parseStoreConfig(config);
} catch (error: unknown) {
logError(error);
}
})();

const srcDirectory = await getSrcDirectory();
if (parsedConfig !== undefined) {
tablegen(parsedConfig, srcDirectory);
} else {
process.exit(1);
}
20 changes: 3 additions & 17 deletions packages/cli/src/commands/tablegen.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import type { CommandModule } from "yargs";
import { mkdirSync, writeFileSync } from "fs";
import path from "path";
import { loadStoreConfig } from "../config/loadStoreConfig.js";
import { renderTablesFromConfig } from "../render-table/renderTablesFromConfig.js";
import { getSrcDirectory } from "../utils/foundry.js";
import { formatSolidity } from "../utils/format.js";
import { tablegen } from "../render-solidity/tablegen.js";

type Options = {
configPath?: string;
Expand All @@ -22,22 +19,11 @@ const commandModule: CommandModule<Options, Options> = {
},

async handler({ configPath }) {
const srcDir = await getSrcDirectory();
const srcDirectory = await getSrcDirectory();

const config = await loadStoreConfig(configPath);
const renderedTables = renderTablesFromConfig(config);

for (const { output, tableName } of renderedTables) {
const formattedOutput = await formatSolidity(output);

const tablePath = config.tables[tableName].route;
const outputDirectory = path.join(srcDir, tablePath);
mkdirSync(outputDirectory, { recursive: true });

const outputPath = path.join(outputDirectory, `${tableName}.sol`);
writeFileSync(outputPath, formattedOutput);
console.log(`Generated schema: ${outputPath}`);
}
tablegen(config, srcDirectory);

process.exit(0);
},
Expand Down
12 changes: 12 additions & 0 deletions packages/cli/src/config/commonSchemas.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { getStaticByteLength, SchemaType } from "@latticexyz/schema-type";
import { z } from "zod";
import {
validateBaseRoute,
validateCapitalizedName,
validateDirectory,
validateEthereumAddress,
validateEnum,
validateName,
validateRoute,
validateSingleLevelRoute,
validateUncapitalizedName,
Expand All @@ -13,6 +16,10 @@ import {
export const ObjectName = z.string().superRefine(validateCapitalizedName);
/** Uncapitalized names of values, like keys and columns */
export const ValueName = z.string().superRefine(validateUncapitalizedName);
/** Name that can start with any case */
export const AnyCaseName = z.string().superRefine(validateName);
/** List of unique enum member names and 0 < length < 256 */
export const UserEnum = z.array(ObjectName).superRefine(validateEnum);

/** Ordinary routes */
export const OrdinaryRoute = z.string().superRefine(validateRoute);
Expand All @@ -26,3 +33,8 @@ export const Directory = z.string().superRefine(validateDirectory);

/** A valid Ethereum address */
export const EthereumAddress = z.string().superRefine(validateEthereumAddress);

/** Static subset of SchemaType enum */
export const StaticSchemaType = z
.nativeEnum(SchemaType)
.refine((arg) => getStaticByteLength(arg) > 0, "SchemaType must be static");
3 changes: 3 additions & 0 deletions packages/cli/src/config/parseStoreConfig.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ describe("StoreUserConfig", () => {
expectTypeOf<StoreUserConfig>().toEqualTypeOf<z.input<typeof StoreConfig>>();
// type equality isn't deep for optionals
expectTypeOf<StoreUserConfig["tables"][string]>().toEqualTypeOf<z.input<typeof StoreConfig>["tables"][string]>();
expectTypeOf<NonNullable<NonNullable<StoreUserConfig["userTypes"]>["enums"]>[string]>().toEqualTypeOf<
NonNullable<NonNullable<z.input<typeof StoreConfig>["userTypes"]>["enums"]>[string]
>();
// TODO If more nested schemas are added, provide separate tests for them
});
Loading