Skip to content

refactor: use zod-openapi for ensanalytics-api#1685

Merged
notrab merged 3 commits intomainfrom
zod-openapi-ensanalytics-api
Feb 26, 2026
Merged

refactor: use zod-openapi for ensanalytics-api#1685
notrab merged 3 commits intomainfrom
zod-openapi-ensanalytics-api

Conversation

@notrab
Copy link
Member

@notrab notrab commented Feb 26, 2026

Lite PR

Tip: Review docs on the ENSNode PR process

Summary

Migrate ensanalytics-api to @hono/zod-openapi route definitions.


Why

Consistent with the pattern established across other migrated routes (ensnode-api, amirealtime-api, resolution-api), enabling OpenAPI spec generation from route definitions without runtime dependencies.


Testing

  • All 6 existing tests pass with no changes to assertions or expected behaviour.
  • Typecheck and lint pass.
  • No handler logic or response text was changed
  • Refactoring only.

Notes for Reviewer (Optional)

  • Test file updated to replace testClient(app) with app.request(). OpenAPIHono's app.openapi() doesn't produce the chained route types that testClient needs for type inference. The app.request() pattern is already used by amirealtime-api.test.ts and by the /referrers/:referrer tests in this same file.

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)

@notrab notrab requested a review from a team as a code owner February 26, 2026 07:04
Copilot AI review requested due to automatic review settings February 26, 2026 07:04
@vercel
Copy link
Contributor

vercel bot commented Feb 26, 2026

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

3 Skipped Deployments
Project Deployment Actions Updated (UTC)
admin.ensnode.io Skipped Skipped Feb 26, 2026 8:09am
ensnode.io Skipped Skipped Feb 26, 2026 8:09am
ensrainbow.io Skipped Skipped Feb 26, 2026 8:09am

@changeset-bot
Copy link

changeset-bot bot commented Feb 26, 2026

⚠️ No Changeset found

Latest commit: 1e1f7b1

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
Contributor

coderabbitai bot commented Feb 26, 2026

📝 Walkthrough

Walkthrough

Introduces a new ENS Analytics API routes module defining paginated referrer leaderboard and detail endpoints. Refactors the handler from inline route definitions to a createApp-based approach using external route descriptors. Updates tests to use direct HTTP requests. Registers the new routes in the route groups.

Changes

Cohort / File(s) Summary
ENS Analytics Routes Definition
apps/ensapi/src/handlers/ensanalytics-api.routes.ts
New module defining OpenAPI route configurations for referrer leaderboard and detail endpoints with pagination and validation schemas (page, recordsPerPage, referrer address). Exports basePath, route descriptors, and routes array.
Handler Refactoring
apps/ensapi/src/handlers/ensanalytics-api.ts
Refactored from factory-based route setup to createApp-based approach with app.openapi registration. Moved validation schemas and route definitions to external routes module. Introduced global middleware via app.use() and consolidated error handling with 503 response for missing cached data.
Test Updates
apps/ensapi/src/handlers/ensanalytics-api.test.ts
Replaced testClient usage with direct HTTP requests via app.request(). Updated page fetch logic to use HTTP responses and deserialize via deserializeReferrerLeaderboardPageResponse().
Route Registration
apps/ensapi/src/stub-routes.ts
Added ensanalyticsRoutes import and registered it in the routeGroups array for OpenAPI generation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 Routes now dance in files so clean,
Where schemas gleam and paths convene,
No more inline, but centered ways,
The openapi refactor plays!
bounce bounce 🎉

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: migrating ensanalytics-api to use zod-openapi, which is the central refactoring effort across all modified files.
Description check ✅ Passed The description follows the template with all required sections completed: Summary, Why, Testing, Notes for Reviewer, and Pre-Review Checklist. Each section is filled with relevant and specific information.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% 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 (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch zod-openapi-ensanalytics-api

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.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR migrates the ensanalytics-api routes to use @hono/zod-openapi for route definitions, aligning with the pattern already established in ensnode-api, amirealtime-api, and resolution-api. This enables OpenAPI spec generation from route definitions without runtime dependencies.

Changes:

  • Created new ensanalytics-api.routes.ts with zod-openapi route definitions
  • Refactored ensanalytics-api.ts to use createApp() and app.openapi() pattern
  • Updated tests to use app.request() instead of testClient() for compatibility with OpenAPIHono

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
apps/ensapi/src/handlers/ensanalytics-api.routes.ts New file defining OpenAPI routes for referrer leaderboard and detail endpoints using createRoute and zod schemas
apps/ensapi/src/handlers/ensanalytics-api.ts Migrated from factory.createApp() to createApp(), replaced route decorators with app.openapi() calls, imported route definitions from routes file
apps/ensapi/src/handlers/ensanalytics-api.test.ts Updated test calls from testClient(app) pattern to app.request() for OpenAPIHono compatibility
apps/ensapi/src/stub-routes.ts Added ensanalytics routes to the route groups for OpenAPI spec generation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 26, 2026

Greptile Summary

Migrated ensanalytics-api to use @hono/zod-openapi route definitions, following the pattern from previously migrated APIs.

  • Separated route definitions into ensanalytics-api.routes.ts with proper validation schemas for query parameters and path parameters
  • Replaced hono-openapi's describeRoute and validate with @hono/zod-openapi's createRoute and app.openapi()
  • Updated tests from testClient() to app.request() pattern for OpenAPIHono compatibility (matches amirealtime-api.test.ts pattern)
  • Added routes to stub-routes.ts for OpenAPI spec generation
  • All handler logic, error handling, and test assertions remain unchanged

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk - it's a clean refactoring with no logic changes
  • All tests pass with no changes to assertions, handler logic is completely preserved, the migration follows the established pattern from other APIs, and validation/error handling remain functionally equivalent
  • No files require special attention

Important Files Changed

Filename Overview
apps/ensapi/src/handlers/ensanalytics-api.routes.ts New file defining OpenAPI routes with proper validation schemas for pagination and referrer address parameters
apps/ensapi/src/handlers/ensanalytics-api.ts Migrated from hono-openapi to @hono/zod-openapi, handler logic unchanged, uses app.openapi() with route definitions
apps/ensapi/src/handlers/ensanalytics-api.test.ts Updated from testClient() to app.request() for OpenAPIHono compatibility, all test assertions preserved
apps/ensapi/src/stub-routes.ts Added ensanalytics routes to stub routes array for OpenAPI spec generation

Last reviewed commit: 037d942

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

4 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

Copy link
Member

@lightwalker-eth lightwalker-eth left a comment

Choose a reason for hiding this comment

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

@notrab Also looks good, thanks 👍

@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io February 26, 2026 08:08 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io February 26, 2026 08:08 Inactive
@vercel vercel bot temporarily deployed to Preview – ensnode.io February 26, 2026 08:08 Inactive
Copilot AI review requested due to automatic review settings February 26, 2026 08:08
@vercel vercel bot temporarily deployed to Preview – ensnode.io February 26, 2026 08:09 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io February 26, 2026 08:09 Inactive
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io February 26, 2026 08:09 Inactive
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
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/handlers/ensanalytics-api.routes.ts`:
- Around line 42-49: The OpenAPI responses for the two route descriptors with
validated inputs are missing a 400 validation response; update the responses
objects in ensanalytics-api.routes.ts (the route descriptors that define
validated inputs around the referrer leaderboard and the other validated route)
to include a 400 entry that maps validation errors to a body shape like {
message, details } and mentions ZodError/standard schema validation, so
generated docs include validation error responses for both routes.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f492ef8 and 1e1f7b1.

📒 Files selected for processing (4)
  • apps/ensapi/src/handlers/ensanalytics-api.routes.ts
  • apps/ensapi/src/handlers/ensanalytics-api.test.ts
  • apps/ensapi/src/handlers/ensanalytics-api.ts
  • apps/ensapi/src/stub-routes.ts

Comment on lines +42 to +49
responses: {
200: {
description: "Successfully retrieved referrer leaderboard page",
},
500: {
description: "Internal server error",
},
},
Copy link
Contributor

@coderabbitai coderabbitai bot Feb 26, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Document 400 validation responses in both route descriptors.

Line 40 and Line 59 define validated inputs, but the responses blocks don’t include 400. This makes generated OpenAPI incomplete for client/error handling.

🛠️ Proposed update
 export const getReferrerLeaderboardRoute = createRoute({
@@
   responses: {
       description: "Successfully retrieved referrer leaderboard page",
     },
+    400: {
+      description: "Invalid query parameters",
+    },
       description: "Internal server error",
     },
   },
 });
@@
 export const getReferrerDetailRoute = createRoute({
@@
   responses: {
       description: "Successfully retrieved referrer detail",
     },
+    400: {
+      description: "Invalid referrer address parameter",
+    },
       description: "Internal server error",
     },
       description: "Service unavailable - referrer leaderboard data not yet cached",

As per coding guidelines: "Map errors to response codes: validation errors (ZodError/Standard Schema) → 400 with { message, details }."

Also applies to: 61-71

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

In `@apps/ensapi/src/handlers/ensanalytics-api.routes.ts` around lines 42 - 49,
The OpenAPI responses for the two route descriptors with validated inputs are
missing a 400 validation response; update the responses objects in
ensanalytics-api.routes.ts (the route descriptors that define validated inputs
around the referrer leaderboard and the other validated route) to include a 400
entry that maps validation errors to a body shape like { message, details } and
mentions ZodError/standard schema validation, so generated docs include
validation error responses for both routes.

Copy link
Member Author

Choose a reason for hiding this comment

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

@coderabbitai this was already the behaviour in the current API. We should follow up with a feature request for this.

Copy link
Contributor

Choose a reason for hiding this comment

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

@notrab, that makes sense — since this PR maintains existing behavior, we can defer the 400 response documentation improvement. Would you like me to open a GitHub issue to track adding 400 validation error responses to the OpenAPI route descriptors for ensanalytics-api (and potentially other migrated routes)?


🧠 Learnings used
Learnt from: CR
Repo: namehash/ensnode PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-22T20:37:05.869Z
Learning: Applies to apps/{ensapi,ensadmin,ensrainbow,fallback-ensapi}/**/*.{ts,tsx} : Use existing Hono validation middleware (Zod schemas + `validate()` from `apps/ensapi/src/lib/handlers/validate.ts`) for API request validation instead of manually calling `zod.parse`/`safeParse` in route handlers

Learnt from: CR
Repo: namehash/ensnode PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-22T20:37:05.869Z
Learning: Applies to apps/{ensapi,ensadmin,ensrainbow,fallback-ensapi}/**/*.{ts,tsx} : Map errors to response codes: validation errors (ZodError/Standard Schema) → 400 with `{ message, details }`; known client errors → 4xx with `{ message }`; server errors → 500 with `{ message }`

Learnt from: CR
Repo: namehash/ensnode PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-22T20:37:05.869Z
Learning: Applies to apps/{ensapi,ensadmin,ensrainbow,fallback-ensapi}/**/*.{ts,tsx} : Use response shape `{ message: string, details?: unknown }` for API errors; do not add a `code` field inconsistently (may be adopted project-wide later)

Learnt from: CR
Repo: namehash/ensnode PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-02-22T20:37:05.869Z
Learning: Applies to apps/{ensapi,ensadmin,ensrainbow,fallback-ensapi}/**/*.{ts,tsx} : Use the shared `errorResponse` helper from `apps/ensapi/src/lib/handlers/error-response.ts` for all error responses in ENSApi and apply equivalent patterns in other Hono apps

Learnt from: notrab
Repo: namehash/ensnode PR: 1673
File: apps/ensapi/src/handlers/registrar-actions-api.ts:102-115
Timestamp: 2026-02-25T07:04:48.803Z
Learning: The registrar-actions-api endpoint (apps/ensapi/src/handlers/registrar-actions-api.ts) uses `serializeRegistrarActionsResponse` with `RegistrarActionsResponseError` and includes a `responseCode` field. This differs from the standard ENSApi `errorResponse` helper pattern to maintain backward compatibility and avoid breaking the established API contract.

Learnt from: notrab
Repo: namehash/ensnode PR: 1661
File: apps/ensapi/src/handlers/amirealtime-api.ts:41-45
Timestamp: 2026-02-22T09:10:50.106Z
Learning: In the ensnode/ensapi project, prefer consistency with existing codebase patterns for c.json() calls; explicit status codes (e.g., c.json(payload, 200)) are not required when the default behavior (200) is already consistent across the codebase.

Learnt from: notrab
Repo: namehash/ensnode PR: 1631
File: apps/ensapi/src/handlers/ensnode-api.ts:23-27
Timestamp: 2026-02-18T16:11:00.691Z
Learning: Dynamic imports inside request handlers can be acceptable if used judiciously, but they introduce asynchronous loading and potential variability in startup latency. This pattern should be reviewed on a per-file basis: prefer top-level imports for commonly used modules and reserve dynamic import for conditional loading or rare code paths. If you continue to use dynamic imports in ensnode-api.ts, ensure you profile startup and per-request latency, verify error handling for promise rejections, and document the reasoning for caching behavior.

Learnt from: Goader
Repo: namehash/ensnode PR: 1663
File: packages/ens-referrals/src/v1/award-models/rev-share-limit/metrics.ts:74-96
Timestamp: 2026-02-24T15:53:06.633Z
Learning: In TypeScript code reviews, prefer placing invariants on type aliases only when the invariant is context-independent or reused across multiple fields. If an invariant depends on surrounding rules or object semantics (e.g., field-specific metrics), keep the invariant as a field JSDoc instead. This guideline applies to TS files broadly (e.g., the repo's v1/award-models and similar modules).

@notrab notrab merged commit b936c67 into main Feb 26, 2026
19 of 20 checks passed
@notrab notrab deleted the zod-openapi-ensanalytics-api branch February 26, 2026 08:24
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.

3 participants