Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
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
9 changes: 7 additions & 2 deletions packages/openapi-generator/src/file-serializer/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,18 @@ export function serializeSchema(schema: OpenApiSchema): string {
const type = serializeSchema(schema.items);
return schema.uniqueItems
? `Set<${type}>`
: 'properties' in schema.items
: 'properties' in schema.items || 'allOf' in schema.items
? `(${type})[]`
: `${type}[]`;
}

if (isObjectSchema(schema)) {
return serializeObjectSchema(schema);
const types: string[] = [];
if (isAllOfSchema(schema)) {
types.push(schema.allOf.map(type => serializeSchema(type)).join(' & '));
}
types.push(serializeObjectSchema(schema));
return types.join(' & ');
}

if (isEnumSchema(schema)) {
Expand Down
5 changes: 4 additions & 1 deletion packages/openapi-generator/src/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,10 @@ async function generateService(
const parsedOpenApiDocument = await parseOpenApiDocument(
openApiDocument,
serviceOptions,
{ strictNaming: !options.skipValidation }
{
strictNaming: !options.skipValidation,
schemaPrefix: options.schemaPrefix
}
);

const serviceDir = resolve(options.outputDir, serviceOptions.directoryName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ describe('parseGeneratorOptions', () => {
verbose: false,
overwrite: false,
config: undefined,
generateESM: false
generateESM: false,
schemaPrefix: undefined
};

it('gets default options', () => {
Expand Down
11 changes: 11 additions & 0 deletions packages/openapi-generator/src/options/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ export type GeneratorOptions = CommonGeneratorOptions & OpenAPIGeneratorOptions;
* Options to configure OpenAPI client generation when using the generator programmatically.
*/
export interface OpenAPIGeneratorOptions {
/**
* Prefix all schema names with a value.
* @experimental
*/
schemaPrefix?: string;
/**
* Whether to generate ECMAScript modules instead of CommonJS modules.
*/
Expand All @@ -37,5 +42,11 @@ export const cliOptions = {
'When enabled, all generated files follow the ECMAScript module syntax.',
type: 'boolean',
default: false
},
schemaPrefix: {
describe:
'When enabled, all generated files follow the ECMAScript module syntax.',
type: 'string',
default: undefined
}
} as const satisfies Options<GeneratorOptions>;
4 changes: 4 additions & 0 deletions packages/openapi-generator/src/parser/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@ export interface ParserOptions {
* Fail parsing on conflicting names.
*/
strictNaming: boolean;
/**
* Add prefix to schema names.
*/
schemaPrefix?: string;
}
19 changes: 19 additions & 0 deletions packages/openapi-generator/src/parser/refs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,25 @@ describe('OpenApiDocumentRefs', () => {
);
});

it('gets the schema naming for reference object with a prefix', async () => {
refs = await createRefs(
{
...emptyDocument,
components: { schemas: { typeName } }
},
{ strictNaming: true, schemaPrefix: 'xyz' }
);

expect(
refs.getSchemaNaming({
$ref: '#/components/schemas/typeName'
})
).toEqual({
schemaName: 'XyzTypeName',
fileName: 'type-name'
});
});

it('renames a schema if needed due to illegal names', async () => {
refs = await createRefs(
{
Expand Down
2 changes: 1 addition & 1 deletion packages/openapi-generator/src/parser/refs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export class OpenApiDocumentRefs {
(mapping, originalName, i) => ({
...mapping,
[`#/components/schemas/${originalName}`]: {
schemaName: schemaNames[i],
schemaName: pascalCase(options.schemaPrefix ?? '') + schemaNames[i],
fileName: fileNames[i]
}
}),
Expand Down
15 changes: 13 additions & 2 deletions packages/openapi-generator/src/parser/schema.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createLogger } from '@sap-cloud-sdk/util';
import { OpenAPIV3 } from 'openapi-types';
import { isReferenceObject } from '../schema-util';
import { isAllOfSchema, isReferenceObject } from '../schema-util';
import {
OpenApiArraySchema,
OpenApiEnumSchema,
Expand Down Expand Up @@ -47,6 +47,14 @@ export function parseSchema(
schema.properties ||
'additionalProperties' in schema
) {
if (isAllOfSchema(schema)) {
return {
...(schema.allOf?.length &&
parseXOfSchema(schema, refs, 'allOf', options)),
...((schema.properties || 'additionalProperties' in schema) &&
parseObjectSchema(schema, refs, options))
};
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[req] I still believe combining allOf and type: object is just incorrect, therefore if both are set and we know a few cases where services do that, I would allow that and treat it as allOf only. Parsing other properties and handling them a certain way is just guess work and as far as I know we haven't seen examples of that before, did we?

Therefore my suggestion is to just move this down below anyOf so objects are prioritized lower.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[pp] I think it could be helpful to have a warning when generating this (incorrect) type. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added info log if allOf and properties are at the same level. It is restructured into the "inheritance" type as discussed

return parseObjectSchema(schema, refs, options);
}

Expand Down Expand Up @@ -221,8 +229,11 @@ function parseXOfSchema(
xOf: 'oneOf' | 'allOf' | 'anyOf',
options: ParserOptions
): any {
const required = schema.required;
return {
[xOf]: (schema[xOf] || []).map(entry => parseSchema(entry, refs, options))
[xOf]: (schema[xOf] || []).map(entry =>
parseSchema({ ...entry, required }, refs, options)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[req] In this case the schema would overwrite anything that is required in the actual entry. We should at least merge this, but I think we shouldn't do this at all.

Copy link
Contributor Author

@deekshas8 deekshas8 Sep 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed this for now. Required will be considered in a followup

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I merge this now. Have also added a test for it.

)
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
* This is a generated file powered by the SAP Cloud SDK for JavaScript.
*/
export * from './test-entity';
export * from './test-entity-2';
export * from './test-entity-3';

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
* This is a generated file powered by the SAP Cloud SDK for JavaScript.
*/
export * from './test-entity';
export * from './test-entity-2';
export * from './test-entity-3';
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright (c) 2024 SAP SE or an SAP affiliate company. All rights reserved.
*
* This is a generated file powered by the SAP Cloud SDK for JavaScript.
*/
import type { TestEntity } from './test-entity';
/**
* Representation of the 'TestEntity2' schema.
*/
export type TestEntity2 = TestEntity & {
booleanProperty: boolean;
} & Record<string, any>;

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright (c) 2024 SAP SE or an SAP affiliate company. All rights reserved.
*
* This is a generated file powered by the SAP Cloud SDK for JavaScript.
*/
import type { TestEntity } from './test-entity';
/**
* Representation of the 'TestEntity2' schema.
*/
export type TestEntity2 = TestEntity & {
booleanProperty: boolean;
} & Record<string, any>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright (c) 2024 SAP SE or an SAP affiliate company. All rights reserved.
*
* This is a generated file powered by the SAP Cloud SDK for JavaScript.
*/
import type { TestEntity } from './test-entity';
/**
* Representation of the 'TestEntity3' schema.
*/
export type TestEntity3 = TestEntity & {
booleanProperty?: boolean;
} & Record<string, any>;

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright (c) 2024 SAP SE or an SAP affiliate company. All rights reserved.
*
* This is a generated file powered by the SAP Cloud SDK for JavaScript.
*/
import type { TestEntity } from './test-entity';
/**
* Representation of the 'TestEntity3' schema.
*/
export type TestEntity3 = TestEntity & {
booleanProperty?: boolean;
} & Record<string, any>;
17 changes: 17 additions & 0 deletions test-resources/openapi-service-specs/swagger-yaml-service.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,20 @@ definitions:
type: integer
description: An integer property
required: false
TestEntity_2:
type: object
allOf:
- $ref: '#/definitions/TestEntity'
- properties:
booleanProperty:
type: boolean
required:
- booleanProperty
TestEntity_3:
type: object
allOf:
- $ref: '#/definitions/TestEntity'
properties:
booleanProperty:
type: boolean