Skip to main content

Lib Directory

Location: src/lib/

Purpose: Shared utility libraries — Supabase client setup, permission helpers, static data, and small pure helpers. This is the only place where service-role / edge-side primitives are defined.

Structure

lib/
├── acessControl/ # (Legacy) feature-access checking
│ └── canAccessFeature.ts

├── constants/
│ └── superAdmin.ts # SUPER_ADMIN_TEAM_ID (server-only constant, hydrated to TeamsContext)

├── data/ # Static reference data
│ ├── california-counties.ts
│ ├── jurisdictionType.ts
│ ├── permissions/
│ │ ├── campaign-sub-groups.ts
│ │ ├── primary-groups.ts
│ │ └── standard-permissions.ts
│ ├── us-states.ts
│ └── usTimeZones.ts

├── email/ # Server-only email helpers
│ ├── invitation-email-templates.ts # HTML templates for team / campaign invites
│ └── send-invite-email.ts # Wraps the `send-email` Supabase Edge Function

├── permissions/
│ └── fetchPermissionsSnapshot.ts # Edge-safe `fetch` against get-permissions-snapshot (Next.js fetch cache + tags)

├── supabase/ # Supabase clients + session middleware
│ ├── check-env-vars.ts # Validates required env vars at startup
│ ├── client.ts # Browser client (anon key)
│ ├── server.ts # SSR client (anon key, cookie-aware)
│ ├── specialServer.ts # Service-role client (server-only)
│ └── updateSession.ts # Edge middleware logic — session sync + permissions cache invalidation

├── chartUtils.ts # Helpers consumed by recharts wrappers
├── cn.ts # `cn(...)` clsx + tailwind-merge
├── date-utils.ts # Date formatting / coercion
├── extractIdsFromPath.ts # Pulls teamId / campaignId out of a URL pathname
├── formatNumber.ts # Locale-aware number formatting
├── getFilterPetColumns.ts # Petition table column selectors
├── getPetitionContextData.ts # Hydrates the petition context for a route
├── getRedirectUrl.ts # Cleans / normalizes the post-login redirect URL
├── getUtcMidnight.ts # Helper for `created_at`-based date filters
├── petition-utils.ts # Petition-specific helpers
├── redis.ts # Singleton Upstash Redis connection + signer set helpers
├── server-utils.ts # `createSuccessResponse` / `createErrorResponse` for FormState
├── team-member-hierarchy.ts # `roles.hierarchy_level` lookups + `canActOnHierarchyLevel`
├── use-forwarded-ref.tsx # Compose forwarded refs
├── utils.ts # `encodedRedirect`, contrast color, percentage format, keyboard helpers, etc.
└── validateDateInput.ts # Date input field validators

Highlights

Supabase clients

  • supabase/client.ts — browser-side, anon key. Use in client components only.
  • supabase/server.ts — RSC / Route Handler client, anon key, cookie-aware via @supabase/ssr. Use in Server Components, Server Actions, and Route Handlers.
  • supabase/specialServer.ts — service-role client. Server-only. Used by app/api/charts/[id]/route.ts and any internal job that must bypass RLS.
  • supabase/updateSession.ts — invoked by the edge middleware. Refreshes Supabase cookies (getClaims() to avoid a network call), redirects unauthenticated requests to /auth/sign-in, and on a real browser refresh hits /api/permissions/revalidate to drop the cached permissions snapshot.

Permissions

  • lib/permissions/fetchPermissionsSnapshot.ts — edge-safe loader. Hits the get-permissions-snapshot Supabase Edge Function via fetch(...) with Next.js fetch caching (revalidate: 3600, tags: [permissions-${userId}]). Safe to import from middleware, route handlers, server actions and RSC.
  • lib/constants/superAdmin.ts — defines SUPER_ADMIN_TEAM_ID. Server-only. Client code reads it through TeamsContext.superAdminTeamId.

Redis

lib/redis.ts lazily creates a TLS connection to Upstash and exposes:

  • getRedisConnection() / resetRedisConnection() — singleton management with reconnect on ECONNRESET / Connection is closed.
  • addSignerToCampaignRedis(campaignId, voterId) / removeSignerFromCampaignRedis(...) — operate on the campaign:{id}:signers set.
  • Process-level SIGTERM / SIGINT handlers gracefully quit() the client.

Hierarchy

lib/team-member-hierarchy.ts is the canonical place to read roles.hierarchy_level for a given user/team. canActOnHierarchyLevel(actor, target, isSuperAdminPrimary) is used by all member-management actions to forbid sideways or upward role changes. See complex-logic/role-hierarchy.

Email

  • lib/email/invitation-email-templates.ts — HTML templates for team / sub-team invites.
  • lib/email/send-invite-email.ts — thin wrapper around supabase.functions.invoke("send-email", ...).