Skip to content

Commit 37b0397

Browse files
deekshas8cloud-sdk-jsmarikaner
authored
chore: Adjust openapi generator for azure spec (#4953)
* add schema prefix option * Changes from lint:fix * parse properties + required * Changes from lint:fix * fix test * fix * Changes from lint:fix * array has type obj with allOf only * Changes from lint:fix * fixes * lint fix + log * fix message * empty string for prefix * clean up * refactor + tests * Changes from lint:fix * Update packages/openapi-generator/src/generator.ts * regenerate with different name * review remarks * add comments * additionalprop * Changes from lint:fix --------- Co-authored-by: cloud-sdk-js <cloud-sdk-js@github.com> Co-authored-by: Marika Marszalkowski <868536+marikaner@users.noreply.github.com>
1 parent fd0ff0a commit 37b0397

24 files changed

+303
-11
lines changed

packages/openapi-generator/src/file-serializer/schema.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ export function serializeSchema(schema: OpenApiSchema): string {
3232
const type = serializeSchema(schema.items);
3333
return schema.uniqueItems
3434
? `Set<${type}>`
35-
: 'properties' in schema.items
35+
: ['properties', 'allOf', 'oneOf', 'anyOf'].some(
36+
prop => prop in schema.items
37+
)
3638
? `(${type})[]`
3739
: `${type}[]`;
3840
}

packages/openapi-generator/src/parser/schema.spec.ts

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,110 @@ describe('parseSchema', () => {
416416
);
417417
});
418418

419+
it('parses xOf schema ignoring type:object at same level', async () => {
420+
const schema: OpenAPIV3.SchemaObject = {
421+
type: 'object',
422+
oneOf: [
423+
{ type: 'object' },
424+
{
425+
anyOf: [
426+
{ type: 'object' },
427+
{ allOf: [{ type: 'object' }, { type: 'string' }] }
428+
]
429+
}
430+
]
431+
};
432+
expect(parseSchema(schema, await createTestRefs(), defaultOptions)).toEqual(
433+
{
434+
oneOf: [
435+
emptyObjectSchema,
436+
{
437+
anyOf: [
438+
emptyObjectSchema,
439+
{ allOf: [emptyObjectSchema, { type: 'string' }] }
440+
]
441+
}
442+
]
443+
}
444+
);
445+
});
446+
447+
it('normalizes xOf schemas with properties at same level', async () => {
448+
const schema: OpenAPIV3.SchemaObject = {
449+
type: 'object',
450+
properties: { prop1: { type: 'string' } },
451+
oneOf: [
452+
{ type: 'object' },
453+
{
454+
allOf: [{ type: 'object' }, { type: 'string' }]
455+
}
456+
]
457+
};
458+
expect(parseSchema(schema, await createTestRefs(), defaultOptions)).toEqual(
459+
{
460+
oneOf: [
461+
emptyObjectSchema,
462+
{ allOf: [emptyObjectSchema, { type: 'string' }] },
463+
{
464+
additionalProperties: { type: 'any' },
465+
properties: [
466+
{
467+
name: 'prop1',
468+
description: undefined,
469+
required: false,
470+
schema: {
471+
type: 'string'
472+
},
473+
schemaProperties: {}
474+
}
475+
]
476+
}
477+
]
478+
}
479+
);
480+
});
481+
482+
it('parses xOf schemas with required', async () => {
483+
const schema: OpenAPIV3.SchemaObject = {
484+
oneOf: [
485+
{ type: 'object' },
486+
{
487+
allOf: [
488+
{ type: 'object', properties: { prop1: { type: 'string' } } },
489+
{ type: 'string' }
490+
],
491+
required: ['prop1']
492+
}
493+
]
494+
};
495+
expect(parseSchema(schema, await createTestRefs(), defaultOptions)).toEqual(
496+
{
497+
oneOf: [
498+
emptyObjectSchema,
499+
{
500+
allOf: [
501+
{
502+
additionalProperties: { type: 'any' },
503+
properties: [
504+
{
505+
name: 'prop1',
506+
description: undefined,
507+
required: true,
508+
schema: {
509+
type: 'string'
510+
},
511+
schemaProperties: {}
512+
}
513+
]
514+
},
515+
{ type: 'string' }
516+
]
517+
}
518+
]
519+
}
520+
);
521+
});
522+
419523
it('parses not schema', async () => {
420524
const schema: OpenAPIV3.SchemaObject = {
421525
not: { type: 'object' }

packages/openapi-generator/src/parser/schema.ts

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,6 @@ export function parseSchema(
4242
return parseArraySchema(schema, refs, options);
4343
}
4444

45-
if (
46-
schema.type === 'object' ||
47-
schema.properties ||
48-
'additionalProperties' in schema
49-
) {
50-
return parseObjectSchema(schema, refs, options);
51-
}
52-
5345
if (schema.enum?.length) {
5446
return parseEnumSchema(schema, options);
5547
}
@@ -66,6 +58,16 @@ export function parseSchema(
6658
return parseXOfSchema(schema, refs, 'anyOf', options);
6759
}
6860

61+
// An object schema should be parsed after allOf, anyOf, oneOf.
62+
// When object.properties are at the same level with anyOf, oneOf, allOf, they should be treated as part of allOf, etc.
63+
if (
64+
schema.type === 'object' ||
65+
schema.properties ||
66+
schema.additionalProperties
67+
) {
68+
return parseObjectSchema(schema, refs, options);
69+
}
70+
6971
if (schema.not) {
7072
return {
7173
not: parseSchema(schema.not, refs, options)
@@ -223,11 +225,42 @@ function parseXOfSchema(
223225
xOf: 'oneOf' | 'allOf' | 'anyOf',
224226
options: ParserOptions
225227
): any {
228+
const normalizedSchema = normalizeSchema(schema, xOf);
229+
226230
return {
227-
[xOf]: (schema[xOf] || []).map(entry => parseSchema(entry, refs, options))
231+
[xOf]: (normalizedSchema[xOf] || []).map(entry =>
232+
parseSchema(
233+
{
234+
...entry,
235+
required: [
236+
// Add required properties from the entry.
237+
...('required' in entry && entry.required ? entry.required : []),
238+
// Add required properties from the top level schema (xOf).
239+
...(normalizedSchema.required || [])
240+
]
241+
},
242+
refs,
243+
options
244+
)
245+
)
228246
};
229247
}
230248

249+
function normalizeSchema(
250+
schema: OpenAPIV3.NonArraySchemaObject,
251+
xOf: 'oneOf' | 'allOf' | 'anyOf'
252+
): OpenAPIV3.NonArraySchemaObject {
253+
if (schema.properties || schema.additionalProperties) {
254+
logger.info(
255+
`Detected schema with ${xOf} and properties in the same level. This was refactored to a schema with ${xOf} only, containing all the properties from the top level.`
256+
);
257+
258+
const { [xOf]: xOfSchema = [], ...objectSchema } = schema;
259+
return { [xOf]: [...xOfSchema, objectSchema] };
260+
}
261+
return schema;
262+
}
263+
231264
/**
232265
* Parse schema properties e.g. 'maxLength', 'minimum', etc.
233266
* @param schema - Original schema representing a ref or schema object.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
* Copyright (c) 2024 SAP SE or an SAP affiliate company. All rights reserved.
3+
*
4+
* This is a generated file powered by the SAP Cloud SDK for JavaScript.
5+
*/
6+
import type { TestEntity } from './test-entity';
7+
/**
8+
* Composition of extended properties (inheritance) and schema-specific properties together with required attribute.
9+
*/
10+
export type EntityXOfInheritance = TestEntity & {
11+
booleanProperty: boolean;
12+
integerProperty2?: number;
13+
} & Record<string, any>;

test-packages/test-services-openapi/swagger-yaml-service/schema/entity-x-of-inheritance.js

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test-packages/test-services-openapi/swagger-yaml-service/schema/entity-x-of-inheritance.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
* Copyright (c) 2024 SAP SE or an SAP affiliate company. All rights reserved.
3+
*
4+
* This is a generated file powered by the SAP Cloud SDK for JavaScript.
5+
*/
6+
import type { TestEntity } from './test-entity';
7+
/**
8+
* Composition of extended properties (inheritance) and schema-specific properties together with required attribute.
9+
*/
10+
export type EntityXOfInheritance = TestEntity & {
11+
booleanProperty: boolean;
12+
integerProperty2?: number;
13+
} & Record<string, any>;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* Copyright (c) 2024 SAP SE or an SAP affiliate company. All rights reserved.
3+
*
4+
* This is a generated file powered by the SAP Cloud SDK for JavaScript.
5+
*/
6+
import type { TestEntity } from './test-entity';
7+
/**
8+
* Entity with xOf and schema properties at same level. This is normalized to only xOf with schema properties inside xOf. Also works if only additionalProperties true is used.
9+
*/
10+
export type EntityXOfNormalizedWithObject =
11+
| TestEntity
12+
| ({
13+
booleanProperty: boolean;
14+
} & Record<string, any>);

test-packages/test-services-openapi/swagger-yaml-service/schema/entity-x-of-normalized-with-object.js

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test-packages/test-services-openapi/swagger-yaml-service/schema/entity-x-of-normalized-with-object.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)