diff --git a/Sources/GraphQLCodeGen/codegen.swift b/Sources/GraphQLCodeGen/codegen.swift index 7deea01..796af8c 100644 --- a/Sources/GraphQLCodeGen/codegen.swift +++ b/Sources/GraphQLCodeGen/codegen.swift @@ -3,7 +3,7 @@ import SwiftSyntax import SwiftSyntaxBuilder import GraphQLParser -enum CodegenErrors: Error { +public enum CodegenErrors: Error { case missingQueryTypeName case missingQueryType @@ -14,7 +14,7 @@ enum CodegenErrors: Error { case TODO(String) } -public class Context { +class Context { let serverUrl: String let schema: __Schema private let documents: [DocumentNode] @@ -40,16 +40,21 @@ public class Context { } var visitedTypes: Set = Set() + + // data used for stdout + var requiredCustomScalars: [String: (desc: String?, specifiedByURL: String?)] = [:] } -private func generateVisitedTypes(ctx: Context) throws -> [DeclSyntaxProtocol] { +func generateVisitedTypes(ctx: Context) throws -> [DeclSyntaxProtocol] { var decls: [DeclSyntaxProtocol] = [] while let tpName = ctx.visitedTypes.popFirst() { - if (isGraphQLBuiltInScalarType(str: tpName)) { continue } guard let tp = ctx.schema.types.first(where: { $0.name == tpName }) else { throw CodegenErrors.invalidType(tpName) } switch tp.kind { + case .SCALAR: + if (isGraphQLBuiltInScalarType(str: tpName)) { continue } + ctx.requiredCustomScalars[tpName] = (desc: tp.description, specifiedByURL: tp.specifiedByURL) case .INPUT_OBJECT: for field in tp.inputFields ?? [] { let innerTp = try getWrappedType(ctx: ctx, type: field.type) @@ -218,5 +223,22 @@ public func generate(serverUrl: String, schema: __Schema, documents: [DocumentNo ) }.formatted().description content += "\n" + + let requiredCustomScalars = ctx.requiredCustomScalars.enumerated() + .sorted(by: { $0.element.key < $1.element.key }) + .map { $0.element } + if (requiredCustomScalars.count > 0) { + print("Please implement custom scalars:") + for (name, (desc, specifiedByURL)) in requiredCustomScalars { + print("- \(name)") + if let desc { + print(" - description: \(desc)") + } + if let specifiedByURL { + print(" - specifiedByURL: \(specifiedByURL)") + } + } + } + return content } diff --git a/Sources/GraphQLCodeGen/generator-primitives.swift b/Sources/GraphQLCodeGen/generator-primitives.swift index 38ccd60..e58cf3a 100644 --- a/Sources/GraphQLCodeGen/generator-primitives.swift +++ b/Sources/GraphQLCodeGen/generator-primitives.swift @@ -24,12 +24,12 @@ func convertSchemaTypeToSwiftType(ctx: Context, type: __Type, nonNull: Bool = fa let tp: TypeSyntaxProtocol switch type.kind { case .SCALAR: + ctx.visitedTypes.insert(type.name!) if let scalarType = GraphQLBuiltInScalarType(rawValue: type.name!) { tp = IdentifierTypeSyntax(name: TokenSyntax.identifier(scalarType.swiftType)) } else { - // TODO: Support custom scalars // https://spec.graphql.org/October2021/#sec-Scalars.Custom-Scalars - throw CodegenErrors.TODO("support convertSchemaTypeToSwiftType for custom scalars") + tp = IdentifierTypeSyntax(name: TokenSyntax.identifier(type.name!)) } case .OBJECT: ctx.visitedTypes.insert(type.name!) @@ -65,7 +65,7 @@ func getWrappedType(ctx: Context, type: __Type) throws -> __Type { case .SCALAR: return type case .OBJECT: - guard let name = type.name else { throw CodegenErrors.invalidType("Expect name for OBJECT type") } + guard let name: String = type.name else { throw CodegenErrors.invalidType("Expect name for OBJECT type") } return ctx.schema.types.first(where: { $0.name == name })! case .INTERFACE: return type