Skip to content

Commit b2f03f2

Browse files
committed
(WIP) Address failing original tests. Add tests for NextGen path.
1 parent 985de8b commit b2f03f2

17 files changed

+897
-205
lines changed

openapi-generator-annotations/lib/src/openapi_generator_annotations_base.dart

Lines changed: 126 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ class Openapi {
104104
/// For use with [useNextGen].
105105
final String? cachePath;
106106

107+
/// Use a custom pubspec when running the generator.
108+
final String? projectPubspecPath;
109+
107110
const Openapi({
108111
this.additionalProperties,
109112
@deprecated this.overwriteExistingFiles,
@@ -123,10 +126,11 @@ class Openapi {
123126
@deprecated this.alwaysRun = false,
124127
this.cachePath,
125128
this.useNextGen = false,
129+
this.projectPubspecPath,
126130
});
127-
// TODO: Enable assertion error
128-
// : assert(cachePath != null && !useNextGen,
129-
// 'useNextGen should be set when providing cachePath');
131+
// TODO: Enable assertion error
132+
// : assert(cachePath != null && !useNextGen,
133+
// 'useNextGen should be set when providing cachePath');
130134
}
131135

132136
class AdditionalProperties {
@@ -211,19 +215,40 @@ class AdditionalProperties {
211215
allowUnicodeIdentifiers: map['allowUnicodeIdentifiers'] ?? false,
212216
ensureUniqueParams: map['ensureUniqueParams'] ?? true,
213217
useEnumExtension: map['useEnumExtension'] ?? true,
214-
prependFormOrBodyParameters: map['prependFormOrBodyParameters'] ?? false,
218+
prependFormOrBodyParameters:
219+
map['prependFormOrBodyParameters'] ?? false,
215220
pubAuthor: map['pubAuthor'],
216221
pubAuthorEmail: map['pubAuthorEmail'],
217222
pubDescription: map['pubDescription'],
218223
pubHomepage: map['pubHomepage'],
219224
pubName: map['pubName'],
220225
pubVersion: map['pubVersion'],
221-
legacyDiscriminatorBehavior: map['legacyDiscriminatorBehavior'] ?? true,
222-
sortModelPropertiesByRequiredFlag: map['sortModelPropertiesByRequiredFlag'] ?? true,
226+
legacyDiscriminatorBehavior:
227+
map['legacyDiscriminatorBehavior'] ?? true,
228+
sortModelPropertiesByRequiredFlag:
229+
map['sortModelPropertiesByRequiredFlag'] ?? true,
223230
sortParamsByRequiredFlag: map['sortParamsByRequiredFlag'] ?? true,
224231
sourceFolder: map['sourceFolder'],
225-
wrapper: EnumTransformer.wrapper(map['wrapper']),
232+
wrapper: EnumTransformer.wrapper(map['wrapper']),
226233
);
234+
235+
Map<String, dynamic> toMap() => {
236+
'allowUnicodeIdentifiers': allowUnicodeIdentifiers,
237+
'ensureUniqueParams': ensureUniqueParams,
238+
'useEnumExtension': useEnumExtension,
239+
'prependFormOrBodyParameters': prependFormOrBodyParameters,
240+
if (pubAuthor != null) 'pubAuthor': pubAuthor,
241+
if (pubAuthorEmail != null) 'pubAuthorEmail': pubAuthorEmail,
242+
if (pubDescription != null) 'pubDescription': pubDescription,
243+
if (pubHomepage != null) 'pubHomepage': pubHomepage,
244+
if (pubName != null) 'pubName': pubName,
245+
if (pubVersion != null) 'pubVersion': pubVersion,
246+
'legacyDiscriminatorBehavior': legacyDiscriminatorBehavior,
247+
'sortModelPropertiesByRequiredFlag': sortModelPropertiesByRequiredFlag,
248+
'sortParamsByRequiredFlag': sortParamsByRequiredFlag,
249+
if (sourceFolder != null) 'sourceFolder': sourceFolder,
250+
'wrapper': EnumTransformer.wrapperName(wrapper)
251+
};
227252
}
228253

229254
/// Allows you to customize how inline schemas are handled or named
@@ -260,6 +285,15 @@ class InlineSchemaOptions {
260285
refactorAllofInlineSchemas: map['refactorAllofInlineSchemas'] ?? true,
261286
resolveInlineEnums: map['resolveInlineEnums'] ?? true,
262287
);
288+
289+
/// A convenience function that simplifies the output to the compiler.
290+
Map<String, dynamic> toMap() => {
291+
if (arrayItemSuffix != null) 'arrayItemSuffix': arrayItemSuffix!,
292+
if (mapItemSuffix != null) 'mapItemSuffix': mapItemSuffix!,
293+
'skipSchemaReuse': skipSchemaReuse,
294+
'refactorAllofInlineSchemas': refactorAllofInlineSchemas,
295+
'resolveInlineEnums': resolveInlineEnums,
296+
};
263297
}
264298

265299
class DioProperties extends AdditionalProperties {
@@ -304,10 +338,21 @@ class DioProperties extends AdditionalProperties {
304338
useEnumExtension: useEnumExtension);
305339

306340
DioProperties.fromMap(Map<String, dynamic> map)
307-
: dateLibrary = map['dateLibrary'],
341+
: dateLibrary = EnumTransformer.dioDateLibrary(map['dateLibrary']),
308342
nullableFields = map['nullableFields'] as bool?,
309-
serializationLibrary = map['serializationLibrary'],
343+
serializationLibrary = EnumTransformer.dioSerializationLibrary(
344+
map['serializationLibrary']),
310345
super.fromMap(map);
346+
347+
Map<String, dynamic> toMap() => Map.from(super.toMap())
348+
..addAll({
349+
if (dateLibrary != null)
350+
'dateLibrary': EnumTransformer.dioDateLibraryName(dateLibrary!),
351+
if (nullableFields != null) 'nullableFields': nullableFields,
352+
if (serializationLibrary != null)
353+
'serializationLibrary':
354+
EnumTransformer.dioSerializationLibraryName(serializationLibrary!),
355+
});
311356
}
312357

313358
class DioAltProperties extends AdditionalProperties {
@@ -372,6 +417,18 @@ class DioAltProperties extends AdditionalProperties {
372417
pubspecDependencies = map['pubspecDependencies'],
373418
pubspecDevDependencies = map['pubspecDevDependencies'],
374419
super.fromMap(map);
420+
421+
Map<String, dynamic> toMap() => Map.from(super.toMap())
422+
..addAll({
423+
if (nullSafe != null) 'nullSafe': nullSafe,
424+
if (nullSafeArrayDefault != null)
425+
'nullSafeArrayDefault': nullSafeArrayDefault,
426+
if (listAnyOf != null) 'listAnyOf': listAnyOf,
427+
if (pubspecDependencies != null)
428+
'pubspecDependencies': pubspecDependencies,
429+
if (pubspecDevDependencies != null)
430+
'pubspecDevDependencies': pubspecDevDependencies,
431+
});
375432
}
376433

377434
enum DioDateLibrary {
@@ -387,7 +444,6 @@ enum DioSerializationLibrary { built_value, json_serializable }
387444

388445
enum SerializationFormat { JSON, PROTO }
389446

390-
391447
/// The name of the generator to use
392448
enum Generator {
393449
/// This generator uses the default http package that comes with dart
@@ -412,12 +468,47 @@ enum Generator {
412468
// remove this work around.
413469
/// Transforms the enums used with the [Openapi] annotation.
414470
class EnumTransformer {
471+
static DioDateLibrary dioDateLibrary(String? name) {
472+
switch (name) {
473+
case 'timemachine':
474+
return DioDateLibrary.timemachine;
475+
default:
476+
return DioDateLibrary.core;
477+
}
478+
}
479+
480+
static String dioDateLibraryName(DioDateLibrary lib) {
481+
switch (lib) {
482+
case DioDateLibrary.timemachine:
483+
return 'timemachine';
484+
default:
485+
return 'core';
486+
}
487+
}
488+
489+
static DioSerializationLibrary dioSerializationLibrary(String? name) {
490+
switch (name) {
491+
case 'json_serializable':
492+
return DioSerializationLibrary.json_serializable;
493+
default:
494+
return DioSerializationLibrary.built_value;
495+
}
496+
}
497+
498+
static String dioSerializationLibraryName(DioSerializationLibrary lib) {
499+
switch (lib) {
500+
case DioSerializationLibrary.json_serializable:
501+
return 'json_serializable';
502+
default:
503+
return 'built_value';
504+
}
505+
}
506+
415507
/// Converts the given [name] to the matching [Generator] name.
416508
///
417509
/// Defaults to [Generator.dart];
418510
static Generator generator(String? name) {
419-
print(name);
420-
switch(name) {
511+
switch (name) {
421512
case 'dio':
422513
return Generator.dio;
423514
case 'dioAlt':
@@ -427,11 +518,22 @@ class EnumTransformer {
427518
}
428519
}
429520

521+
static String generatorName(Generator generator) {
522+
switch (generator) {
523+
case Generator.dio:
524+
return 'dart-dio';
525+
case Generator.dioAlt:
526+
return 'dart2-api';
527+
default:
528+
return 'dart';
529+
}
530+
}
531+
430532
/// Converts the given [name] to the matching [Wrapper] name.
431533
///
432534
/// Defaults to [Wrapper.none];
433535
static Wrapper wrapper(String? name) {
434-
switch(name) {
536+
switch (name) {
435537
case 'fvm':
436538
return Wrapper.fvm;
437539
case 'flutterw':
@@ -440,6 +542,17 @@ class EnumTransformer {
440542
return Wrapper.none;
441543
}
442544
}
545+
546+
static String wrapperName(Wrapper wrapper) {
547+
switch (wrapper) {
548+
case Wrapper.flutterw:
549+
return 'flutterw';
550+
case Wrapper.fvm:
551+
return 'fvm';
552+
default:
553+
return 'none';
554+
}
555+
}
443556
}
444557

445558
enum Wrapper { fvm, flutterw, none }

openapi-generator/lib/src/extensions/type_methods.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,16 +81,16 @@ extension ReadProperty on ConstantReader {
8181
return defaultValue;
8282
}
8383

84-
if (defaultValue is AdditionalProperties ||
85-
defaultValue is InlineSchemaOptions) {
84+
if (defaultValue is AdditionalProperties? ||
85+
defaultValue is InlineSchemaOptions?) {
8686
final mapping = v
8787
.revive()
8888
.namedArguments
8989
.map((key, value) => MapEntry(key, convertToPropertyValue(value)));
90-
if (defaultValue is AdditionalProperties) {
91-
if (defaultValue is DioProperties) {
90+
if (defaultValue is AdditionalProperties?) {
91+
if (defaultValue is DioProperties?) {
9292
return DioProperties.fromMap(mapping) as T;
93-
} else if (defaultValue is DioAltProperties) {
93+
} else if (defaultValue is DioAltProperties?) {
9494
return DioAltProperties.fromMap(mapping) as T;
9595
} else {
9696
return AdditionalProperties.fromMap(mapping) as T;

openapi-generator/lib/src/gen_on_spec_changes.dart

Lines changed: 47 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import 'dart:convert';
33
import 'dart:developer';
44
import 'dart:io';
55

6+
import 'package:http/http.dart' as http;
7+
import 'package:logging/logging.dart';
8+
import 'package:openapi_generator/src/models/output_message.dart';
69
import 'package:yaml/yaml.dart';
710

811
// .json
@@ -28,22 +31,52 @@ FutureOr<Map<String, dynamic>> loadSpec(
2831
// If the spec file doesn't match any of the currently supported spec formats
2932
// reject the request.
3033
if (!_supportedRegexes.any((fileEnding) => fileEnding.hasMatch(specPath))) {
31-
return Future.error('Invalid spec file format');
34+
return Future.error(
35+
OutputMessage(
36+
message: 'Invalid spec file format.',
37+
level: Level.SEVERE,
38+
stackTrace: StackTrace.current,
39+
),
40+
);
3241
}
3342

34-
final file = File(specPath);
35-
if (file.existsSync()) {
36-
final contents = await file.readAsString();
37-
late Map<String, dynamic> spec;
38-
if (yamlRegex.hasMatch(specPath)) {
39-
// Load yaml and convert to file
40-
spec = convertYamlMapToDartMap(yamlMap: loadYaml(contents));
43+
final isRemote = RegExp(r'^https?://').hasMatch(specPath);
44+
if (!isRemote) {
45+
final file = File(specPath);
46+
if (file.existsSync()) {
47+
final contents = await file.readAsString();
48+
late Map<String, dynamic> spec;
49+
if (yamlRegex.hasMatch(specPath)) {
50+
// Load yaml and convert to file
51+
spec = convertYamlMapToDartMap(yamlMap: loadYaml(contents));
52+
} else {
53+
// Convert to json map via json.decode
54+
spec = jsonDecode(contents);
55+
}
56+
57+
return spec;
58+
}
59+
} else {
60+
// TODO: Support custom headers?
61+
final url = Uri.parse(specPath);
62+
final resp = await http.get(url);
63+
if (resp.statusCode == 200) {
64+
if (yamlRegex.hasMatch(specPath)) {
65+
return convertYamlMapToDartMap(yamlMap: loadYaml(resp.body));
66+
} else {
67+
return jsonDecode(resp.body);
68+
}
4169
} else {
42-
// Convert to json map via json.decode
43-
spec = jsonDecode(contents);
70+
return Future.error(
71+
OutputMessage(
72+
message:
73+
'Unable to request remote spec. Ensure it is public or use a local copy instead.',
74+
level: Level.SEVERE,
75+
additionalContext: resp.statusCode,
76+
stackTrace: StackTrace.current,
77+
),
78+
);
4479
}
45-
46-
return spec;
4780
}
4881

4982
// In the event that the cached spec isn't found, provide an empty mapping
@@ -53,7 +86,8 @@ FutureOr<Map<String, dynamic>> loadSpec(
5386
return {};
5487
}
5588

56-
return Future.error('Unable to find spec file $specPath');
89+
return Future.error(
90+
OutputMessage(message: 'Unable to find spec file $specPath'));
5791
}
5892

5993
/// Verify if the [loadedSpec] has a diff compared to the [cachedSpec].

openapi-generator/lib/src/models/command.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ class Command {
2626
: wrapper == Wrapper.flutterw
2727
? './flutterw'
2828
: 'fvm',
29-
[if (wrapper != Wrapper.none) executable, ...arguments],
29+
arguments,
3030
);
3131
}

0 commit comments

Comments
 (0)