Skip to content

Commit 8131e8e

Browse files
committed
feat(cli): removed jar binary from library and made the jar downloadable by auto generated config
fixes #153
1 parent c9a179a commit 8131e8e

File tree

3 files changed

+300
-45
lines changed

3 files changed

+300
-45
lines changed

example/lib/main.dart

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// Openapi Generator last run: : 2024-10-31T23:11:13.130123
21
import 'package:flutter/material.dart';
32
import 'package:openapi_generator_annotations/openapi_generator_annotations.dart';
43

@@ -13,7 +12,7 @@ void main() {
1312
RemoteSpec(path: 'https://petstore3.swagger.io/api/v3/openapi.json'),
1413
typeMappings: {'Pet': 'ExamplePet'},
1514
generatorName: Generator.dioAlt,
16-
updateAnnotatedFile: true,
15+
updateAnnotatedFile: false,
1716
runSourceGenOnOutput: true,
1817
outputDirectory: 'api/petstore_api',
1918
)

openapi-generator-cli/bin/main.dart

+75-41
Original file line numberDiff line numberDiff line change
@@ -69,21 +69,29 @@ String constructJarUrl(String version) {
6969
}
7070

7171
/// Downloads a JAR file to the specified output path if it doesn't already exist
72-
Future<void> downloadJar(String url, String outputPath) async {
72+
Future<void> downloadJar(
73+
String url,
74+
String outputPath, {
75+
http.Client? client, // Injected HTTP client for testing
76+
void Function(String message) log =
77+
_logOutput, // Optional log function for testing
78+
}) async {
7379
outputPath = resolvePath(outputPath);
7480
final file = File(outputPath);
81+
client ??=
82+
http.Client(); // Use the injected client or default to a new client
83+
7584
if (!await file.exists()) {
76-
_logOutput('Downloading $url...');
85+
log('Downloading $url...');
7786

7887
final request = http.Request('GET', Uri.parse(url));
79-
final response = await request.send();
88+
final response = await client.send(request);
8089

8190
if (response.statusCode == 200) {
8291
final contentLength = response.contentLength ?? 0;
8392
final output = file.openWrite();
8493
var downloadedBytes = 0;
8594

86-
// Listen to the stream and write to the file in smaller chunks
8795
await response.stream.listen(
8896
(chunk) {
8997
downloadedBytes += chunk.length;
@@ -92,15 +100,15 @@ Future<void> downloadJar(String url, String outputPath) async {
92100
// Display progress if content length is known
93101
if (contentLength != 0) {
94102
final progress = (downloadedBytes / contentLength) * 100;
95-
stdout.write('\rProgress: ${progress.toStringAsFixed(2)}%');
103+
log('\rProgress: ${progress.toStringAsFixed(2)}%');
96104
}
97105
},
98106
onDone: () async {
99107
await output.close();
100-
print('\nDownloaded to $outputPath\n');
108+
log('\nDownloaded to $outputPath\n');
101109
},
102110
onError: (e) {
103-
print('\nDownload failed: $e\n');
111+
log('\nDownload failed: $e\n');
104112
},
105113
cancelOnError: true,
106114
).asFuture();
@@ -109,13 +117,13 @@ Future<void> downloadJar(String url, String outputPath) async {
109117
'Failed to download $url. Status code: ${response.statusCode}');
110118
}
111119
} else {
112-
print('[info] $outputPath found. No need to download');
120+
log('[info] $outputPath found. No need to download');
113121
}
114122
}
115123

116124
/// Executes the OpenAPI Generator using all JARs in the classpath
117-
Future<void> executeWithClasspath(
118-
List<String> jarPaths, List<String> arguments) async {
125+
Future<void> executeWithClasspath(List<String> jarPaths, List<String> arguments,
126+
[ProcessRunner process = const ProcessRunner()]) async {
119127
final javaOpts = Platform.environment['JAVA_OPTS'] ?? '';
120128
final classpath = jarPaths.join(Platform.isWindows ? ';' : ':');
121129
final commands = [
@@ -129,14 +137,31 @@ Future<void> executeWithClasspath(
129137
commands.insert(0, javaOpts);
130138
}
131139

132-
final result = await Process.run('java', commands);
140+
final result =
141+
await process.run('java', commands, runInShell: Platform.isWindows);
133142
print(result.stdout);
134143
print(result.stderr);
135144
}
136145

137-
/// Main function handling config loading, JAR downloading, and command execution
138146
Future<void> main(List<String> arguments) async {
139-
exitCode = 0; // presume success
147+
await runMain(
148+
arguments: arguments,
149+
loadConfig: loadOrCreateConfig,
150+
downloadJar: downloadJar,
151+
executeWithClasspath: executeWithClasspath,
152+
log: _logOutput,
153+
);
154+
}
155+
156+
Future<void> runMain({
157+
required List<String> arguments,
158+
required Future<Map<String, dynamic>> Function(String) loadConfig,
159+
required Future<void> Function(String, String) downloadJar,
160+
required Future<void> Function(List<String>, List<String>)
161+
executeWithClasspath,
162+
required void Function(String) log,
163+
}) async {
164+
exitCode = 0;
140165

141166
// Determine config path from arguments or default to 'openapi_generator_config.json'
142167
final configArgIndex = arguments.indexOf('--config');
@@ -145,22 +170,21 @@ Future<void> main(List<String> arguments) async {
145170
? arguments[configArgIndex + 1]
146171
: 'openapi_generator_config.json';
147172

148-
print('Using config file: $configFilePath');
149-
150-
final config = await loadOrCreateConfig(configFilePath);
151-
final String version = (config[ConfigKeys.openapiGeneratorVersion] ??
152-
ConfigDefaults.openapiGeneratorVersion);
153-
final String additionalCommands = config[ConfigKeys.additionalCommands] ??
154-
ConfigDefaults.additionalCommands;
155-
final String? overrideUrl = config[ConfigKeys.downloadUrlOverride];
156-
final cachePath = resolvePath(
157-
config[ConfigKeys.jarCachePath] ?? ConfigDefaults.jarCacheDir);
173+
log('Using config file: $configFilePath');
158174

159-
final customGeneratorUrls = List<String>.from(
160-
config[ConfigKeys.customGeneratorUrls] ??
161-
ConfigDefaults.customGeneratorUrls);
162175
try {
163-
// Load or create configuration
176+
final config = await loadConfig(configFilePath);
177+
final version = config[ConfigKeys.openapiGeneratorVersion] ??
178+
ConfigDefaults.openapiGeneratorVersion;
179+
final additionalCommands = config[ConfigKeys.additionalCommands] ??
180+
ConfigDefaults.additionalCommands;
181+
final overrideUrl = config[ConfigKeys.downloadUrlOverride];
182+
final cachePath = resolvePath(
183+
config[ConfigKeys.jarCachePath] ?? ConfigDefaults.jarCacheDir);
184+
185+
final customGeneratorUrls = List<String>.from(
186+
config[ConfigKeys.customGeneratorUrls] ??
187+
ConfigDefaults.customGeneratorUrls);
164188

165189
// Ensure the cache directory exists
166190
await Directory(cachePath).create(recursive: true);
@@ -173,15 +197,14 @@ Future<void> main(List<String> arguments) async {
173197
await downloadJar(overrideUrl ?? constructJarUrl(version), openapiJarPath);
174198

175199
// Download each custom generator JAR if it doesn't exist and store in `customJarPaths`
176-
for (var i = 0; i < customGeneratorUrls.length; i++) {
177-
final customJarUrl = customGeneratorUrls[i];
200+
for (var customJarUrl in customGeneratorUrls) {
178201
final originalFileName = customJarUrl.split('/').last;
179202
final customJarPath = '$cachePath/custom-$originalFileName';
180203
await downloadJar(customJarUrl, customJarPath);
181204
customJarPaths.add(customJarPath);
182205
}
183206

184-
// Combine all JAR paths (OpenAPI Generator + custom generators) for the classpath
207+
// Combine all JAR paths for the classpath
185208
final jarPaths = [openapiJarPath, ...customJarPaths];
186209

187210
// Prepare additional arguments, excluding the --config flag and its value
@@ -190,19 +213,30 @@ Future<void> main(List<String> arguments) async {
190213
...arguments.where((arg) => arg != '--config' && arg != configFilePath),
191214
];
192215

193-
// Execute using all JARs in the classpath
216+
// Execute with classpath
194217
await executeWithClasspath(
195-
jarPaths,
196-
filteredArguments
197-
.map(
198-
(e) => e.trim(),
199-
)
200-
.where(
201-
(element) => element.isNotEmpty,
202-
)
203-
.toList());
218+
jarPaths,
219+
filteredArguments
220+
.map((e) => e.trim())
221+
.where((e) => e.isNotEmpty)
222+
.toList(),
223+
);
204224
} catch (e) {
205-
_logOutput('Error: $e');
225+
log('Error: $e');
206226
exitCode = 1;
207227
}
208228
}
229+
230+
class ProcessRunner {
231+
const ProcessRunner();
232+
233+
Future<ProcessResult> run(String executable, List<String> arguments,
234+
{Map<String, String>? environment,
235+
String? workingDirectory,
236+
bool runInShell = false}) {
237+
return Process.run(executable, arguments,
238+
environment: environment,
239+
workingDirectory: workingDirectory,
240+
runInShell: runInShell);
241+
}
242+
}

0 commit comments

Comments
 (0)