Skip to content

replace lazyProxy#1852

Closed
sevenzing wants to merge 0 commit intomainfrom
v1.9-patches
Closed

replace lazyProxy#1852
sevenzing wants to merge 0 commit intomainfrom
v1.9-patches

Conversation

@sevenzing
Copy link
Copy Markdown
Contributor

@sevenzing sevenzing commented Mar 31, 2026

Summary

remove lazyProxy with lazy for drizzle


Why

  • Why this change exists. Link to related GitHub issues where relevant.

Testing

  • How this was tested.
  • If you didn't test it, say why.

Notes for Reviewer (Optional)

  • Anything non-obvious or worth a heads-up.

Pre-Review Checklist (Blocking)

  • This PR does not introduce significant changes and is low-risk to review quickly.
  • Relevant changesets are included (or are not required)

@sevenzing sevenzing requested a review from a team as a code owner March 31, 2026 17:07
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 31, 2026

⚠️ No Changeset found

Latest commit: ab1750c

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

📝 Walkthrough

Walkthrough

This PR refactors database singleton access patterns across the ENS API from lazy property proxies to runtime getter functions. The singleton module now exports getEnsDb() and getEnsIndexerSchema() getter functions instead of ensDb and ensIndexerSchema properties, with new EnsDb and EnsIndexerSchema type aliases added for type-only imports. All 40+ dependent files are updated to call these getters at runtime within function bodies rather than relying on module-level singleton imports.

Changes

Cohort / File(s) Summary
Singleton Module
apps/ensapi/src/lib/ensdb/singleton.ts
Converted ensDb and ensIndexerSchema from lazyProxy properties to lazy getter functions (getEnsDb, getEnsIndexerSchema). Added exported type aliases EnsDb and EnsIndexerSchema for type-only imports.
Test Files
apps/ensapi/src/config/config.singleton.test.ts
Updated imports to destructure getEnsDb and getEnsIndexerSchema instead of singleton instances; changed assertions to verify getter function existence.
Find-Domains Utilities
apps/ensapi/src/graphql-api/lib/find-domains/*
Updated canonical-registries-cte, find-domains-resolver, and layer files (base-domain-set, filter-by-*, with-ordering-metadata) to call getters at runtime within function bodies.
Canonical Path & Domain Resolution
apps/ensapi/src/graphql-api/lib/get-canonical-path.ts, get-domain-by-interpreted-name.ts, get-domain-resolver.ts, get-latest-registration.ts
Introduced per-function ensDb/ensIndexerSchema initialization via getter calls before executing database queries.
Find-Events Resolver
apps/ensapi/src/graphql-api/lib/find-events/find-events-resolver.ts
Replaced singleton imports with getters; updated EventJoinTable type derivation from typeof ensIndexerSchema to EnsIndexerSchema type reference; added local variable initialization in eventsWhereConditions and resolveFindEvents.
GraphQL Schema Loaders & Resolvers
apps/ensapi/src/graphql-api/schema/query.ts, domain.ts, account.ts, registration.ts, resolver.ts, registry.ts, event.ts, renewal.ts, resolver-records.ts, permissions.ts
Updated load functions and field resolvers to fetch ensDb/ensIndexerSchema via getters at execution time; converted concise arrow functions to block bodies for local variable binding.
GraphQL Schema Type References
apps/ensapi/src/graphql-api/schema/label.ts, registry-permissions-user.ts, resolver-permissions-user.ts
Updated builder.objectRef generic type arguments from typeof ensIndexerSchema.<table>.$inferSelect to EnsIndexerSchema["<table>"]["$inferSelect"]; changed type imports to use EnsIndexerSchema.
Analytics & Utilities
apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/database*.ts, name-tokens/find-name-tokens-for-domain.ts, protocol-acceleration/...ts, registrar-actions/find-registrar-actions.ts
Added runtime getter calls for ensDb/ensIndexerSchema within function bodies; updated type annotations from singleton instance references to EnsIndexerSchema type references.
Handlers
apps/ensapi/src/handlers/subgraph/subgraph-api.ts
Replaced module-level ensIndexerSchema import with getEnsIndexerSchema() call; moved schema filtering inside lazy middleware factory to defer initialization.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Poem

🐰 Getters now hop at runtime's call,
No more singletons at import's thrall,
Each function fresh, a DB delight,
Lazy loading done just right!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is incomplete, with only a summary line ('remove lazyProxy with lazy for drizzle') and empty placeholders for Why and Testing sections, failing to meet template requirements. Complete the description by filling in the Why, Testing, and Notes sections with relevant details, context, linked issues, and testing approach as required by the repository template.
Title check ❓ Inconclusive The title 'replace lazyProxy' is vague and generic, using a non-descriptive term that doesn't convey meaningful information about what this change accomplishes or its impact. Revise the title to be more specific and informative, such as 'Replace lazyProxy with lazy getter functions for database access' to clarify the purpose and scope of the change.
✅ Passed checks (1 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 88.46% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch v1.9-patches

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Mar 31, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
admin.ensnode.io Ready Ready Preview, Comment Mar 31, 2026 5:26pm
ensnode.io Ready Ready Preview, Comment Mar 31, 2026 5:26pm
ensrainbow.io Ready Ready Preview, Comment Mar 31, 2026 5:26pm

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 31, 2026

Greptile Summary

This PR replaces lazyProxy-wrapped ensDb and ensIndexerSchema module-level exports with lazy getter functions (getEnsDb() / getEnsIndexerSchema()) throughout the ensapi application. The motivation is that Drizzle ORM relies heavily on object introspection (symbol iteration, Object.keys, property descriptors) that a JavaScript Proxy cannot transparently forward, causing subtle runtime failures when Drizzle objects were wrapped in lazyProxy.

Key changes:

  • singleton.ts now exports getEnsDb and getEnsIndexerSchema (lazy-cached getter functions) instead of ensDb/ensIndexerSchema proxy objects; ensDbClient still correctly uses lazyProxy as it is not a Drizzle object.
  • EnsDb and EnsIndexerSchema type aliases are added to singleton.ts for clean type-only imports, replacing the previous pattern of typeof ensIndexerSchema.x.$inferSelect.
  • All 35+ call sites are updated to call getEnsDb() / getEnsIndexerSchema() at the top of their functions (never at module level), preserving the deferred-initialization guarantee that prevents crashes during OpenAPI schema generation when env vars are absent.
  • In subgraph-api.ts, filterSchemaByPrefix(\"subgraph_\", ensIndexerSchema) was moved from module level into the lazy() factory, ensuring the real (non-proxy) schema is passed to subgraphGraphQLMiddleware.
  • The test for getEnsDb/getEnsIndexerSchema is intentionally weakened to only assert the functions are exported (not called), avoiding a real DB connection attempt at test time.

Confidence Score: 5/5

Safe to merge — the refactor is mechanically consistent across all call sites and correctly addresses a known Drizzle-Proxy incompatibility.

No logic bugs, data-loss risks, or security concerns found. Every consumer has been updated from the module-level proxy pattern to the function-call pattern at request/invocation time. The lazy caching in the lazy() helper ensures no redundant DB initialization on repeated calls. All remaining observations are P2 style-level.

No files require special attention — the refactor is uniform and low-risk.

Important Files Changed

Filename Overview
apps/ensapi/src/lib/ensdb/singleton.ts Core change: replaces lazyProxy-wrapped ensDb/ensIndexerSchema with lazy getter functions (getEnsDb/getEnsIndexerSchema) and exports EnsDb/EnsIndexerSchema type aliases; ensDbClient still correctly uses lazyProxy
apps/ensapi/src/handlers/subgraph/subgraph-api.ts Moves filterSchemaByPrefix() call from module level into the lazy factory, ensuring getEnsIndexerSchema() is never called at import time and the real (non-proxy) schema object is passed to Drizzle introspection
apps/ensapi/src/config/config.singleton.test.ts Test updated to only verify exports exist (not call them), with a comment explaining that calling getEnsDb/getEnsIndexerSchema would trigger a real DB connection; slightly weaker coverage but justified
apps/ensapi/src/graphql-api/lib/find-events/find-events-resolver.ts EventJoinTable union type updated to use EnsIndexerSchema indexed access (semantically equivalent); getEnsIndexerSchema() called at top of eventsWhereConditions before the early-return guard
apps/ensapi/src/lib/registrar-actions/find-registrar-actions.ts getEnsIndexerSchema() moved into buildOrderByClause/buildWhereClause helpers and getEnsDb() into _countRegistrarActions/_findRegistrarActions; all at function scope, correct

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    ENV[Environment Variables] --> ensDbClient
    ensDbClient["ensDbClient - lazyProxy wrapping EnsDbReader"] --> getEnsDb
    ensDbClient --> getEnsIndexerSchema
    getEnsDb["getEnsDb - lazy getter function"] --> Queries["DB Queries - GraphQL resolvers, finders, analytics"]
    getEnsIndexerSchema["getEnsIndexerSchema - lazy getter function"] --> Schema["Schema References - type-safe column access"]

    subgraph Before
        B1["ensDb = lazyProxy(...)"] --> B2["Drizzle introspection fails - Proxy intercepts symbols and keys"]
    end

    subgraph After
        A1["getEnsDb = lazy(...)"] --> A2["Real Drizzle object - introspection works correctly"]
    end
Loading

Reviews (1): Last reviewed commit: "replace lazyProxy" | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/ensapi/src/config/config.singleton.test.ts`:
- Line 25: Update the stale test comments that call ensDbClient a "lazyProxy" to
reflect the current design: describe these exports (ensDbClient, getEnsDb,
getEnsIndexerSchema) as lazy getter exports or lazy exports instead of
"lazyProxy"; locate the comments adjacent to the import line for
ensDbClient/getEnsDb/getEnsIndexerSchema and the comment block covering lines
~30-33 and replace wording so it consistently refers to "lazy getter exports"
(or equivalent) to match the PR migration language.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 16daed26-ba13-483c-82ed-5fb774b0dda8

📥 Commits

Reviewing files that changed from the base of the PR and between ab1750c and dbfdc6c.

📒 Files selected for processing (37)
  • apps/ensapi/src/config/config.singleton.test.ts
  • apps/ensapi/src/graphql-api/lib/find-domains/canonical-registries-cte.ts
  • apps/ensapi/src/graphql-api/lib/find-domains/find-domains-resolver.ts
  • apps/ensapi/src/graphql-api/lib/find-domains/layers/base-domain-set.ts
  • apps/ensapi/src/graphql-api/lib/find-domains/layers/filter-by-canonical.ts
  • apps/ensapi/src/graphql-api/lib/find-domains/layers/filter-by-name.ts
  • apps/ensapi/src/graphql-api/lib/find-domains/layers/filter-by-owner.ts
  • apps/ensapi/src/graphql-api/lib/find-domains/layers/filter-by-parent.ts
  • apps/ensapi/src/graphql-api/lib/find-domains/layers/filter-by-registry.ts
  • apps/ensapi/src/graphql-api/lib/find-domains/layers/with-ordering-metadata.ts
  • apps/ensapi/src/graphql-api/lib/find-events/find-events-resolver.ts
  • apps/ensapi/src/graphql-api/lib/get-canonical-path.ts
  • apps/ensapi/src/graphql-api/lib/get-domain-by-interpreted-name.ts
  • apps/ensapi/src/graphql-api/lib/get-domain-resolver.ts
  • apps/ensapi/src/graphql-api/lib/get-latest-registration.ts
  • apps/ensapi/src/graphql-api/schema/account.ts
  • apps/ensapi/src/graphql-api/schema/domain.ts
  • apps/ensapi/src/graphql-api/schema/event.ts
  • apps/ensapi/src/graphql-api/schema/label.ts
  • apps/ensapi/src/graphql-api/schema/permissions.ts
  • apps/ensapi/src/graphql-api/schema/query.ts
  • apps/ensapi/src/graphql-api/schema/registration.ts
  • apps/ensapi/src/graphql-api/schema/registry-permissions-user.ts
  • apps/ensapi/src/graphql-api/schema/registry.ts
  • apps/ensapi/src/graphql-api/schema/renewal.ts
  • apps/ensapi/src/graphql-api/schema/resolver-permissions-user.ts
  • apps/ensapi/src/graphql-api/schema/resolver-records.ts
  • apps/ensapi/src/graphql-api/schema/resolver.ts
  • apps/ensapi/src/handlers/subgraph/subgraph-api.ts
  • apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/database-v1.ts
  • apps/ensapi/src/lib/ensanalytics/referrer-leaderboard/database.ts
  • apps/ensapi/src/lib/ensdb/singleton.ts
  • apps/ensapi/src/lib/name-tokens/find-name-tokens-for-domain.ts
  • apps/ensapi/src/lib/protocol-acceleration/find-resolver.ts
  • apps/ensapi/src/lib/protocol-acceleration/get-primary-name-from-index.ts
  • apps/ensapi/src/lib/protocol-acceleration/get-records-from-index.ts
  • apps/ensapi/src/lib/registrar-actions/find-registrar-actions.ts


it("constructs EnsDbReader from real env wiring without errors", async () => {
const { ensDbClient, ensDb, ensIndexerSchema } = await import("@/lib/ensdb/singleton");
const { ensDbClient, getEnsDb, getEnsIndexerSchema } = await import("@/lib/ensdb/singleton");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Update stale lazyProxy terminology in adjacent test comments.

This block now verifies lazy getter exports, but nearby comments still describe ensDbClient as lazyProxy, which conflicts with the PR’s migration language and makes intent harder to follow.

✏️ Suggested comment cleanup
-    // ensDbClient is a lazyProxy — construction is deferred until first property access.
+    // ensDbClient is lazily initialized — construction is deferred until first property access.
@@
-    // ensDbClient is a lazyProxy — import succeeds but first property access triggers construction,
+    // ensDbClient is lazily initialized — import succeeds but first property access triggers construction,
@@
-    // ensDbClient is a lazyProxy — import succeeds but first property access triggers construction,
+    // ensDbClient is lazily initialized — import succeeds but first property access triggers construction,

Also applies to: 30-33

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

In `@apps/ensapi/src/config/config.singleton.test.ts` at line 25, Update the stale
test comments that call ensDbClient a "lazyProxy" to reflect the current design:
describe these exports (ensDbClient, getEnsDb, getEnsIndexerSchema) as lazy
getter exports or lazy exports instead of "lazyProxy"; locate the comments
adjacent to the import line for ensDbClient/getEnsDb/getEnsIndexerSchema and the
comment block covering lines ~30-33 and replace wording so it consistently
refers to "lazy getter exports" (or equivalent) to match the PR migration
language.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant