Skip to content

Commit

Permalink
feat(core): support nx-plugin-openapi for more advanced openapi gener…
Browse files Browse the repository at this point in the history
…ation (nx-dotnet#589)
  • Loading branch information
AgentEnder authored Jan 17, 2023
1 parent 09c3b4e commit ee1c7b1
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 36 deletions.
4 changes: 4 additions & 0 deletions docs/core/generators/add-swagger-target.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ Generates a swagger setup for a given project
### target

- (string): What should the project be called?

### useNxPluginOpenAPI

- (boolean): Should the codegen target use nx-plugin-openapi instead?
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.
### pathScheme

- (string): Determines if the project should follow NX or dotnet path naming conventions

### useNxPluginOpenAPI

- (boolean): If using a codgen project, use openapi-generator
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@docusaurus/theme-search-algolia": "^2.1.0",
"@mdx-js/react": "^1.6.21",
"@swc/helpers": "~0.3.3",
"@trumbitta/nx-plugin-openapi": "^1.12.1",
"@types/xmldoc": "^1.1.6",
"chokidar": "^3.5.2",
"clsx": "^1.1.1",
Expand Down
149 changes: 113 additions & 36 deletions packages/core/src/generators/add-swagger-target/add-swagger-target.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import {
addProjectConfiguration,
ensurePackage,
GeneratorCallback,
getWorkspaceLayout,
joinPathFragments,
ProjectConfiguration,
readProjectConfiguration,
readWorkspaceConfiguration,
Tree,
updateProjectConfiguration,
updateWorkspaceConfiguration,
} from '@nrwl/devkit';
import { libraryGenerator } from '@nrwl/js/src/generators/library/library';

Expand All @@ -16,6 +20,7 @@ export default async function generateSwaggerSetup(
host: Tree,
options: AddSwaggerJsonExecutorSchema,
) {
const tasks: GeneratorCallback[] = [];
const project = readProjectConfiguration(host, options.project);
project.targets ??= {};
if (!options.output) {
Expand All @@ -25,6 +30,7 @@ export default async function generateSwaggerSetup(
'swagger.json',
);
generateShellProject(host, {
...options,
swaggerProject: options.swaggerProject,
project: options.project,
codegenProject: options.codegenProject,
Expand All @@ -33,19 +39,14 @@ export default async function generateSwaggerSetup(
throw new Error('Either specify --output or --swagger-project');
}
} else {
if (options.codegenProject) {
if (options.codegenProject && !options.useNxPluginOpenAPI) {
project.targets.codegen = {
executor: '@nx-dotnet/core:openapi-codegen',
options: {
openapiJsonPath: options.output,
outputProject: options.codegenProject,
},
dependsOn: [
{
target: options.target || 'swagger',
projects: 'self',
},
],
dependsOn: ['swagger'],
};
}
}
Expand All @@ -54,22 +55,16 @@ export default async function generateSwaggerSetup(
};

if (options.codegenProject) {
await libraryGenerator(host, {
name: options.codegenProject,
directory: 'generated',
buildable: true,
});
const codegenProjectConfiguration = readProjectConfiguration(
host,
`generated-${options.codegenProject}`,
);
codegenProjectConfiguration.implicitDependencies ??= [];
codegenProjectConfiguration.implicitDependencies.push(
options.swaggerProject ? options.swaggerProject : options.project,
);
tasks.push(...(await generateCodegenProject(host, options)));
}

updateProjectConfiguration(host, options.project, project);

return async () => {
for (const task of tasks) {
await task();
}
};
}

function swaggerProjectRoot(host: Tree, swaggerProject: string) {
Expand All @@ -82,7 +77,7 @@ function swaggerProjectRoot(host: Tree, swaggerProject: string) {

function generateShellProject(
host: Tree,
options: { project: string; swaggerProject: string; codegenProject?: string },
options: AddSwaggerJsonExecutorSchema & { swaggerProject: string },
) {
const root = swaggerProjectRoot(host, options.swaggerProject);
const targets: ProjectConfiguration['targets'] = {};
Expand All @@ -94,26 +89,108 @@ function generateShellProject(
executor: 'nx:noop',
outputs: [root],
};
targets.codegen = {
executor: '@nx-dotnet/core:openapi-codegen',
options: {
openapiJsonPath: `${swaggerProjectRoot(
host,
options.swaggerProject,
)}/swagger.json`,
outputProject: `generated-${options.codegenProject}`,
},
dependsOn: [
{
projects: 'dependencies',
target: 'swagger',
if (!options.useNxPluginOpenAPI) {
targets.codegen = {
executor: '@nx-dotnet/core:openapi-codegen',
options: {
openapiJsonPath: `${swaggerProjectRoot(
host,
options.swaggerProject,
)}/swagger.json`,
outputProject: `generated-${options.codegenProject}`,
},
],
};
dependsOn: ['^swagger'],
};
}
}
addProjectConfiguration(host, options.swaggerProject, {
root,
targets,
implicitDependencies: [options.project],
});
}

async function generateCodegenProject(
host: Tree,
options: AddSwaggerJsonExecutorSchema,
): Promise<GeneratorCallback[]> {
const tasks: GeneratorCallback[] = [];
const nameWithDirectory = `generated-${options.codegenProject}`;
if (options.useNxPluginOpenAPI) {
ensurePackage(host, '@trumbitta/nx-plugin-openapi', '^1.12.1');
const {
default: nxPluginOpenAPIGenerator,
}: // eslint-disable-next-line @typescript-eslint/no-var-requires
typeof import('@trumbitta/nx-plugin-openapi/src/generators/api-lib/generator') = require('@trumbitta/nx-plugin-openapi/src/generators/api-lib/generator');
const {
default: nxPluginOpenAPIInitGenerator,
}: // eslint-disable-next-line @typescript-eslint/no-var-requires
typeof import('@trumbitta/nx-plugin-openapi/src/generators/init/generator') = require('@trumbitta/nx-plugin-openapi/src/generators/init/generator');

tasks.push(await nxPluginOpenAPIInitGenerator(host));

tasks.push(
await nxPluginOpenAPIGenerator(host, {
isRemoteSpec: false,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
name: options.codegenProject!,
directory: 'generated',
generator: 'typescript-fetch',
sourceSpecLib: options.swaggerProject,
}),
);

const configuration = readProjectConfiguration(host, nameWithDirectory);
configuration.targets ??= {};
const targetConfiguration = configuration.targets?.['generate-sources'];
targetConfiguration.options['sourceSpecPathOrUrl'] = joinPathFragments(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
readProjectConfiguration(host, options.swaggerProject!).root,
'swagger.json',
);
targetConfiguration.dependsOn = ['^swagger'];
configuration.targets['codegen'] = targetConfiguration;
delete configuration.targets['generate-sources'];
updateProjectConfiguration(host, nameWithDirectory, configuration);
} else {
tasks.push(
await libraryGenerator(host, {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
name: options.codegenProject!,
directory: 'generated',
buildable: true,
}),
);
const codegenProjectConfiguration = readProjectConfiguration(
host,
nameWithDirectory,
);
codegenProjectConfiguration.implicitDependencies ??= [];
codegenProjectConfiguration.implicitDependencies.push(
options.swaggerProject ? options.swaggerProject : options.project,
);
updateProjectConfiguration(
host,
nameWithDirectory,
codegenProjectConfiguration,
);
}

const wc = readWorkspaceConfiguration(host);

const cacheableOperations: string[] | null =
wc.tasksRunnerOptions?.default?.options?.cacheableOperations;
if (cacheableOperations) {
cacheableOperations.push('codegen', options.target ?? 'swagger');
}

const newBuildDeps = ['codegen', '^codegen'];
wc.targetDefaults ??= {};
wc.targetDefaults['build'] ??= {};
wc.targetDefaults['build'].dependsOn ??= [];
wc.targetDefaults['build'].dependsOn.push(...newBuildDeps);

updateWorkspaceConfiguration(host, wc);

return tasks;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export type AddSwaggerJsonExecutorSchema = {
target?: string;
swaggerProject?: string;
codegenProject?: string;
useNxPluginOpenAPI?: boolean;
};
5 changes: 5 additions & 0 deletions packages/core/src/generators/add-swagger-target/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
"type": "string",
"description": "What should the project be called?",
"default": "swagger"
},
"useNxPluginOpenAPI": {
"type": "boolean",
"description": "Should the codegen target use nx-plugin-openapi instead?",
"default": "false"
}
},
"required": ["project"]
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/generators/app/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@
{ "value": "dotnet", "label": "Dotnet naming conventions" }
]
}
},
"useNxPluginOpenAPI": {
"type": "boolean",
"description": "If using a codgen project, use openapi-generator"
}
},
"required": ["name", "language"]
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/generators/utils/generate-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ export async function GenerateProject(
project: normalizedOptions.projectName,
swaggerProject: `${normalizedOptions.projectName}-swagger`,
codegenProject: `${normalizedOptions.projectName}-types`,
useNxPluginOpenAPI: normalizedOptions.useNxPluginOpenAPI,
});
}

Expand Down
1 change: 1 addition & 0 deletions packages/core/src/models/project-generator-schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ export interface NxDotnetProjectGeneratorSchema {
solutionFile?: string | boolean;
skipSwaggerLib: boolean;
pathScheme: 'nx' | 'dotnet';
useNxPluginOpenAPI?: boolean;
}
1 change: 1 addition & 0 deletions packages/core/src/models/swagger-executor-configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export function getSwaggerExecutorConfiguration(
options: {
output: outputDirectory,
},
dependsOn: ['build'],
};
}

Expand Down
7 changes: 7 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5433,6 +5433,13 @@
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==

"@trumbitta/nx-plugin-openapi@^1.12.1":
version "1.12.1"
resolved "https://registry.yarnpkg.com/@trumbitta/nx-plugin-openapi/-/nx-plugin-openapi-1.12.1.tgz#c350213980509373fd25e48efc6d86c85071d657"
integrity sha512-vSQ+cDMtPuB/aBHtwrHsNKgElD55ubUMxsyCm7Vv81e/UQrNhIQ+/4zBFj3QWE2WO1PEi3TQD6jF5nbg173bUQ==
dependencies:
cross-spawn "^7.0.3"

"@trysound/[email protected]":
version "0.2.0"
resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad"
Expand Down

0 comments on commit ee1c7b1

Please sign in to comment.