chore: add ESLint rules for date formatting and .collect() conventions#379
Conversation
Add no-restricted-syntax rules to catch native toLocaleString/toLocaleDateString/ toLocaleTimeString usage (directing to useDateFormat hook or formatDate utility) and .collect() in Convex files (directing to for-await or paginated queries). Migrate existing violations to use shared date formatting utilities and add justified eslint-disable comments for bounded .collect() usages. Fix Badge variant types in audit log table.
📝 WalkthroughWalkthroughThis pull request centralizes date formatting across the codebase by introducing a Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
services/platform/app/features/settings/audit-logs/components/audit-log-table.tsx (1)
86-97: 🧹 Nitpick | 🔵 TrivialBadge variant mapping looks correct; consider extracting for readability.
The nested ternary on line 90 is functional but dense. A small helper or map would improve scanability, especially if more statuses are added later.
♻️ Optional: extract status-to-variant mapping
+const statusVariantMap: Record<string, 'green' | 'yellow' | 'destructive'> = { + success: 'green', + denied: 'yellow', +}; + cell: ({ row }) => { const status = row.original.status; return ( <Badge - variant={status === 'success' ? 'green' : status === 'denied' ? 'yellow' : 'destructive'} + variant={statusVariantMap[status] ?? 'destructive'} > {status} </Badge> ); },services/platform/app/features/settings/api-keys/components/api-key-table.tsx (1)
52-80: 🧹 Nitpick | 🔵 TrivialNo date format preset specified — intentional?
All three
formatDatecalls here omit the preset argument, whileaudit-log-table.tsx(line 127) andhuman-input-request-card.tsx(line 243) pass'long'. If the default preset produces a shorter/different format that's suitable for table cells, this is fine. Otherwise, consider aligning on an explicit preset for consistency across the app.
🤖 Fix all issues with AI agents
In `@services/platform/app/features/chat/components/human-input-request-card.tsx`:
- Line 243: Remove the unnecessary new Date() wrapper around timestamp in the
human input card and align the preset used by formatDate with the other
component: replace formatDate(new Date(timestamp), 'long') with either
formatDate(timestamp) to use the default ('medium') preset (matching
api-key-table's formatDate(row.original.createdAt)) or explicitly use
formatDate(timestamp, 'medium'); if you intentionally need the 'long' preset for
different visual context, keep 'long' but add a short comment in
human-input-request-card explaining why it differs from api-key-table to make
the divergence explicit.
In
`@services/platform/app/features/settings/api-keys/components/api-key-table.tsx`:
- Line 94: The useDateFormat hook returns new function references (formatDate,
formatDateSmartWithLocale, formatDateHeaderWithLocale, formatRelative) each
render which invalidates memoization where formatDate is a dependency; fix this
by wrapping each exported formatter in useCallback inside useDateFormat (e.g.,
create formatDateWithLocale, formatDateSmartWithLocale,
formatDateHeaderWithLocale, formatRelative using useCallback and listing their
real deps like locale and any t/locale-derived values) so their references are
stable and memoized consumers (such as the columns memo in api-key-table.tsx)
won't rerun on every render.
In `@services/platform/eslint.config.mjs`:
- Around line 65-77: The override for convex files replaces the earlier
no-restricted-syntax array, dropping the toLocale* selectors; update the convex
override so its rules.no-restricted-syntax array merges the existing
date-formatting selectors with the collect selector instead of replacing them.
Locate the rule key "no-restricted-syntax" in the convex-specific config object
(the block containing the selector
'CallExpression[callee.property.name="collect"]') and add the three toLocale
selectors (e.g., a selector matching
CallExpression[callee.property.name=/toLocale(Date|Time)?String/]) into that
same array so both restrictions apply to convex/**/*.ts files.
- Around line 57-61: The current ESLint rule using the AST selector
CallExpression[callee.property.name="toLocaleString"] falsely flags number
formatting too; update the rule so it only targets Date usages (e.g., restrict
the selector to calls on Date instances like
CallExpression[callee.object.type="Identifier"][callee.property.name="toLocaleString"]
with an additional type check for Date) or split into two rules (one for dates
that suggests useDateFormat()/formatDate() and one for numeric formatting with
an appropriate message), and if you keep a broad selector, at minimum change the
message to mention both date and number formatting to avoid misleading guidance.
…d-convention-fixes # Conflicts: # services/platform/app/features/chat/components/human-input-request-card.tsx # services/platform/app/features/settings/audit-logs/components/audit-log-table.tsx # services/platform/lib/utils/onedrive-helpers.ts
- Remove duplicate useDateFormat import in api-key-table - Update ESLint messages to reference useFormatDate() hook - Merge date formatting selectors into Convex ESLint block to prevent flat config override from silently dropping them
Add no-restricted-syntax rules to catch native toLocaleString/toLocaleDateString/ toLocaleTimeString usage (directing to useDateFormat hook or formatDate utility) and .collect() in Convex files (directing to for-await or paginated queries).
Migrate existing violations to use shared date formatting utilities and add justified eslint-disable comments for bounded .collect() usages. Fix Badge variant types in audit log table.
Summary by CodeRabbit
Release Notes
Bug Fixes
Chores