Repository: ponder-sh/ponder (ts)

Issue:
bug: using enum column in primary key fails codegen
If I use an enum column as part of  primary key, running `ponder codegen` command returns an error:
```
8:42:52 AM ERROR build      Error while building schema:
BuildError: Internal error: Expected enum column "nodeType" to have an "enum" property
```

Dropping the enum column from primaryKey columns list allows codegen to complete successfully.

### Context

Version: 0.7.16

Schema definition:
```ts
export const gsNodeType = onchainEnum("gs_node_type", ["basic", "premium"]);

export const gsNode = onchainTable(
  "gs_node",
  (t) => ({
    ownerAddress: t.hex().notNull(),
    nodeType: gsNodeType().notNull(),
    currentStakedAmount: t.bigint().notNull(),
    changedAtBlock: t.bigint().notNull(),
  }),
  (t) => ({
    pk: primaryKey({ columns: [t.ownerAddress, t.nodeType] }),
  })
);
```

Pull request description:
fix: enum primary key
Closes #1332 

Patch:
diff --git a/.changeset/pretty-beers-watch.md b/.changeset/pretty-beers-watch.md
new file mode 100644
index 00000000..53f32b7b
--- /dev/null
+++ b/.changeset/pretty-beers-watch.md
@@ -0,0 +1,5 @@
+---
+"ponder": patch
+---
+
+Fixed a graphql bug when using enums in a primary key.
diff --git a/packages/core/src/graphql/index.ts b/packages/core/src/graphql/index.ts
index f29047c1..155bb05a 100644
--- a/packages/core/src/graphql/index.ts
+++ b/packages/core/src/graphql/index.ts
@@ -34,6 +34,7 @@ import {
 } from "drizzle-orm";
 import {
   type PgEnum,
+  PgEnumColumn,
   PgInteger,
   PgSerial,
   isPgEnum,
@@ -443,19 +444,16 @@ const columnToGraphQLCore = (
     return GraphQLBigInt;
   }
 
-  if (column.columnType === "PgEnumColumn") {
-    const enumObject = (column as any)?.enum as
-      | PgEnum<[string, ...string[]]>
-      | undefined;
-    if (enumObject === undefined) {
+  if (column instanceof PgEnumColumn) {
+    if (column.enum === undefined) {
       throw new Error(
         `Internal error: Expected enum column "${getColumnTsName(column)}" to have an "enum" property`,
       );
     }
-    const enumType = enumTypes[enumObject.enumName];
+    const enumType = enumTypes[column.enum.enumName];
     if (enumType === undefined) {
       throw new Error(
-        `Internal error: Expected to find a GraphQL enum named "${enumObject.enumName}"`,
+        `Internal error: Expected to find a GraphQL enum named "${column.enum.enumName}"`,
       );
     }
 


Test patch:
diff --git a/packages/core/src/graphql/index.test.ts b/packages/core/src/graphql/index.test.ts
index e89f5ec4..f971b788 100644
--- a/packages/core/src/graphql/index.test.ts
+++ b/packages/core/src/graphql/index.test.ts
@@ -270,6 +270,53 @@ test("enum, enum not null, enum array, enum array not null", async (context) =>
   await cleanup();
 });
 
+test("enum primary key", async (context) => {
+  const testEnum = onchainEnum("enum", ["A", "B"]);
+  const table = onchainTable(
+    "table",
+    (t) => ({
+      a: t.text().notNull(),
+      enum: testEnum("enum").notNull(),
+    }),
+    (table) => ({
+      pk: primaryKey({ columns: [table.a, table.enum] }),
+    }),
+  );
+  const schema = { testEnum, table };
+
+  const { database, indexingStore, metadataStore, cleanup } =
+    await setupDatabaseServices(context, { schema });
+  const contextValue = buildContextValue(database, metadataStore);
+  const query = (source: string) =>
+    execute({ schema: graphqlSchema, contextValue, document: parse(source) });
+
+  await indexingStore.insert(schema.table).values({
+    a: "0",
+    enum: "A",
+  });
+
+  const graphqlSchema = buildGraphQLSchema(schema);
+
+  const result = await query(`
+    query {
+      table(a: "0", enum: "A") {
+        a
+        enum
+      }
+    }
+  `);
+
+  expect(result.errors?.[0]?.message).toBeUndefined();
+  expect(result.data).toMatchObject({
+    table: {
+      a: "0",
+      enum: "A",
+    },
+  });
+
+  await cleanup();
+});
+
 test("json, json not null", async (context) => {
   const schema = {
     table: onchainTable("table", (t) => ({