/** * @file Deep Link Type Definitions and Validation Schemas * @author Matthew Raymer * * This file defines the type system and validation schemas for deep linking in the TimeSafari app. * It uses Zod for runtime validation while providing TypeScript types for compile-time checking. * * Type Strategy: * 1. Define base URL schema to validate the fundamental deep link structure * 2. Define route-specific parameter schemas with exact validation rules * 3. Generate TypeScript types from Zod schemas for type safety * 4. Export both schemas and types for use in deep link handling * * Usage: * - Import schemas for runtime validation in deep link handlers * - Import types for type-safe parameter handling in components * - Use DeepLinkParams type for type-safe access to route parameters * * @example * // Runtime validation * const params = deepLinkSchemas.claim.parse({ id: "123", view: "details" }); * * // Type-safe parameter access * function handleClaimParams(params: DeepLinkParams["claim"]) { * // TypeScript knows params.id exists and params.view is optional * } */ import { z } from "zod"; // Parameter validation schemas for each route type export const deepLinkSchemas = { claim: z.object({ id: z.string(), }), "claim-add-raw": z.object({ id: z.string(), claim: z.string().optional(), claimJwtId: z.string().optional(), }), "claim-cert": z.object({ id: z.string(), }), "confirm-gift": z.object({ id: z.string(), }), "contact-edit": z.object({ did: z.string(), }), "contact-import": z.object({ jwt: z.string(), }), contacts: z.object({ contactJwt: z.string().optional(), inviteJwt: z.string().optional(), }), did: z.object({ did: z.string(), }), "invite-one-accept": z.object({ // optional because A) it could be a query param, and B) the page displays an input if things go wrong jwt: z.string().optional(), }), "onboard-meeting-members": z.object({ id: z.string(), }), project: z.object({ id: z.string(), }), "user-profile": z.object({ id: z.string(), }), }; // Create a type from the array export type DeepLinkRoute = (typeof VALID_DEEP_LINK_ROUTES)[number]; // Update your schema definitions to use this type export const baseUrlSchema = z.object({ scheme: z.literal("timesafari"), path: z.string(), queryParams: z.record(z.string()).optional(), }); // Add a union type of all valid route paths export const VALID_DEEP_LINK_ROUTES = Object.keys( deepLinkSchemas, ) as readonly (keyof typeof deepLinkSchemas)[]; export type DeepLinkParams = { [K in keyof typeof deepLinkSchemas]: z.infer<(typeof deepLinkSchemas)[K]>; }; export interface DeepLinkError extends Error { code: string; details?: unknown; } // Use the type to ensure route validation export const routeSchema = z.enum( VALID_DEEP_LINK_ROUTES as [string, ...string[]], );