Merge branch 'develop' into test/65-isolate-http-suites
This commit is contained in:
@@ -218,7 +218,10 @@ nvm use --silent
|
||||
npm run openapi:generate
|
||||
```
|
||||
|
||||
Команда собирает backend и записывает `openapi.json` в корень репозитория.
|
||||
Команда собирает backend и записывает `openapi.json` в корень репозитория
|
||||
атомарно: через временный файл и rename, без частичной записи при сбое.
|
||||
`npm run openapi:check` только сравнивает runtime schema с файлом и завершается
|
||||
с ошибкой при расхождении, не перезаписывая его.
|
||||
Сервер и HTTP-порт не запускаются; Nest preview читает metadata без создания
|
||||
провайдеров и подключения к БД/T-Bank. Настроенный `.env` и реальные секреты
|
||||
не нужны. `openapi.json` исключён из Git и каждый раз создаётся из DTO/Swagger
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"scripts": {
|
||||
"build": "prisma generate && nest build",
|
||||
"openapi:generate": "npm run build && node scripts/generate-openapi.cjs",
|
||||
"openapi:check": "npm run build && node scripts/generate-openapi.cjs --check",
|
||||
"format": "npm run lint:fix",
|
||||
"start": "nest start",
|
||||
"start:dev": "NODE_ENV=development nest start --watch --path tsconfig.dev.json",
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
const { randomBytes } = require('node:crypto');
|
||||
const { writeFile } = require('node:fs/promises');
|
||||
const { readFile, rename, rm, writeFile } = require('node:fs/promises');
|
||||
const { resolve } = require('node:path');
|
||||
|
||||
// Relative to the working directory, as before: the contract test runs the script in a temporary directory.
|
||||
const target = resolve(process.cwd(), 'openapi.json');
|
||||
const checkOnly = process.argv.includes('--check');
|
||||
|
||||
// Schema generation needs no deployment configuration or real credentials.
|
||||
Object.assign(process.env, {
|
||||
@@ -19,23 +24,48 @@ const { NestFactory } = require('@nestjs/core');
|
||||
const { AppModule } = require('../dist/src/app.module.js');
|
||||
const { API_PREFIX, createOpenApiDocument } = require('../dist/src/openapi.js');
|
||||
|
||||
async function generate() {
|
||||
async function render() {
|
||||
const app = await NestFactory.create(AppModule, {
|
||||
preview: true,
|
||||
logger: false,
|
||||
});
|
||||
try {
|
||||
app.setGlobalPrefix(API_PREFIX);
|
||||
await writeFile(
|
||||
'openapi.json',
|
||||
JSON.stringify(createOpenApiDocument(app), null, 2) + '\n',
|
||||
);
|
||||
return JSON.stringify(createOpenApiDocument(app), null, 2) + '\n';
|
||||
} finally {
|
||||
await app.close();
|
||||
}
|
||||
}
|
||||
|
||||
generate().catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
// Read-only: compares the runtime document with the committed artifact and never writes.
|
||||
async function check(content) {
|
||||
const current = await readFile(target, 'utf8').catch(() => null);
|
||||
if (current !== content) {
|
||||
console.error(
|
||||
'openapi.json is out of date with the runtime schema. Run `npm run openapi:generate`.',
|
||||
);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
console.log('openapi.json matches the runtime schema.');
|
||||
}
|
||||
|
||||
// Atomic update: write a sibling temp file, then rename over the target, so a failed run never leaves partial output.
|
||||
async function update(content) {
|
||||
const temp = `${target}.${process.pid}.tmp`;
|
||||
try {
|
||||
// eslint-disable-next-line security/detect-non-literal-fs-filename -- Operator-selected working directory and fixed artifact name; no request input.
|
||||
await writeFile(temp, content);
|
||||
// eslint-disable-next-line security/detect-non-literal-fs-filename -- Operator-selected working directory and fixed artifact name; no request input.
|
||||
await rename(temp, target);
|
||||
} finally {
|
||||
await rm(temp, { force: true });
|
||||
}
|
||||
}
|
||||
|
||||
render()
|
||||
.then((content) => (checkOnly ? check(content) : update(content)))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user