Skip to content

Commit 8497832

Browse files
authored
feat: add prod server builder (#1161)
1 parent d4c7380 commit 8497832

File tree

10 files changed

+288
-101
lines changed

10 files changed

+288
-101
lines changed
Lines changed: 21 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
import 'dart:io';
2-
31
import 'package:dart_frog_cli/src/command.dart';
42
import 'package:dart_frog_cli/src/commands/build/templates/dart_frog_prod_server_bundle.dart';
53
import 'package:dart_frog_cli/src/commands/commands.dart';
6-
import 'package:dart_frog_cli/src/runtime_compatibility.dart'
7-
as runtime_compatibility;
4+
import 'package:dart_frog_cli/src/prod_server_builder/prod_server_builder.dart';
85
import 'package:mason/mason.dart';
6+
import 'package:meta/meta.dart';
97

108
/// {@template build_command}
119
/// `dart_frog build` command which creates a production build`.
@@ -14,11 +12,12 @@ class BuildCommand extends DartFrogCommand {
1412
/// {@macro build_command}
1513
BuildCommand({
1614
super.logger,
17-
void Function(Directory)? ensureRuntimeCompatibility,
18-
GeneratorBuilder? generator,
19-
}) : _ensureRuntimeCompatibility = ensureRuntimeCompatibility ??
20-
runtime_compatibility.ensureRuntimeCompatibility,
21-
_generator = generator ?? MasonGenerator.fromBundle {
15+
@visibleForTesting GeneratorBuilder? generator,
16+
@visibleForTesting
17+
ProdServerBuilderConstructor? prodServerBuilderConstructor,
18+
}) : _generator = generator ?? MasonGenerator.fromBundle,
19+
_prodServerBuilderConstructor =
20+
prodServerBuilderConstructor ?? ProdServerBuilder.new {
2221
argParser.addOption(
2322
'dart-version',
2423
defaultsTo: 'stable',
@@ -27,8 +26,8 @@ class BuildCommand extends DartFrogCommand {
2726
);
2827
}
2928

30-
final void Function(Directory) _ensureRuntimeCompatibility;
3129
final GeneratorBuilder _generator;
30+
final ProdServerBuilderConstructor _prodServerBuilderConstructor;
3231

3332
@override
3433
final String description = 'Create a production build.';
@@ -38,31 +37,21 @@ class BuildCommand extends DartFrogCommand {
3837

3938
@override
4039
Future<int> run() async {
41-
_ensureRuntimeCompatibility(cwd);
42-
40+
final dartVersion = results['dart-version'] as String;
4341
final generator = await _generator(dartFrogProdServerBundle);
44-
var vars = <String, dynamic>{
45-
'dartVersion': results['dart-version'],
46-
};
4742

48-
logger.detail('[codegen] running pre-gen...');
49-
await generator.hooks.preGen(
50-
vars: vars,
51-
workingDirectory: cwd.path,
52-
onVarsChanged: (v) => vars = v,
43+
final builder = _prodServerBuilderConstructor(
44+
logger: logger,
45+
dartVersion: dartVersion,
46+
workingDirectory: cwd,
47+
prodServerBundleGenerator: generator,
5348
);
5449

55-
logger.detail('[codegen] running generate...');
56-
final _ = await generator.generate(
57-
DirectoryGeneratorTarget(cwd),
58-
vars: vars,
59-
fileConflictResolution: FileConflictResolution.overwrite,
60-
);
61-
62-
logger.detail('[codegen] running post-gen...');
63-
await generator.hooks.postGen(workingDirectory: cwd.path);
64-
65-
logger.detail('[codegen] complete.');
66-
return ExitCode.success.code;
50+
try {
51+
return (await builder.build()).code;
52+
} catch (e) {
53+
logger.err(e.toString());
54+
return ExitCode.software.code;
55+
}
6756
}
6857
}

packages/dart_frog_cli/lib/src/commands/create/create.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class CreateCommand extends DartFrogCommand {
4848
};
4949

5050
logger.detail('[codegen] running generate...');
51-
final _ = await generator.generate(
51+
await generator.generate(
5252
DirectoryGeneratorTarget(outputDirectory),
5353
vars: vars,
5454
);

packages/dart_frog_cli/lib/src/commands/dev/dev.dart

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ class DevCommand extends DartFrogCommand {
1515
DevCommand({
1616
super.logger,
1717
GeneratorBuilder? generator,
18-
DevServerRunnerBuilder? devServerRunnerBuilder,
18+
DevServerRunnerConstructor? devServerRunnerConstructor,
1919
}) : _generator = generator ?? MasonGenerator.fromBundle,
20-
_devServerRunnerBuilder =
21-
devServerRunnerBuilder ?? DevServerRunner.new {
20+
_devServerRunnerConstructor =
21+
devServerRunnerConstructor ?? DevServerRunner.new {
2222
argParser
2323
..addOption(
2424
'port',
@@ -43,7 +43,8 @@ class DevCommand extends DartFrogCommand {
4343
static const _defaultDartVmServicePort = '8181';
4444

4545
final GeneratorBuilder _generator;
46-
final DevServerRunnerBuilder _devServerRunnerBuilder;
46+
final DevServerRunnerConstructor _devServerRunnerConstructor;
47+
4748
@override
4849
final String description = 'Run a local development server.';
4950

@@ -119,7 +120,7 @@ class DevCommand extends DartFrogCommand {
119120
}
120121
}
121122

122-
_devServerRunner = _devServerRunnerBuilder(
123+
_devServerRunner = _devServerRunnerConstructor(
123124
devServerBundleGenerator: generator,
124125
logger: logger,
125126
workingDirectory: cwd,

packages/dart_frog_cli/lib/src/daemon/domain/dev_server_domain.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ class DevServerDomain extends DomainBase {
1717
super.daemon, {
1818
@visibleForTesting super.getId,
1919
@visibleForTesting GeneratorBuilder? generator,
20-
@visibleForTesting DevServerRunnerBuilder? devServerRunnerBuilder,
20+
@visibleForTesting DevServerRunnerConstructor? devServerRunnerConstructor,
2121
}) : _generator = generator ?? MasonGenerator.fromBundle,
22-
_devServerRunnerBuilder =
23-
devServerRunnerBuilder ?? DevServerRunner.new {
22+
_devServerRunnerConstructor =
23+
devServerRunnerConstructor ?? DevServerRunner.new {
2424
addHandler('start', _start);
2525
addHandler('reload', _reload);
2626
addHandler('stop', _stop);
@@ -32,7 +32,7 @@ class DevServerDomain extends DomainBase {
3232
final _devServerRunners = <String, DevServerRunner>{};
3333

3434
final GeneratorBuilder _generator;
35-
final DevServerRunnerBuilder _devServerRunnerBuilder;
35+
final DevServerRunnerConstructor _devServerRunnerConstructor;
3636

3737
/// Starts a [DevServerRunner] for the given [request].
3838
Future<DaemonResponse> _start(DaemonRequest request) async {
@@ -80,7 +80,7 @@ class DevServerDomain extends DomainBase {
8080
idGenerator: getId,
8181
);
8282

83-
final devServerRunner = _devServerRunnerBuilder(
83+
final devServerRunner = _devServerRunnerConstructor(
8484
logger: logger,
8585
port: '$port',
8686
address: ip,

packages/dart_frog_cli/lib/src/dev_server_runner/dev_server_runner.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ final _dartVmServiceAlreadyInUseErrorRegex = RegExp(
3939
);
4040

4141
/// Typedef for [DevServerRunner.new].
42-
typedef DevServerRunnerBuilder = DevServerRunner Function({
42+
typedef DevServerRunnerConstructor = DevServerRunner Function({
4343
required Logger logger,
4444
required String port,
4545
required io.InternetAddress? address,
@@ -169,7 +169,7 @@ class DevServerRunner {
169169
);
170170

171171
logger.detail('[codegen] running generate...');
172-
final _ = await devServerBundleGenerator.generate(
172+
await devServerBundleGenerator.generate(
173173
_target,
174174
vars: vars,
175175
fileConflictResolution: FileConflictResolution.overwrite,
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import 'dart:io' as io;
2+
3+
import 'package:dart_frog_cli/src/runtime_compatibility.dart';
4+
import 'package:mason/mason.dart';
5+
import 'package:meta/meta.dart';
6+
7+
/// Typedef for [ProdServerBuilder.new].
8+
typedef ProdServerBuilderConstructor = ProdServerBuilder Function({
9+
required Logger logger,
10+
required String dartVersion,
11+
required io.Directory workingDirectory,
12+
required MasonGenerator prodServerBundleGenerator,
13+
});
14+
15+
/// {@template prod_server_builder}
16+
/// A class that builds the production server runtime code.
17+
///
18+
/// This class is responsible for:
19+
/// - Ensuring that the current version of `package:dart_frog` is compatible
20+
/// with the generated code.
21+
/// - Generating the production server runtime code.
22+
///
23+
/// {@endtemplate}
24+
class ProdServerBuilder {
25+
/// {@macro prod_server_builder}
26+
ProdServerBuilder({
27+
required this.logger,
28+
required this.dartVersion,
29+
required this.workingDirectory,
30+
required this.prodServerBundleGenerator,
31+
@visibleForTesting
32+
RuntimeCompatibilityCallback? runtimeCompatibilityCallback,
33+
}) : _ensureRuntimeCompatibility =
34+
runtimeCompatibilityCallback ?? ensureRuntimeCompatibility;
35+
36+
/// The Dart SDK version used to build the Dockerfile.
37+
final String dartVersion;
38+
39+
/// [Logger] instance used to wrap stdout.
40+
final Logger logger;
41+
42+
/// The working directory of the dart_frog project.
43+
final io.Directory workingDirectory;
44+
45+
/// The [MasonGenerator] used to generate the prod server runtime code.
46+
final MasonGenerator prodServerBundleGenerator;
47+
48+
final RuntimeCompatibilityCallback _ensureRuntimeCompatibility;
49+
50+
/// Builds the production server runtime code.
51+
Future<ExitCode> build() async {
52+
_ensureRuntimeCompatibility(workingDirectory);
53+
54+
var vars = <String, dynamic>{
55+
'dartVersion': dartVersion,
56+
};
57+
58+
logger.detail('[codegen] running pre-gen...');
59+
await prodServerBundleGenerator.hooks.preGen(
60+
vars: vars,
61+
workingDirectory: workingDirectory.path,
62+
onVarsChanged: (v) => vars = v,
63+
);
64+
65+
logger.detail('[codegen] running generate...');
66+
await prodServerBundleGenerator.generate(
67+
DirectoryGeneratorTarget(workingDirectory),
68+
vars: vars,
69+
fileConflictResolution: FileConflictResolution.overwrite,
70+
);
71+
72+
logger.detail('[codegen] running post-gen...');
73+
await prodServerBundleGenerator.hooks.postGen(
74+
workingDirectory: workingDirectory.path,
75+
);
76+
77+
logger.detail('[codegen] complete.');
78+
79+
return ExitCode.success;
80+
}
81+
}

0 commit comments

Comments
 (0)