Files
crowd-funder-for-time-pwa/doc/DEEP_LINKS.md
T

5.2 KiB

TimeSafari Deep Linking Documentation

Type System Overview

The deep linking system uses a multi-layered type safety approach:

  1. Runtime Validation (Zod Schemas)

    • Validates URL structure
    • Enforces parameter requirements
    • Sanitizes input data
    • Provides detailed validation errors
    • Generates TypeScript types automatically
  2. TypeScript Types

    • Generated from Zod schemas using z.infer
    • Ensures compile-time type safety
    • Provides IDE autocompletion
    • Catches type errors during development
    • Maintains single source of truth for types
  3. Router Integration

    • Type-safe parameter passing
    • Route-specific parameter validation
    • Query parameter type checking
    • Automatic type inference for route parameters

Type System Implementation

Zod Schema to TypeScript Type Generation

// Define the schema
const claimSchema = z.object({
  id: z.string(),
  view: z.enum(["details", "certificate", "raw"]).optional()
});

// TypeScript type is automatically generated
type ClaimParams = z.infer<typeof claimSchema>;
// Equivalent to:
// type ClaimParams = {
//   id: string;
//   view?: "details" | "certificate" | "raw";
// }

Type Safety Layers

  1. Schema Definition

    // src/interfaces/deepLinks.ts
    export const deepLinkSchemas = {
      claim: z.object({
        id: z.string(),
        view: z.enum(["details", "certificate", "raw"]).optional()
      }),
      // Other route schemas...
    };
    
  2. Type Generation

    // Types are automatically generated from schemas
    export type DeepLinkParams = {
      [K in keyof typeof deepLinkSchemas]: z.infer<(typeof deepLinkSchemas)[K]>;
    };
    
  3. Runtime Validation

    // In DeepLinkHandler
    const result = deepLinkSchemas.claim.safeParse(params);
    if (!result.success) {
      // Handle validation errors
      console.error(result.error);
    }
    

Error Handling Types

export interface DeepLinkError extends Error {
  code: string;
  details?: unknown;
}

// Usage in error handling
try {
  await handler.handleDeepLink(url);
} catch (error) {
  if (error instanceof DeepLinkError) {
    // Type-safe error handling
    console.error(error.code, error.message);
  }
}

Implementation Files

  • src/interfaces/deepLinks.ts: Type definitions and validation schemas
  • src/services/deepLinks.ts: Deep link processing service
  • src/main.capacitor.ts: Capacitor integration
  • src/views/DeepLinkRedirectView.vue: Page to handle links to both mobile and web

Type Safety Examples

// Parameter type safety
type ClaimParams = DeepLinkParams["claim"];
// TypeScript knows this has:
// - id: string
// - view?: "details" | "certificate" | "raw"
// Runtime validation
const result = deepLinkSchemas.claim.safeParse({
id: "123",
view: "details"
});
// Validates at runtime with detailed error messages

Supported URL Schemes

All deep links follow the format: timesafari://<route>/<param>?<query>

App Routes

These take no parameters.

  • timesafari:// — no route at all opens the app at the home feed.
  • timesafari://account
  • timesafari://discover
    • Query params, all optional:
      • searchText: prefills the search box
      • searchPeople: any value switches to the people tab
      • hideOnboarding: "true" suppresses the onboarding prompt
  • timesafari://invite-one
  • timesafari://new-activity
  • timesafari://onboard-meeting-list
  • timesafari://projects
  • timesafari://recent-offers-to-user
  • timesafari://recent-offers-to-user-projects
  • timesafari://search-area
  • timesafari://share-my-contact-info
  • timesafari://statistics

Help Routes

  • timesafari://help
  • timesafari://help-notifications
  • timesafari://help-notification-types
  • timesafari://help-onboarding
  • timesafari://help-terms

Claim Routes

  • timesafari://claim/:id

    • Query params:
      • view: "details" | "certificate" | "raw"
  • timesafari://claim-cert/:id

  • timesafari://claim-add-raw/:id

    • Query params:
      • claim: JSON string of claim data
      • claimJwtId: JWT ID for claim

Contact Routes

  • timesafari://contact-edit/:did

  • timesafari://contact-import/:jwt

    • Query params:
      • contacts: JSON array of contacts
  • timesafari://contact-qr and timesafari://contact-qr-scan-full

    Both open the page that displays your contact QR code, scans someone else's, and prompts you to set your name if your identity does not carry one. The destination view is chosen by platform, not by which of the two paths was used: a full-screen camera view where a native scanner is available, an ordinary page where the in-page web reader is used.

    Prefer contact-qr when publishing a link. The same path is appended to the web address by /deep-link/<path>, and /contact-qr is the web route that serves this page in a browser.

Project Routes

  • timesafari://project/:id
    • Query params:
      • view: "details" | "edit"

Invite Routes

  • timesafari://invite-one-accept/:jwt
    • Query params:
      • type: "one" | "many"

Gift Routes

  • timesafari://confirm-gift/:id
    • Query params:
      • action: "confirm" | "details"

Offer Routes

  • timesafari://offer-details/:id
    • Query params:
      • view: "details"