dink-pets-shared
v1.0.14
Published
Shared types, schemas, and utilities for DINK Pets mobile app and server.
Readme
dink-pets-shared
Shared types, schemas, and utilities for DINK Pets mobile app and server.
Enum Architecture
Enums are auto-generated from Prisma schema. Do not edit src/enums.ts manually.
Why?
Prisma's generated client includes Node.js code that crashes React Native. We extract enum definitions to pure TypeScript that works everywhere.
Structure
Each enum generates three exports:
// Array of valid values (camelCase, plural)
export const petRoles = ["OWNER", "COOWNER", "CARETAKER"] as const;
// Zod schema for validation (PascalCase)
export const PetRole = z.enum(petRoles);
// TypeScript type inferred from Zod
export type PetRole = z.infer<typeof PetRole>;Why Zod schemas instead of TypeScript enums?
TypeScript enums are nominally typed. Even with identical values, TS treats enums from different files as incompatible types:
// These are INCOMPATIBLE even though values match:
enum PrismaRole { OWNER = "OWNER" } // from Prisma client
enum SharedRole { OWNER = "OWNER" } // from shared packageZod schemas produce string union types which are structurally typed:
type PetRole = "OWNER" | "COOWNER" | "CARETAKER"
// Prisma's "OWNER" string is assignable to this union
const fromPrisma: PrismaEnum.PetRole = PrismaEnum.OWNER;
const works: PetRole = fromPrisma; // OK!Import Rules
| Context | Import From | Why |
|---------|-------------|-----|
| Server (database ops) | ./generated/prisma/index.js | Use Prisma's types for queries |
| Mobile | dink-pets-shared | Can't use Prisma (Node.js code) |
| Shared validation | ./enums.js (local) | Zod schemas accept any matching string |
Regenerating
Enums regenerate automatically:
# In shared/
npm run build
# In server/ (runs postgenerate hook)
npx prisma generateManual regeneration:
node shared/scripts/generate-enums.jsUsage
Accessing string values:
Use .enum property on the Zod schema:
// Get the string "WALK"
ActivityType.enum.WALK // "WALK"
// Use in z.literal() for discriminated unions
z.literal(ActivityType.enum.WALK)
// Use in Record keys
const labels: Record<AchievementType, string> = {
[AchievementType.enum.FIRST_WALK]: "First Walk",
};Creating z.enum() validators:
Use the const array, not the Zod schema:
// Correct - petRoles is the array
z.enum(petRoles)
// Wrong - PetRole is already a z.enum schema
z.enum(PetRole) // Type errorType annotations:
// Use the type (same name as schema)
function checkRole(role: PetRole) { ... }
// Works with Prisma values (structural typing)
const prismaRole = await prisma.petAccess.findFirst();
checkRole(prismaRole.role); // OK!Files
scripts/generate-enums.js- Generator scriptsrc/enums.ts- Auto-generated, gitignored
