feat(deploy): production deployment setup and fixes

- Debian-based api image (bookworm-slim), docker/debian mirrors, prisma
  binaryTargets for openssl 3.0
- nginx: admin SPA under /admin, TLS via acme.sh (ZeroSSL) + auto-renewal
  cron, http->https redirect
- prisma: add origin_goods.delisted migration, sync missing schema
  (good_image/tag_font_color/good_tags), fix users.createdAt Timestamptz
- api: CORS wildcard reflection, helmet CORP cross-origin, price
  backfill in persistProductDetail, categoryIcon ancestor fallback,
  mediaByColor per-color gallery in public goods detail
- admin: /admin base path (vite + router)
- import-data.mjs: udt_name casting, serial sequence advance fix
This commit is contained in:
yeuimu
2026-08-26 14:23:09 +08:00
parent be0b90e68f
commit 6c61a4e871
982 changed files with 74156 additions and 179393 deletions
@@ -1,87 +0,0 @@
# Async Patterns
In Next.js 15+, `params`, `searchParams`, `cookies()`, and `headers()` are asynchronous.
## Async Params and SearchParams
Always type them as `Promise<...>` and await them.
### Pages and Layouts
```tsx
type Props = { params: Promise<{ slug: string }> }
export default async function Page({ params }: Props) {
const { slug } = await params
}
```
### Route Handlers
```tsx
export async function GET(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
const { id } = await params
}
```
### SearchParams
```tsx
type Props = {
params: Promise<{ slug: string }>
searchParams: Promise<{ query?: string }>
}
export default async function Page({ params, searchParams }: Props) {
const { slug } = await params
const { query } = await searchParams
}
```
### Synchronous Components
Use `React.use()` for non-async components:
```tsx
import { use } from 'react'
type Props = { params: Promise<{ slug: string }> }
export default function Page({ params }: Props) {
const { slug } = use(params)
}
```
### generateMetadata
```tsx
type Props = { params: Promise<{ slug: string }> }
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { slug } = await params
return { title: slug }
}
```
## Async Cookies and Headers
```tsx
import { cookies, headers } from 'next/headers'
export default async function Page() {
const cookieStore = await cookies()
const headersList = await headers()
const theme = cookieStore.get('theme')
const userAgent = headersList.get('user-agent')
}
```
## Migration Codemod
```bash
npx @next/codemod@latest next-async-request-api .
```