Skip to content
Closed
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
49c7deb
Setup drizzle-kit migrations
tk-o Mar 12, 2026
0c65914
Make ENSDb Writer Worker to execute database migrations
tk-o Mar 12, 2026
3a4ebe6
Update tests and mocks for EnsDbWriterWorker
tk-o Mar 12, 2026
b94f93d
Scope `drizzle-kit` as dev dependency to ENSIndexer
tk-o Mar 12, 2026
c5ef04d
docs(changeset): Introduced database migration toolkit based on `driz…
tk-o Mar 12, 2026
20af541
docs(changeset): Extended `EnsDbClient` with `EnsDbMigration` interfa…
tk-o Mar 12, 2026
b235706
docs(changeset): Introduced `EnsDbMigration` interface.
tk-o Mar 12, 2026
a6ea0b9
Update integration tests config
tk-o Mar 12, 2026
a9b1d39
Add unit tests for migration exec task
tk-o Mar 12, 2026
c07ac36
Streamline interface name as `EnsDbClientMigration`
tk-o Mar 12, 2026
1767c4e
Use ENSNode Schema for internal drizzle migration tables
tk-o Mar 12, 2026
e979489
ENSNode GraphQL API: Ergonomic Permissions (#1745)
shrugs Mar 12, 2026
9429530
ENSv2 Plugin Events (#1744)
shrugs Mar 12, 2026
1252713
Revert "Build ENSApi Config with ENSDb Cleint" in order to reduce sco…
tk-o Mar 13, 2026
069f133
Move ENSDb module contents from ENSNode SDK into ENSNode Schema packa…
tk-o Mar 13, 2026
867d643
Create Drizzle utils for future ENSDb SDK
tk-o Mar 13, 2026
0d2ee64
Create `EnsNodeDbReader` class to be shared among ENSNode apps.
tk-o Mar 13, 2026
da33e32
rename topic0 to selector in schema and API (#1760)
shrugs Mar 13, 2026
6b8c42f
Create `EnsNodeDbWriter` to be shared with ENSIndexer app (which is c…
tk-o Mar 13, 2026
b803f50
Improve naming and code docs for ENSIndexer Schema defintions
tk-o Mar 13, 2026
d08743c
Use `EnsNodeDbWriter` in ENSIndexer app
tk-o Mar 13, 2026
f276efe
fix: allow ensv2 apis to be used without ensv2 datasource (#1758)
shrugs Mar 13, 2026
ddda81c
fix(deps): resolve devalue prototype pollution vulnerability (#1765)
shrugs Mar 13, 2026
337ef4b
ENSv2 Permissions & Events Filters Integration Tests (#1761)
shrugs Mar 13, 2026
2d760ee
Create `EnsIndexerDbReader` class to be used among ENSNode apps for u…
tk-o Mar 13, 2026
6c8b6d7
Revert "Update example env file"
tk-o Mar 13, 2026
1be0947
Revert "Update config builder test"
tk-o Mar 13, 2026
7705910
Update EnsNodeDb migrations to match the updated schema
tk-o Mar 13, 2026
16e5660
Integrate `EnsNodeDbWriter` into ENSIndexer app
tk-o Mar 13, 2026
d53f0bf
Update tests and mocks following `EnsDbWriterWorker` integration
tk-o Mar 13, 2026
5297c9c
Remove unused code
tk-o Mar 13, 2026
12359f8
Integrate `EnsIndexerDbReader` into ENSApi`
tk-o Mar 13, 2026
f35edb0
Fix exports for ENSDb Schema definitions
tk-o Mar 13, 2026
79a176d
Revert "Update integration tests config"
tk-o Mar 13, 2026
b4b5b0b
Revert "Apply terraform script updates"
tk-o Mar 13, 2026
cd31c03
fix(deps): resolve undici and yauzl security vulnerabilities (#1768)
shrugs Mar 15, 2026
24f66e7
Merge remote-tracking branch 'origin/main' into feat/ensdb-migrations
tk-o Mar 16, 2026
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
5 changes: 5 additions & 0 deletions .changeset/big-impalas-brush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ensindexer": minor
---

Extended `EnsDbClient` with `EnsDbClientMigration` interface implementation.
Comment on lines +1 to +5
5 changes: 5 additions & 0 deletions .changeset/seven-hands-ask.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@ensnode/ensnode-sdk": minor
---

Introduced `EnsDbClientMigration` interface.
Comment on lines +1 to +5
5 changes: 5 additions & 0 deletions .changeset/silly-bats-smell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ensindexer": minor
---

Introduced database migration toolkit based on `drizzle-kit`.
13 changes: 13 additions & 0 deletions apps/ensindexer/drizzle-kit/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { fileURLToPath } from "node:url";

import { defineConfig } from "drizzle-kit";

// Resolve the path to the database schema file for Drizzle migrations.
const dbSchemaPath = fileURLToPath(new URL("./schema.ts", import.meta.url));

export default defineConfig({
casing: "snake_case",
dialect: "postgresql",
out: `drizzle-kit/migrations`,
schema: dbSchemaPath,
});
8 changes: 8 additions & 0 deletions apps/ensindexer/drizzle-kit/migrations/0000_smiling_prima.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CREATE SCHEMA IF NOT EXISTS ensnode;

CREATE TABLE "ensnode"."ensnode_metadata" (
"ens_indexer_ref" text NOT NULL,
"key" text NOT NULL,
"value" jsonb NOT NULL,
CONSTRAINT "ensnode_metadata_pkey" PRIMARY KEY("ens_indexer_ref","key")
);
55 changes: 55 additions & 0 deletions apps/ensindexer/drizzle-kit/migrations/meta/0000_snapshot.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"id": "d05a87cf-3971-41ac-9eab-a15a54711a47",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
"tables": {
"ensnode.ensnode_metadata": {
"name": "ensnode_metadata",
"schema": "ensnode",
"columns": {
"ens_indexer_ref": {
"name": "ens_indexer_ref",
"type": "text",
"primaryKey": false,
"notNull": true
},
"key": {
"name": "key",
"type": "text",
"primaryKey": false,
"notNull": true
},
"value": {
"name": "value",
"type": "jsonb",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {
"ensnode_metadata_pkey": {
"name": "ensnode_metadata_pkey",
"columns": ["ens_indexer_ref", "key"]
}
},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}
13 changes: 13 additions & 0 deletions apps/ensindexer/drizzle-kit/migrations/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": 1773295356548,
"tag": "0000_smiling_prima",
"breakpoints": true
}
]
}
2 changes: 2 additions & 0 deletions apps/ensindexer/drizzle-kit/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Re-export the ENSNode schema for Drizzle migrations.
export * from "@ensnode/ensnode-schema/ensnode";
4 changes: 3 additions & 1 deletion apps/ensindexer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"test": "vitest",
"lint": "biome check --write .",
"lint:ci": "biome ci",
"typecheck": "tsc --noEmit"
"typecheck": "tsc --noEmit",
"drizzle-gen": "drizzle-kit generate --config ./drizzle-kit/config.ts"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Would it make sense to move this idea into the ensdb-sdk package? Please ignore if not relevant.

@tk-o tk-o Mar 13, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think it's best to keep migrations in an application that has runtime that will eventually execute these migrations.

},
"dependencies": {
"@ensdomains/ensjs": "^4.0.2",
Expand All @@ -47,6 +48,7 @@
"@types/dns-packet": "^5.6.5",
"@types/node": "catalog:",
"@types/pg": "8.16.0",
"drizzle-kit": "0.31.9",
"typescript": "catalog:",
"vitest": "catalog:"
}
Expand Down
16 changes: 14 additions & 2 deletions apps/ensindexer/src/lib/ensdb-client/ensdb-client.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import { and, eq, sql } from "drizzle-orm/sql";
import { migrate } from "drizzle-orm/node-postgres/migrator";
import { and, eq } from "drizzle-orm/sql";

import * as ensNodeSchema from "@ensnode/ensnode-schema/ensnode";
import {
type CrossChainIndexingStatusSnapshot,
deserializeCrossChainIndexingStatusSnapshot,
deserializeEnsIndexerPublicConfig,
type EnsDbClientMigration,
type EnsDbClientMutation,
type EnsDbClientQuery,
type EnsIndexerPublicConfig,
Expand Down Expand Up @@ -38,7 +40,7 @@ interface DrizzleDb extends NodePgDatabase<typeof ensNodeSchema> {}
* - ENSDb version
* - ENSIndexer Public Config, and Indexing Status Snapshot and CrossChainIndexingStatusSnapshot.
*/
export class EnsDbClient implements EnsDbClientQuery, EnsDbClientMutation {
export class EnsDbClient implements EnsDbClientQuery, EnsDbClientMutation, EnsDbClientMigration {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Terminology use here is not aligned.

Is this a client for ALL of ENSDb? My understanding is no. Therefore, why is it called EnsDbClient?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@lightwalker-eth As suggested in this comment, we might rename EnsDbClient to EnsDbClientForEnsNode. Open to other suggestions.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@tk-o Replied in Slack 👍

/**
* Drizzle database instance for ENSDb.
*/
Expand Down Expand Up @@ -191,4 +193,14 @@ export class EnsDbClient implements EnsDbClientQuery, EnsDbClientMutation {
set: { value: metadata.value },
});
}

/**
* @inheritdoc
*/
async migrate(migrationsDirPath: string): Promise<void> {
return migrate(this.db, {
migrationsFolder: migrationsDirPath,
migrationsSchema: ensNodeSchema.ENSNODE_SCHEMA_NAME,
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {

import type { EnsDbClient } from "@/lib/ensdb-client/ensdb-client";
import * as ensDbClientMock from "@/lib/ensdb-client/ensdb-client.mock";
import { EnsDbWriterWorker } from "@/lib/ensdb-writer-worker/ensdb-writer-worker";
import type { IndexingStatusBuilder } from "@/lib/indexing-status-builder";
import type { PublicConfigBuilder } from "@/lib/public-config-builder";

Expand All @@ -23,12 +24,27 @@ export function createMockEnsDbClient(
} as unknown as EnsDbClient;
}

export function createMockEnsDbWriterWorker(
ensDbClient: EnsDbClient,
publicConfigBuilder: PublicConfigBuilder,
indexingStatusBuilder: IndexingStatusBuilder,
migrationsDirPath: string = "/mock/migrations",
) {
return new EnsDbWriterWorker(
ensDbClient,
publicConfigBuilder,
indexingStatusBuilder,
migrationsDirPath,
);
}

export function baseEnsDbClient() {
return {
getEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
upsertEnsDbVersion: vi.fn().mockResolvedValue(undefined),
upsertEnsIndexerPublicConfig: vi.fn().mockResolvedValue(undefined),
upsertIndexingStatusSnapshot: vi.fn().mockResolvedValue(undefined),
migrate: vi.fn().mockResolvedValue(undefined),
};
}

Expand Down
Loading
Loading