生成Swagger JSON文件而无需运行Nest JS服务器

发布于 2025-02-12 13:04:53 字数 284 浏览 0 评论 0原文


does anyone know of a way(either official or through a 3rd-party tool) to generate swagger json files without needing the nest js server to run?

我有一个带有控制器路由的Nest JS应用程序,并用 @Nest/Swagger Decorator进行了注释,用于文档。我知道我可以通过启动服务器和访问 /api-json来获取Swagger JSON文件,但是我需要能够生成此文件而无需先启动服务器。

does anyone know of a way(either official or through a 3rd-party tool) to generate swagger json files without needing the nest js server to run?

I have a nest js application with controller routes and DTO's annotated with @nest/swagger decorators for documentation. I know I can get the swagger json files by starting the server and visiting /api-json but I need the ability to generate this file without having to start the server first.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

江心雾 2025-02-19 13:04:53

我在没有启动服务器的情况下从我的E2E测试中生成了一个摇摇欲坠的文件。

下面的代码在一个 *.json文件中生成了一个摇摇欲坠的规格,您可以将其粘贴到 https://editor.swagger.io/

// my-api.e2e-spec.ts

import { Test, TestingModule } from '@nestjs/testing';
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import { HttpModule } from '@nestjs/axios';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import * as fs from 'fs';

describe('My E2E Tests', () => {
  let app: NestFastifyApplication;

  beforeAll(async () => {
    const module: TestingModule = await Test.createTestingModule({
      imports: [HttpModule],
    }).compile();

    app = module.createNestApplication(new FastifyAdapter());
    app.setGlobalPrefix('/api/v1');
    await app.init();
    await app.getHttpAdapter().getInstance().ready();
  });

  afterAll(async () => {
    await app.close();
  });

  it('should generate swagger spec', async () => {
    const config = new DocumentBuilder().setTitle('My API').setDescription('My API').setVersion('1.0').build();

    const document = SwaggerModule.createDocument(app, config);
    fs.writeFileSync('./swagger.json', JSON.stringify(document));
  });
});

注意:我的包装中的 @nestjs/Swagger的版本是5.2.0

I managed to generate a swagger file from my e2e tests without starting the server.

The code below generates a swagger spec in a *.json file that you can paste into https://editor.swagger.io/

// my-api.e2e-spec.ts

import { Test, TestingModule } from '@nestjs/testing';
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import { HttpModule } from '@nestjs/axios';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
import * as fs from 'fs';

describe('My E2E Tests', () => {
  let app: NestFastifyApplication;

  beforeAll(async () => {
    const module: TestingModule = await Test.createTestingModule({
      imports: [HttpModule],
    }).compile();

    app = module.createNestApplication(new FastifyAdapter());
    app.setGlobalPrefix('/api/v1');
    await app.init();
    await app.getHttpAdapter().getInstance().ready();
  });

  afterAll(async () => {
    await app.close();
  });

  it('should generate swagger spec', async () => {
    const config = new DocumentBuilder().setTitle('My API').setDescription('My API').setVersion('1.0').build();

    const document = SwaggerModule.createDocument(app, config);
    fs.writeFileSync('./swagger.json', JSON.stringify(document));
  });
});

Note: My version of @nestjs/swagger in my package.json is 5.2.0

逐鹿 2025-02-19 13:04:53

就我而言,PostgreSQL数据源是一种依赖性,因此我最终决定使用内存数据库,pg-mem在E2E测试上运行。这是我实现Swagger.json导出的方式。

src/app.module.ts

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      load: [generalConfig],
    }),
    TypeOrmModule.forRootAsync({
      name: 'default',
      imports: [ConfigModule, SharedModule],
      useClass: DatabaseConfig,
    }),
    SharedModule,
    InfoModule,
  ],
})
export class AppModule {}

test/swagger.e2e-spec.ts

import request from 'supertest';
import * as path from 'path';
import { writeFileSync } from 'fs';
import { DataType, newDb } from 'pg-mem';
import { DataSource } from 'typeorm';
import { INestApplication } from '@nestjs/common';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { Test } from '@nestjs/testing';
import { AppModule } from '../src/app.module';

describe('SwaggerController (e2e)', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const db = newDb();
    db.public.registerFunction({
      name: 'current_database',
      args: [],
      returns: DataType.text,
      implementation: () => 'localdb',
    });
    db.public.registerFunction({
      name: 'version',
      args: [],
      returns: DataType.text,
      implementation: () => '1',
    });
    // Get PG in memory DB connection
    const datasource = (await db.adapters.createTypeormDataSource({
      type: 'postgres',
      autoLoadEntities: true,
      synchronize: true,
    })) as any;
    await datasource.initialize();
    await datasource.synchronize();

    const moduleFixture = await Test.createTestingModule({
      imports: [AppModule],
    })
      .overrideProvider(DataSource)
      .useValue(datasource)
      .compile();

    app = moduleFixture.createNestApplication();

    const config = new DocumentBuilder()
      .setTitle('NestJS App')
      .setDescription('NestJS App description')
      .setVersion('1.0')
      .build();
    const document = SwaggerModule.createDocument(app, config);
    SwaggerModule.setup('docs', app, document);

    await app.init();
  });

  afterAll(async () => {
    await app.close();
  });

  it('/docs (GET)', () => {
    return request(app.getHttpServer()).get('/docs').expect(200);
  });

  it('/docs-json (GET)', () => {
    return request(app.getHttpServer())
      .get('/docs-json')
      .expect(200)
      .expect((res) => {
        const swaggerJson = JSON.stringify(res.body, null, 2);
        const outputPath = path.resolve(process.cwd(), 'swagger.json');
        writeFileSync(outputPath, swaggerJson, { encoding: 'utf8' });
      });
  });
});

如果您依赖” > nest-cli.json,例如用于架构定义属性生成,默认情况下,该配置不是在e2e执行上应用于ts-jest在存储器中即时编译您的源代码文件(参考:

noreferrer”> https://docs.nestjs.com/openapi/cli-plugin#integration-with-with-ts-jest-e2e-tests ),因此您需要在 test/Swagger 。

const transformer = require('@nestjs/swagger/plugin');

module.exports.name = 'nestjs-swagger-transformer';
// you should change the version number anytime you change the configuration below - otherwise, jest will not detect changes
module.exports.version = 1;

module.exports.factory = (cs) => {
  return transformer.before(
    {
      // @nestjs/swagger/plugin options (can be empty)
    },
    cs.program, // "cs.tsCompiler.program" for older versions of Jest (<= v27)
  );
};

{
  ...
  "transform": {
    "^.+\\.(t|j)s$": [
      "ts-jest",
      {
        "astTransformers": {
          "before": ["./test/swagger.transformer.config.js"]
        }
      }
    ]
  }
}

In my case, PostgreSQL datasource was a dependency, so I eventually decided to use memory database, pg-mem to run on e2e test. Here is how I achieved the swagger.json export.

src/app.module.ts

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
      load: [generalConfig],
    }),
    TypeOrmModule.forRootAsync({
      name: 'default',
      imports: [ConfigModule, SharedModule],
      useClass: DatabaseConfig,
    }),
    SharedModule,
    InfoModule,
  ],
})
export class AppModule {}

test/swagger.e2e-spec.ts

import request from 'supertest';
import * as path from 'path';
import { writeFileSync } from 'fs';
import { DataType, newDb } from 'pg-mem';
import { DataSource } from 'typeorm';
import { INestApplication } from '@nestjs/common';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { Test } from '@nestjs/testing';
import { AppModule } from '../src/app.module';

describe('SwaggerController (e2e)', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const db = newDb();
    db.public.registerFunction({
      name: 'current_database',
      args: [],
      returns: DataType.text,
      implementation: () => 'localdb',
    });
    db.public.registerFunction({
      name: 'version',
      args: [],
      returns: DataType.text,
      implementation: () => '1',
    });
    // Get PG in memory DB connection
    const datasource = (await db.adapters.createTypeormDataSource({
      type: 'postgres',
      autoLoadEntities: true,
      synchronize: true,
    })) as any;
    await datasource.initialize();
    await datasource.synchronize();

    const moduleFixture = await Test.createTestingModule({
      imports: [AppModule],
    })
      .overrideProvider(DataSource)
      .useValue(datasource)
      .compile();

    app = moduleFixture.createNestApplication();

    const config = new DocumentBuilder()
      .setTitle('NestJS App')
      .setDescription('NestJS App description')
      .setVersion('1.0')
      .build();
    const document = SwaggerModule.createDocument(app, config);
    SwaggerModule.setup('docs', app, document);

    await app.init();
  });

  afterAll(async () => {
    await app.close();
  });

  it('/docs (GET)', () => {
    return request(app.getHttpServer()).get('/docs').expect(200);
  });

  it('/docs-json (GET)', () => {
    return request(app.getHttpServer())
      .get('/docs-json')
      .expect(200)
      .expect((res) => {
        const swaggerJson = JSON.stringify(res.body, null, 2);
        const outputPath = path.resolve(process.cwd(), 'swagger.json');
        writeFileSync(outputPath, swaggerJson, { encoding: 'utf8' });
      });
  });
});

If you rely on "@nestjs/swagger plugin at nest-cli.json such as for schema definition property generation, the config is not applied on e2e execution by default as ts-jest compiles your source code files on the fly, in memory (Ref: https://docs.nestjs.com/openapi/cli-plugin#integration-with-ts-jest-e2e-tests) So you need to create a config file below

test/swagger.transformer.config.js

const transformer = require('@nestjs/swagger/plugin');

module.exports.name = 'nestjs-swagger-transformer';
// you should change the version number anytime you change the configuration below - otherwise, jest will not detect changes
module.exports.version = 1;

module.exports.factory = (cs) => {
  return transformer.before(
    {
      // @nestjs/swagger/plugin options (can be empty)
    },
    cs.program, // "cs.tsCompiler.program" for older versions of Jest (<= v27)
  );
};

and update jest-e2e.json in transform block

{
  ...
  "transform": {
    "^.+\\.(t|j)s
quot;: [
      "ts-jest",
      {
        "astTransformers": {
          "before": ["./test/swagger.transformer.config.js"]
        }
      }
    ]
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文