Skip to content

refactor(convex): extract validators into separate files#37

Merged
larryro merged 4 commits into
mainfrom
refactor/extract-convex-validators
Dec 30, 2025
Merged

refactor(convex): extract validators into separate files#37
larryro merged 4 commits into
mainfrom
refactor/extract-convex-validators

Conversation

@larryro

@larryro larryro commented Dec 30, 2025

Copy link
Copy Markdown
Collaborator

Summary

  • Creates dedicated validators.ts files for each Convex model domain
  • Moves Convex validators from types.ts to separate validators.ts files
  • Reduces code in type files by ~1,470 lines while adding ~1,306 lines in organized validator files
  • Improves maintainability by separating validation logic from type definitions

Affected Domains

  • approvals
  • conversations
  • customers
  • documents
  • email_providers
  • integrations
  • organizations
  • products
  • tone_of_voice
  • websites
  • wf_definitions
  • wf_executions
  • wf_step_defs

Test plan

  • Verify Convex functions still work correctly with extracted validators
  • Run type checking to ensure no TypeScript errors
  • Test affected API endpoints

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor
    • Reorganized internal validation logic by separating validators into dedicated modules across the platform. This improves code structure and maintainability without affecting any functionality or user-facing behavior.

✏️ Tip: You can customize this high-level summary in your review settings.

- Create dedicated validators.ts files for each model domain
- Move Convex validators from types.ts to validators.ts files
- Reduces code duplication and improves maintainability
- Affected domains: approvals, conversations, customers, documents,
  email_providers, integrations, organizations, products, tone_of_voice,
  websites, wf_definitions, wf_executions, wf_step_defs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Dec 30, 2025

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR systematically refactors the codebase to separate validator definitions from type definitions across multiple model modules. New validators.ts files are created to house Convex validator definitions, while types.ts files are updated to use TypeScript type inference (via Infer<typeof validator>) instead of inline validator/interface declarations. Import statements are updated throughout the codebase to reference validators from their new module locations, and barrel index files are updated to re-export both validators and types separately. This consolidates validator logic in dedicated modules while deriving types from those validators.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • tale-project/poc2#440 — Introduces and uses approvalResourceTypeValidator alongside other approval validators that are also affected by this refactoring
  • talecorp/poc2#143 — Splits conversation validators and types into separate modules, which aligns with the conversation-related changes in this PR
  • optimize chat agent #5 — Modifies the same customer_action.ts file to update validator import sources alongside other validator-related changes

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
services/platform/convex/model/wf_executions/types.ts (1)

8-110: Document the manual types pattern and sync strategy.

The manual TypeScript interfaces are maintained separately from runtime validators, creating a risk of drift. While this separation can provide better IDE support, it requires careful coordination.

Consider one of these approaches:

  1. Document the pattern (quick fix): Add a comment explaining why types are manual and how to keep them synchronized with validators:

    /**
     * MANUAL TYPES (these rely on Doc types, not validators)
     * 
     * Note: These TypeScript interfaces are maintained separately from runtime
     * validators in ./validators.ts for better IDE support. When updating validators,
     * ensure corresponding type definitions are updated to match.
     */
  2. Use type inference (recommended): Import validators and derive types to ensure they stay in sync:

    import type { Infer } from 'convex/values';
    import {
      updateExecutionStatusArgsValidator,
      completeExecutionArgsValidator,
      // ... other validators
    } from './validators';
    
    export type UpdateExecutionStatusArgs = Infer<typeof updateExecutionStatusArgsValidator>;
    export type CompleteExecutionArgs = Infer<typeof completeExecutionArgsValidator>;

Based on learnings, approach #1 is acceptable for this codebase if properly documented.

services/platform/convex/model/integrations/types.ts (1)

73-73: Consider adding a comment explaining the Shopify API version.

A brief comment noting when this version was chosen or a link to Shopify's versioning documentation would help future maintainers understand update implications.

Comment thread services/platform/convex/model/conversations/types.ts
Comment thread services/platform/convex/model/conversations/validators.ts
Comment thread services/platform/convex/model/conversations/validators.ts
Comment thread services/platform/convex/model/conversations/validators.ts
Comment thread services/platform/convex/model/customers/validators.ts
Comment thread services/platform/convex/model/documents/validators.ts
Comment thread services/platform/convex/model/organizations/validators.ts
Comment thread services/platform/convex/model/wf_definitions/validators.ts
Comment thread services/platform/convex/model/wf_step_defs/validators.ts
- Use v.id('organizations') instead of v.string() for _id in organizationValidator
- Use workflowStatusValidator for status field in workflowUpdateValidator
- Use stepTypeValidator for stepType field in getStepsByTypeArgsValidator

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
larryro and others added 2 commits December 30, 2025 14:36
…alidators

The conversation return validators in conversations.ts were missing the
lastMessageAt field which is part of the schema (added for efficient
sorting by last message time). This caused ReturnsValidationError when
workflow actions returned conversation objects with this field populated.

Affected validators:
- getConversationById
- getConversationByExternalMessageId
- queryConversations
- getConversation (RLS)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ReactFlow's StoreUpdater component was detecting data changes on every
render because callback functions were included in node.data and edge.data
objects. Since function references change on each render, this triggered
an infinite update loop.

The fix:
- Create AutomationCallbacksContext to pass callbacks via React context
- Remove callback functions from node.data and edge.data objects
- Use stable stepsKey for memoization instead of callback dependencies
- Update AutomationStep to get callbacks from context

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@larryro larryro merged commit 9c2e381 into main Dec 30, 2025
2 checks passed
@larryro larryro deleted the refactor/extract-convex-validators branch December 30, 2025 08:02
larryro pushed a commit that referenced this pull request Dec 30, 2025
- Update conversationPriorityValidator to use 'medium' instead of 'normal'
  to match frontend usage
- Replace v.optional(v.string()) with v.optional(conversationPriorityValidator)
  in all conversation mutation/query definitions
- Update interface types (CreateConversationArgs, UpdateConversationsArgs,
  QueryConversationsArgs) to use ConversationPriority type
- Add 'urgent' to CONVERSATION_PRIORITY constant for consistency
- Add ConversationPriority type to workflow action helpers
- Update schema.ts comment to reflect correct priority values

Closes issue identified in PR #37 review (CodeRabbit comment #2652223390)
larryro pushed a commit that referenced this pull request Dec 30, 2025
- Update conversationPriorityValidator to use 'medium' instead of 'normal'
  to match frontend usage
- Replace v.optional(v.string()) with v.optional(conversationPriorityValidator)
  in all conversation mutation/query definitions
- Update interface types (CreateConversationArgs, UpdateConversationsArgs,
  QueryConversationsArgs) to use ConversationPriority type
- Add 'urgent' to CONVERSATION_PRIORITY constant for consistency
- Add ConversationPriority type to workflow action helpers
- Update schema.ts comment to reflect correct priority values

Closes issue identified in PR #37 review (CodeRabbit comment #2652223390)
yannickmonney pushed a commit that referenced this pull request Apr 8, 2026
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
larryro added a commit that referenced this pull request May 17, 2026
…— limits + analytics polish

Closes round-5 findings #32, #33, #37, #38, #44.

- `security:tts-audio-fetch` switches from fixed-window 120/min to
  token-bucket rate:120/min, capacity:240. A single ~200-chunk replay
  on a NAT/office IP no longer hits a minute-boundary 429 mid-playback;
  sustained traffic still settles at the same 120/min rate.
- `gcOrgTtsChunks` cron moves from daily (`0 5 * * *`) to hourly
  (`0 * * * *`). Per-run caps are unchanged; a transient failure
  recovers in ~60 min instead of ~24 hours, and deployments with more
  orgs than `MAX_ORGS_PER_RUN` finish a full sweep within a day.
- `getOrgUsageMetrics` topModels now excludes TTS rows. Mixing them
  with LLM rows on a single "Tokens" axis showed misleading "0 tokens"
  entries for TTS spend (TTS bills per character, transcription per
  minute, LLM per token). Mirrors transcription's existing exclusion.
  A kind-aware "Units" column is a follow-up.
- `personalization-settings.tsx` capability-probe catch distinguishes
  transient ConvexError codes (RATE_LIMITED, CONTENTION) from genuine
  unavailability. On a transient error the page leaves
  `providerAvailable` as `null` (unknown) instead of flipping into the
  destructive "provider unavailable" banner. Helper isolated via the
  `isTransientProbeError` guard.
- `fr.json` voice-output strings replace `touche` with `clique` for
  blocked / decode-error labels. `touche` reads as the noun "key
  (keyboard)" or the 2nd-person indicative of `toucher`; the rest of
  fr.json already uses `clique` consistently for UI click/tap actions.
larryro added a commit that referenced this pull request May 17, 2026
…— limits + analytics polish

Closes round-5 findings #32, #33, #37, #38, #44.

- `security:tts-audio-fetch` switches from fixed-window 120/min to
  token-bucket rate:120/min, capacity:240. A single ~200-chunk replay
  on a NAT/office IP no longer hits a minute-boundary 429 mid-playback;
  sustained traffic still settles at the same 120/min rate.
- `gcOrgTtsChunks` cron moves from daily (`0 5 * * *`) to hourly
  (`0 * * * *`). Per-run caps are unchanged; a transient failure
  recovers in ~60 min instead of ~24 hours, and deployments with more
  orgs than `MAX_ORGS_PER_RUN` finish a full sweep within a day.
- `getOrgUsageMetrics` topModels now excludes TTS rows. Mixing them
  with LLM rows on a single "Tokens" axis showed misleading "0 tokens"
  entries for TTS spend (TTS bills per character, transcription per
  minute, LLM per token). Mirrors transcription's existing exclusion.
  A kind-aware "Units" column is a follow-up.
- `personalization-settings.tsx` capability-probe catch distinguishes
  transient ConvexError codes (RATE_LIMITED, CONTENTION) from genuine
  unavailability. On a transient error the page leaves
  `providerAvailable` as `null` (unknown) instead of flipping into the
  destructive "provider unavailable" banner. Helper isolated via the
  `isTransientProbeError` guard.
- `fr.json` voice-output strings replace `touche` with `clique` for
  blocked / decode-error labels. `touche` reads as the noun "key
  (keyboard)" or the 2nd-person indicative of `toucher`; the rest of
  fr.json already uses `clique` consistently for UI click/tap actions.
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.

1 participant