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

Closes #23 Use title to create inner schema names #24

Merged
merged 1 commit into from
Oct 31, 2023
Merged
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
24 changes: 14 additions & 10 deletions lib/src/generators/schema.dart
Original file line number Diff line number Diff line change
Expand Up @@ -342,36 +342,39 @@ class SchemaGenerator extends BaseGenerator {
// Keep track of the required converter logic
final List<String> converters = [];

// Name of the union constructor
final uNameConstr = '_Union$union';

schema.mapOrNull(
object: (s) {
for (final a in (s.anyOf ?? <Schema>[])) {
a.mapOrNull(
string: (o) {
final uName = '${union}String';
final uName = '${uNameConstr}String';
converters.add('$uName(value: final v) => v,');
file.writeAsStringSync(
'const factory $union.string(${o.toDartType()} value,) = $uName;\n\n',
mode: FileMode.append,
);
},
number: (o) {
final uName = '${union}Number';
final uName = '${uNameConstr}Number';
converters.add('$uName(value: final v) => v,');
file.writeAsStringSync(
'const factory $union.number(${o.toDartType()} value,) = $uName;\n\n',
mode: FileMode.append,
);
},
integer: (o) {
final uName = '${union}Integer';
final uName = '${uNameConstr}Integer';
converters.add('$uName(value: final v) => v,');
file.writeAsStringSync(
'const factory $union.integer(${o.toDartType()} value,) = $uName;\n\n',
mode: FileMode.append,
);
},
enumeration: (o) {
final uName = '${union}Enum';
final uName = '${uNameConstr}Enum';
converters.add(
'$uName(value: final v) => _\$${o.title}EnumMap[v]!,',
);
Expand All @@ -382,7 +385,7 @@ class SchemaGenerator extends BaseGenerator {
},
array: (o) {
final factoryName = 'array${o.title?.split('Array').last}';
final uName = '$union${factoryName.pascalCase}';
final uName = '$uNameConstr${factoryName.pascalCase}';
converters.add('$uName(value: final v) => v,');
file.writeAsStringSync(
'const factory $union.$factoryName(${o.toDartType()} value,) = $uName;\n\n',
Expand Down Expand Up @@ -581,11 +584,12 @@ class SchemaGenerator extends BaseGenerator {

String customConverter = '';

// Prefix with expected custom converter
if ((p.anyOf?.isNotEmpty ?? false) &&
(p.title?.toLowerCase().startsWith('union') ?? false)) {
customConverter =
'@_${p.toDartType().replaceAll('?', '')}Converter()';
// Prefix with expected custom converter for primitive union types
if ((p.anyOf?.isNotEmpty ?? false)) {
if (!p.anyOf!.map((e) => e.type).contains(SchemaType.object)) {
customConverter =
'@_${p.toDartType().replaceAll('?', '')}Converter()';
}
}

// Handle union defaults
Expand Down
38 changes: 27 additions & 11 deletions lib/src/open_api/spec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class OpenApi with _$OpenApi {
final (schemaOut, extraOut) = _extraComponentSchemas(
schemaKey: s,
schemaMap: schemas[s],
allSchemaNames: (schemas.keys.toList() + schemaExtra.keys.toList()),
);
schemas[s] = schemaOut;
if (extraOut.isNotEmpty) {
Expand Down Expand Up @@ -623,6 +624,7 @@ Map<String, dynamic> _formatSpecFromJson({
(Map<String, dynamic>, Map<String, dynamic>) _extraComponentSchemas({
required String schemaKey,
required Map<String, dynamic> schemaMap,
required List<String> allSchemaNames,
}) {
final schema = Schema.fromJson(schemaMap);
final Map<String, dynamic> schemaExtra = {};
Expand All @@ -640,16 +642,25 @@ Map<String, dynamic> _formatSpecFromJson({
var p = Map<String, dynamic>.from(entry.value);

// Generate a new schema name
String newSchema = schemaKey;
String parentSchema = schemaKey;
if (schema.title != null) {
newSchema = schema.title!.pascalCase;
parentSchema = schema.title!.pascalCase;
}

// Fallback name - this is most likely to be unique/safe
final newSchemaFallback = '$parentSchema${entry.key.pascalCase}'.pascalCase;

String newSchema = '';
if (p['title'] != null) {
newSchema += (p['title']!).toString().pascalCase;
// If the property has a title, use that
newSchema = (p['title']!).toString().pascalCase;
if (allSchemaNames.contains(newSchema)) {
newSchema = newSchemaFallback;
}
} else {
newSchema += entry.key.pascalCase;
// Else, use the parent schema name and the property name as suffix
newSchema = newSchemaFallback;
}
newSchema = newSchema.pascalCase;

if (p['type'] == 'enumeration' && p.containsKey('enum')) {
// Handle inner enum definitions
Expand Down Expand Up @@ -688,6 +699,7 @@ Map<String, dynamic> _formatSpecFromJson({
newSchema: newSchema,
propertyKey: entry.key,
propertyMap: p,
allSchemaNames: allSchemaNames,
);
if (extraPropSchema.isNotEmpty) {
props[entry.key] = newPropSchema;
Expand All @@ -707,6 +719,7 @@ Map<String, dynamic> _formatSpecFromJson({
final (schemaOut, schemaExtraInner) = _extraComponentSchemas(
schemaKey: entry.key,
schemaMap: entry.value,
allSchemaNames: allSchemaNames,
);
schemaExtra[entry.key] = schemaOut;
schemaExtra.addAll(schemaExtraInner);
Expand All @@ -724,13 +737,12 @@ Map<String, dynamic> _formatSpecFromJson({
required String newSchema,
required String propertyKey,
required Map<String, dynamic> propertyMap,
required List<String> allSchemaNames,
}) {
final Map<String, dynamic> schemaExtra = {};
final p = Map<String, dynamic>.from(propertyMap);
var propertyMapOut = Map<String, dynamic>.from(propertyMap);

final newSchemaUnion = 'Union$newSchema';

// Package treats oneOf as anyOf under the hood
// Rename oneOf to anyOf to reuse the same logic
if (p.containsKey('oneOf') && !p.containsKey('anyOf')) {
Expand All @@ -747,7 +759,11 @@ Map<String, dynamic> _formatSpecFromJson({
}
final aType =
aMap['type'].toString().replaceAll('enumeration', 'enum').pascalCase;
final anyOfName = '$newSchema$aType';

String anyOfName = '$newSchema$aType';
if (aMap['title'] != null) {
anyOfName = aMap['title'].toString().pascalCase;
}
aMap['title'] = anyOfName;

// Convert to schema
Expand Down Expand Up @@ -780,8 +796,8 @@ Map<String, dynamic> _formatSpecFromJson({

if (anyOf.isNotEmpty) {
// Create a custom union schema that is composed of the any of schemas
schemaExtra[newSchemaUnion] = Schema.object(
title: newSchemaUnion,
schemaExtra[newSchema] = Schema.object(
title: newSchema,
description: p['description'],
anyOf: anyOf,
).toJson();
Expand All @@ -790,7 +806,7 @@ Map<String, dynamic> _formatSpecFromJson({
description: p['description'],
defaultValue: p['default'] is Map ? null : p['default'],
nullable: p['nullable'],
ref: newSchemaUnion,
ref: newSchema,
).toJson();
}
}
Expand Down