// The typed hook surface for the `app` api — bound ONCE, here, and imported by // every screen instead of `@voltro/client`. // // `AppProcedures` is emitted by codegen into the sibling api's // `rpcGroup.generated.ts`: a type-level map of every rpc tag to the descriptor // behind it. Feeding it to `createHooks` makes the tag a literal union and the // input/output types INFER: // // const notes = useSubscription('notes.list') // rows, typed // const create = useMutation('notes.create') // input + output typed // // So no screen declares a row `interface` mirroring the api any more. The old // `useSubscription>('app', 'notes.list')` spelled the api // name at every call site, left the tag an unchecked string (a typo was a // runtime error), and the `` was an ASSERTION nothing compared against the // server. All three are compile-checked now. // // `'app'` is the key this project's api is registered under. The api is a // type-only import — `import type` is erased, so Metro never resolves it and // nothing server-side reaches the bundle. It is a devDependency for exactly // that reason; scaffold the pair (`create-project --api=api-backend --mobile`), // which is what this template's README already assumes. // // RUNTIME: live. `voltro codegen` writes this app's api binding into // `.framework/mobileApis.generated.ts` (from `voltro.mobile.ts`), and // `../client.ts` connects it through the same supervisor the web client uses. // The start scripts run codegen, so `pnpm ios` needs no separate step. import { createHooks } from '@voltro/client' import type { AppProcedures } from '@{{projectName}}/api/rpcGroup' // Destructured on purpose — `react-hooks/rules-of-hooks` only treats a member // call as a hook when the object is PascalCase, so top-level `useX` identifiers // are what keep the React lint rules working at every call site. export const { useSubscription, useMutation, useAction } = createHooks('app')