Skip to content

Commit 720f073

Browse files
committed
handle minProperties = 1 and maxProperties = 1
1 parent 51ad95d commit 720f073

2 files changed

Lines changed: 45 additions & 2 deletions

File tree

tools/proto-convert/src/SchemaModifier.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ export class SchemaModifier {
3333
this.handleOneOfConst(schema, schemaName)
3434
this.collapseOrMergeOneOfArray(schema)
3535
this.collapseOneOfObjectPropContainsTitleSchema(schema)
36+
// Only mark x-oneof-constraint for top-level schemas, not nested in allOf/anyOf/oneOf
37+
if (schemaName && !['allOf', 'anyOf', 'oneOf'].includes(schemaName)) {
38+
this.markTopLevelOneOfConstraint(schema);
39+
}
3640
},
3741
});
3842
const visit = new Set();
@@ -437,4 +441,30 @@ export class SchemaModifier {
437441

438442
this.logger.info(`Converted additionalProperties to named property '${propertyName}' with type: object`);
439443
}
444+
445+
markTopLevelOneOfConstraint(schema: OpenAPIV3.SchemaObject): void {
446+
if (schema.minProperties === 1 && schema.maxProperties === 1) {
447+
(schema as any)['x-oneof-constraint'] = true;
448+
this.logger.info(`Marked schema with x-oneof-constraint`);
449+
return;
450+
}
451+
452+
const composedKeys = ['allOf', 'anyOf', 'oneOf'] as const;
453+
for (const key of composedKeys) {
454+
const items = schema[key];
455+
if (Array.isArray(items)) {
456+
for (const item of items) {
457+
if (item && typeof item === 'object' && !('$ref' in item)) {
458+
const itemSchema = item as any;
459+
if (itemSchema.minProperties === 1 && itemSchema.maxProperties === 1) {
460+
(schema as any)['x-oneof-constraint'] = true;
461+
this.logger.info(`Marked schema with x-oneof-constraint (found in nested ${key})`);
462+
return;
463+
}
464+
}
465+
}
466+
}
467+
}
468+
}
469+
440470
}

tools/proto-convert/src/config/protobuf-schema-template/model.mustache

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ import "{{{import}}}.proto";
2929
{{/-first}}
3030
{{/oneOf}}
3131
{{^oneOf}}
32-
{{#vars}}
32+
{{#vars}}
33+
{{^vendorExtensions.x-oneof}}
3334
{{#description}}
3435
// {{{.}}}
3536
{{/description}}
@@ -47,8 +48,20 @@ import "{{{import}}}.proto";
4748

4849
{{enumName}} {{name}} = {{vendorExtensions.x-protobuf-index}};
4950
{{/isEnum}}
50-
51+
{{/vendorExtensions.x-oneof}}
52+
{{/vars}}
53+
{{#vendorExtensions.x-oneof-constraint}}
54+
oneof {{classVarName}} {
55+
{{#vars}}
56+
{{#vendorExtensions.x-oneof}}
57+
{{#description}}
58+
// {{{.}}}
59+
{{/description}}
60+
{{#vendorExtensions.x-protobuf-type}}{{{.}}} {{/vendorExtensions.x-protobuf-type}}{{{vendorExtensions.x-protobuf-data-type}}} {{{name}}} = {{vendorExtensions.x-protobuf-index}}{{#vendorExtensions.x-protobuf-packed}} [packed=true]{{/vendorExtensions.x-protobuf-packed}}{{#vendorExtensions.x-protobuf-json-name}} [json_name="{{vendorExtensions.x-protobuf-json-name}}"]{{/vendorExtensions.x-protobuf-json-name}};
61+
{{/vendorExtensions.x-oneof}}
5162
{{/vars}}
63+
}
64+
{{/vendorExtensions.x-oneof-constraint}}
5265
{{/oneOf}}
5366
}
5467
{{/isEnum}}

0 commit comments

Comments
 (0)