feat(tanstack): initialize TanStack project with routing, API, and error handling components

This commit is contained in:
Mauricio Siu
2025-04-06 03:53:25 -06:00
parent a0636d8083
commit 0d6ff904a8
51 changed files with 7387 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
import { createMiddleware } from '@tanstack/react-start'
const preLogMiddleware = createMiddleware()
.client(async (ctx) => {
const clientTime = new Date()
return ctx.next({
context: {
clientTime,
},
sendContext: {
clientTime,
},
})
})
.server(async (ctx) => {
const serverTime = new Date()
return ctx.next({
sendContext: {
serverTime,
durationToServer:
serverTime.getTime() - ctx.context.clientTime.getTime(),
},
})
})
export const logMiddleware = createMiddleware()
.middleware([preLogMiddleware])
.client(async (ctx) => {
const res = await ctx.next()
const now = new Date()
console.log('Client Req/Res:', {
duration: res.context.clientTime.getTime() - now.getTime(),
durationToServer: res.context.durationToServer,
durationFromServer: now.getTime() - res.context.serverTime.getTime(),
})
return res
})

View File

@@ -0,0 +1,36 @@
import { notFound } from '@tanstack/react-router'
import { createServerFn } from '@tanstack/react-start'
import axios from 'redaxios'
export type PostType = {
id: string
title: string
body: string
}
export const fetchPost = createServerFn({ method: 'GET' })
.validator((d: string) => d)
.handler(async ({ data }) => {
console.info(`Fetching post with id ${data}...`)
const post = await axios
.get<PostType>(`https://jsonplaceholder.typicode.com/posts/${data}`)
.then((r) => r.data)
.catch((err) => {
console.error(err)
if (err.status === 404) {
throw notFound()
}
throw err
})
return post
})
export const fetchPosts = createServerFn({ method: 'GET' }).handler(
async () => {
console.info('Fetching posts...')
return axios
.get<Array<PostType>>('https://jsonplaceholder.typicode.com/posts')
.then((r) => r.data.slice(0, 10))
},
)

33
tanstack/src/utils/seo.ts Normal file
View File

@@ -0,0 +1,33 @@
export const seo = ({
title,
description,
keywords,
image,
}: {
title: string
description?: string
image?: string
keywords?: string
}) => {
const tags = [
{ title },
{ name: 'description', content: description },
{ name: 'keywords', content: keywords },
{ name: 'twitter:title', content: title },
{ name: 'twitter:description', content: description },
{ name: 'twitter:creator', content: '@tannerlinsley' },
{ name: 'twitter:site', content: '@tannerlinsley' },
{ name: 'og:type', content: 'website' },
{ name: 'og:title', content: title },
{ name: 'og:description', content: description },
...(image
? [
{ name: 'twitter:image', content: image },
{ name: 'twitter:card', content: 'summary_large_image' },
{ name: 'og:image', content: image },
]
: []),
]
return tags
}

View File

@@ -0,0 +1,7 @@
export type User = {
id: number
name: string
email: string
}
export const DEPLOY_URL = 'http://localhost:3000'