Skip to content

Build ENSRainbow config#1425

Open
djstrong wants to merge 63 commits intomainfrom
1407-build-ensrainbow-config
Open

Build ENSRainbow config#1425
djstrong wants to merge 63 commits intomainfrom
1407-build-ensrainbow-config

Conversation

@djstrong
Copy link
Contributor

@djstrong djstrong commented Dec 22, 2025

Related to #1407

Lite PR

Summary

  • Built new Zod-based configuration system for ENSRainbow, replacing ad-hoc env parsing with structured validation
  • Added /v1/config endpoint returning public config (version, label set, records count) and deprecated /v1/version
  • Server now requires an initialized database (precalculated record count) before starting; empty or uninitialized DB yields a clear error and directs you to run ingestion first

Why

  • Centralizes configuration management with proper validation and type safety
  • Provides comprehensive public config endpoint for clients to discover service capabilities
  • Ensures /v1/config is always accurate and avoids serving with an empty DB; run ingestion before starting the server
  • Improves developer experience with better error messages and validation

Testing

  • Added comprehensive test suite for config schema validation (config.schema.test.ts) covering success cases, validation errors, invariants, and edge cases
  • Updated existing CLI and server command tests to work with new config system
  • Verified new /v1/config endpoint in server command tests

Notes for Reviewer (Optional)

  • The old /v1/version endpoint is deprecated but still functional for backward compatibility
  • Config is built at module load time and will exit process on validation failure (appropriate for CLI apps)
  • Behavior change: Deployments that previously started the server with an empty DB will now get a clear error and must run ingestion first (documented in the changeset for release notes)

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)

@vercel
Copy link
Contributor

vercel bot commented Dec 22, 2025

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

Project Deployment Actions Updated (UTC)
admin.ensnode.io Ready Ready Preview, Comment Feb 16, 2026 8:53pm
ensnode.io Ready Ready Preview, Comment Feb 16, 2026 8:53pm
ensrainbow.io Ready Ready Preview, Comment Feb 16, 2026 8:53pm

@changeset-bot
Copy link

changeset-bot bot commented Dec 22, 2025

🦋 Changeset detected

Latest commit: 55bb40a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 19 packages
Name Type
ensrainbow Patch
@ensnode/ensrainbow-sdk Patch
ensindexer Patch
@ensnode/ponder-metadata Patch
ensadmin Patch
ensapi Patch
fallback-ensapi Patch
@ensnode/datasources Patch
@ensnode/ensnode-schema Patch
@ensnode/ensnode-react Patch
@ensnode/ensnode-sdk Patch
@ensnode/ponder-sdk Patch
@ensnode/ponder-subgraph Patch
@ensnode/shared-configs Patch
@docs/ensnode Patch
@docs/ensrainbow Patch
@docs/mintlify Patch
@namehash/ens-referrals Patch
@namehash/namehash-ui Patch

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

Copilot AI review requested due to automatic review settings January 21, 2026 13:22
@coderabbitai
Copy link

coderabbitai bot commented Jan 21, 2026

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Centralizes ENSRainbow configuration with Zod schemas and a runtime config, tightens port validation, removes legacy env helpers, adds startup DB sanity checks, caches and exposes GET /v1/config (SDK client support), updates CLI/tests for port coercion and isolation, and adds extensive config tests and zod dependency.

Changes

Cohort / File(s) Summary
Config schema & infra
apps/ensrainbow/src/config/config.schema.ts, apps/ensrainbow/src/config/index.ts, apps/ensrainbow/src/config/types.ts, apps/ensrainbow/src/config/defaults.ts, apps/ensrainbow/src/config/environment.ts, apps/ensrainbow/src/config/validations.ts
Add Zod-backed schemas, environment type, defaults (default port/data-dir), DB-schema invariant validation, builders buildConfigFromEnvironment and buildENSRainbowPublicConfig, and export a runtime config built from process.env.
CLI, tests & env typing
apps/ensrainbow/src/cli.ts, apps/ensrainbow/src/cli.test.ts, apps/ensrainbow/types/env.d.ts
CLI now sources defaults from centralized config; port option uses PortSchema coercion and errors on invalid ports; tests refactored for module isolation and expanded port scenarios; global ProcessEnv now extends ENSRainbowEnvironment.
Removed env helpers
apps/ensrainbow/src/lib/env.ts
Remove legacy env helpers and in-file env parsing (DEFAULT_PORT, getEnvPort, getDefaultDataSubDir); functionality moved into config layer.
API startup & endpoints
apps/ensrainbow/src/lib/api.ts, apps/ensrainbow/src/commands/server-command.ts, apps/ensrainbow/src/commands/server-command.test.ts
On startup perform precalculated DB sanity check and abort on failure; compute and cache public config at startup; add GET /v1/config returning cached config; reduce per-request debug logs; tests for /v1/config and CORS.
SDK client
packages/ensrainbow-sdk/src/client.ts
Add config(): Promise<ENSRainbowPublicConfig> to fetch /v1/config, introduce ENSRainbowPublicConfig type, and mark prior version response as deprecated in favor of the new public config.
Shared validation tightening
packages/ensnode-sdk/src/shared/config/zod-schemas.ts, packages/ensnode-sdk/src/shared/config/types.ts
Introduce PortSchemaBase and PortNumber type; require integer ports in [1,65535], tighten error messages; expose PortSchema as optional wrapper.
Config tests
apps/ensrainbow/src/config/config.schema.test.ts, apps/ensrainbow/src/config/env-config.test.ts
Add extensive unit tests covering buildConfigFromEnvironment, public config builder, path normalization, port/DB/label validations, invariants, and many edge/error cases.
Dependency & changeset
apps/ensrainbow/package.json, .changeset/young-carrots-cheer.md
Add zod dependency and a changeset describing the new /v1/config endpoint and deprecation of /v1/version.
Misc tests
apps/ensrainbow/src/cli.test.ts, apps/ensrainbow/src/commands/server-command.test.ts
Refactor CLI tests for port behavior and add health/serve port tests; add tests ensuring cached /v1/config behavior remains stable after DB changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant SDK as "SDK Client"
  participant Server as "ENSRainbow API"
  participant DB as "Database"
  participant Builder as "buildENSRainbowPublicConfig"

  SDK->>Server: GET /v1/config
  Server->>DB: getServerLabelSet() (cached)
  Server->>DB: labelCount() (startup-cached)
  DB-->>Server: labelSet, count
  Server->>Builder: assemble public config (version, labelSet, recordsCount)
  Builder-->>Server: ENSRainbowPublicConfig
  Server-->>SDK: 200 + ENSRainbowPublicConfig
Loading
sequenceDiagram
  autonumber
  participant CLI as "CLI"
  participant ConfigBuilder as "buildConfigFromEnvironment"
  participant Zod as "Zod schemas"
  participant Process as "process.env"

  CLI->>ConfigBuilder: request config from env
  ConfigBuilder->>Zod: parse & validate environment
  Zod-->>ConfigBuilder: validated ENSRainbowConfig or errors
  alt valid
    ConfigBuilder-->>CLI: return ENSRainbowConfig
    CLI->>CLI: proceed with startup using config (serve/ingest)
  else invalid
    ConfigBuilder->>Process: log errors (pretty)
    Process->>Process: exit non-zero
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

ensnode-sdk

Poem

🐇 I nibbled env vars, stitched defaults with care,

Zod guarded ports and paths, tidy as my hare,
Startup checks now watchful, cached config on show,
Clients fetch the carrots — records counted slow,
A joyful hop for code, and off I bound — hoorah! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Build ENSRainbow config' accurately describes the main objective of the changeset, which is to implement a new Zod-based configuration system for ENSRainbow.
Description check ✅ Passed PR description comprehensively covers all template sections with clear summaries, detailed rationale, testing approach, reviewer notes, and addresses the significant behavior change impact.

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

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 1407-build-ensrainbow-config

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

@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: 6

🤖 Fix all issues with AI agents
In `@apps/ensrainbow/src/config/config.schema.ts`:
- Around line 65-71: The current ternary for labelSet uses a truthy check
(env.LABEL_SET_ID || env.LABEL_SET_VERSION) which treats empty strings as
missing; change the condition to explicit undefined checks so an empty string is
treated as a provided value and validation will run — e.g. replace the condition
with (env.LABEL_SET_ID !== undefined || env.LABEL_SET_VERSION !== undefined) and
still return the object with labelSetId: env.LABEL_SET_ID and labelSetVersion:
env.LABEL_SET_VERSION when true; keep the symbol name labelSet and the env keys
env.LABEL_SET_ID / env.LABEL_SET_VERSION so locators remain obvious.
- Around line 33-36: The schema currently calls getDefaultDataDir() at module
load in ENSRainbowConfigSchema (dataDir:
DataDirSchema.default(getDefaultDataDir())), capturing process.cwd() too early;
remove the eager default from ENSRainbowConfigSchema and instead handle lazy
evaluation in buildConfigFromEnvironment by supplying dataDir: env.DATA_DIR ??
getDefaultDataDir() when parsing/building the config, keeping
ENSRainbowConfigSchema (and DataDirSchema/PortSchema) purely declarative and
ensuring getDefaultDataDir() runs only at build time.
- Around line 18-24: The path transform in the config schema currently treats
paths starting with "/" as absolute; update the transform used on the config
field to use Node's path.isAbsolute(path) instead of path.startsWith("/"), and
ensure the Node "path" module is imported (or isAbsolute is referenced)
alongside the existing join and process.cwd() usage in the transform callback so
Windows absolute paths like "C:\..." are detected correctly and returned
unchanged.
- Around line 73-83: Replace the terminal process.exit(1) in the catch block
with throwing a descriptive error so callers can handle failures; specifically,
inside the catch for buildConfigFromEnvironment (or whatever function constructs
ENSRainbowConfig) throw a custom error (e.g., ConfigBuildError) or rethrow the
existing Error with context including the prettified ZodError output and the
message "Failed to build ENSRainbowConfig", while keeping the existing logger
calls for ZodError and generic Error; move any process.exit(1) behavior out to
the CLI/entrypoint so tests can catch the thrown error and decide whether to
exit.

In `@apps/ensrainbow/src/config/validations.ts`:
- Around line 7-10: The current type ZodCheckFnInput<T> uses the internal
z.core.ParsePayload<T>; change it to rely on Zod's documented types or a simple
explicit input shape instead: remove z.core.ParsePayload and either use the
public helper z.input with a Zod type (e.g., z.input<z.ZodType<T>>) or replace
ZodCheckFnInput<T> with a small explicit interface/alias (e.g., unknown or
Record<string, any> or a narrow shape your check expects) so the code no longer
depends on the unstable z.core namespace; update any usages of ZodCheckFnInput
to match the new public type.

In `@apps/ensrainbow/src/lib/env.ts`:
- Around line 7-10: The getEnvPort function unsafely asserts process.env as
ENSRainbowEnvironment and rebuilds the full config on every call; remove the
type assertion and instead import the ENSRainbowConfig type (import type {
ENSRainbowConfig } ...) and let buildConfigFromEnvironment validate process.env
at runtime, receiving an ENSRainbowConfig result; then read and return
config.port. Also memoize the built config in a module-level variable so
getEnvPort calls reuse the same config instead of reconstructing it each time
(references: getEnvPort, buildConfigFromEnvironment, ENSRainbowEnvironment,
ENSRainbowConfig).

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

Introduces a Zod-based, centralized environment configuration builder for the ENSRainbow app, aligning it with the configuration patterns used in other apps in the monorepo.

Changes:

  • Added ENSRainbow config schema, environment types, defaults, and cross-field validations.
  • Updated ENSRainbow CLI/env port handling to use the new config builder and centralized defaults.
  • Tightened shared PortSchema validation to require integer ports; added zod as a direct ENSRainbow dependency.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
pnpm-lock.yaml Adds zod to the ENSRainbow importer lock entry.
packages/ensnode-sdk/src/shared/config/zod-schemas.ts Updates shared PortSchema to require integer ports.
apps/ensrainbow/src/lib/env.ts Switches env port resolution to buildConfigFromEnvironment(...).
apps/ensrainbow/src/config/validations.ts Adds ENSRainbow-specific invariant validation for schema version.
apps/ensrainbow/src/config/types.ts Re-exports ENSRainbow config type.
apps/ensrainbow/src/config/index.ts Adds a config module entrypoint exporting types/functions/defaults.
apps/ensrainbow/src/config/environment.ts Defines typed raw environment shape for ENSRainbow.
apps/ensrainbow/src/config/defaults.ts Centralizes ENSRainbow default port and data dir.
apps/ensrainbow/src/config/config.schema.ts Adds ENSRainbow Zod schema + config builder with logging/exit-on-failure behavior.
apps/ensrainbow/src/cli.ts Uses new defaults module for data dir default; continues using env-derived port.
apps/ensrainbow/src/cli.test.ts Updates port tests to reflect process-exit behavior on invalid PORT values.
apps/ensrainbow/package.json Adds zod as an explicit dependency for ENSRainbow.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

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

@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io January 21, 2026 15:45 Inactive
@vercel vercel bot temporarily deployed to Preview – ensnode.io January 21, 2026 15:45 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io January 21, 2026 15:45 Inactive
Copilot AI review requested due to automatic review settings January 21, 2026 15:48
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io January 21, 2026 15:48 Inactive
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io January 21, 2026 15:48 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 22 out of 24 changed files in this pull request and generated 4 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.


import type { PortNumber } from "@ensnode/ensnode-sdk/internal";

import type { AbsolutePathSchemaBase, DbSchemaVersionSchemaBase } from "./config.schema";
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

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

AbsolutePathSchemaBase and DbSchemaVersionSchemaBase are values (Zod schemas) and are later referenced via typeof ... in z.infer<>. Importing them with import type will cause a TS compile error (a type-only import can’t be used in a typeof type query). Import these as normal imports, or move the inferred types into the schema module to avoid the value reference here.

Suggested change
import type { AbsolutePathSchemaBase, DbSchemaVersionSchemaBase } from "./config.schema";
import { AbsolutePathSchemaBase, DbSchemaVersionSchemaBase } from "./config.schema";

Copilot uses AI. Check for mistakes.
…CountError and streamline response structure
@vercel vercel bot temporarily deployed to Preview – ensnode.io February 16, 2026 14:32 Inactive
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io February 16, 2026 14:32 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io February 16, 2026 14:32 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 23 out of 25 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.

…nds for improved visibility of configuration
@vercel vercel bot temporarily deployed to Preview – ensnode.io February 16, 2026 15:38 Inactive
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io February 16, 2026 15:38 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io February 16, 2026 15:38 Inactive
…ety and improve clarity in CLI configuration
Copilot AI review requested due to automatic review settings February 16, 2026 20:46
@vercel vercel bot temporarily deployed to Preview – ensnode.io February 16, 2026 20:46 Inactive
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io February 16, 2026 20:46 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io February 16, 2026 20:46 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 28 out of 30 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)

apps/ensrainbow/src/lib/server.ts:154

  • The error message on line 152 ("Label count not initialized. Check the validate command.") appears to be for a different error path than the NoPrecalculatedCountError case. However, given that NoPrecalculatedCountError is the only specific error being thrown by getPrecalculatedRainbowRecordCount when the count is not found, this catch block for generic errors seems unlikely to be reached for a "not initialized" scenario. Consider whether this error message is still appropriate or if it should be updated to reflect unexpected database errors rather than initialization issues.
      logger.error(error, "Failed to retrieve precalculated rainbow record count");
      return {
        status: StatusCode.Error,
        error: "Label count not initialized. Check the validate command.",
        errorCode: ErrorCode.ServerError,
      } satisfies EnsRainbow.CountServerError;

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

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.

Build ENSRainbow config

3 participants