build method

  1. @override
Future<void> build(
  1. BuildStep buildStep
)

Generates the outputs for a given BuildStep.

Implementation

@override
Future<void> build(BuildStep buildStep) async {
  // Find all generated .spark.g.part files
  final sparkFiles = Glob('lib/**/*.spark.g.part');
  final routes = <_RouteInfo>[];
  final imports = <String>{};

  await for (final file in buildStep.findAssets(sparkFiles)) {
    log.info('RouterBuilder found part: ${file.path}');
    final content = await buildStep.readAsString(file);

    // Parse route info from the generated content
    final routeMatches = RegExp(
      r"const _\$(\w+)Route = \(([\s\S]*?)\);",
    ).allMatches(content);

    for (final match in routeMatches) {
      final className = match.group(1)!;
      final routeBody = match.group(2)!;

      final path = _extractValue(routeBody, 'path');
      final methods = _extractList(routeBody, 'methods');
      final pathParams = _extractList(routeBody, 'pathParams');

      // Extract the handler function
      final handlerMatch = RegExp(
        'Future<Response> _\\\$handle$className\\([\\s\\S]*?\\) async \\{[\\s\\S]*?\\n\\}',
      ).firstMatch(content);

      final handlerCode = handlerMatch?.group(0);

      if (path != null && handlerCode != null) {
        routes.add(
          _RouteInfo(
            className: className,
            path: path,
            methods: methods,
            pathParams: pathParams,
            handlerCode: handlerCode,
          ),
        );
      }
    }
    // Add import for the source file
    final sourcePath = file.path.replaceAll('.spark.g.part', '.dart');
    imports.add(sourcePath);
  }

  if (routes.isEmpty) {
    // No pages found, generate empty router
    await _writeEmptyRouter(buildStep);
    return;
  }

  final buffer = StringBuffer();

  // Header
  buffer.writeln('// GENERATED CODE - DO NOT MODIFY BY HAND');
  buffer.writeln('// Generated by spark_generator');
  buffer.writeln('// ignore_for_file: type=lint');
  buffer.writeln();

  // Imports
  buffer.writeln();
  buffer.writeln("import 'dart:async';");
  buffer.writeln("import 'dart:convert';");
  buffer.writeln("import 'dart:io';");
  buffer.writeln("import 'dart:isolate';");
  buffer.writeln("import 'dart:math';");
  buffer.writeln();
  buffer.writeln("import 'package:shelf/shelf.dart';");
  buffer.writeln("import 'package:shelf/shelf_io.dart' as shelf_io;");
  buffer.writeln("import 'package:shelf_router/shelf_router.dart';");
  buffer.writeln("import 'package:spark_framework/server.dart';");
  buffer.writeln();

  // Import source files that contain the page classes
  for (final import in imports) {
    final importPath = import.replaceFirst('lib/', '');
    buffer.writeln(
      "import 'package:${buildStep.inputId.package}/$importPath';",
    );
  }
  buffer.writeln();

  // Generate helper functions
  _writeHelperFunctions(buffer);

  // Generate handlers
  for (final route in routes) {
    buffer.writeln(route.handlerCode);
    buffer.writeln();
  }

  // Generate createSparkRouter
  buffer.writeln('/// Creates a router with all registered Spark pages.');
  buffer.writeln('///');
  buffer.writeln('/// This router contains handlers for:');
  for (final route in routes) {
    buffer.writeln('/// - `${route.path}` -> ${route.className}');
  }
  buffer.writeln('Router createSparkRouter() {');
  buffer.writeln('  final router = Router();');
  buffer.writeln();

  // Register each route
  for (final route in routes) {
    for (final method in route.methods) {
      final methodLower = method.toLowerCase();
      if (route.pathParams.isEmpty) {
        buffer.writeln(
          "  router.$methodLower('${route.path}', _\$handle${route.className});",
        );
      } else {
        buffer.writeln(
          "  router.$methodLower('${route.path}', (Request request, ${route.pathParams.map((p) => 'String $p').join(', ')}) =>",
        );
        buffer.writeln(
          '      _\$handle${route.className}(request, ${route.pathParams.join(', ')}));',
        );
      }
    }
  }
  buffer.writeln();
  buffer.writeln('  return router;');
  buffer.writeln('}');
  buffer.writeln();

  // Generate SparkServerConfig
  _writeServerConfig(buffer);

  // Generate createSparkServer
  _writeCreateSparkServer(buffer);

  // Write output
  final outputId = AssetId(
    buildStep.inputId.package,
    'lib/spark_router.g.dart',
  );
  await buildStep.writeAsString(outputId, buffer.toString());
}