Skip to content

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

Why

  • Centralizes configuration management with proper validation and type safety
  • Provides comprehensive public config endpoint for clients to discover service capabilities
  • 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)

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 10, 2026 7:25am
ensnode.io Ready Ready Preview, Comment Feb 10, 2026 7:25am
ensrainbow.io Ready Ready Preview, Comment Feb 10, 2026 7:25am

@changeset-bot
Copy link

changeset-bot bot commented Dec 22, 2025

🦋 Changeset detected

Latest commit: aeb14c9

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 The PR description follows the required template with all key sections present: Summary, Why, Testing, Notes for Reviewer, and Pre-Review Checklist with the changeset item checked.

✏️ 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
Copilot AI review requested due to automatic review settings February 9, 2026 20:37
@vercel vercel bot temporarily deployed to Preview – ensnode.io February 9, 2026 20:37 Inactive
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io February 9, 2026 20:37 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io February 9, 2026 20:37 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 20 out of 22 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.

Comment on lines 131 to 142
coerce: (port: number) => {
// Validate port using PortSchema (make it required by parsing with a non-optional schema)
const result = PortSchema.safeParse(port);
if (!result.success) {
const firstError = result.error.issues[0];
throw new Error(`Invalid port: ${firstError?.message ?? "invalid port number"}`);
}
if (result.data === undefined) {
throw new Error("Invalid port: port is required");
}
return result.data;
},
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

The coerce handler is validating with PortSchema, but PortSchema is explicitly optional. This makes the extra result.data === undefined branch necessary and contradicts the comment about using a non-optional schema. Prefer validating with the non-optional PortSchemaBase (or a .required()/non-optional variant) so the return type is always a number and the undefined branch + comment mismatch can be removed.

Copilot uses AI. Check for mistakes.
Comment on lines 37 to 42
} catch (_error) {
logger.error("Cannot start server: database is empty or uninitialized.");
logger.error("The database must contain ingested data before the server can start.");
logger.error("Please run the ingestion command first to populate the database.");
// Throw error to ensure process exits with non-zero status code for CI/CD and scripts
throw new Error("Database is empty or uninitialized. Cannot start server.");
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

The getPrecalculatedRainbowRecordCount() pre-check treats any thrown error as "database is empty or uninitialized" and discards the underlying error context. This can misdiagnose cases like a corrupted/invalid precalculated count value or LevelDB read errors. Consider either (a) including the original error message in the thrown/logged output, or (b) only mapping the specific "no precalculated count" case to the "empty/uninitialized" guidance and letting other errors propagate.

Suggested change
} catch (_error) {
logger.error("Cannot start server: database is empty or uninitialized.");
logger.error("The database must contain ingested data before the server can start.");
logger.error("Please run the ingestion command first to populate the database.");
// Throw error to ensure process exits with non-zero status code for CI/CD and scripts
throw new Error("Database is empty or uninitialized. Cannot start server.");
} catch (error) {
// Log the underlying error so issues like corruption or read failures are visible
logger.error(error, "Error while checking precalculated rainbow record count");
logger.error("Cannot start server: database is empty or uninitialized.");
logger.error("The database must contain ingested data before the server can start.");
logger.error("Please run the ingestion command first to populate the database.");
// Throw error to ensure process exits with non-zero status code for CI/CD and scripts
const originalMessage =
error instanceof Error ? error.message : String(error);
throw new Error(
`Database is empty or uninitialized. Cannot start server. Underlying error: ${originalMessage}`,
);

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings February 9, 2026 20:58
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io February 9, 2026 20:58 Inactive
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io February 9, 2026 20:58 Inactive
@vercel vercel bot temporarily deployed to Preview – ensnode.io February 9, 2026 20:58 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 19 out of 21 changed files in this pull request and generated 5 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.

Comment on lines +10 to +11
LABEL_SET_ID?: string;
LABEL_SET_VERSION?: string;
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

LABEL_SET_ID / LABEL_SET_VERSION are declared as supported env vars but are not consumed by buildConfigFromEnvironment (and appear unused elsewhere). Either wire them into the config schema or remove them to avoid implying unsupported configuration knobs.

Suggested change
LABEL_SET_ID?: string;
LABEL_SET_VERSION?: string;

Copilot uses AI. Check for mistakes.
Comment on lines +400 to +403
const errorData = (await response.json()) as { error?: string; errorCode?: number };
throw new Error(
errorData.error ?? `Failed to fetch ENSRainbow config: ${response.statusText}`,
);
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

config() throws on non-2xx responses after unconditionally calling response.json(). If the server returns a non-JSON body for errors (e.g., 404 HTML/plain text), this will throw a JSON parse error and hide the real HTTP failure. Consider wrapping JSON parsing in try/catch and falling back to response.text() (and include status/statusText) when the body isn’t JSON.

Suggested change
const errorData = (await response.json()) as { error?: string; errorCode?: number };
throw new Error(
errorData.error ?? `Failed to fetch ENSRainbow config: ${response.statusText}`,
);
let errorMessage = `Failed to fetch ENSRainbow config: ${response.status} ${response.statusText}`;
try {
const bodyText = await response.text();
if (bodyText) {
try {
const errorData = JSON.parse(bodyText) as { error?: string; errorCode?: number };
if (errorData && errorData.error) {
errorMessage = errorData.error;
} else {
errorMessage = `${errorMessage} - ${bodyText}`;
}
} catch {
// Body is not valid JSON; include raw text in the message.
errorMessage = `${errorMessage} - ${bodyText}`;
}
}
} catch {
// If reading the body fails, fall back to the default message.
}
throw new Error(errorMessage);

Copilot uses AI. Check for mistakes.
@vercel vercel bot temporarily deployed to Preview – ensnode.io February 9, 2026 22:46 Inactive
@vercel vercel bot temporarily deployed to Preview – admin.ensnode.io February 9, 2026 22:46 Inactive
@vercel vercel bot temporarily deployed to Preview – ensrainbow.io February 9, 2026 22:46 Inactive
@djstrong djstrong requested a review from Copilot February 9, 2026 23:01
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 19 out of 21 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.

Comment on lines +1 to +2
import config from "@/config";

Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

Importing the default config at module load means env validation runs before yargs parses CLI args. If a user has an invalid PORT/DATA_DIR/DB_SCHEMA_VERSION in the environment, the CLI will exit even when --port/--data-dir would otherwise override those values, which contradicts the “CLI arguments take precedence” note. Consider building the env config lazily (after argv parsing) or validating only the subset of env vars that are actually used as defaults for the chosen command.

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +44
// Check if the database is empty (no precalculated count)
// This prevents starting a server that can't serve any data
try {
await db.getPrecalculatedRainbowRecordCount();
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
if (message.includes("No precalculated count found")) {
logger.error("Cannot start server: database is empty or uninitialized.");
logger.error("The database must contain ingested data before the server can start.");
logger.error("Please run the ingestion command first to populate the database.");
throw new Error("Database is empty or uninitialized. Cannot start server.");
}
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

This startup check relies on substring-matching the thrown error message ("No precalculated count found...") to detect an empty/uninitialized DB. That’s brittle: changing the message in getPrecalculatedRainbowRecordCount() would silently change server behavior. Prefer a structured signal (e.g., return null/Result type, throw a dedicated error class, or expose a boolean hasPrecalculatedRainbowRecordCount() helper) and branch on that instead of parsing strings.

Suggested change
// Check if the database is empty (no precalculated count)
// This prevents starting a server that can't serve any data
try {
await db.getPrecalculatedRainbowRecordCount();
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
if (message.includes("No precalculated count found")) {
logger.error("Cannot start server: database is empty or uninitialized.");
logger.error("The database must contain ingested data before the server can start.");
logger.error("Please run the ingestion command first to populate the database.");
throw new Error("Database is empty or uninitialized. Cannot start server.");
}
// Check if the database has a precalculated count.
// This prevents starting a server that can't serve any data.
try {
await db.getPrecalculatedRainbowRecordCount();
} catch (error) {

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +44
// Check if the database is empty (no precalculated count)
// This prevents starting a server that can't serve any data
try {
await db.getPrecalculatedRainbowRecordCount();
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
if (message.includes("No precalculated count found")) {
logger.error("Cannot start server: database is empty or uninitialized.");
logger.error("The database must contain ingested data before the server can start.");
logger.error("Please run the ingestion command first to populate the database.");
throw new Error("Database is empty or uninitialized. Cannot start server.");
}
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

This PR changes server startup behavior to refuse to start when the database has no precalculated record count (treated as empty/uninitialized), but the PR description focuses on config + the new /v1/config endpoint. Please document this behavioral change (and its rationale) in the PR description or release notes, since it can break existing deployments that previously started with an empty DB.

Copilot uses AI. Check for mistakes.
@@ -1,4 +1,5 @@
import packageJson from "@/../package.json";
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

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

In ESM, importing JSON without an import attribute can throw at runtime (ERR_IMPORT_ASSERTION_TYPE_MISSING) depending on the loader/bundler. Elsewhere in the repo the pattern is import packageJson ... with { type: "json" }. For consistency and to avoid runtime differences between tsx/vitest/node, update this import to use the same JSON import attribute form.

Suggested change
import packageJson from "@/../package.json";
import packageJson from "@/../package.json" with { type: "json" };

Copilot uses AI. Check for mistakes.
@djstrong
Copy link
Contributor Author

There is a problem with current solution and also layered Configs (EnvConfig -> ArgsConfig). If env value is invalid but arg value is valid then the validation process will fail on building EnvConfig but it should pass IMO.
If we do not validate env values then CLI defaults might be invalid and the validation should be done after merging env values with arg values - is it the correct way?

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