Skip to content

Commit

Permalink
feat(store): add types for v2 config resolvers (#2290)
Browse files Browse the repository at this point in the history
Co-authored-by: David Blass <[email protected]>
  • Loading branch information
alvrs and ssalbdivad authored Mar 7, 2024
1 parent 36a3185 commit 927fe85
Show file tree
Hide file tree
Showing 16 changed files with 1,569 additions and 10 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ templates/*/pnpm-lock.yaml

test-data/world-logs-bulk-*.json
test-data/world-logs-query.json

.attest
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@
"release:version": "changeset version && pnpm install --lockfile-only && bun scripts/changelog.ts",
"sort-package-json": "npx sort-package-json package.json 'packages/*/package.json' 'templates/*/package.json' 'templates/*/packages/*/package.json' 'examples/*/package.json' 'examples/*/packages/*/package.json' 'e2e/*/package.json' 'e2e/*/packages/*/package.json' 'docs/package.json'",
"test": "pnpm run --recursive --filter=!@latticexyz/services test",
"test:ci": "pnpm run --recursive --parallel --filter=!@latticexyz/services test:ci"
"test:ci": "pnpm run --recursive --parallel --filter=!@latticexyz/services test:ci",
"type-stats-repo": "attest stats packages/*"
},
"lint-staged": {
"*.{ts,tsx}": "eslint --cache --fix",
"*.{ts,tsx,css,md,mdx,sol}": "prettier --write",
"package.json": "pnpm sort-package-json"
},
"devDependencies": {
"@arktype/attest": "0.6.4",
"@changesets/cli": "^2.26.1",
"@types/node": "^18.15.11",
"@typescript-eslint/eslint-plugin": "5.46.1",
Expand Down
2 changes: 2 additions & 0 deletions packages/store/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,13 @@
"test:ci": "pnpm run test"
},
"dependencies": {
"@arktype/util": "0.0.25",
"@latticexyz/common": "workspace:*",
"@latticexyz/config": "workspace:*",
"@latticexyz/protocol-parser": "workspace:*",
"@latticexyz/schema-type": "workspace:*",
"abitype": "1.0.0",
"arktype": "1.0.29-alpha",
"viem": "2.7.12",
"zod": "^3.21.4"
},
Expand Down
1 change: 1 addition & 0 deletions packages/store/ts/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from "./defaults";
export * from "./storeConfig";

export * from "./experimental/resolveConfig";
export * from "./v2/store";
1 change: 1 addition & 0 deletions packages/store/ts/config/v2/generics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type get<input, key> = key extends keyof input ? input[key] : undefined;
36 changes: 36 additions & 0 deletions packages/store/ts/config/v2/schema.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { describe, it } from "vitest";
import { resolveSchema } from "./schema";
import { extendScope, AbiTypeScope } from "./scope";
import { attest } from "@arktype/attest";

describe("resolveSchema", () => {
it("should map user types to their primitive type", () => {
const scope = extendScope(AbiTypeScope, { CustomType: "address" });
const resolved = resolveSchema({ regular: "uint256", user: "CustomType" }, scope);
const expected = {
regular: {
type: "uint256",
internalType: "uint256",
},
user: {
type: "address",
internalType: "CustomType",
},
} as const;
attest<typeof expected>(resolved).type.toString.snap(
'{ regular: { type: "uint256"; internalType: "uint256"; }; user: { type: "address"; internalType: "CustomType"; }; }',
);
});

it("should throw if a type is not part of the scope", () => {
const scope = extendScope(AbiTypeScope, { CustomType: "address" });
resolveSchema(
{
regular: "uint256",
// @ts-expect-error Type '"NotACustomType"' is not assignable to type 'AbiType | "CustomType"'.
user: "NotACustomType",
},
scope,
);
});
});
23 changes: 23 additions & 0 deletions packages/store/ts/config/v2/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { evaluate } from "@arktype/util";
import { AbiTypeScope } from "./scope";

export type SchemaInput<scope extends AbiTypeScope = AbiTypeScope> = {
[key: string]: keyof scope["types"];
};

export type resolveSchema<schema extends SchemaInput<scope>, scope extends AbiTypeScope> = evaluate<{
[key in keyof schema]: {
/** the Solidity primitive ABI type */
type: scope["types"][schema[key]];
/** the user defined type or Solidity primitive ABI type */
internalType: schema[key];
};
}>;

export function resolveSchema<schema extends SchemaInput<scope>, scope extends AbiTypeScope = AbiTypeScope>(
schema: schema,
scope?: scope,
): resolveSchema<schema, scope> {
// TODO: runtime implementation
return {} as never;
}
39 changes: 39 additions & 0 deletions packages/store/ts/config/v2/scope.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { attest } from "@arktype/attest";
import { describe, it } from "vitest";
import { AbiTypeScope, EmptyScope, ScopeOptions, extendScope, getStaticAbiTypeKeys } from "./scope";

describe("extendScope", () => {
it("should extend the provided scope", () => {
const extendedScope = extendScope(EmptyScope, { static: "uint256", dynamic: "string" });
attest<ScopeOptions<{ static: "uint256"; dynamic: "string" }>>(extendedScope).type.toString.snap(
'{ types: { static: "uint256"; dynamic: "string"; }; }',
);

const furtherExtendedScope = extendScope(extendedScope, { static2: "uint256", dynamic2: "string" });
attest<ScopeOptions<{ static: "uint256"; dynamic: "string"; static2: "uint256"; dynamic2: "string" }>>(
furtherExtendedScope,
).type.toString.snap(
'{ types: { static: "uint256"; dynamic: "string"; static2: "uint256"; dynamic2: "string"; }; }',
);
});
});

describe("getStaticAbiTypeKeys", () => {
it("returns only static keys", () => {
attest<
"static" | "otherStatic",
getStaticAbiTypeKeys<{ static: "uint256"; otherStatic: "address"; dynamic: "string" }>
>();
});

it("returns only static keys with a scope", () => {
const extendedScope = extendScope(AbiTypeScope, { static: "uint256", dynamic: "string" });
attest<
"static" | "customStatic",
getStaticAbiTypeKeys<
{ static: "uint256"; dynamic: "string"; customStatic: "static"; customDynamic: "dynamic" },
typeof extendedScope
>
>();
});
});
36 changes: 36 additions & 0 deletions packages/store/ts/config/v2/scope.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Dict, evaluate } from "@arktype/util";
import { SchemaInput } from "./schema";
import { StaticAbiType, DynamicAbiType } from "@latticexyz/schema-type";

export type AbiType = StaticAbiType | DynamicAbiType;

export const EmptyScope = { types: {} } as const satisfies ScopeOptions;
export type EmptyScope = typeof EmptyScope;

export type AbiTypeScope = ScopeOptions<{ [t in AbiType]: t }>;
export const AbiTypeScope = { types: {} } as AbiTypeScope; // TODO: runtime implementation

export type ScopeOptions<types extends Dict<string, AbiType> = Dict<string, AbiType>> = {
types: types;
};

export type getStaticAbiTypeKeys<
types extends SchemaInput<scope>,
scope extends AbiTypeScope = AbiTypeScope,
> = SchemaInput extends types
? string
: {
[key in keyof types]: scope["types"][types[key]] extends StaticAbiType ? key : never;
}[keyof types];

export type extendScope<scope extends ScopeOptions, additionalTypes extends Dict<string, AbiType>> = evaluate<
ScopeOptions<evaluate<scope["types"] & additionalTypes>>
>;

export function extendScope<scope extends ScopeOptions, additionalTypes extends Dict<string, AbiType>>(
scope: scope,
additionalTypes: additionalTypes,
): extendScope<scope, additionalTypes> {
// TODO: runtime implementation
return {} as never;
}
Loading

0 comments on commit 927fe85

Please sign in to comment.