// The app's deep-link table + a pure resolver. // // A deep link maps an inbound URL — a universal link (`https://…/orders/42`), a // custom-scheme URL (`{{appName}}://orders/42`), or a push payload's // `data.deepLink` — to an in-app navigation. `defineDeepLink` + the pure matcher // come from `@voltro/react-native`; this module is browser/RN-safe (no Metro, no // screens), which is exactly why it is unit-testable without a simulator. // // Declaration order wins in `dispatchDeepLink`, so list more-specific patterns // FIRST. The `navigate` callback is injected (the screen layer passes // expo-router's `router.push`), keeping this table pure + testable. import { defineDeepLink, dispatchDeepLink, type DeepLinkDescriptor, } from '@voltro/react-native' /** Build the app's deep links against a navigate function (expo-router's `push`). */ export const makeDeepLinks = ( navigate: (href: string) => void, ): ReadonlyArray => [ defineDeepLink({ pattern: '/orders/:id', handler: ({ id }) => navigate(`/orders/${id}`) }), defineDeepLink({ pattern: '/settings', handler: () => navigate('/settings') }), ] /** * Route an inbound URL through the link table. Returns `true` when a link * matched (its handler ran → navigation happened), `false` when nothing did so * the caller can fall back to a default route. */ export const handleDeepLink = ( links: ReadonlyArray, url: string, ): boolean => { // `dispatchDeepLink` matches AND runs. Doing it in two steps here does not // typecheck: the descriptors are a heterogeneous array, so the handler that // comes back declares params the match that produced it cannot satisfy. return dispatchDeepLink(links, url) !== null }