buildSchema method

FutureOr<void> buildSchema(
  1. BuildStep buildStep,
  2. AssetId schemaId,
  3. Glob generatedFiles,
  4. List<Glob> excludeFiles,
)

Implementation

FutureOr<void> buildSchema(
  BuildStep buildStep,
  AssetId schemaId,
  Glob generatedFiles,
  List<Glob> excludeFiles,
) async {
  /// BuiltValue classes with serializers. These will be added automatically
  /// using `@SerializersFor`.
  final builtClasses = SplayTreeSet<ClassElement>(
    (a, b) => a.name!.compareTo(b.name!),
  );

  /// Non BuiltValue classes with serializers (i.e. inline fragment classes).
  /// These need to be added manually since `@SerializersFor` only recognizes
  /// BuiltValue classes.
  final nonBuiltClasses = SplayTreeSet<ClassElement>(
    (a, b) => a.name!.compareTo(b.name!),
  );

  final excludeFileIds = <String, AssetId>{};
  for (final excludeGlob in excludeFiles) {
    await for (final fileAssetId in buildStep.findAssets(excludeGlob)) {
      excludeFileIds[fileAssetId.path] = fileAssetId;
    }
  }

  await for (final input in buildStep.findAssets(generatedFiles)) {
    if (excludeFileIds.containsKey(input.path)) continue;
    final lib = await buildStep.resolver.libraryFor(input);
    final classes = extractClassesToGenerateSerializersFor(lib);
    builtClasses.addAll(classes.builtClasses);
    nonBuiltClasses.addAll(classes.nonBuiltClasses);
  }

  final additionalSerializers = <Expression>{
    // GraphQL Operation serializer
    refer(
      'OperationSerializer',
      'package:gql_code_builder_serializers/gql_code_builder_serializers.dart',
    ).call([]),
    // User-defined custom serializers
    ...config.customSerializers.map((ref) => ref.call([])),
    // Serializers from data classes that aren't caught by `@SerializersFor`
    ...nonBuiltClasses.map<Expression>(
      (c) => refer(c.name!, c.library.uri.toString()).property('serializer'),
    ),
  };

  // if the schema is defined in a different package
  // we need to import the serializers from that package
  // and add them to the serializers of this package
  final isExternalSchema = schemaId.package != buildStep.inputId.package;

  final externalSerializersExpression = isExternalSchema
      ? refer(
          'serializers',
          _externalSchemaSerializersImport(schemaId, config),
        ).property('serializers')
      : null;

  if (isExternalSchema) {
    final externalSchemaId = outputAssetId(
      schemaId,
      schemaExtension,
      config.outputDir,
    );

    final externalSchemaLibrary = await buildStep.resolver.libraryFor(
      externalSchemaId,
    );

    final externalSchemaClasses = extractClassesToGenerateSerializersFor(
      externalSchemaLibrary,
    );

    builtClasses.addAll(externalSchemaClasses.builtClasses);
    nonBuiltClasses.addAll(externalSchemaClasses.nonBuiltClasses);
  }

  final library = buildSerializerLibrary(
    builtClasses,
    outputFileName.replaceFirst('.gql.dart', '.gql.g.dart'),
    additionalSerializers,
    externalSerializers: externalSerializersExpression,
  );

  final allocator = PickAllocator(
    doNotPick: ['package:built_value/serializer.dart'],
    include: [
      'package:built_collection/built_collection.dart',
      'package:ferry_exec/ferry_exec.dart',
      ...config.typeOverrides.values
          .map((ref) => ref.url)
          .whereType<String>(),
    ],
    aliasedImports: {
      if (isExternalSchema)
        _externalSchemaSerializersImport(schemaId, config):
            '_\$external_serializers',
    },
  );

  final outputId = AssetId(
    buildStep.inputId.package,
    p.joinAll(pathSegments(schemaId)),
  );

  await writeDocument(outputId, library, allocator, buildStep);
}