Skip to content

Commit

Permalink
config to zustand tables
Browse files Browse the repository at this point in the history
  • Loading branch information
holic committed Jul 19, 2024
1 parent 69e23a3 commit 8d23a38
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 27 deletions.
1 change: 1 addition & 0 deletions packages/store-sync/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"test:ci": "vitest --run"
},
"dependencies": {
"@arktype/util": "0.0.40",
"@latticexyz/block-logs-stream": "workspace:*",
"@latticexyz/common": "workspace:*",
"@latticexyz/config": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { describe, expect, it } from "vitest";
import { tablesByLabel } from "./tablesByLabel";
import { configToTables } from "./configToTables";
import { defineWorld } from "@latticexyz/world";
import { resourceToHex } from "@latticexyz/common";

describe("tablesByLabel", () => {
it("maps table label to component name", async () => {
describe("configToTables", () => {
it("flattens tables from single namespace", async () => {
const config = defineWorld({
namespace: "app",
tables: {
ExceedsResourceNameSizeLimit: "bytes32",
},
});

const tables = tablesByLabel(config.tables);
const tables = configToTables(config);
expect(tables.ExceedsResourceNameSizeLimit.tableId).toBe(
resourceToHex({
type: "table",
Expand All @@ -23,4 +23,7 @@ describe("tablesByLabel", () => {
expect(tables.ExceedsResourceNameSizeLimit.label).toBe("ExceedsResourceNameSizeLimit");
expect(tables.ExceedsResourceNameSizeLimit.name).toBe("ExceedsResourceN");
});

// TODO: add test with multiple namespaces
// TODO: add test where the label is the same for two tables in different namespaces to make sure TS + runtime agree on which takes precedence
});
30 changes: 30 additions & 0 deletions packages/store-sync/src/zustand/configToTables.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { satisfy, show } from "@arktype/util";
import { Tables } from "@latticexyz/config";
import { Store } from "@latticexyz/store";

type flattenedTables<config extends Store> = config extends { readonly namespaces: infer namespaces }
? {
[namespaceLabel in keyof namespaces]: namespaces[namespaceLabel] extends { readonly tables: infer tables }
? `${namespaceLabel & string}__${keyof tables & string}`
: never;
}[keyof namespaces]
: never;

// TODO: figure out how TS handles overlapping table labels so we can make runtime match
// TODO: move satisfy to type test

export type configToTables<config extends Store> = satisfy<
Tables,
{
readonly [key in flattenedTables<config> as key extends `${string}__${infer tableLabel}`
? tableLabel
: never]: key extends `${infer namespaceLabel}__${infer tableLabel}`
? config["namespaces"][namespaceLabel]["tables"][tableLabel]
: never;
}
>;

export function configToTables<config extends Store>(config: config): show<configToTables<config>> {
const tables = Object.values(config.namespaces).flatMap((namespace) => Object.values(namespace.tables));
return Object.fromEntries(tables.map((table) => [table.label, table])) as never;
}
31 changes: 17 additions & 14 deletions packages/store-sync/src/zustand/getAllTables.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
import { Store as StoreConfig } from "@latticexyz/store";
import { Tables } from "@latticexyz/config";
import { tablesByLabel } from "./tablesByLabel";
import { mergeRight } from "./mergeRight";
import storeConfig from "@latticexyz/store/mud.config";
import worldConfig from "@latticexyz/world/mud.config";
import { configToTables } from "./configToTables";
import { satisfy, show } from "@arktype/util";

const storeTables = storeConfig.tables;
type storeTables = typeof storeTables;
type mudTables = mergeRight<configToTables<typeof storeConfig>, configToTables<typeof worldConfig>>;
const mudTables = {
...configToTables(storeConfig),
...configToTables(worldConfig),
};

const worldTables = worldConfig.tables;
type worldTables = typeof worldTables;

export type getAllTables<config extends StoreConfig, extraTables extends Tables> = tablesByLabel<
mergeRight<config["tables"], mergeRight<extraTables, mergeRight<storeTables, worldTables>>>
// TODO: validate that extraTables keys correspond to table labels?
// TODO: move satisfy to type test
export type getAllTables<config extends StoreConfig, extraTables extends Tables> = satisfy<
Tables,
mergeRight<configToTables<config>, mergeRight<extraTables, mudTables>>
>;

export function getAllTables<config extends StoreConfig, extraTables extends Tables>(
config: config,
extraTables: extraTables,
): getAllTables<config, extraTables> {
return tablesByLabel({
...config.tables,
): show<getAllTables<config, extraTables>> {
return {
...configToTables(config),
...extraTables,
...storeTables,
...worldTables,
}) as never;
...mudTables,
} as never;
}
9 changes: 0 additions & 9 deletions packages/store-sync/src/zustand/tablesByLabel.ts

This file was deleted.

3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 8d23a38

Please sign in to comment.