Skip to main content

Types Directory

Location: src/types/

Purpose: TypeScript type definitions and interfaces shared across the application. Each file owns a single domain.

Structure

types/
├── campaign.ts # CampaignType (id, name, slug, banners, colors, etc.)
├── common.ts # QueryResponse — { message, error, data }
├── credentialsRecord.ts # External-service credentials records
├── dashboard.ts # Dashboard config + chart shapes for the dashboard builder
├── error.ts # Generic error wrapper type
├── form.ts # FormState — { message, error, data?, zodIssues? }
├── formComponent.ts # Shared form-component prop types
├── permissionKey.ts # PermissionKeyType
├── permissionSetsRecord.ts # Responsibilities (permission-set bundles)
├── petitions.ts # Petition + format + circulator types
├── rateRecord.ts # Rate ladder records for circulators
├── regionRecord.ts # Region (sub-area) records
├── rolesRecord.ts # Role + hierarchy_level + scope
├── signature.ts # Signature row + ESFormEntry
├── teamsRecord.ts # Team + sub-team + UserTeamsRecordType
├── transactionRecord.ts # Circulator transactions
├── turnInRecord.ts # Turn-in records
├── user.ts # UserType
└── voter.ts # Voter / person search types returned by Directus

Key shared types

  • QueryResponse (common.ts) — return shape for every service in src/services/**: { message: string; error: boolean; data: any }.
  • FormState (form.ts) — return shape for every Server Action: { message: string; error: boolean; data?: unknown; zodIssues?: Record<string, string[]> }.
  • SessionContext (defined in src/middleware/types.ts, re-used here via TeamsContext) — surfaces permissionKeys, userTeamRole, etc., to the client.
  • PermissionsSnapshot (defined in src/lib/permissions/fetchPermissionsSnapshot.ts) — { teamAccess, campaignAccess?, permissionKeys? } returned by the get-permissions-snapshot edge function.

Conventions

  • Files are named after the domain noun, mostly camelCase.ts.
  • Database "record" types end in Record (e.g. rateRecord.ts).
  • Re-use shared envelopes (QueryResponse, FormState) instead of inventing per-call shapes.