Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions apps/ensindexer/drizzle.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { defineConfig } from "drizzle-kit";

export default defineConfig({
dialect: "postgresql",
schema: "./drizzle.schema.ts",
out: "./drizzle",
dbCredentials: {
url: "postgresql://dbuser:abcd1234@localhost:54320/ensnode_local_ponder_0_16",
Comment on lines +3 to +8
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

drizzle.config.ts hardcodes a Postgres connection URL including credentials. This is easy to accidentally use against the wrong DB and is risky to commit (even if the password is “local”). Prefer reading the URL from env (e.g. process.env.DATABASE_URL) and/or using dotenv-style config, or omit dbCredentials and pass it via CLI when generating migrations.

Suggested change
export default defineConfig({
dialect: "postgresql",
schema: "./drizzle.schema.ts",
out: "./drizzle",
dbCredentials: {
url: "postgresql://dbuser:abcd1234@localhost:54320/ensnode_local_ponder_0_16",
const connectionString = process.env.DATABASE_URL;
if (!connectionString) {
throw new Error("DATABASE_URL environment variable is required for drizzle config");
}
export default defineConfig({
dialect: "postgresql",
schema: "./drizzle.schema.ts",
out: "./drizzle",
dbCredentials: {
url: connectionString,

Copilot uses AI. Check for mistakes.
},
Comment on lines +7 to +9
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Remove hardcoded database credentials from source.

Line 8 commits a concrete DB user/password, which is a security and configuration-management risk.

Proposed secure config change
 import { defineConfig } from "drizzle-kit";
 
+const databaseUrl = process.env.ENSDB_DATABASE_URL;
+if (!databaseUrl) {
+  throw new Error("ENSDB_DATABASE_URL is required");
+}
+
 export default defineConfig({
   dialect: "postgresql",
   schema: "./drizzle.schema.ts",
   out: "./drizzle",
   dbCredentials: {
-    url: "postgresql://dbuser:abcd1234@localhost:54320/ensnode_local_ponder_0_16",
+    url: databaseUrl,
   },
 });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
dbCredentials: {
url: "postgresql://dbuser:abcd1234@localhost:54320/ensnode_local_ponder_0_16",
},
import { defineConfig } from "drizzle-kit";
const databaseUrl = process.env.ENSDB_DATABASE_URL;
if (!databaseUrl) {
throw new Error("ENSDB_DATABASE_URL is required");
}
export default defineConfig({
dialect: "postgresql",
schema: "./drizzle.schema.ts",
out: "./drizzle",
dbCredentials: {
url: databaseUrl,
},
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ensindexer/drizzle.config.ts` around lines 7 - 9, Remove the hardcoded
DB URL in the dbCredentials.url setting and replace it with a secure
configuration source (e.g., read from environment variable or a secrets/config
service); update the code that sets dbCredentials (the dbCredentials object and
its url property) to use process.env (or your project's config loader) and
validate presence of the variable at startup, failing fast with a clear error if
it's missing.

});
1 change: 1 addition & 0 deletions apps/ensindexer/drizzle.schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "@ensnode/ensnode-schema/offchain";
6 changes: 6 additions & 0 deletions apps/ensindexer/drizzle/0000_orange_veda.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE SCHEMA "offchain";
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

This migration uses CREATE SCHEMA "offchain"; without IF NOT EXISTS. This can fail on databases where the schema already exists (or under concurrent startups where two processes try to apply the first migration at once). Consider making schema creation idempotent (e.g. CREATE SCHEMA IF NOT EXISTS ...) or otherwise guarding it to avoid startup/migration crashes.

Suggested change
CREATE SCHEMA "offchain";
CREATE SCHEMA IF NOT EXISTS "offchain";

Copilot uses AI. Check for mistakes.
--> statement-breakpoint
CREATE TABLE "offchain"."ensnode_metadata" (
"key" text PRIMARY KEY NOT NULL,
"value" jsonb NOT NULL
);
46 changes: 46 additions & 0 deletions apps/ensindexer/drizzle/meta/0000_snapshot.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"id": "771c3fcb-f4ef-439b-b931-1a2bf77a117a",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
"tables": {
"offchain.ensnode_metadata": {
"name": "ensnode_metadata",
"schema": "offchain",
"columns": {
"key": {
"name": "key",
"type": "text",
"primaryKey": true,
"notNull": true
},
"value": {
"name": "value",
"type": "jsonb",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {
"offchain": "offchain"
},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
13 changes: 13 additions & 0 deletions apps/ensindexer/drizzle/meta/_journal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"version": "7",
"dialect": "postgresql",
"entries": [
{
"idx": 0,
"version": "7",
"when": 1772604594657,
"tag": "0000_orange_veda",
"breakpoints": true
}
]
}
1 change: 1 addition & 0 deletions apps/ensindexer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"@types/dns-packet": "^5.6.5",
"@types/node": "catalog:",
"@types/pg": "8.16.0",
"drizzle-kit": "0.30.1",
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider using catalog: for drizzle-kit version.

Other dependencies in this file use catalog: for version management. Using a hardcoded version (0.30.1) for drizzle-kit breaks that consistency and may lead to version drift across workspaces.

♻️ Suggested change
-    "drizzle-kit": "0.30.1",
+    "drizzle-kit": "catalog:",

Then add the version to your pnpm catalog configuration.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"drizzle-kit": "0.30.1",
"drizzle-kit": "catalog:",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ensindexer/package.json` at line 50, The dependency entry for
"drizzle-kit" in package.json is pinned to a hardcoded version ("0.30.1");
update the "drizzle-kit" version specifier to use your workspace catalog syntax
(e.g., replace the literal "0.30.1" with the catalog reference used elsewhere)
and then add that version to the pnpm catalog configuration so the workspace
uses the centralized version management; locate the "drizzle-kit" key in the
dependencies section of package.json to make this change.

"typescript": "catalog:",
"vitest": "catalog:"
}
Expand Down
37 changes: 16 additions & 21 deletions apps/ensindexer/src/lib/ensdb-client/ensdb-client.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import { migrate } from "drizzle-orm/node-postgres/migrator";
import { eq, sql } from "drizzle-orm/sql";
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove unused sql import to fix CI failure.

The pipeline reports unused imports. The sql import is no longer used after the upsert refactor.

🧹 Suggested fix
-import { eq, sql } from "drizzle-orm/sql";
+import { eq } from "drizzle-orm/sql";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { eq, sql } from "drizzle-orm/sql";
import { eq } from "drizzle-orm/sql";
🧰 Tools
🪛 GitHub Actions: Test: CI

[warning] 3-14: Unused imports might be the result of an incomplete refactoring.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ensindexer/src/lib/ensdb-client/ensdb-client.ts` at line 3, Remove the
unused `sql` named import from the import statement that currently reads `import
{ eq, sql } from "drizzle-orm/sql";` in ensdb-client.ts; leave only the used
symbol(s) such as `eq` so the file no longer imports `sql`, which will resolve
the CI unused-import failure.


import { ensNodeMetadata } from "@ensnode/ensnode-schema";
import { ensNodeMetadata } from "@ensnode/ensnode-schema/offchain";
import {
Comment on lines +5 to 6
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

ensNodeMetadata is now defined under the offchain schema, but makeDrizzle() still calls setDatabaseSchema(schema, databaseSchemaName) based on the constructor argument. If callers keep passing the on-chain DATABASE_SCHEMA (e.g. ensnode/public), the client will query DATABASE_SCHEMA.ensnode_metadata while migrations create offchain.ensnode_metadata, causing runtime failures. Consider removing the schema monkeypatch for this client (let the table’s own pgSchema("offchain") win) or hardcoding/deriving the offchain schema name separately from the on-chain schema config.

Copilot uses AI. Check for mistakes.
type CrossChainIndexingStatusSnapshot,
deserializeCrossChainIndexingStatusSnapshot,
Expand Down Expand Up @@ -65,6 +66,10 @@ export class EnsDbClient implements EnsDbClientQuery, EnsDbClientMutation {
});
}

async runMigrations(migrationsFolder: string): Promise<void> {
await migrate(this.db, { migrationsFolder });
}
Comment on lines +69 to +71
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

runMigrations() is a new public method on EnsDbClient and is now a required call path from EnsDbWriterWorker, but there’s no unit test asserting it wires through to Drizzle’s migrate() with the provided folder. Since this file already has dedicated unit tests, consider adding a small test that mocks drizzle-orm/node-postgres/migrator and verifies the correct call.

Copilot uses AI. Check for mistakes.

/**
* @inheritdoc
*/
Expand Down Expand Up @@ -176,25 +181,15 @@ export class EnsDbClient implements EnsDbClientQuery, EnsDbClientMutation {
private async upsertEnsNodeMetadata<
EnsNodeMetadataType extends SerializedEnsNodeMetadata = SerializedEnsNodeMetadata,
>(metadata: EnsNodeMetadataType): Promise<void> {
await this.db.transaction(async (tx) => {
// Ponder live-query triggers insert into live_query_tables.
// Because this worker writes outside the Ponder runtime connection pool,
// the temp table must be ensured to exist on this connection. Without this,
// the upsert would fail with "relation 'live_query_tables' does not exist" error.
await tx.execute(
sql`CREATE TEMP TABLE IF NOT EXISTS live_query_tables (table_name TEXT PRIMARY KEY)`,
);

await tx
.insert(ensNodeMetadata)
.values({
key: metadata.key,
value: metadata.value,
})
.onConflictDoUpdate({
target: ensNodeMetadata.key,
set: { value: metadata.value },
});
});
await this.db
.insert(ensNodeMetadata)
.values({
key: metadata.key,
value: metadata.value,
})
.onConflictDoUpdate({
target: ensNodeMetadata.key,
set: { value: metadata.value },
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ describe("EnsDbWriterWorker", () => {

const ensDbClient = {
getEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
runMigrations: vi.fn().mockResolvedValue(undefined),
upsertEnsDbVersion: vi.fn().mockResolvedValue(undefined),
upsertEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
upsertIndexingStatusSnapshot: vi.fn().mockResolvedValue(undefined),
Expand All @@ -79,6 +80,7 @@ describe("EnsDbWriterWorker", () => {
await worker.run();

// assert - verify initial upserts happened
expect(ensDbClient.runMigrations).toHaveBeenCalledTimes(1);
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Assert migration-folder argument, not only call count.

Line 83 only verifies invocation count; it won’t catch an incorrect folder being passed to runMigrations.

Suggested test hardening
-    expect(ensDbClient.runMigrations).toHaveBeenCalledTimes(1);
+    expect(ensDbClient.runMigrations).toHaveBeenCalledTimes(1);
+    expect(ensDbClient.runMigrations).toHaveBeenCalledWith(
+      expect.stringMatching(/(?:\/|\\)drizzle$/),
+    );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
expect(ensDbClient.runMigrations).toHaveBeenCalledTimes(1);
expect(ensDbClient.runMigrations).toHaveBeenCalledTimes(1);
expect(ensDbClient.runMigrations).toHaveBeenCalledWith(
expect.stringMatching(/(?:\/|\\)drizzle$/),
);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ensindexer/src/lib/ensdb-writer-worker/ensdb-writer-worker.test.ts` at
line 83, The test currently only asserts call count for
ensDbClient.runMigrations; update it to also assert the migration-folder
argument is correct by checking the actual call arguments (e.g., use
toHaveBeenCalledWith or toHaveBeenCalledTimes(1) plus
expect(ensDbClient.runMigrations).toHaveBeenCalledWith(expectedMigrationsPath,
...)) — locate the assertion in ensdb-writer-worker.test.ts around the
expect(ensDbClient.runMigrations).toHaveBeenCalledTimes(1) line and replace or
augment it to verify the passed migrations folder value (reference the expected
variable or hard-coded path used by the worker).

expect(ensDbClient.upsertEnsDbVersion).toHaveBeenCalledWith(publicConfig.versionInfo.ensDb);
expect(ensDbClient.upsertEnsIndexerPublicConfig).toHaveBeenCalledWith(publicConfig);

Expand All @@ -99,6 +101,7 @@ describe("EnsDbWriterWorker", () => {

const ensDbClient = {
getEnsIndexerPublicConfig: vi.fn().mockResolvedValue(publicConfig),
runMigrations: vi.fn().mockResolvedValue(undefined),
upsertEnsDbVersion: vi.fn().mockResolvedValue(undefined),
upsertEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
upsertIndexingStatusSnapshot: vi.fn().mockResolvedValue(undefined),
Expand Down Expand Up @@ -148,6 +151,7 @@ describe("EnsDbWriterWorker", () => {

const ensDbClient = {
getEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
runMigrations: vi.fn().mockResolvedValue(undefined),
upsertEnsDbVersion: vi.fn().mockResolvedValue(undefined),
upsertEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
upsertIndexingStatusSnapshot: vi.fn().mockResolvedValue(undefined),
Expand Down Expand Up @@ -196,6 +200,7 @@ describe("EnsDbWriterWorker", () => {

const ensDbClient = {
getEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
runMigrations: vi.fn().mockResolvedValue(undefined),
upsertEnsDbVersion: vi.fn().mockResolvedValue(undefined),
upsertEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
upsertIndexingStatusSnapshot,
Expand Down Expand Up @@ -245,6 +250,7 @@ describe("EnsDbWriterWorker", () => {

const ensDbClient = {
getEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
runMigrations: vi.fn().mockResolvedValue(undefined),
upsertEnsDbVersion: vi.fn().mockResolvedValue(undefined),
upsertEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
upsertIndexingStatusSnapshot: vi.fn().mockResolvedValue(undefined),
Expand Down Expand Up @@ -283,6 +289,7 @@ describe("EnsDbWriterWorker", () => {

const ensDbClient = {
getEnsIndexerPublicConfig: vi.fn().mockResolvedValue(storedConfig),
runMigrations: vi.fn().mockResolvedValue(undefined),
upsertEnsDbVersion: vi.fn().mockResolvedValue(undefined),
upsertEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
upsertIndexingStatusSnapshot: vi.fn().mockResolvedValue(undefined),
Expand Down Expand Up @@ -315,6 +322,7 @@ describe("EnsDbWriterWorker", () => {

const ensDbClient = {
getEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
runMigrations: vi.fn().mockResolvedValue(undefined),
upsertEnsDbVersion: vi.fn().mockResolvedValue(undefined),
upsertEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
upsertIndexingStatusSnapshot: vi.fn().mockResolvedValue(undefined),
Expand Down Expand Up @@ -344,6 +352,7 @@ describe("EnsDbWriterWorker", () => {

const ensDbClient = {
getEnsIndexerPublicConfig: vi.fn().mockRejectedValue(dbError),
runMigrations: vi.fn().mockResolvedValue(undefined),
upsertEnsDbVersion: vi.fn().mockResolvedValue(undefined),
upsertEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
upsertIndexingStatusSnapshot: vi.fn().mockResolvedValue(undefined),
Expand Down Expand Up @@ -399,6 +408,7 @@ describe("EnsDbWriterWorker", () => {

const ensDbClient = {
getEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
runMigrations: vi.fn().mockResolvedValue(undefined),
upsertEnsDbVersion: vi.fn().mockResolvedValue(undefined),
upsertEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
upsertIndexingStatusSnapshot: vi
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { resolve } from "node:path";
import { fileURLToPath } from "node:url";

import { getUnixTime, secondsToMilliseconds } from "date-fns";
import pRetry from "p-retry";

Expand All @@ -21,6 +24,14 @@ import type { IndexingStatusBuilder } from "@/lib/indexing-status-builder/indexi
*/
const INDEXING_STATUS_RECORD_UPDATE_INTERVAL: Duration = 1;

const defaultMigrationsFolder = fileURLToPath(new URL("../../../drizzle", import.meta.url));

const resolveMigrationsFolder = (): string => {
const envValue = process.env.ENSDB_MIGRATIONS_FOLDER;
const migrationsFolder = envValue ? resolve(envValue) : defaultMigrationsFolder;
return migrationsFolder;
};

/**
* ENSDb Writer Worker
*
Expand Down Expand Up @@ -85,6 +96,11 @@ export class EnsDbWriterWorker {
throw new Error("EnsDbWriterWorker is already running");
}

const migrationsFolder = resolveMigrationsFolder();
console.log(`[EnsDbWriterWorker]: Running ENSDb migrations from ${migrationsFolder}...`);
await this.ensDbClient.runMigrations(migrationsFolder);
console.log(`[EnsDbWriterWorker]: ENSDb migrations completed`);

// Fetch data required for task 1 and task 2.
const inMemoryConfig = await this.getValidatedEnsIndexerPublicConfig();

Expand Down
7 changes: 6 additions & 1 deletion packages/ensnode-schema/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"Ponder"
],
"exports": {
".": "./src/ponder.schema.ts"
".": "./src/ponder.schema.ts",
"./offchain": "./src/offchain.schema.ts"
Comment on lines +19 to +20
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the full package.json structure for ensnode-schema
cat packages/ensnode-schema/package.json

Repository: namehash/ensnode

Length of output: 1355


🏁 Script executed:

# Check for tsup configuration
fd -t f 'tsup' packages/ensnode-schema/ --exec cat {}

Repository: namehash/ensnode

Length of output: 388


🏁 Script executed:

# Check if offchain.schema.ts exists
ls -la packages/ensnode-schema/src/ | grep -E '\.ts$'

Repository: namehash/ensnode

Length of output: 191


🏁 Script executed:

# Look for any build configuration in the ensnode-schema directory
ls -la packages/ensnode-schema/

Repository: namehash/ensnode

Length of output: 540


🏁 Script executed:

# Check the content of offchain.schema.ts to understand its purpose
cat packages/ensnode-schema/src/offchain.schema.ts

Repository: namehash/ensnode

Length of output: 110


🏁 Script executed:

# Check if there are any references to offchain in the codebase to understand usage intent
rg "offchain.schema" --type ts --type json

Repository: namehash/ensnode

Length of output: 141


Add offchain.schema.ts to the tsup build configuration and update publishConfig.exports.

The exports field declares ./offchain but tsup is not configured to build it. The tsup.config.ts entry array only includes src/ponder.schema.ts, so dist/offchain.schema.d.ts and dist/offchain.schema.js files will not be generated. Additionally, publishConfig.exports must be updated to declare the offchain entry point for published consumers.

🔧 Suggested fixes

Update tsup.config.ts to include the offchain entry:

export default defineConfig({
- entry: ["src/ponder.schema.ts"],
+ entry: ["src/ponder.schema.ts", "src/offchain.schema.ts"],
  platform: "neutral",

Update publishConfig in package.json to include the offchain export:

  "publishConfig": {
    "access": "public",
    "exports": {
+     ".": {
        "types": "./dist/ponder.schema.d.ts",
        "default": "./dist/ponder.schema.js"
+     },
+     "./offchain": {
+       "types": "./dist/offchain.schema.d.ts",
+       "default": "./dist/offchain.schema.js"
+     }
    },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ensnode-schema/package.json` around lines 19 - 20, The package
exports include "./offchain" but tsup isn't building src/offchain.schema.ts;
update the tsup entry list in tsup.config.ts to include "src/offchain.schema.ts"
alongside "src/ponder.schema.ts" so that dist/offchain.schema.js and
dist/offchain.schema.d.ts are generated, and update package.json's
publishConfig.exports to add an "./offchain" export pointing to the built files
(e.g., the dist/offchain.schema.js and its types) so published consumers can
import the offchain entry.

},
"files": [
"dist"
Expand All @@ -40,9 +41,13 @@
"ponder": "catalog:",
"viem": "catalog:"
},
"peerDependencies": {
"drizzle-orm": "catalog:"
},
"devDependencies": {
"@ensnode/ensnode-sdk": "workspace:",
"@ensnode/shared-configs": "workspace:*",
"drizzle-orm": "catalog:",
"tsup": "catalog:",
"typescript": "catalog:"
}
Expand Down
1 change: 1 addition & 0 deletions packages/ensnode-schema/src/offchain.schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./schemas/ensnode-metadata.schema";
1 change: 0 additions & 1 deletion packages/ensnode-schema/src/ponder.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* Merge the various sub-schemas into a single ponder (drizzle) schema.
*/

export * from "./schemas/ensnode-metadata.schema";
export * from "./schemas/ensv2.schema";
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

Removing the ensnode-metadata export from the main ponder schema breaks existing imports of ensNodeMetadata from @ensnode/ensnode-schema (e.g. apps/ensindexer/src/lib/ensdb-client/ensdb-client.test.ts). Either update all in-repo imports to use @ensnode/ensnode-schema/offchain, or re-export the metadata table from the root entrypoint for backward compatibility while consumers migrate.

Copilot uses AI. Check for mistakes.
export * from "./schemas/protocol-acceleration.schema";
export * from "./schemas/registrars.schema";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
* Schema Definitions that hold metadata about the ENSNode instance.
*/

import { onchainTable } from "ponder";
import { pgSchema } from "drizzle-orm/pg-core";

export const offchainSchema = pgSchema("offchain");

/**
* ENSNode Metadata
Expand All @@ -12,7 +14,7 @@ import { onchainTable } from "ponder";
* - `EnsNodeMetadataEnsIndexerPublicConfig`
* - `EnsNodeMetadataEnsIndexerIndexingStatus`
*/
export const ensNodeMetadata = onchainTable("ensnode_metadata", (t) => ({
export const ensNodeMetadata = offchainSchema.table("ensnode_metadata", (t) => ({
/**
* Key
*
Expand Down
Loading
Loading