Skip to content

Commit 254c876

Browse files
claudekevin-sakemaer
authored andcommitted
Add --verbose/-v flag to spark dev command
When -v is passed, spark dev now shows: - build_runner [INFO] log lines (normally suppressed) - Dart DevTools and VM Service connection messages from the server - File watcher events with path and type - Verbose build_runner output via BuildRunnerUtils https://claude.ai/code/session_01NUdshW8WDJYzKGLqwuotJv
1 parent 9b33d2c commit 254c876

2 files changed

Lines changed: 97 additions & 5 deletions

File tree

packages/spark_cli/lib/src/commands/dev_command.dart

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ class DevCommand extends Command<void> {
5151
console: _console,
5252
workingDirectory: _workingDirectory,
5353
);
54+
argParser.addFlag(
55+
'verbose',
56+
abbr: 'v',
57+
help: 'Show verbose log output.',
58+
);
5459
}
5560

5661
late final BuildRunnerUtils _buildUtils;
@@ -65,6 +70,9 @@ class DevCommand extends Command<void> {
6570
String get _routerFilePath =>
6671
p.join(_workingDirectory.path, 'lib', 'spark_router.g.dart');
6772

73+
// Verbose logging flag
74+
bool _verbose = false;
75+
6876
// Error handling components
6977
final ConsoleOutput _console = ConsoleOutput();
7078
final DevErrorCollector _errorCollector = DevErrorCollector();
@@ -75,6 +83,7 @@ class DevCommand extends Command<void> {
7583

7684
@override
7785
Future<void> run() async {
86+
_verbose = argResults!['verbose'] as bool;
7887
_console.printInfo('Starting development environment...');
7988

8089
await DirectoryUtils.cleanDirectory(
@@ -133,6 +142,7 @@ class DevCommand extends Command<void> {
133142
var hasCompleted = false;
134143

135144
_buildRunnerProcess = await _buildUtils.startWatch(
145+
verbose: _verbose,
136146
extraArgs: ['--output', 'web:build/web'],
137147
onLog: (line) {
138148
if (line.contains('Succeeded after') ||
@@ -171,8 +181,8 @@ class DevCommand extends Command<void> {
171181
hasCompleted = true;
172182
completer.completeError(StateError('Initial build failed'));
173183
}
174-
} else if (line.contains('[INFO]')) {
175-
// Suppress INFO logs
184+
} else if (line.contains('[INFO]') && !_verbose) {
185+
// Suppress INFO logs unless verbose
176186
} else if (line.contains('Building...')) {
177187
_console.clear();
178188
_buildUtils.parser.clear();
@@ -308,9 +318,10 @@ class DevCommand extends Command<void> {
308318
}
309319
} else if (line.contains('Server running at')) {
310320
_console.printSuccess(line);
311-
} else if (line.contains('The Dart DevTools') ||
312-
line.contains('Connecting to VM Service')) {
313-
// Suppress noise
321+
} else if ((line.contains('The Dart DevTools') ||
322+
line.contains('Connecting to VM Service')) &&
323+
!_verbose) {
324+
// Suppress noise unless verbose
314325
} else {
315326
_console.printGray('[Server] $line');
316327
}
@@ -429,6 +440,9 @@ class DevCommand extends Command<void> {
429440
_console.printGray('Watching for file changes...');
430441
final watcher = _watcherFactory(_workingDirectory.path);
431442
_fileWatcherSubscription = watcher.events.listen((event) {
443+
if (_verbose) {
444+
_console.printGray('[Watcher] ${event.type}: ${event.path}');
445+
}
432446
if (event.path.endsWith('.dart') &&
433447
!event.path.endsWith('.g.dart') &&
434448
!event.path.contains('${p.separator}.dart_tool') &&

packages/spark_cli/test/dev_command_test.dart

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,84 @@ void main() {
141141
},
142142
);
143143

144+
test('accepts --verbose flag and shows INFO logs', () async {
145+
File(
146+
p.join(tempDir.path, 'main.dart'),
147+
).writeAsStringSync('void main() {}');
148+
149+
final printedLines = <String>[];
150+
151+
runZoned(
152+
() {
153+
return runner.run(['dev', '--verbose']);
154+
},
155+
zoneSpecification: ZoneSpecification(
156+
print: (self, parent, zone, line) {
157+
printedLines.add(line);
158+
},
159+
),
160+
);
161+
162+
await Future.delayed(const Duration(milliseconds: 100));
163+
164+
// Simulate an [INFO] log line from build_runner
165+
buildRunnerProcess.stdoutController.add(
166+
utf8.encode('[INFO] Running build...\n'),
167+
);
168+
169+
await Future.delayed(const Duration(milliseconds: 100));
170+
171+
// In verbose mode, [INFO] lines should NOT be suppressed and should
172+
// appear in output via BuildRunnerUtils._pipeStream (printed as gray).
173+
// The onLog callback also receives the line but since it doesn't match
174+
// any known pattern it falls through without being suppressed.
175+
expect(
176+
printedLines.any((line) => line.contains('[INFO] Running build...')),
177+
isTrue,
178+
reason: 'INFO logs should be visible in verbose mode',
179+
);
180+
181+
processRunner.processes.clear();
182+
});
183+
184+
test('suppresses INFO logs without --verbose', () async {
185+
File(
186+
p.join(tempDir.path, 'main.dart'),
187+
).writeAsStringSync('void main() {}');
188+
189+
final printedLines = <String>[];
190+
191+
runZoned(
192+
() {
193+
return runner.run(['dev']);
194+
},
195+
zoneSpecification: ZoneSpecification(
196+
print: (self, parent, zone, line) {
197+
printedLines.add(line);
198+
},
199+
),
200+
);
201+
202+
await Future.delayed(const Duration(milliseconds: 100));
203+
204+
// Simulate an [INFO] log line from build_runner
205+
buildRunnerProcess.stdoutController.add(
206+
utf8.encode('[INFO] Running build...\n'),
207+
);
208+
209+
await Future.delayed(const Duration(milliseconds: 100));
210+
211+
// Without verbose, [INFO] lines from onLog should be suppressed.
212+
// BuildRunnerUtils._pipeStream also won't print because verbose=false.
213+
expect(
214+
printedLines.any((line) => line.contains('[INFO] Running build...')),
215+
isFalse,
216+
reason: 'INFO logs should be suppressed without --verbose',
217+
);
218+
219+
processRunner.processes.clear();
220+
});
221+
144222
test('deletes existing build folder on startup', () async {
145223
// Setup using shared tempDir
146224
final buildDir = Directory(p.join(tempDir.path, 'build'));

0 commit comments

Comments
 (0)