#TanStack Start + Query + db access example

1 messages · Page 1 of 1 (latest)

verbal wadi
#

Does anyone have a simple CRUD example app that uses Start and Query with db access? I'm porting a side project from NextJS which uses these + Drizzle and trying to find a tidy way to structure my query functions => server functions => Drizzle functions for best readability and reusability

fossil fern
#

I can't share the repository I'm working on but are you more interested in the architecture or the setup (e.g. how things are wired up)?

verbal wadi
#

I'm trying to get things cleanly organised to avoid any accidental direct calling of server code from client code (mostly due to copying across NextJS server actions into the app). What I've come up with for now is -

// /routes/contacts.tsx
export const Route = createFileRoute('/contacts')({
  component: ContactsPage,
  loader: ({ context }) => {
    context.queryClient.prefetchQuery(contactsQueryOptions())
  },
  ssr: false,
})

function ContactsPage() {
  const contacts = useContacts()
  return ( ... )
}
// /components/contacts/useContacts.tsx
export const contactsQueryOptions = () =>
  queryOptions({
    queryKey: ['contacts'],
    queryFn: async () => await getContactsSF(),
  })

export default function useContacts() {
  const { data: contact } = useQuery(contactsQueryOptions())
  return contact
}
// /lib/server/contactsServer.ts
export const getContactSF = createServerFn({ method: 'GET' })
  .validator((data: number) => data)
  .handler(async (ctx) => getContact(ctx.data))

export const getContactSF = createServerFn({ method: 'GET' })
  .validator((data: number) => data)
  .handler(async (ctx) => getContact(ctx.data))

export const addContactSF = createServerFn({ method: 'POST' })
  .validator((data: NewContact) => data)
  .handler(async ({ data }) => await addContact(data))
// /lib/db/contacts.ts
export async function getContact(contactId: number) {
  const result = await db.query.contacts.findFirst({
    where: (contacts, { eq }) => eq(contacts.id, contactId),
  })
  return result
}

export async function addContact(contact: NewContact) {
  const result = await db.insert(contacts).values([contact])
  return result.changes
}