fix(数据): 支持大体积 AppData 并修正默认状态

关键改动:

- 后端显式注册 10mb JSON/urlencoded body parser,支持较大的 AppData 写入

- 前端版本派生数据缺失状态时默认 planned,而不是 released

- 增加请求体限制和版本默认状态测试

Co-Authored-By: Codex GPT-5 <codex@openai.com>
This commit is contained in:
Script Generator
2026-07-02 19:19:43 +08:00
parent 68b768788b
commit 121114af6a
5 changed files with 87 additions and 3 deletions

View File

@@ -0,0 +1,38 @@
import { configureHttpBodyParsers, DEFAULT_HTTP_BODY_LIMIT } from './http-body-limit';
jest.mock('express', () => ({
json: jest.fn(() => 'json-parser'),
urlencoded: jest.fn(() => 'urlencoded-parser'),
}));
const express = jest.requireMock('express') as {
json: jest.Mock;
urlencoded: jest.Mock;
};
describe('configureHttpBodyParsers', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('registers JSON and urlencoded parsers with a large AppData-safe limit', () => {
const app = { use: jest.fn() };
configureHttpBodyParsers(app as never);
expect(DEFAULT_HTTP_BODY_LIMIT).toBe('10mb');
expect(express.json).toHaveBeenCalledWith({ limit: '10mb' });
expect(express.urlencoded).toHaveBeenCalledWith({ extended: true, limit: '10mb' });
expect(app.use).toHaveBeenNthCalledWith(1, 'json-parser');
expect(app.use).toHaveBeenNthCalledWith(2, 'urlencoded-parser');
});
it('allows overriding the body limit for deployments with larger documents', () => {
const app = { use: jest.fn() };
configureHttpBodyParsers(app as never, '25mb');
expect(express.json).toHaveBeenCalledWith({ limit: '25mb' });
expect(express.urlencoded).toHaveBeenCalledWith({ extended: true, limit: '25mb' });
});
});

View File

@@ -0,0 +1,12 @@
import type { INestApplication } from '@nestjs/common';
import { json, urlencoded } from 'express';
export const DEFAULT_HTTP_BODY_LIMIT = '10mb';
export function configureHttpBodyParsers(
app: Pick<INestApplication, 'use'>,
limit = process.env.HTTP_BODY_LIMIT || DEFAULT_HTTP_BODY_LIMIT,
) {
app.use(json({ limit }));
app.use(urlencoded({ extended: true, limit }));
}

View File

@@ -3,6 +3,7 @@ import { ValidationPipe } from '@nestjs/common';
import { existsSync } from 'fs';
import { resolve } from 'path';
import { AppModule } from './app.module';
import { configureHttpBodyParsers } from './http-body-limit';
// 加载 .envNode v20+ 内置 loadEnvFile
// 优先 cwd/.env其次 dist 上一级(编译运行时 cwd 可能在 dist/
@@ -14,7 +15,8 @@ for (const candidate of [resolve(process.cwd(), '.env'), resolve(__dirname, '../
}
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const app = await NestFactory.create(AppModule, { bodyParser: false });
configureHttpBodyParsers(app);
app.setGlobalPrefix('api/v1');
app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
app.enableCors();