Skip to content

Commit

Permalink
feat: add generationHook and openapi-to-trpc-router basic generation
Browse files Browse the repository at this point in the history
  • Loading branch information
ulates-sap committed May 29, 2024
1 parent aa4e96b commit 65db424
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 15 deletions.
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

0 comments on commit 65db424

Please sign in to comment.