Skip to content

Commit

Permalink
feat(core): executor to generate swagger json (#437)
Browse files Browse the repository at this point in the history
Adds a new target to projects created with the `webapi` template by default called `swagger`.

You can add this target (and supporting library) to any existing apis by running via `nx g @nx-dotnet/core:add-swagger-target` 

This generates/updates a `swagger.json` file inside a supporting library. The end goal is that you would use this generated file to generate typescript interfaces.

> Generation of `swagger.json` assumes that your webapi project uses `Swashbuckle.AspNetCore`, and does have swagger setup. If it does not, this target + supporting library **will not** function out of the box.
  • Loading branch information
AgentEnder authored May 31, 2022
1 parent 8bacf69 commit 6c33d1a
Show file tree
Hide file tree
Showing 65 changed files with 654 additions and 476 deletions.
19 changes: 19 additions & 0 deletions docs/core/executors/update-swagger.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# @nx-dotnet/core:update-swagger

## Swagger executor

Extract openapi swagger documentation from the webapi

## Options

### output

- (string): Where should the swagger output be stored

### swaggerDoc

- (string): Which swagger doc should be used?

### startupAssembly

- (string): Path from workspace root to the built api's startup dll file
27 changes: 27 additions & 0 deletions docs/core/generators/add-swagger-target.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# @nx-dotnet/core:add-swagger-target

## Swagger Target Generator

Generates a swagger setup for a given project

## Options

### swaggerDoc

- (string): Which swagger doc should be used?

### startupAssembly

- (string): Path from workspace root to the built api's startup dll file

### <span className="required">project</span>

- (string): Which project should the target be added to?

### swaggerProject

- (string): What should the project created to hold the swagger files be called?

### target

- (string): What should the project be called?
4 changes: 4 additions & 0 deletions docs/core/generators/application.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@ Generate a dotnet project under the application directory.
- (string): The name of the solution file to add the project to

- (boolean): Should the project be added to the default solution file?

### skipSwaggerLib

- (): By default, if using webapi template, an additional library is scaffolded for swagger files. This skips that setup.
4 changes: 4 additions & 0 deletions docs/core/generators/library.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,7 @@ Generate a dotnet project under the library directory.
- (string): The name of the solution file to add the project to

- (boolean): Should the project be added to the default solution file?

### skipSwaggerLib

- (): By default, if using webapi template, an additional library is scaffolded for swagger files. This skips that setup.
8 changes: 8 additions & 0 deletions docs/core/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ Generate a .NET test project for an existing application or library

Import existing projects into your nx workspace

### [add-swagger-target](./generators/add-swagger-target.md)

Generate a target to extract the swagger.json file from a .NET webapi

## Executors

### [build](./executors/build.md)
Expand All @@ -138,3 +142,7 @@ publish executor
### [format](./executors/format.md)

Formats and lints a project using the dotnet-format tool

### [update-swagger](./executors/update-swagger.md)

Generates a swagger document for an API project
6 changes: 2 additions & 4 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ slug: /

## [@nx-dotnet/core](./core)

- 5 Executors
- 9 Generators
- 6 Executors
- 10 Generators

## [@nx-dotnet/nx-ghpages](./nx-ghpages)

Expand All @@ -17,5 +17,3 @@ slug: /
## [@nx-dotnet/nxdoc](./nxdoc)

- 1 Generator

## [@nx-dotnet/typescript](./typescript)
1 change: 0 additions & 1 deletion docs/typescript/_category_.yml

This file was deleted.

8 changes: 0 additions & 8 deletions docs/typescript/index.md

This file was deleted.

2 changes: 1 addition & 1 deletion e2e/core-e2e/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ module.exports = {
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/e2ecore-e2e',
testTimeout: 120000,
testTimeout: 150000,
};
64 changes: 43 additions & 21 deletions e2e/core-e2e/tests/nx-dotnet.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe('nx-dotnet e2e', () => {
const testLib = uniq('lib');

await runNxCommandAsync(
`generate @nx-dotnet/core:app ${testApp} --language="C#" --template="webapi"`,
`generate @nx-dotnet/core:app ${testApp} --language="C#" --template="webapi" --skipSwaggerLib`,
);

await runNxCommandAsync(
Expand Down Expand Up @@ -73,7 +73,7 @@ describe('nx-dotnet e2e', () => {
);

await runNxCommandAsync(
`generate @nx-dotnet/core:app ${testApp} --language="C#" --template="webapi"`,
`generate @nx-dotnet/core:app ${testApp} --language="C#" --template="webapi" --skipSwaggerLib`,
);

await runNxCommandAsync(
Expand All @@ -93,26 +93,29 @@ describe('nx-dotnet e2e', () => {
it('should obey dry-run', async () => {
const app = uniq('app');
await runNxCommandAsync(
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --dry-run`,
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skipSwaggerLib --dry-run`,
);

expect(() => checkFilesExist(`apps/${app}`)).toThrow();
});

it('should generate an app', async () => {
it('should generate an app without swagger library', async () => {
const app = uniq('app');
await runNxCommandAsync(
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi"`,
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skip-swagger-lib`,
);

expect(() => checkFilesExist(`apps/${app}`)).not.toThrow();
expect(() =>
checkFilesExist(`libs/generated/${app}-swaggger/project.json`),
).toThrow();
});

it('should build and test an app', async () => {
const app = uniq('app');
const testProj = `${app}-test`;
await runNxCommandAsync(
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi"`,
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skip-swagger-lib`,
);

await runNxCommandAsync(`build ${app}`);
Expand All @@ -126,7 +129,7 @@ describe('nx-dotnet e2e', () => {
const app = uniq('app');
const lib = uniq('lib');
await runNxCommandAsync(
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi"`,
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skip-swagger-lib`,
);
await runNxCommandAsync(
`generate @nx-dotnet/core:lib ${lib} --language="C#" --template="classlib"`,
Expand All @@ -145,7 +148,7 @@ describe('nx-dotnet e2e', () => {
it('should update output paths', async () => {
const app = uniq('app');
await runNxCommandAsync(
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi"`,
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skip-swagger-lib`,
);
const configFilePath = findProjectFileInPathSync(
join(e2eDir, 'apps', app),
Expand All @@ -161,9 +164,10 @@ describe('nx-dotnet e2e', () => {
it('should lint', async () => {
const app = uniq('app');
await runNxCommandAsync(
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi"`,
`generate @nx-dotnet/core:app ${app} --template webapi --language="C#" --skip-swagger-lib`,
);
const promise = runNxCommandAsync(`lint ${app}`).then((x) => x.stderr);
console.log('LINT TEST PROJECT GENERATED', app);
const promise = runNxCommandAsync(`lint ${app}`);
await expect(promise).rejects.toThrow(
expect.objectContaining({
message: expect.stringContaining('WHITESPACE'),
Expand All @@ -176,7 +180,7 @@ describe('nx-dotnet e2e', () => {
it('should add a reference to the target project', async () => {
const app = uniq('app');
await runNxCommandAsync(
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --test-template="none"`,
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skip-swagger-lib --test-template="none"`,
);
await runNxCommandAsync(
`generate @nx-dotnet/core:test ${app} --language="C#" --template="nunit"`,
Expand All @@ -200,7 +204,7 @@ describe('nx-dotnet e2e', () => {
it('should create test project using suffix', async () => {
const app = uniq('app');
await runNxCommandAsync(
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --test-template="none"`,
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skip-swagger-lib --test-template="none"`,
);
await runNxCommandAsync(
`generate @nx-dotnet/core:test ${app} --language="C#" --template="nunit" --suffix="integration-tests"`,
Expand All @@ -222,7 +226,7 @@ describe('nx-dotnet e2e', () => {
it('should obey dry-run', async () => {
const lib = uniq('lib');
await runNxCommandAsync(
`generate @nx-dotnet/core:lib ${lib} --language="C#" --template="webapi" --dry-run`,
`generate @nx-dotnet/core:lib ${lib} --language="C#" --template="webapi" --skip-swagger-lib --dry-run`,
);

expect(() => checkFilesExist(`libs/${lib}`)).toThrow();
Expand All @@ -231,7 +235,7 @@ describe('nx-dotnet e2e', () => {
it('should generate an lib', async () => {
const lib = uniq('lib');
await runNxCommandAsync(
`generate @nx-dotnet/core:lib ${lib} --language="C#" --template="webapi"`,
`generate @nx-dotnet/core:lib ${lib} --language="C#" --template="classlib"`,
);

expect(() => checkFilesExist(`libs/${lib}`)).not.toThrow();
Expand Down Expand Up @@ -284,7 +288,7 @@ describe('nx-dotnet e2e', () => {
it("shouldn't create a solution by default if not specified", async () => {
const app = uniq('app');
await runNxCommandAsync(
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi"`,
`generate @nx-dotnet/core:app ${app} --language="C#" --skip-swagger-lib --template="webapi"`,
);

expect(() => checkFilesExist(`apps/${app}`)).not.toThrow();
Expand All @@ -294,7 +298,7 @@ describe('nx-dotnet e2e', () => {
it('should create a default solution file if specified as true', async () => {
const app = uniq('app');
await runNxCommandAsync(
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --solutionFile`,
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skip-swagger-lib --solutionFile`,
);

expect(() => checkFilesExist(`apps/${app}`)).not.toThrow();
Expand All @@ -315,12 +319,12 @@ describe('nx-dotnet e2e', () => {
it('should add successive projects to default solution file', async () => {
const app1 = uniq('app');
await runNxCommandAsync(
`generate @nx-dotnet/core:app ${app1} --language="C#" --template="webapi" --solutionFile`,
`generate @nx-dotnet/core:app ${app1} --language="C#" --skip-swagger-lib --template="webapi" --solutionFile`,
);

const app2 = uniq('app2');
await runNxCommandAsync(
`generate @nx-dotnet/core:app ${app2} --language="C#" --template="webapi" --solutionFile`,
`generate @nx-dotnet/core:app ${app2} --language="C#" --skip-swagger-lib --template="webapi" --solutionFile`,
);

const slnFile = readFile('proj.nx-dotnet.sln');
Expand All @@ -333,7 +337,7 @@ describe('nx-dotnet e2e', () => {
it('should add test project to same solution as app project', async () => {
const app = uniq('app');
await runNxCommandAsync(
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --test-template="xunit" --solutionFile`,
`generate @nx-dotnet/core:app ${app} --language="C#" --template="webapi" --skip-swagger-lib --test-template="xunit" --solutionFile`,
);

const slnFile = readFile('proj.nx-dotnet.sln');
Expand Down Expand Up @@ -399,7 +403,7 @@ describe('nx-dotnet e2e', () => {
const appProject = uniq('app');
const testProject = `${appProject}-test`;
runNxCommand(
`generate @nx-dotnet/core:app ${appProject} --language="C#" --template="webapi" --test-runner xunit`,
`generate @nx-dotnet/core:app ${appProject} --language="C#" --template="webapi" --skip-swagger-lib --test-runner xunit`,
);

expect(() => runNxCommand(`test ${testProject}`)).not.toThrow();
Expand Down Expand Up @@ -428,7 +432,7 @@ public class UnitTest1
const appProject = uniq('app');
const testProject = `${appProject}-test`;
runNxCommand(
`generate @nx-dotnet/core:app ${appProject} --language="C#" --template="webapi" --test-runner xunit`,
`generate @nx-dotnet/core:app ${appProject} --language="C#" --template="webapi" --skip-swagger-lib --test-runner xunit`,
);
const p = runCommandUntil(
`test ${testProject} --watch`,
Expand All @@ -441,6 +445,24 @@ public class UnitTest1
await expect(p).resolves.not.toThrow();
});
});

describe('swagger integration', () => {
it('should generate swagger project for webapi', async () => {
const api = uniq('api');
await runNxCommandAsync(
`generate @nx-dotnet/core:app ${api} --language="C#" --template="webapi"`,
);

expect(() => checkFilesExist(`apps/${api}`)).not.toThrow();
expect(() =>
checkFilesExist(`libs/generated/${api}-swagger`),
).not.toThrow();
expect(() => runNxCommand(`swagger ${api}`)).not.toThrow();
expect(() =>
checkFilesExist(`libs/generated/${api}-swagger/swagger.json`),
).not.toThrow();
});
});
});

function initializeGitRepo(cwd: string) {
Expand Down
14 changes: 0 additions & 14 deletions e2e/typescript-e2e/jest.config.js

This file was deleted.

16 changes: 0 additions & 16 deletions e2e/typescript-e2e/project.json

This file was deleted.

5 changes: 0 additions & 5 deletions e2e/typescript-e2e/tests/typescript.spec.ts

This file was deleted.

13 changes: 0 additions & 13 deletions e2e/typescript-e2e/tsconfig.json

This file was deleted.

9 changes: 0 additions & 9 deletions e2e/typescript-e2e/tsconfig.spec.json

This file was deleted.

2 changes: 0 additions & 2 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ module.exports = {
'<rootDir>/e2e/core-e2e',
'<rootDir>/e2e/nx-ghpages-e2e',
'<rootDir>/e2e/nxdoc-e2e',
'<rootDir>/e2e/typescript-e2e',
'<rootDir>/packages/core',
'<rootDir>/packages/dotnet',
'<rootDir>/packages/nx-ghpages',
'<rootDir>/packages/nxdoc',
'<rootDir>/packages/typescript',
'<rootDir>/packages/utils',
'<rootDir>/smoke/core',
],
Expand Down
Loading

0 comments on commit 6c33d1a

Please sign in to comment.