-
Notifications
You must be signed in to change notification settings - Fork 196
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(store-sync): extra table definitions #1840
Changes from 7 commits
59c5ab3
b434be3
ee84330
19e1d8b
3f00458
0b8cdbe
2b6a328
b9e8c6f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,7 @@ import { encodeEntity, syncToRecs } from "@latticexyz/store-sync/recs"; | |
import { getNetworkConfig } from "./getNetworkConfig"; | ||
import { world } from "./world"; | ||
import IWorldAbi from "contracts/out/IWorld.sol/IWorld.abi.json"; | ||
import { ContractWrite, createBurnerAccount, getContract, transportObserver } from "@latticexyz/common"; | ||
import { ContractWrite, createBurnerAccount, getContract, resourceToHex, transportObserver } from "@latticexyz/common"; | ||
import { Subject, share } from "rxjs"; | ||
import mudConfig from "contracts/mud.config"; | ||
import { createClient as createFaucetClient } from "@latticexyz/faucet"; | ||
|
@@ -40,10 +40,23 @@ export async function setupNetwork() { | |
const { components, latestBlock$, storedBlockLogs$, waitForTransaction } = await syncToRecs({ | ||
world, | ||
config: mudConfig, | ||
tables: { | ||
KeysWithValue: { | ||
namespace: "keywval", | ||
name: "Inventory", | ||
tableId: resourceToHex({ type: "table", namespace: "keywval", name: "Inventory" }), | ||
keySchema: { | ||
valueHash: { type: "bytes32" }, | ||
}, | ||
valueSchema: { | ||
keysWithValue: { type: "bytes32[]" }, | ||
}, | ||
}, | ||
}, | ||
address: networkConfig.worldAddress as Hex, | ||
publicClient, | ||
startBlock: BigInt(networkConfig.initialBlockNumber), | ||
}); | ||
} as const); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what would break without There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the manually defined tables were missing strong types for namespace/name without this |
||
|
||
try { | ||
console.log("creating faucet client"); | ||
|
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,10 @@ | ||
import { StoreConfig } from "@latticexyz/store"; | ||
import { Component as RecsComponent, Metadata as RecsMetadata, Type as RecsType } from "@latticexyz/recs"; | ||
import { SchemaAbiTypeToRecsType } from "./schemaAbiTypeToRecsType"; | ||
import { SchemaAbiType } from "@latticexyz/schema-type"; | ||
import { Metadata } from "@latticexyz/recs"; | ||
import { KeySchema, ValueSchema } from "@latticexyz/protocol-parser"; | ||
|
||
export type StoreComponentMetadata = RecsMetadata & { | ||
export type StoreComponentMetadata = Metadata & { | ||
componentName: string; | ||
tableName: string; | ||
// TODO: migrate to store's KeySchema/ValueSchema | ||
keySchema: KeySchema; | ||
valueSchema: ValueSchema; | ||
}; | ||
|
||
export type ConfigToRecsComponents<TConfig extends StoreConfig> = { | ||
[tableName in keyof TConfig["tables"] & string]: RecsComponent< | ||
{ | ||
__staticData: RecsType.OptionalString; | ||
__encodedLengths: RecsType.OptionalString; | ||
__dynamicData: RecsType.OptionalString; | ||
} & { | ||
[fieldName in keyof TConfig["tables"][tableName]["valueSchema"] & string]: RecsType & | ||
SchemaAbiTypeToRecsType<SchemaAbiType & TConfig["tables"][tableName]["valueSchema"][fieldName]>; | ||
}, | ||
StoreComponentMetadata & { | ||
componentName: tableName; | ||
tableName: `${TConfig["namespace"]}:${tableName}`; | ||
keySchema: TConfig["tables"][tableName]["keySchema"]; | ||
valueSchema: TConfig["tables"][tableName]["valueSchema"]; | ||
} | ||
>; | ||
}; |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import { StoreConfig } from "@latticexyz/store"; | ||
import { Table, resolveConfig } from "@latticexyz/store"; | ||
import { debug } from "./debug"; | ||
import { World as RecsWorld, getComponentValue, hasComponent, removeComponent, setComponent } from "@latticexyz/recs"; | ||
import { defineInternalComponents } from "./defineInternalComponents"; | ||
|
@@ -9,39 +9,40 @@ import { Hex, size } from "viem"; | |
import { isTableRegistrationLog } from "../isTableRegistrationLog"; | ||
import { logToTable } from "../logToTable"; | ||
import { hexKeyTupleToEntity } from "./hexKeyTupleToEntity"; | ||
import { ConfigToRecsComponents } from "./common"; | ||
import { StorageAdapter, StorageAdapterBlock } from "../common"; | ||
import { configToRecsComponents } from "./configToRecsComponents"; | ||
import { singletonEntity } from "./singletonEntity"; | ||
import storeConfig from "@latticexyz/store/mud.config"; | ||
import worldConfig from "@latticexyz/world/mud.config"; | ||
import { TablesToComponents, tablesToComponents } from "./tablesToComponents"; | ||
|
||
export type RecsStorageOptions<TConfig extends StoreConfig = StoreConfig> = { | ||
const storeTables = resolveConfig(storeConfig).tables; | ||
const worldTables = resolveConfig(worldConfig).tables; | ||
|
||
export type RecsStorageOptions<tables extends Record<string, Table>> = { | ||
world: RecsWorld; | ||
// TODO: make config optional? | ||
config: TConfig; | ||
tables: tables; | ||
shouldSkipUpdateStream?: () => boolean; | ||
}; | ||
|
||
export type RecsStorageAdapter<TConfig extends StoreConfig = StoreConfig> = { | ||
export type RecsStorageAdapter<tables extends Record<string, Table>> = { | ||
storageAdapter: StorageAdapter; | ||
Comment on lines
-26
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm still not used to |
||
components: ConfigToRecsComponents<TConfig> & | ||
ConfigToRecsComponents<typeof storeConfig> & | ||
ConfigToRecsComponents<typeof worldConfig> & | ||
components: TablesToComponents<tables> & | ||
TablesToComponents<typeof storeTables> & | ||
TablesToComponents<typeof worldTables> & | ||
ReturnType<typeof defineInternalComponents>; | ||
}; | ||
|
||
export function recsStorage<TConfig extends StoreConfig = StoreConfig>({ | ||
export function recsStorage<tables extends Record<string, Table>>({ | ||
world, | ||
config, | ||
tables, | ||
shouldSkipUpdateStream, | ||
}: RecsStorageOptions<TConfig>): RecsStorageAdapter<TConfig> { | ||
}: RecsStorageOptions<tables>): RecsStorageAdapter<tables> { | ||
world.registerEntity({ id: singletonEntity }); | ||
|
||
const components = { | ||
...configToRecsComponents(world, config), | ||
...configToRecsComponents(world, storeConfig), | ||
...configToRecsComponents(world, worldConfig), | ||
...tablesToComponents(world, tables), | ||
...tablesToComponents(world, storeTables), | ||
...tablesToComponents(world, worldTables), | ||
...defineInternalComponents(world), | ||
}; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { Component, Type, World, defineComponent } from "@latticexyz/recs"; | ||
import { StoreComponentMetadata } from "./common"; | ||
import { SchemaAbiTypeToRecsType, schemaAbiTypeToRecsType } from "./schemaAbiTypeToRecsType"; | ||
import { SchemaAbiType } from "@latticexyz/schema-type"; | ||
import { Table } from "@latticexyz/store"; | ||
import { mapObject } from "@latticexyz/common/utils"; | ||
|
||
export type TableToComponent<table extends Table> = Component< | ||
{ | ||
__staticData: Type.OptionalString; | ||
__encodedLengths: Type.OptionalString; | ||
__dynamicData: Type.OptionalString; | ||
} & { | ||
[fieldName in keyof table["valueSchema"] & string]: Type & | ||
SchemaAbiTypeToRecsType<SchemaAbiType & table["valueSchema"][fieldName]["type"]>; | ||
}, | ||
StoreComponentMetadata & { | ||
componentName: table["name"]; | ||
tableName: `${table["namespace"]}:${table["name"]}`; | ||
keySchema: { [name in keyof table["keySchema"] & string]: table["keySchema"][name]["type"] }; | ||
valueSchema: { [name in keyof table["valueSchema"] & string]: table["valueSchema"][name]["type"] }; | ||
} | ||
>; | ||
|
||
export function tableToComponent<table extends Table>(world: World, table: table): TableToComponent<table> { | ||
return defineComponent( | ||
world, | ||
{ | ||
...Object.fromEntries( | ||
Object.entries(table.valueSchema).map(([fieldName, { type: schemaAbiType }]) => [ | ||
fieldName, | ||
schemaAbiTypeToRecsType[schemaAbiType as SchemaAbiType], | ||
]) | ||
), | ||
__staticData: Type.OptionalString, | ||
__encodedLengths: Type.OptionalString, | ||
__dynamicData: Type.OptionalString, | ||
}, | ||
{ | ||
id: table.tableId, | ||
metadata: { | ||
componentName: table.name, | ||
tableName: `${table.namespace}:${table.name}`, | ||
keySchema: mapObject(table.keySchema, ({ type }) => type), | ||
valueSchema: mapObject(table.valueSchema, ({ type }) => type), | ||
}, | ||
} | ||
) as TableToComponent<table>; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { Table } from "@latticexyz/store"; | ||
import { TableToComponent, tableToComponent } from "./tableToComponent"; | ||
import { mapObject } from "@latticexyz/common/utils"; | ||
import { World } from "@latticexyz/recs"; | ||
|
||
export type TablesToComponents<tables extends Record<string, Table>> = { | ||
[tableName in keyof tables]: TableToComponent<tables[tableName]>; | ||
}; | ||
|
||
export function tablesToComponents<tables extends Record<string, Table>>( | ||
world: World, | ||
tables: tables | ||
): TablesToComponents<tables> { | ||
return mapObject(tables, (table) => tableToComponent(world, table)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so
syncToRecs
syncs all tables passedmudConfig
or intables
correct? What inmudConfig
do we need in here besides the resolved tables? If it's only that, should we just pass a tables key (iesyncToRecs({ tables: { ...mudConfig.tables, ...additionalTables } })
)? (mostly wondering about longer term when the config is resolved by default, fine to not do that here yet to avoid breaking changes)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
long term I think we should do that, yep! I just didn't want to encourage the intermediate step of using the experimental
resolveConfig
in user land