Skip to content

Commit

Permalink
Squashed 'apollo-ios-codegen/' changes from e4f12df6..92f94b4d
Browse files Browse the repository at this point in the history
92f94b4d feature: Add suffix to schema type filenames (#580)

git-subtree-dir: apollo-ios-codegen
git-subtree-split: 92f94b4d9556b71359fbe7a55c5bcdb6bc3249c0
  • Loading branch information
gh-action-runner authored and gh-action-runner committed Jan 22, 2025
1 parent ddbe228 commit dcf0c85
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,9 @@ public struct ApolloCodegenConfiguration: Codable, Equatable {
public let pruneGeneratedFiles: Bool
/// Whether generated GraphQL operation and local cache mutation class types will be marked as `final`.
public let markOperationDefinitionsAsFinal: Bool
/// `true` will add a filename suffix matching the schema type, the default is `false`. This can be used to
/// avoid filename conflicts when operation type names match schema type names.
public let appendSchemaTypeFilenameSuffix: Bool

/// Default property values
public struct Default {
Expand All @@ -705,6 +708,7 @@ public struct ApolloCodegenConfiguration: Codable, Equatable {
public static let conversionStrategies: ConversionStrategies = .init()
public static let pruneGeneratedFiles: Bool = true
public static let markOperationDefinitionsAsFinal: Bool = false
public static let appendSchemaTypeFilenameSuffix: Bool = false
}

/// Designated initializer.
Expand All @@ -725,7 +729,11 @@ public struct ApolloCodegenConfiguration: Codable, Equatable {
/// - conversionStrategies: Rules for how to convert the names of values from the schema in
/// generated code.
/// - pruneGeneratedFiles: Whether unused generated files will be automatically deleted.
/// - markOperationDefinitionsAsFinal: Whether generated GraphQL operation and local cache mutation class types will be marked as `final`.
/// - markOperationDefinitionsAsFinal: Whether generated GraphQL operation and local cache mutation
/// class types will be marked as `final`.
/// - appendSchemaTypeFilenameSuffix: `true` will add a filename suffix matching the schema type, the
/// default is `false`. This can be used to avoid filename conflicts when operation type names match
/// schema type names.
public init(
additionalInflectionRules: [InflectionRule] = Default.additionalInflectionRules,
deprecatedEnumCases: Composition = Default.deprecatedEnumCases,
Expand All @@ -737,7 +745,8 @@ public struct ApolloCodegenConfiguration: Codable, Equatable {
warningsOnDeprecatedUsage: Composition = Default.warningsOnDeprecatedUsage,
conversionStrategies: ConversionStrategies = Default.conversionStrategies,
pruneGeneratedFiles: Bool = Default.pruneGeneratedFiles,
markOperationDefinitionsAsFinal: Bool = Default.markOperationDefinitionsAsFinal
markOperationDefinitionsAsFinal: Bool = Default.markOperationDefinitionsAsFinal,
appendSchemaTypeFilenameSuffix: Bool = Default.appendSchemaTypeFilenameSuffix
) {
self.additionalInflectionRules = additionalInflectionRules
self.deprecatedEnumCases = deprecatedEnumCases
Expand All @@ -750,6 +759,7 @@ public struct ApolloCodegenConfiguration: Codable, Equatable {
self.conversionStrategies = conversionStrategies
self.pruneGeneratedFiles = pruneGeneratedFiles
self.markOperationDefinitionsAsFinal = markOperationDefinitionsAsFinal
self.appendSchemaTypeFilenameSuffix = appendSchemaTypeFilenameSuffix
}

// MARK: Codable
Expand All @@ -768,6 +778,7 @@ public struct ApolloCodegenConfiguration: Codable, Equatable {
case conversionStrategies
case pruneGeneratedFiles
case markOperationDefinitionsAsFinal
case appendSchemaTypeFilenameSuffix
}

public init(from decoder: any Decoder) throws {
Expand Down Expand Up @@ -833,6 +844,11 @@ public struct ApolloCodegenConfiguration: Codable, Equatable {
Bool.self,
forKey: .markOperationDefinitionsAsFinal
) ?? Default.markOperationDefinitionsAsFinal

appendSchemaTypeFilenameSuffix = try values.decodeIfPresent(
Bool.self,
forKey: .appendSchemaTypeFilenameSuffix
) ?? Default.appendSchemaTypeFilenameSuffix
}

public func encode(to encoder: any Encoder) throws {
Expand All @@ -849,6 +865,7 @@ public struct ApolloCodegenConfiguration: Codable, Equatable {
try container.encode(self.conversionStrategies, forKey: .conversionStrategies)
try container.encode(self.pruneGeneratedFiles, forKey: .pruneGeneratedFiles)
try container.encode(self.markOperationDefinitionsAsFinal, forKey: .markOperationDefinitionsAsFinal)
try container.encode(self.appendSchemaTypeFilenameSuffix, forKey: .appendSchemaTypeFilenameSuffix)
}
}

Expand Down Expand Up @@ -1702,7 +1719,7 @@ extension ApolloCodegenConfiguration.OutputOptions {
/// - pruneGeneratedFiles: Whether unused generated files will be automatically deleted.
/// - markOperationDefinitionsAsFinal: Whether generated GraphQL operation and local cache mutation class types will be marked as `final`.
@available(*, deprecated,
renamed: "init(additionalInflectionRules:queryStringLiteralFormat:deprecatedEnumCases:schemaDocumentation:selectionSetInitializers:operationDocumentFormat:cocoapodsCompatibleImportStatements:warningsOnDeprecatedUsage:conversionStrategies:pruneGeneratedFiles:markOperationDefinitionsAsFinal:)"
renamed: "init(additionalInflectionRules:queryStringLiteralFormat:deprecatedEnumCases:schemaDocumentation:selectionSetInitializers:operationDocumentFormat:cocoapodsCompatibleImportStatements:warningsOnDeprecatedUsage:conversionStrategies:pruneGeneratedFiles:markOperationDefinitionsAsFinal:appendSchemaTypeFilenameSuffix:)"
)
public init(
additionalInflectionRules: [InflectionRule] = Default.additionalInflectionRules,
Expand All @@ -1728,6 +1745,7 @@ extension ApolloCodegenConfiguration.OutputOptions {
self.pruneGeneratedFiles = pruneGeneratedFiles
self.markOperationDefinitionsAsFinal = markOperationDefinitionsAsFinal
self.schemaCustomization = Default.schemaCustomization
self.appendSchemaTypeFilenameSuffix = Default.appendSchemaTypeFilenameSuffix
}

/// Deprecated initializer.
Expand Down Expand Up @@ -1778,6 +1796,7 @@ extension ApolloCodegenConfiguration.OutputOptions {
self.pruneGeneratedFiles = pruneGeneratedFiles
self.markOperationDefinitionsAsFinal = markOperationDefinitionsAsFinal
self.schemaCustomization = Default.schemaCustomization
self.appendSchemaTypeFilenameSuffix = Default.appendSchemaTypeFilenameSuffix
}

/// Whether the generated operations should use Automatic Persisted Queries.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ struct CustomScalarFileGenerator: FileGenerator {

var target: FileTarget { .customScalar }
var fileName: String { graphqlScalar.render(as: .filename) }
var fileSuffix: String? { ".scalar" }
var overwrite: Bool { false }
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ struct EnumFileGenerator: FileGenerator {

var target: FileTarget { .enum }
var fileName: String { graphqlEnum.render(as: .filename) }
var fileSuffix: String? { ".enum" }
}
26 changes: 25 additions & 1 deletion Sources/ApolloCodegenLib/FileGenerators/FileGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import GraphQLCompiler
protocol FileGenerator {
var fileName: String { get }
var fileExtension: String { get }
var fileSuffix: String? { get }
var overwrite: Bool { get }
var template: any TemplateRenderer { get }
var target: FileTarget { get }
Expand All @@ -15,6 +16,7 @@ protocol FileGenerator {
extension FileGenerator {
var overwrite: Bool { true }
var fileExtension: String { overwrite ? "graphql.swift" : "swift" }
var fileSuffix: String? { nil }

/// Generates the file writing the template content to the specified config output paths.
///
Expand All @@ -25,15 +27,27 @@ extension FileGenerator {
forConfig config: ApolloCodegen.ConfigurationContext,
fileManager: ApolloFileManager = .default
) async throws -> [ApolloCodegen.NonFatalError] {
let filename = resolveFilename(forConfig: config)
let directoryPath = target.resolvePath(forConfig: config)
let filePath = URL(fileURLWithPath: directoryPath)
.resolvingSymlinksInPath()
.appendingPathComponent(fileName.firstUppercased)
.appendingPathComponent(filename)
.appendingPathExtension(fileExtension)
.path

let (rendered, errors) = template.render()

if !self.overwrite, let _ = fileSuffix {
let preSuffixFilename = fileName.firstUppercased
let preSuffixFilePath = URL(fileURLWithPath: directoryPath)
.resolvingSymlinksInPath()
.appendingPathComponent(preSuffixFilename)
.appendingPathExtension(fileExtension)
.path

try await fileManager.renameFile(atPath: preSuffixFilePath, toPath: filePath)
}

try await fileManager.createFile(
atPath: filePath,
data: rendered.data(using: .utf8),
Expand All @@ -42,6 +56,16 @@ extension FileGenerator {

return errors
}

/// Filename to be used taking into account any generated filename options.
private func resolveFilename(forConfig config: ApolloCodegen.ConfigurationContext) -> String {
let prefix = fileName.firstUppercased
guard config.options.appendSchemaTypeFilenameSuffix, let suffix = self.fileSuffix else {
return prefix
}

return prefix + suffix
}
}

// MARK: - FileTarget (path resolver)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ struct InputObjectFileGenerator: FileGenerator {
}
var target: FileTarget { .inputObject }
var fileName: String { graphqlInputObject.render(as: .filename) }
var fileSuffix: String? { ".inputObject" }
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ struct InterfaceFileGenerator: FileGenerator {

var target: FileTarget { .interface }
var fileName: String { graphqlInterface.render(as: .filename) }
var fileSuffix: String? { ".interface" }
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ struct ObjectFileGenerator: FileGenerator {

var target: FileTarget { .object }
var fileName: String { graphqlObject.render(as: .filename) }
var fileSuffix: String? { ".object" }
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ struct UnionFileGenerator: FileGenerator {
) }
var target: FileTarget { .union }
var fileName: String { graphqlUnion.render(as: .filename) }
var fileSuffix: String? { ".union" }
}
21 changes: 15 additions & 6 deletions Sources/ApolloCodegenLib/FileManager+Apollo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ public class ApolloFileManager {
try base.removeItem(atPath: path)
}

/// Creates a file at the specified path and writes any given data to it. If a file already exists at `path`, this method overwrites the
/// contents of that file if the current process has the appropriate privileges to do so.
/// Creates a file at the specified path and writes any given data to it. If a file already exists at `path` this
/// method can be configured to overwrite the contents of that file, if the current process has the appropriate
/// privileges to do so.
///
/// - Parameters:
/// - path: Path to the file.
Expand All @@ -106,17 +107,25 @@ public class ApolloFileManager {
await _writtenFiles.addWrittenFile(path: path)
}

/// Creates the containing directory (including all intermediate directories) for the given file URL if necessary. This method will not
/// overwrite any existing directory.
public func renameFile(atPath oldPath: String, toPath newPath: String) async throws {
guard doesFileExist(atPath: oldPath) else { return }

try base.moveItem(atPath: oldPath, toPath: newPath)

await _writtenFiles.addWrittenFile(path: newPath)
}

/// Creates the containing directory (including all intermediate directories) for the given file URL if necessary.
/// This method will not overwrite any existing directory.
///
/// - Parameter fileURL: The URL of the file to create a containing directory for if necessary.
public func createContainingDirectoryIfNeeded(forPath path: String) throws {
let parent = URL(fileURLWithPath: path).deletingLastPathComponent()
try createDirectoryIfNeeded(atPath: parent.path)
}

/// Creates the directory (including all intermediate directories) for the given URL if necessary. This method will not overwrite any
/// existing directory.
/// Creates the directory (including all intermediate directories) for the given URL if necessary. This method will
/// not overwrite any existing directory.
///
/// - Parameter path: The path of the directory to create if necessary.
public func createDirectoryIfNeeded(atPath path: String) throws {
Expand Down

0 comments on commit dcf0c85

Please sign in to comment.