refactor: consolidate duplicated cross-cutting constants#34
Conversation
Introduce a dependency-free src/lib/constants.ts as the single source of truth for constants that are duplicated or span the client/server boundary, and replace the scattered magic numbers with named imports: - AUDIT_LOG_FETCH_LIMIT (1000): the audit-log fetch limit, used by both the client request (useQuery) and the server-side clamp (query-service). These previously drifted (client 1000 vs server 500); now they can't. - AUDIT_LOG_DEFAULT_LIMIT (100): server default when no limit is given. - LIVE_QUERY_REFETCH_INTERVAL_MS (5000): polling cadence shared by the active-sessions and audit-log queries (was inlined 3x). - MCP_MAX_RESULT_ROWS (1000) / MCP_CATALOG_PAGE_SIZE (100): MCP row cap and catalog page size (mcp.ts keeps its local MAX_RESULT_ROWS/PAGE_SIZE names, now sourced from the shared module, so importers/tests are intact). Scope is intentionally limited to duplicated / cross-tier / contract constants; well-named feature-local constants (panel widths, breakpoints, retry counts, etc.) are left next to their feature. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
This PR introduces a dependency-free shared constants module (src/lib/constants.ts) to eliminate duplicated cross-tier “magic numbers” and ensure client/server runtime contracts (notably audit-log limits and MCP row caps) stay in sync.
Changes:
- Added
src/lib/constants.tsas a single source of truth for shared audit-log, live polling, and MCP constants. - Updated client query hooks to use named constants for audit-log fetch limits and polling intervals.
- Updated server audit-log handlers and MCP server constants to source values from the shared module while preserving existing local constant names where needed.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/lib/constants.ts |
Adds centralized, dependency-free shared constants for cross-tier contracts and duplicated values. |
src/hooks/useQuery.ts |
Replaces inline polling intervals and audit-log limit constant with shared imports. |
server/services/query-service.ts |
Replaces hardcoded audit-log limit clamp/default values with shared constants. |
server/mcp.ts |
Sources MCP page size and max result rows from shared constants while keeping existing exported names. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Greptile SummaryThis PR introduces
Confidence Score: 4/5Safe to merge — all value changes are no-ops (same numbers, different names) and tests confirm no regressions. The refactor is mechanically correct and tests pass. The one thing worth a follow-up is that server/ now imports from src/lib/, a boundary enforced only by a comment. If that invariant is ever violated by accident the server build breaks, but since the file is currently four literal export const declarations the risk is low today. server/mcp.ts — the ../src/lib/constants import path crosses the server/client directory boundary without a lint or tsconfig guard. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
C["src/lib/constants.ts\n(single source of truth)"]
C -->|AUDIT_LOG_FETCH_LIMIT\nAUDIT_LOG_DEFAULT_LIMIT| QS["server/services/query-service.ts\ngetAuditLogEntries\ngetSystemAuditLogEntries"]
C -->|MCP_MAX_RESULT_ROWS\nMCP_CATALOG_PAGE_SIZE| MCP["server/mcp.ts\nMAX_RESULT_ROWS\nPAGE_SIZE"]
C -->|AUDIT_LOG_FETCH_LIMIT\nLIVE_QUERY_REFETCH_INTERVAL_MS| UQ["src/hooks/useQuery.ts\nuseAuditLogEntries\nuseSystemAuditLogEntries\nuseActiveProcesses"]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
C["src/lib/constants.ts\n(single source of truth)"]
C -->|AUDIT_LOG_FETCH_LIMIT\nAUDIT_LOG_DEFAULT_LIMIT| QS["server/services/query-service.ts\ngetAuditLogEntries\ngetSystemAuditLogEntries"]
C -->|MCP_MAX_RESULT_ROWS\nMCP_CATALOG_PAGE_SIZE| MCP["server/mcp.ts\nMAX_RESULT_ROWS\nPAGE_SIZE"]
C -->|AUDIT_LOG_FETCH_LIMIT\nLIVE_QUERY_REFETCH_INTERVAL_MS| UQ["src/hooks/useQuery.ts\nuseAuditLogEntries\nuseSystemAuditLogEntries\nuseActiveProcesses"]
Reviews (1): Last reviewed commit: "refactor: consolidate duplicated cross-c..." | Re-trigger Greptile |
| import { detectRequiredPermissions } from './lib/sql-permissions' | ||
| import { buildExecutableSql, formatExecutionError } from './lib/execute-sql' | ||
| import { auditSQL } from './lib/audit' | ||
| import { MCP_CATALOG_PAGE_SIZE, MCP_MAX_RESULT_ROWS } from '../src/lib/constants' |
There was a problem hiding this comment.
Server importing from
src/lib/ without tooling guard
server/ code now depends on a path inside src/lib/, which is typically the client-side tree. The file's own comment asks it to stay dependency-free, but there is no ESLint boundary rule or separate tsconfig path alias enforcing that invariant. If a future contributor adds any browser-only import to src/lib/constants.ts (or even accidentally imports from another src/lib/ module that does), the server will break at startup — and the error would only surface at runtime or in CI, not at edit time. A shared/ or common/ directory at the root, or a lint rule banning server/** from importing src/**, would make the constraint machine-checked rather than comment-enforced.
There was a problem hiding this comment.
Reasonable hardening idea, but worth noting this isn't a new boundary: server/ already imports from src/lib/ today — e.g. server/lib/sql-permissions.ts imports src/lib/sql/core and src/lib/sql/pg-system-functions. So this PR follows the established pattern rather than introducing the cross-tree dependency, and src/lib/constants.ts is pure literal export consts (no imports of its own), so the dependency-free invariant holds today.
Machine-enforcing it (an ESLint no-restricted-imports rule banning browser-only imports from server-reachable src/lib modules, or relocating the genuinely-shared pieces to a root shared/ dir) is a good idea — but it's a repo-wide change that should also cover the existing sql/* imports, so I'd do it as a separate follow-up rather than scope-creep this constants PR. Leaving as-is here.
What
Adds a dependency-free
src/lib/constants.tsas the single source of truth for constants that are duplicated or span the client/server boundary, and replaces the scattered magic numbers with named imports (task #10).AUDIT_LOG_FETCH_LIMITAUDIT_LOG_LIMITand server clampMath.min(req.limit, 1000)×2 — these had already drifted into the 500-vs-1000 bugAUDIT_LOG_DEFAULT_LIMIT: 100default in both audit handlersLIVE_QUERY_REFETCH_INTERVAL_MSrefetchInterval: 5000×3 (active sessions + both audit hooks)MCP_MAX_RESULT_ROWSMAX_RESULT_ROWSinmcp.tsMCP_CATALOG_PAGE_SIZEPAGE_SIZEinmcp.tsmcp.tskeeps its localMAX_RESULT_ROWS/PAGE_SIZEnames (now sourced from the shared module) so existing internal usages andtests/mcp.test.ts's import stay intact.Scope (deliberate)
Limited to duplicated / cross-tier / contract constants. Well-named feature-local constants (panel widths,
MOBILE_BREAKPOINT,MAX_AUTO_RETRIES, AI token caps, cookie maxAge, …) are intentionally left next to their feature — a global "constants drawer" hurts locality and review-ability. Scope approved by @tianzhou and @PG-Codex in the task thread.Verification
pnpm build— passed (existing Vite/Rolldown warnings only)pnpm test tests/audit.test.ts tests/mcp.test.ts— 53 passedeslinton changed lines — clean (the 2 pre-existingquery-service.tslint errors —tableInfoprefer-const, unuseddefinitionLower— are unrelated and left out of scope, consistent with prior PRs)🤖 Generated with Claude Code