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): refactor tablegen and add more advanced features #437

Merged
merged 43 commits into from
Feb 28, 2023

Conversation

dk1a
Copy link
Contributor

@dk1a dk1a commented Feb 24, 2023

Pretty much rewrote the whole thing.
StoreUserConfig is a good summary of what's going on.
All tables in store are now autogenerated, check them out.
I didn't want to mess with world too much, so made just RouteAccess autogenerated (it's interesting because it has 2 keys with different types, and uses storeArgument flag)

#438 has a summary

@dk1a dk1a mentioned this pull request Feb 25, 2023
47 tasks
struct Route {
address addr;
bytes4 selector;
uint8 executionMode;
}

library Route_ {
library RouteTable {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I missed the naming conversation but did ya'll consider RouteStore as a name option?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'll be confusing when a table that writes to Store is also called Store. We already have World, which is Store. Wouldn't want everything to be a Store

Copy link
Member

@holic holic Feb 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thought is that users will mostly be interacting with these autogen files, not the underlying ones (i.e. Store). But I understand if this creates confusion on our end.

"Table" just feels like an overloaded term. Folks with SQL experience will have preconceived notions about what it does/should do, and folks without SQL experience may be a little confused by it the term "table". We have a chance to shed this here.

(All that said, I don't feel super strongly, just wanting to stress test our name choices as it'll be hard to change later)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the SQL analogy (I have SQL experience, although I'm obviously not a great example).
We even have hooks/indexers. And a planned postgres integration. In solidity it's just a limited key/value store of course.
But I'm starting to think of how foreign keys would fit in here

Copy link
Member

@holic holic Feb 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to circle back on this: we all chatted in discord and ended up with removing the suffix altogether on libraries, and adding "data" suffix to structs, allowing users to choose their naming scheme

@dk1a dk1a changed the title feat(cli): add routes and schemaMode to tablegen, add minor improvements feat(cli): refactor tablegen and add features Feb 27, 2023
}
export class NotInsideProjectError extends Error {
name = "NotInsideProjectError";
message = "You are not inside a MUD project";
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

small thing: I would probably add

export class MudCliError extends Error {}

then

export class NotInsideProjectError extends MudCliError {
  ...
}

just so downstream folks can easily catch all CLI errors in one conditional

(I am thinking we might eventually have a centralized MudError but a cli-specific one in the meantime is still handy)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That said, I'm not sure how these interact with Zod error classes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just so downstream folks can easily catch all CLI errors in one conditional

There aren't really supposed to be downstream folks rn, the renderer is cli-only currently, and everything is handled by logError.
When I do make it standalone that sounds like a good thing to add though. Zod errors can probably be wrapped to also be identifiable somehow

console.log(chalk.yellow(`Error during output formatting: ${message}`));
return content;
}
}
Copy link
Member

@holic holic Feb 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not blocking but we can also call out to forge fmt and use the project's local foundry.toml (in the same way that we use it for src etc. dirs) for formatting config

cat File.sol | forge fmt --raw -

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method isn't really file-related, it's used at the render stage, so it's not aware of the filesystem at all, and when renderer is standalone it could even be used without files at all.
Also since it's all js using prettier is just more convenient.
I think if people want custom formatting they can do their own fmt, this func is just for new mudders who don't have that set up yet, so they don't see super ugly files

Copy link
Member

@alvrs alvrs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another very impressive PR! Just a couple smaller nits / questions

packages/cli/src/utils/errors.ts Show resolved Hide resolved
packages/cli/src/config/loadConfig.ts Outdated Show resolved Hide resolved
packages/cli/src/utils/errors.ts Show resolved Hide resolved
packages/cli/src/config/loadConfig.ts Show resolved Hide resolved
packages/cli/src/config/loadStoreConfig.ts Outdated Show resolved Hide resolved
packages/cli/src/render-table/index.ts Outdated Show resolved Hide resolved
packages/cli/src/render-table/index.ts Outdated Show resolved Hide resolved

const FullTable = z
.object({
route: OrdinaryRoute.default("/tables"),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like this can't be empty correct? I think we should allow registering tables at the root level of a World (eg. /RootTable), which would require passing the empty root route here, however this wouldn't work as nicely with using the same route as output path for the generated file

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, it's the one case that messes up route->folder.
Do we really need root tables?

Copy link
Member

@alvrs alvrs Feb 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be useful, if only to allow users to minimize route lengths. Just feels like we shouldn't prevent a setup that uses tables at the root. We could even just put the auto-generated file into the "base directory" (right now foundry's src config - but we could add a config field to allow overriding the table base directory).

Not blocking for this PR though, let's discuss and change in a follow up if needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just allowing root routes is easy actually - replace validateRoute with validateBaseRoute in zod schema.
Having an extra config option for baseDirectory is also pretty trivial, although baseRoute+baseDirectory feels like a bit much.

Btw I don't bundle systems and tables together here. Systems are writers, and for systems that have access to everything (i.e. use delegatecall) I agree root is the best place.

Problems I have with root tables:

  • Encourages flat setup. It's intuitive for small projects, but projects that need MUD aren't really small imo. No root simplifies the switch from "/tables" to "/skills", "/items" etc.
  • Tables no longer have access groups. If you want to give access to several at once, you'd give root route. You shouldn't give out root access.
  • Unlike systems, root tables don't signify a root permission. They don't have to exist

Rather than root routes I think it'd be more useful to consider shorthands/config reorgs for setting the same route for multiple tables/systems

My current folders (they would more or less become routes in v2, and this sorta setup is what I'm optimizing for):
Screenshot 2023-02-28 033836

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the other hand, if route and folder path are completely separated, it feels like my problems with root tables kinda evaporate. And maybe we should have route: "" by default, but path: "/tables" by default, and have no significant relationship between the 2

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Encourages flat setup. It's intuitive for small projects, but projects that need MUD aren't really small imo. No root simplifies the switch from "/tables" to "/skills", "/items" etc.

I think with v2 there are a lot of good reasons for small projects to use MUD too (eg default compatibility with indexers and network stack), so my preference would be to make all project configurations possible, including simple/flat ones.

I still agree with making more complex / nested project structures like your example easy to achieve too. After thinking about it more I think separating on-chan route and filesystem outputPath like you proposed makes the most sense, because it allows for any configuration of routes and filesystem structure. This also makes the id computation consistent with systems, where it's always keccak256(baseRoute/route/SystemName) with route being "" by default. (Also for systems route is independent from the file system path too because they are not auto-generated/)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While working on the system deploy script I am realizing it would be most intuitive if route allows users to completely override the route, without a default /SystemName or /TableName appended at the end. So basically if route is omitted the default route should be baseRoute/SystemOrTableName, while if the route key is present it should be baseRoute/route. Otherwise we might prevent some configurations where the route has to be some explicit value that's not the contract name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While working on the system deploy script I am realizing it would be most intuitive if route allows users to completely override the route, without a default /SystemName or /TableName appended at the end. So basically if route is omitted the default route should be baseRoute/SystemOrTableName, while if the route key is present it should be baseRoute/route. Otherwise we might prevent some configurations where the route has to be some explicit value that's not the contract name.

Sounds good! I can change that in store config in one of the upcoming PRs

@alvrs alvrs changed the title feat(cli): refactor tablegen and add features feat(cli): refactor tablegen and add more advanced features Feb 28, 2023
@alvrs alvrs merged commit 4777719 into v2 Feb 28, 2023
@dk1a dk1a deleted the dk1a/v2-tablegen-2 branch May 9, 2023 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants