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
+61 -61
View File
@@ -1,61 +1,61 @@
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Patch,
Post,
UseGuards,
} from '@nestjs/common';
import {
ApiBearerAuth,
ApiOperation,
ApiTags,
} from '@nestjs/swagger';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { CountriesService } from './countries.service';
import { CreateCountryDto } from './dto/create-country.dto';
import { UpdateCountryDto } from './dto/update-country.dto';
@ApiTags('countries')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Controller('countries')
export class CountriesController {
constructor(private readonly service: CountriesService) {}
@Get()
@ApiOperation({ summary: 'List all countries' })
findAll() {
return this.service.findAll();
}
@Get(':id')
@ApiOperation({ summary: 'Get one country' })
findOne(@Param('id', ParseIntPipe) id: string) {
return this.service.findOne(BigInt(id));
}
@Post()
@ApiOperation({ summary: 'Create a country' })
create(@Body() dto: CreateCountryDto) {
return this.service.create(dto);
}
@Patch(':id')
@ApiOperation({ summary: 'Update a country' })
update(
@Param('id', ParseIntPipe) id: string,
@Body() dto: UpdateCountryDto,
) {
return this.service.update(BigInt(id), dto);
}
@Delete(':id')
@ApiOperation({ summary: 'Delete a country' })
remove(@Param('id', ParseIntPipe) id: string) {
return this.service.remove(BigInt(id));
}
}
import {
Body,
Controller,
Delete,
Get,
Param,
ParseIntPipe,
Patch,
Post,
UseGuards,
} from '@nestjs/common';
import {
ApiBearerAuth,
ApiOperation,
ApiTags,
} from '@nestjs/swagger';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { CountriesService } from './countries.service';
import { CreateCountryDto } from './dto/create-country.dto';
import { UpdateCountryDto } from './dto/update-country.dto';
@ApiTags('countries')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Controller('countries')
export class CountriesController {
constructor(private readonly service: CountriesService) {}
@Get()
@ApiOperation({ summary: 'List all countries' })
findAll() {
return this.service.findAll();
}
@Get(':id')
@ApiOperation({ summary: 'Get one country' })
findOne(@Param('id', ParseIntPipe) id: string) {
return this.service.findOne(BigInt(id));
}
@Post()
@ApiOperation({ summary: 'Create a country' })
create(@Body() dto: CreateCountryDto) {
return this.service.create(dto);
}
@Patch(':id')
@ApiOperation({ summary: 'Update a country' })
update(
@Param('id', ParseIntPipe) id: string,
@Body() dto: UpdateCountryDto,
) {
return this.service.update(BigInt(id), dto);
}
@Delete(':id')
@ApiOperation({ summary: 'Delete a country' })
remove(@Param('id', ParseIntPipe) id: string) {
return this.service.remove(BigInt(id));
}
}