@@ -5,9 +5,11 @@ import 'dart:async';
5
5
import 'dart:io' ;
6
6
7
7
import 'package:aft/aft.dart' ;
8
+ import 'package:aft/src/options/fail_fast_option.dart' ;
8
9
import 'package:aft/src/options/glob_options.dart' ;
9
10
import 'package:async/async.dart' ;
10
11
import 'package:aws_common/aws_common.dart' ;
12
+ import 'package:mason_logger/mason_logger.dart' ;
11
13
import 'package:mustache_template/mustache_template.dart' ;
12
14
import 'package:path/path.dart' as p;
13
15
import 'package:shelf/shelf_io.dart' as io;
@@ -27,7 +29,11 @@ class DocsCommand extends AmplifyCommand {
27
29
String get description => 'Build and deploy API documentation' ;
28
30
}
29
31
30
- abstract class _DocsSubcommand extends AmplifyCommand with GlobOptions {
32
+ abstract class _DocsSubcommand extends AmplifyCommand
33
+ with FailFastOption , GlobOptions {
34
+ late final Logger mLogger =
35
+ Logger (level: verbose ? Level .verbose : Level .info);
36
+
31
37
@override
32
38
PackageSelector get basePackageSelector {
33
39
final currentPackage = workingDirectory.pubspec;
@@ -45,9 +51,15 @@ abstract class _DocsSubcommand extends AmplifyCommand with GlobOptions {
45
51
['doc' , '--output' , output.path],
46
52
mode: verbose ? ProcessStartMode .inheritStdio : ProcessStartMode .normal,
47
53
workingDirectory: package.path,
54
+ environment: environment,
55
+ runInShell: true ,
48
56
);
57
+ final error = StringBuffer ();
58
+ process
59
+ ..captureStdout (sink: error.write)
60
+ ..captureStderr (sink: error.write);
49
61
if (await process.exitCode != 0 ) {
50
- throw Exception ('Failed to build docs for ${package .name }' );
62
+ throw Exception ('`dart doc` failed for ${package .name }: \n $ error ' );
51
63
}
52
64
return output;
53
65
}
@@ -75,15 +87,19 @@ abstract class _DocsSubcommand extends AmplifyCommand with GlobOptions {
75
87
76
88
/// Runs pre-build commands if a package uses `code_excerpter` to
77
89
/// separate code snippets from docs.
78
- Future <void > _prebuildDocs (PackageInfo package) async {
90
+ Future <void > _prebuildDocs (
91
+ PackageInfo package, {
92
+ Progress ? progress,
93
+ }) async {
94
+ final log = progress? .update ?? mLogger.detail;
79
95
final docsPackageDir = Directory (p.join (package.path, 'doc' ));
80
96
final docsPackage = PackageInfo .fromDirectory (docsPackageDir);
81
97
if (docsPackage == null ) {
82
98
return ;
83
99
}
84
100
85
101
// Re-generate code snippet yaml
86
- logger. debug ('Re-generating code snippets for ${package .name }...' );
102
+ log ('Re-generating code snippets for ${package .name }...' );
87
103
await pubAction (package: docsPackage, arguments: ['get' ]);
88
104
await runBuildRunner (
89
105
docsPackage,
@@ -93,7 +109,7 @@ abstract class _DocsSubcommand extends AmplifyCommand with GlobOptions {
93
109
);
94
110
95
111
// Update docs with code snippet yaml
96
- logger. debug ('Injecting updated code snippets for ${package .name }...' );
112
+ log ('Injecting updated code snippets for ${package .name }...' );
97
113
await pubAction (package: package, arguments: ['get' ]);
98
114
await pubAction (
99
115
package: package,
@@ -109,14 +125,21 @@ abstract class _DocsSubcommand extends AmplifyCommand with GlobOptions {
109
125
}
110
126
111
127
/// Compiles docs for [package] into [outputDir] .
112
- Future <Directory > _buildDocs (PackageInfo package, String outputDir) async {
113
- logger.info ('Building docs for ${package .name }...' );
114
- await _prebuildDocs (package);
128
+ Future <Directory > _buildDocs (
129
+ PackageInfo package,
130
+ String outputDir, {
131
+ Progress ? progress,
132
+ }) async {
133
+ progress ?? = mLogger.progress ('Pre-building docs for ${package .name }' );
134
+ await _prebuildDocs (package, progress: progress);
135
+ progress.update ('Running `dart doc` for ${package .name }' );
115
136
final buildDir = await _dartDoc (package);
116
137
final packageOutputDir = Directory (
117
138
p.join (outputDir, package.name),
118
139
);
140
+ progress.update ('Copying docs to root dir' );
119
141
await _copyDir (buildDir, packageOutputDir);
142
+ progress.complete ('Built docs for ${package .name }!' );
120
143
return packageOutputDir;
121
144
}
122
145
@@ -125,25 +148,43 @@ abstract class _DocsSubcommand extends AmplifyCommand with GlobOptions {
125
148
if (commandPackages.isEmpty) {
126
149
exitError ('No packages selected' );
127
150
}
128
- final packageOutputs = < Map <String , Object ?>> [];
151
+ final buildOutputs =
152
+ FutureGroup <(PackageInfo , Progress , Result <Directory >)>();
129
153
for (final package in commandPackages.values) {
130
- final packageOutputDir = await _buildDocs (package, outputDir);
131
- packageOutputs.add ({
132
- 'name' : package.name,
133
- 'path' : p.relative (package.path, from: rootDir.path),
134
- 'link' : p.relative (
135
- packageOutputDir.path,
136
- from: outputDir,
137
- ),
138
- });
154
+ final progress = mLogger.progress ('Building docs for ${package .name }' );
155
+ final buildFuture = _buildDocs (package, outputDir, progress: progress);
156
+ buildOutputs.add (
157
+ failFast
158
+ ? buildFuture.then ((res) => (package, progress, ValueResult (res)))
159
+ : Result .capture (buildFuture)
160
+ .then ((res) => (package, progress, res)),
161
+ );
162
+ }
163
+ buildOutputs.close ();
164
+
165
+ final packageOutputs = < Map <String , Object ?>> [];
166
+ for (final (package, progress, buildRes) in await buildOutputs.future) {
167
+ switch (buildRes) {
168
+ case ValueResult (value: final buildDir):
169
+ packageOutputs.add ({
170
+ 'name' : package.name,
171
+ 'path' : p.relative (package.path, from: rootDir.path),
172
+ 'link' : p.relative (buildDir.path, from: outputDir),
173
+ });
174
+ case ErrorResult (: final error, : final stackTrace):
175
+ progress.fail ('Error building docs for ${package .name }' );
176
+ mLogger
177
+ ..err (error.toString ())
178
+ ..err (stackTrace.toString ());
179
+ }
139
180
}
140
181
final renderedHtml = Template (_indexTmpl).renderString ({
141
182
'packages' : packageOutputs,
142
183
});
143
184
final indexFile = File (p.join (outputDir, 'index.html' ));
144
185
await indexFile.create ();
145
186
await indexFile.writeAsString (renderedHtml);
146
- logger. info ('Successfully built docs' );
187
+ mLogger. success ('Successfully built docs' );
147
188
}
148
189
}
149
190
@@ -249,7 +290,7 @@ class _DocsServeSubcommand extends _DocsSubcommand {
249
290
}
250
291
251
292
/// Watches a [package] for changes and calls [onChange] whenever a file is changed.
252
- class _PackageWatcher with Closeable {
293
+ class _PackageWatcher implements Closeable {
253
294
_PackageWatcher (this .package, {required this .onChange}) {
254
295
_listenForEvents ();
255
296
}
0 commit comments