-
Notifications
You must be signed in to change notification settings - Fork 15
feat(docs): OpenAPI spec sync with CI validation and PR previews #1550
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 5d563ea The changes in this PR will be included in the next version bump. This PR includes changesets to release 18 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR introduces automated OpenAPI specification generation and documentation for ENSApi. It adds CI infrastructure for generating specs via mock config mode, updates documentation to serve the generated spec, integrates Mintlify rebuild automation, and removes deprecated ENSAnalytics v1 routes. Changes
Sequence DiagramsequenceDiagram
participant CI as GitHub Actions CI
participant Bash as generate_openapi_spec.sh
participant Server as ENSApi Server<br/>(OPENAPI_GENERATE_MODE=true)
participant TS as TypeScript Generation Script
participant Docs as Documentation System
CI->>Bash: Trigger spec generation
Bash->>Server: Start ENSApi in generate mode
activate Server
Bash->>Bash: Poll /openapi.json until ready
Bash->>Server: GET /openapi.json
Server-->>Bash: OpenAPI spec (middleware allows)
deactivate Server
Bash->>TS: Execute generation command
TS->>TS: Fetch & validate spec
TS->>TS: Format with Biome
TS-->>Bash: Write openapi.json
alt --check mode
Bash->>Bash: Compare with committed spec
Bash-->>CI: Pass/Fail validation
end
Bash->>Docs: Spec available for documentation
Docs->>Docs: Render API reference from spec
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this 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 adds OpenAPI specification generation and documentation capabilities to the ENSNode project. It introduces a script to fetch and save the OpenAPI spec from a running ENSApi instance, integrates it with Mintlify documentation, and adds CI checks to ensure the spec stays in sync with production.
Changes:
- Added a 5,106-line OpenAPI specification file documenting all ENSApi endpoints
- Created a generation script to fetch and update the spec from a running instance
- Configured Mintlify docs to reference both production and local OpenAPI specs
- Added CI workflow to validate spec synchronization on the main branch
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/docs.ensnode.io/openapi.json | Complete OpenAPI 3.1.0 specification documenting all ENSApi endpoints including resolution, meta, explore, and ENSAwards APIs |
| apps/ensapi/scripts/generate-openapi.ts | TypeScript script to fetch OpenAPI spec from running instance and save to docs directory |
| apps/ensapi/package.json | Added npm script openapi:generate to run the generation script |
| docs/docs.ensnode.io/docs.json | Updated configuration to reference production API spec and added hidden preview section for local spec |
| .github/workflows/test_ci.yml | Added CI job to verify OpenAPI spec stays in sync with production on main branch |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🤖 Fix all issues with AI agents
In @.github/workflows/test_ci.yml:
- Around line 51-55: The openapi-sync-check job currently only runs when
github.ref == 'refs/heads/main', which lets PRs merge with out-of-sync specs;
update the condition on the openapi-sync-check job (the if: line) to also run
for pull requests (e.g., include github.event_name == 'pull_request' or
github.head_ref checks) and mark it non-blocking for PRs by using
continue-on-error: true (or alternatively remove the if entirely and rely on
branch protection or add contributor documentation). Target the job named
openapi-sync-check and the existing if: github.ref == 'refs/heads/main'
condition when making the change.
In `@apps/ensapi/scripts/generate-openapi.ts`:
- Around line 23-24: ensapiUrl may end with a trailing slash causing openapiUrl
to become "//openapi.json"; normalize ensapiUrl before composing openapiUrl (the
variables to change are ensapiUrl and openapiUrl in generate-openapi.ts) by
trimming any trailing '/' from ensapiUrl (or using a URL-safe join) so
openapiUrl is built as `${normalizedEnsapiUrl}/openapi.json` even when
ENSAPI_URL or process.argv[2] includes a trailing slash; ensure
DEFAULT_ENSAPI_URL remains fallback and normalization runs after selecting the
value.
- Line 12: Update the header comment string that reads "Writes openapi.json to
the docs directory for Mintilify" and correct the product name typo to
"Mintlify" so the comment reads "Writes openapi.json to the docs directory for
Mintlify"; locate this exact comment text in generate-openapi.ts and make the
single-word change.
- Around line 28-33: Add a timeout to the fetch in generate-openapi.ts by
creating an AbortSignal via AbortSignal.timeout(ms) and passing it as the signal
option to the fetch(openapiUrl) call; handle the abort case by catching the
thrown error (check for AbortError or error.name === 'AbortError') and log a
clear timeout message before exiting, and ensure the existing non-ok response
handling remains unchanged.
In `@docs/docs.ensnode.io/docs.json`:
- Around line 29-34: The docs.json "Preview" group references a non-existent
page "ensapi/preview"; fix by either adding a new page file named preview.mdx
under the docs/docs.ensnode.io/ensapi/ folder (so the path matches
"ensapi/preview") or remove the entire Preview group entry (the object with
"group": "Preview", "pages": ["ensapi/preview"], "openapi": "./openapi.json",
"hidden": true) from docs.json; update whichever you choose and ensure the
"pages" array references only existing MDX/MD files.
There was a problem hiding this 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
🤖 Fix all issues with AI agents
In @.github/workflows/test_ci.yml:
- Around line 58-70: The CI step runs the openapi:generate npm script which
currently relies on a hardcoded production default; make the behavior explicit
by passing the production URL via the ENSAPI_URL env in the workflow step or by
updating the openapi:generate script to accept an ENSAPI_URL argument and
default it to https://api.alpha.ensnode.io; update the step that invokes
openapi:generate to export ENSAPI_URL or call the script with the URL so the
action is explicit and maintainable.
There was a problem hiding this 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 5 out of 6 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: lightwalker.eth <126201998+lightwalker-eth@users.noreply.github.com>
There was a problem hiding this 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 15 out of 17 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this 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 18 out of 20 changed files in this pull request and generated 3 comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // use ENSAnalytics API at /ensanalytics | ||
| app.route("/ensanalytics", ensanalyticsApi); | ||
|
|
||
| // use ENSAnalytics API v1 at /v1/ensanalytics | ||
| app.route("/v1/ensanalytics", ensanalyticsApiV1); | ||
|
|
||
| // use Am I Realtime API at /amirealtime | ||
| app.route("/amirealtime", amIRealtimeApi); |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change removes the /v1/ensanalytics route (and the corresponding V1 cache shutdown) even though the repo still contains ensanalytics-api-v1.ts and V1 middleware/cache code. If this isn’t an intentional breaking API change, please restore the route (and graceful shutdown for the V1 cache) or remove the unused V1 implementation/tests in a dedicated PR and document the deprecation.
|
|
||
| # Start ENSApi in background | ||
| cd "$REPO_ROOT" | ||
| OPENAPI_GENERATE_MODE=true pnpm --filter ensapi start & |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ENSAPI_PORT is documented as configurable, but the script never passes it through to the ENSApi process (via PORT). In OPENAPI_GENERATE_MODE, ENSApi will start on its default port, so setting ENSAPI_PORT will cause the readiness curl and generator to target the wrong port. Pass PORT=$ENSAPI_PORT (or set ENSAPI_PORT to also export PORT) when starting ENSApi.
| OPENAPI_GENERATE_MODE=true pnpm --filter ensapi start & | |
| PORT="$ENSAPI_PORT" OPENAPI_GENERATE_MODE=true pnpm --filter ensapi start & |
|
|
||
| const OUTPUT_PATH = resolve(import.meta.dirname, "../openapi.json"); |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import.meta.dirname is not a standard Node.js import.meta property, so this path resolution is likely to throw at runtime under Node/tsx. Use import.meta.url + fileURLToPath/new URL() (or equivalent) to build an absolute path to ../openapi.json instead.
| const OUTPUT_PATH = resolve(import.meta.dirname, "../openapi.json"); | |
| import { fileURLToPath } from "node:url"; | |
| const OUTPUT_PATH = fileURLToPath(new URL("../openapi.json", import.meta.url)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/ensapi/src/config/config.schema.ts (1)
130-141: 🧹 Nitpick | 🔵 TrivialNormal path doesn't explicitly set
inOpenApiGenerateMode.This is fine since the schema has
.default(false), but for readability and explicitness, consider addinginOpenApiGenerateMode: falseto the normal config parse input. This makes it immediately clear to readers that the normal path never enables generate mode, without needing to trace back to the schema definition.
🤖 Fix all issues with AI agents
In @.github/scripts/generate_openapi_spec.sh:
- Around line 23-32: The for-loop iterating over "$@" uses shift (inside the
block handling --check) which is misleading because the for-loop snapshot isn't
affected; remove the shift or convert the loop to a proper while/shift pattern.
Specifically, either delete the shift line inside the case that sets
CHECK_MODE=true (leaving the for arg in "$@" intact and no positional
consumption), or replace the "for arg in \"$@\"; do ... done" with a "while [ $#
-gt 0 ]; do arg=\"$1\"; case $arg in ... esac; shift; done" pattern so the shift
actually consumes arguments; update references to CHECK_MODE and the --check
case accordingly.
- Around line 1-15: The script uses "set -e" but doesn't enable pipefail, so
failures in piped commands can be masked; update the generate_openapi_spec.sh
startup options by adding "set -o pipefail" (alongside the existing "set -e")
near the top of the script so that piped command failures cause the script to
fail fast and Surface errors during OpenAPI generation.
In `@apps/ensapi/src/config/config.schema.test.ts`:
- Around line 74-83: Update the test that calls buildConfigFromEnvironment with
OPENAPI_GENERATE_MODE: "false" to also assert the warning message content so we
guard the warning's origin; replace or augment
expect(logger.warn).toHaveBeenCalled() with an assertion like
expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining("OPENAPI_GENERATE_MODE")
or the specific substring your code logs) or use
toHaveBeenCalledWith(expect.stringMatching(/invalid.*OPENAPI_GENERATE_MODE/i))
to verify the message includes the expected text from the warning emitted by
buildConfigFromEnvironment.
In `@apps/ensapi/src/config/openapi-mock-config.ts`:
- Line 23: The current assignment port: port || ENSApi_DEFAULT_PORT mixes types
(port is string | undefined, ENSApi_DEFAULT_PORT is number); update the
expression in openapi-mock-config.ts to use the nullish coalescing operator and
an explicit string conversion so the resulting type is consistently string —
e.g., use port ?? String(ENSApi_DEFAULT_PORT) (or, if you prefer number output,
use port ? Number(port) ?? ENSApi_DEFAULT_PORT); change the expression
referencing ENSApi_DEFAULT_PORT and port accordingly so PortSchema receives a
consistent type.
In `@apps/ensapi/src/index.ts`:
- Around line 69-70: The v1 ENSAnalytics endpoints are no longer mounted so
callers to /v1/ensanalytics/* will 404; fix by restoring a v1 mount or updating
consumers: either add a new route that mounts the existing ensanalyticsApi (or a
v1-compat wrapper) at app.route("/v1/ensanalytics", ensanalyticsApi) so requests
to /v1/ensanalytics/referrers and /v1/ensanalytics/referrers/:referrer work, or
update external callers (e.g., packages/ens-referrals/src/v1/client.ts) to use
/ensanalytics instead and remove any v1-specific files; locate usage around the
existing app.route("/ensanalytics", ensanalyticsApi) to implement the chosen
solution.
In `@docs/docs.ensnode.io/README.md`:
- Around line 46-52: Update the "Generating the Spec" section so it's explicit
which working directory to use: add a short note (e.g., "Run from the repository
root:") immediately above the code block referencing ./
.github/scripts/generate_openapi_spec.sh, or change the invocation to an
absolute/root-relative form that clearly runs from repo root; ensure the script
name generate_openapi_spec.sh is unchanged and the code block shows the correct
command to run from the repository root.
- Line 5: Split the long introductory sentence "Learn more about
[ENSNode](https://ensnode.io) from [the "Starlight" ENSNode
docs](https://ensnode.io/docs/). Everything from these "Starlight" docs is
planned to be transitioned into these Mintlify docs soon." into two shorter
sentences or insert a line break after the first clause so it reads as a brief
invitation (e.g., "Learn more about ENSNode from the 'Starlight' ENSNode docs."
followed by the transitional sentence about migrating content into Mintlify
docs); update the README.md entry containing that exact sentence accordingly for
improved raw Markdown readability.
| #!/bin/bash | ||
|
|
||
| # Generate OpenAPI spec from ENSApi | ||
| # This script can be used both locally and in CI | ||
| # | ||
| # Usage: | ||
| # ./generate_openapi_spec.sh # Generate spec (default) | ||
| # ./generate_openapi_spec.sh --check # Generate and verify against committed version | ||
| # | ||
| # Environment variables: | ||
| # ENSAPI_PORT - Port for ENSApi (default: 4334) | ||
| # STARTUP_TIMEOUT - Seconds to wait for server startup (default: 30) | ||
| # SKIP_VALIDATION - Set to "true" to skip Mintlify validation (default: false) | ||
|
|
||
| set -e |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Add set -o pipefail for safer pipe error handling.
With set -e but no pipefail, failures in the left-hand side of pipes (e.g., if curl fails but output is piped through sed/tail later in other scripts) can be silently swallowed. Since this script uses set -e, adding pipefail ensures consistent fail-fast behavior.
Proposed fix
-set -e
+set -euo pipefail📝 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.
| #!/bin/bash | |
| # Generate OpenAPI spec from ENSApi | |
| # This script can be used both locally and in CI | |
| # | |
| # Usage: | |
| # ./generate_openapi_spec.sh # Generate spec (default) | |
| # ./generate_openapi_spec.sh --check # Generate and verify against committed version | |
| # | |
| # Environment variables: | |
| # ENSAPI_PORT - Port for ENSApi (default: 4334) | |
| # STARTUP_TIMEOUT - Seconds to wait for server startup (default: 30) | |
| # SKIP_VALIDATION - Set to "true" to skip Mintlify validation (default: false) | |
| set -e | |
| #!/bin/bash | |
| # Generate OpenAPI spec from ENSApi | |
| # This script can be used both locally and in CI | |
| # | |
| # Usage: | |
| # ./generate_openapi_spec.sh # Generate spec (default) | |
| # ./generate_openapi_spec.sh --check # Generate and verify against committed version | |
| # | |
| # Environment variables: | |
| # ENSAPI_PORT - Port for ENSApi (default: 4334) | |
| # STARTUP_TIMEOUT - Seconds to wait for server startup (default: 30) | |
| # SKIP_VALIDATION - Set to "true" to skip Mintlify validation (default: false) | |
| set -euo pipefail |
🤖 Prompt for AI Agents
In @.github/scripts/generate_openapi_spec.sh around lines 1 - 15, The script
uses "set -e" but doesn't enable pipefail, so failures in piped commands can be
masked; update the generate_openapi_spec.sh startup options by adding "set -o
pipefail" (alongside the existing "set -e") near the top of the script so that
piped command failures cause the script to fail fast and Surface errors during
OpenAPI generation.
| # Parse arguments | ||
| CHECK_MODE=false | ||
| for arg in "$@"; do | ||
| case $arg in | ||
| --check) | ||
| CHECK_MODE=true | ||
| shift | ||
| ;; | ||
| esac | ||
| done |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
shift inside a for arg in "$@" loop is misleading.
The shift on line 29 modifies positional parameters but doesn't affect the for loop's iteration (which snapshots "$@" at the start). It's harmless but misleading—readers may think it's skipping the next argument. Consider removing it or switching to a while loop if you need to consume arguments.
Proposed cleanup
# Parse arguments
CHECK_MODE=false
for arg in "$@"; do
case $arg in
--check)
CHECK_MODE=true
- shift
;;
esac
done📝 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.
| # Parse arguments | |
| CHECK_MODE=false | |
| for arg in "$@"; do | |
| case $arg in | |
| --check) | |
| CHECK_MODE=true | |
| shift | |
| ;; | |
| esac | |
| done | |
| # Parse arguments | |
| CHECK_MODE=false | |
| for arg in "$@"; do | |
| case $arg in | |
| --check) | |
| CHECK_MODE=true | |
| ;; | |
| esac | |
| done |
🤖 Prompt for AI Agents
In @.github/scripts/generate_openapi_spec.sh around lines 23 - 32, The for-loop
iterating over "$@" uses shift (inside the block handling --check) which is
misleading because the for-loop snapshot isn't affected; remove the shift or
convert the loop to a proper while/shift pattern. Specifically, either delete
the shift line inside the case that sets CHECK_MODE=true (leaving the for arg in
"$@" intact and no positional consumption), or replace the "for arg in \"$@\";
do ... done" with a "while [ $# -gt 0 ]; do arg=\"$1\"; case $arg in ... esac;
shift; done" pattern so the shift actually consumes arguments; update references
to CHECK_MODE and the --check case accordingly.
| it("logs warning when OPENAPI_GENERATE_MODE has invalid value", async () => { | ||
| mockFetch.mockResolvedValueOnce({ | ||
| ok: true, | ||
| json: () => Promise.resolve(serializeENSIndexerPublicConfig(ENSINDEXER_PUBLIC_CONFIG)), | ||
| }); | ||
|
|
||
| await buildConfigFromEnvironment({ ...BASE_ENV, OPENAPI_GENERATE_MODE: "false" }); | ||
|
|
||
| expect(logger.warn).toHaveBeenCalled(); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Consider asserting the warning message content.
The test confirms logger.warn was called but doesn't verify the message. Asserting on the message string (or at least a substring) would guard against regressions where the warning is triggered by a different code path.
Suggested improvement
- expect(logger.warn).toHaveBeenCalled();
+ expect(logger.warn).toHaveBeenCalledWith(
+ expect.stringContaining("OPENAPI_GENERATE_MODE is set to 'false'"),
+ );📝 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.
| it("logs warning when OPENAPI_GENERATE_MODE has invalid value", async () => { | |
| mockFetch.mockResolvedValueOnce({ | |
| ok: true, | |
| json: () => Promise.resolve(serializeENSIndexerPublicConfig(ENSINDEXER_PUBLIC_CONFIG)), | |
| }); | |
| await buildConfigFromEnvironment({ ...BASE_ENV, OPENAPI_GENERATE_MODE: "false" }); | |
| expect(logger.warn).toHaveBeenCalled(); | |
| }); | |
| it("logs warning when OPENAPI_GENERATE_MODE has invalid value", async () => { | |
| mockFetch.mockResolvedValueOnce({ | |
| ok: true, | |
| json: () => Promise.resolve(serializeENSIndexerPublicConfig(ENSINDEXER_PUBLIC_CONFIG)), | |
| }); | |
| await buildConfigFromEnvironment({ ...BASE_ENV, OPENAPI_GENERATE_MODE: "false" }); | |
| expect(logger.warn).toHaveBeenCalledWith( | |
| expect.stringContaining("OPENAPI_GENERATE_MODE is set to 'false'"), | |
| ); | |
| }); |
🤖 Prompt for AI Agents
In `@apps/ensapi/src/config/config.schema.test.ts` around lines 74 - 83, Update
the test that calls buildConfigFromEnvironment with OPENAPI_GENERATE_MODE:
"false" to also assert the warning message content so we guard the warning's
origin; replace or augment expect(logger.warn).toHaveBeenCalled() with an
assertion like
expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining("OPENAPI_GENERATE_MODE")
or the specific substring your code logs) or use
toHaveBeenCalledWith(expect.stringMatching(/invalid.*OPENAPI_GENERATE_MODE/i))
to verify the message includes the expected text from the warning emitted by
buildConfigFromEnvironment.
| */ | ||
| export function buildOpenApiMockConfig(port?: string): EnsApiConfigInput { | ||
| return { | ||
| port: port || ENSApi_DEFAULT_PORT, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Minor: port || ENSApi_DEFAULT_PORT mixes types.
The port parameter is string | undefined, while ENSApi_DEFAULT_PORT is a number (4334). The || fallback produces string | number. This works because PortSchema coerces both, but it's a subtle type mismatch. Consider using port ?? String(ENSApi_DEFAULT_PORT) or port ?? ENSApi_DEFAULT_PORT with a note, for explicit intent. Not a bug since the schema handles it.
🤖 Prompt for AI Agents
In `@apps/ensapi/src/config/openapi-mock-config.ts` at line 23, The current
assignment port: port || ENSApi_DEFAULT_PORT mixes types (port is string |
undefined, ENSApi_DEFAULT_PORT is number); update the expression in
openapi-mock-config.ts to use the nullish coalescing operator and an explicit
string conversion so the resulting type is consistently string — e.g., use port
?? String(ENSApi_DEFAULT_PORT) (or, if you prefer number output, use port ?
Number(port) ?? ENSApi_DEFAULT_PORT); change the expression referencing
ENSApi_DEFAULT_PORT and port accordingly so PortSchema receives a consistent
type.
| // use ENSAnalytics API at /ensanalytics | ||
| app.route("/ensanalytics", ensanalyticsApi); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# Check for remaining references to v1 ensanalytics or referrerLeaderboardCacheV1
rg -n "v1.*ensanalytics|ensanalytics.*v1|referrerLeaderboardCacheV1" --type tsRepository: namehash/ensnode
Length of output: 1843
🏁 Script executed:
# Get the full context of the index.ts file around lines 69-70
cat -n apps/ensapi/src/index.ts | head -80 | tail -20Repository: namehash/ensnode
Length of output: 632
🏁 Script executed:
# Check git history to see what was removed from this route
git log --oneline -20 -- apps/ensapi/src/index.tsRepository: namehash/ensnode
Length of output: 104
🏁 Script executed:
# Check if there are any references in documentation or comments about v1 endpoints
rg -n "v1.*ensanalytics|ensanalytics.*v1" --type md --type json --type yamlRepository: namehash/ensnode
Length of output: 42
🏁 Script executed:
# Check what ensanalyticsApi is and where it's defined
rg -n "ensanalyticsApi" --type ts -A 3Repository: namehash/ensnode
Length of output: 576
🏁 Script executed:
# Look at the ensanalytics-api-v1.ts handler to see its routes
cat -n apps/ensapi/src/handlers/ensanalytics-api-v1.ts | head -50Repository: namehash/ensnode
Length of output: 2109
🏁 Script executed:
# Check if ensanalyticsApi imports or includes the v1 handler
fd "ensanalytics-api" --type f --extension ts | head -10Repository: namehash/ensnode
Length of output: 255
🏁 Script executed:
# Check the imports in index.ts to see where ensanalyticsApi comes from
head -50 apps/ensapi/src/index.ts | grep -n "import\|ensanalytics"Repository: namehash/ensnode
Length of output: 1194
🏁 Script executed:
# Check the ensanalytics-api.ts handler to see if it includes v1 routes
cat -n apps/ensapi/src/handlers/ensanalytics-api.tsRepository: namehash/ensnode
Length of output: 7531
🏁 Script executed:
# Check if ensanalytics-api-v1.ts is imported anywhere else
rg -n "ensanalytics-api-v1|from.*ensanalytics-api-v1" --type tsRepository: namehash/ensnode
Length of output: 560
🏁 Script executed:
# Check the git diff to see what changed in index.ts
git diff HEAD~10 -- apps/ensapi/src/index.ts 2>/dev/null || echo "Could not get git diff, checking current content"Repository: namehash/ensnode
Length of output: 108
Address breaking change: v1 ENSAnalytics route is no longer served.
The v1 route has been removed from the main app (not mounted in index.ts), but external consumers like packages/ens-referrals/src/v1/client.ts still depend on it. Requests to /v1/ensanalytics/referrers and /v1/ensanalytics/referrers/:referrer will now fail.
Either restore the v1 route in index.ts, update external consumers to use the non-v1 endpoint at /ensanalytics, or remove v1-related files and dependencies entirely.
🤖 Prompt for AI Agents
In `@apps/ensapi/src/index.ts` around lines 69 - 70, The v1 ENSAnalytics endpoints
are no longer mounted so callers to /v1/ensanalytics/* will 404; fix by
restoring a v1 mount or updating consumers: either add a new route that mounts
the existing ensanalyticsApi (or a v1-compat wrapper) at
app.route("/v1/ensanalytics", ensanalyticsApi) so requests to
/v1/ensanalytics/referrers and /v1/ensanalytics/referrers/:referrer work, or
update external callers (e.g., packages/ens-referrals/src/v1/client.ts) to use
/ensanalytics instead and remove any v1-specific files; locate usage around the
existing app.route("/ensanalytics", ensanalyticsApi) to implement the chosen
solution.
|
|
||
| [docs.ensnode.io](https://docs.ensnode.io) runs on [Mintlify](https://mintlify.com). | ||
|
|
||
| Learn more about [ENSNode](https://ensnode.io) from [the "Starlight" ENSNode docs](https://ensnode.io/docs/). Everything from these "Starlight" docs is planned to be transitioned into these Mintlify docs soon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Consider splitting the long introductory sentence for readability.
This line is quite long. A line break or splitting into two sentences would improve readability in raw Markdown.
🤖 Prompt for AI Agents
In `@docs/docs.ensnode.io/README.md` at line 5, Split the long introductory
sentence "Learn more about [ENSNode](https://ensnode.io) from [the "Starlight"
ENSNode docs](https://ensnode.io/docs/). Everything from these "Starlight" docs
is planned to be transitioned into these Mintlify docs soon." into two shorter
sentences or insert a line break after the first clause so it reads as a brief
invitation (e.g., "Learn more about ENSNode from the 'Starlight' ENSNode docs."
followed by the transitional sentence about migrating content into Mintlify
docs); update the README.md entry containing that exact sentence accordingly for
improved raw Markdown readability.
| ### Generating the Spec | ||
|
|
||
| When you modify API routes or schemas in ENSApi, regenerate the OpenAPI spec: | ||
|
|
||
| ```bash | ||
| ./.github/scripts/generate_openapi_spec.sh | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify the working directory for the generation script.
The "Generating the Spec" section follows the "Local Development" section which instructs cd docs/docs.ensnode.io. The script path ./.github/scripts/generate_openapi_spec.sh is relative to the repository root, not the docs directory. A reader following the README top-to-bottom may already be in the docs/docs.ensnode.io directory.
Consider adding a note like "Run from the repository root:" above the code block to prevent confusion.
🤖 Prompt for AI Agents
In `@docs/docs.ensnode.io/README.md` around lines 46 - 52, Update the "Generating
the Spec" section so it's explicit which working directory to use: add a short
note (e.g., "Run from the repository root:") immediately above the code block
referencing ./ .github/scripts/generate_openapi_spec.sh, or change the
invocation to an absolute/root-relative form that clearly runs from repo root;
ensure the script name generate_openapi_spec.sh is unchanged and the code block
shows the correct command to run from the repository root.
Lite PR
Summary
openapi:generatescript to fetch and save OpenAPI spec from ENSApiopenapi.jsonstays in sync with productionWhy
Production API docs were getting out of sync with deployed API, and there was no way to preview API doc changes in PRs.
This setup ensures:
Testing
Ran
./.github/scripts/generate_openapi_spec.shlocally:Notes for Reviewer (Optional)
Pre-Review Checklist (Blocking)