Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add generationHook function option feature #4716

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/green-months-marry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sap-cloud-sdk/openapi-generator': minor
---

Provide optional openapi-generator generationHook option allowing an api generation hook function handle for the clients to hook into the service/api generation process and allow them to implement any custom side-effects they might require.
55 changes: 43 additions & 12 deletions packages/openapi-generator/src/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ import { convertOpenApiSpec } from './document-converter';
import { sdkMetadata } from './sdk-metadata';
import {
cliOptions,
GenerationHookHandler,
GeneratorOptions,
ParsedGeneratorOptions,
ProgrammaticOptions,
tsconfigJson
} from './options';

Expand Down Expand Up @@ -68,7 +70,7 @@ export async function generate(
* @internal
*/
export async function generateWithParsedOptions(
options: ParsedGeneratorOptions
options: ParsedGeneratorOptions & ProgrammaticOptions
): Promise<void> {
if (!options.input.length || options.outputDir === '') {
throw new Error('Either input or outputDir were not set.');
Expand All @@ -85,13 +87,15 @@ export async function generateWithParsedOptions(

const optionsPerService = await getOptionsPerService(inputFilePaths, options);
const tsConfig = await tsconfigJson(options);
const generationHook = options.generationHook;

const promises = inputFilePaths.map(inputFilePath =>
generateService(
inputFilePath,
options,
optionsPerService[getRelPathWithPosixSeparator(inputFilePath)],
tsConfig
tsConfig,
generationHook
)
);

Expand Down Expand Up @@ -142,17 +146,24 @@ async function getFileCreationOptions(
* @param inputFilePath - Path to the input file.
* @param tsConfig - File content for the `tsconfig.json`.
* @param options - Generation options.
* @param generationHook - Generation hoook function.
*/
async function generateSources(
serviceDir: string,
openApiDocument: OpenApiDocument,
inputFilePath: string,
tsConfig: string | undefined,
options: ParsedGeneratorOptions
options: ParsedGeneratorOptions,
generationHook?: GenerationHookHandler
): Promise<void> {
await mkdir(serviceDir, { recursive: true });

await generateMandatorySources(serviceDir, openApiDocument, options);
await generateMandatorySources(
serviceDir,
openApiDocument,
options,
generationHook
);

if (options.metadata) {
await generateMetadata(openApiDocument, inputFilePath, options);
Expand Down Expand Up @@ -188,7 +199,8 @@ async function generateSources(
async function generateMandatorySources(
serviceDir: string,
openApiDocument: OpenApiDocument,
options: ParsedGeneratorOptions
options: ParsedGeneratorOptions,
generationHook?: GenerationHookHandler
): Promise<void> {
const createFileOptions = await getFileCreationOptions(options);
if (openApiDocument.schemas.length) {
Expand All @@ -202,7 +214,12 @@ async function generateMandatorySources(
);
}

await createApis(serviceDir, openApiDocument, createFileOptions);
await createApis(
serviceDir,
openApiDocument,
createFileOptions,
generationHook
);
await createFile(
serviceDir,
'index.ts',
Expand All @@ -214,17 +231,28 @@ async function generateMandatorySources(
async function createApis(
serviceDir: string,
openApiDocument: OpenApiDocument,
options: CreateFileOptions
options: CreateFileOptions,
generationHook?: GenerationHookHandler
): Promise<void> {
await Promise.all(
openApiDocument.apis.map(api =>
openApiDocument.apis.map(api => {
if (generationHook) {
generationHook(
serviceDir,
openApiDocument.serviceName,
api.name,
api,
options
);
}

createFile(
serviceDir,
`${kebabCase(api.name)}.ts`,
apiFile(api, openApiDocument.serviceName),
options
)
)
);
})
);
}

Expand Down Expand Up @@ -252,12 +280,14 @@ async function createSchemaFiles(
* @param options - Options to configure generation.
* @param serviceOptions - Service options as defined in the options per service.
* @param tsConfig - File content for the `tsconfig.json`.
* @param generationHook - Generation hoook function.
*/
async function generateService(
inputFilePath: string,
options: ParsedGeneratorOptions,
serviceOptions: ServiceOptions,
tsConfig: string | undefined
tsConfig: string | undefined,
generationHook?: GenerationHookHandler
): Promise<void> {
const openApiDocument = await convertOpenApiSpec(inputFilePath);
const parsedOpenApiDocument = await parseOpenApiDocument(
Expand All @@ -272,7 +302,8 @@ async function generateService(
parsedOpenApiDocument,
inputFilePath,
tsConfig,
options
options,
generationHook
);
logger.info(`Successfully generated client for '${inputFilePath}'`);
}
Expand Down
6 changes: 5 additions & 1 deletion packages/openapi-generator/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@
*/

export { generate } from './generator';
export { GeneratorOptions } from './options';
export {
GeneratorOptions,
ProgrammaticOptions,
GenerationHookHandler
} from './options';
26 changes: 24 additions & 2 deletions packages/openapi-generator/src/options/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,35 @@ import {
ParsedOptions,
Options,
getCommonCliOptions,
CommonGeneratorOptions
CommonGeneratorOptions,
CreateFileOptions
} from '@sap-cloud-sdk/generator-common/internal';

/**
* Represents the generationHook function type.
*/
export type GenerationHookHandler = (
serviceDirPath: string,
serviceName: string,
apiServiceName: string,
api: any,
options: CreateFileOptions
) => void;

// eslint-disable-next-line jsdoc/require-jsdoc
export interface ProgrammaticOptions {
/**
* Generation process allows hooking into the process of Services generation.
* If you provide this (function) option, it will be triggered for each generated API
* allowing you to hook into API generation process and generate any custom API related code.
*/
generationHook?: GenerationHookHandler;
}

/**
* Options to configure OData client generation when using the generator programmatically.
*/
export type GeneratorOptions = CommonGeneratorOptions;
export type GeneratorOptions = CommonGeneratorOptions & ProgrammaticOptions;

/**
* @internal
Expand Down
Loading