Skip to content

Commit

Permalink
feature: Adding CLI command for Operation Manifest (#3152)
Browse files Browse the repository at this point in the history
  • Loading branch information
BobaFetters committed Jul 26, 2023
1 parent e95cec8 commit a47a8af
Show file tree
Hide file tree
Showing 14 changed files with 551 additions and 60 deletions.
16 changes: 12 additions & 4 deletions Apollo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
54DDB0921EA045870009DD99 /* InMemoryNormalizedCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = 54DDB0911EA045870009DD99 /* InMemoryNormalizedCache.swift */; };
5AC6CA4322AAF7B200B7C94D /* GraphQLHTTPMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AC6CA4222AAF7B200B7C94D /* GraphQLHTTPMethod.swift */; };
5BB2C0232380836100774170 /* VersionNumberTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB2C0222380836100774170 /* VersionNumberTests.swift */; };
662EA65E2A701483008A1931 /* GenerateOperationManifest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 662EA65D2A701483008A1931 /* GenerateOperationManifest.swift */; };
662EA6602A705BD7008A1931 /* GenerateOperationManifestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 662EA65F2A705BD7008A1931 /* GenerateOperationManifestTests.swift */; };
66321AE72A126C4400CC35CB /* IR+Formatting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66321AE62A126C4400CC35CB /* IR+Formatting.swift */; };
66B18E872A15367300525DFB /* URLSessionClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B4F4542244A2AD300C2CF7D /* URLSessionClientTests.swift */; };
66B18E902A16BF9B00525DFB /* MockURLProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66B18E8E2A16BF9B00525DFB /* MockURLProtocol.swift */; };
Expand Down Expand Up @@ -769,7 +771,7 @@
E687B3DC28B398E600A9551C /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = E687B3CA28B398E600A9551C /* Constants.swift */; };
E687B3DD28B398E600A9551C /* InputOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E687B3CC28B398E600A9551C /* InputOptions.swift */; };
E687B3DE28B398E600A9551C /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = E687B3CD28B398E600A9551C /* Error.swift */; };
E687B3DF28B398E600A9551C /* ParsableCommand+RootOutputURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = E687B3CF28B398E600A9551C /* ParsableCommand+RootOutputURL.swift */; };
E687B3DF28B398E600A9551C /* ParsableCommand+Apollo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E687B3CF28B398E600A9551C /* ParsableCommand+Apollo.swift */; };
E687B3E028B398E600A9551C /* FileManager+Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = E687B3D028B398E600A9551C /* FileManager+Data.swift */; };
E687B3E128B398E600A9551C /* String+Data.swift in Sources */ = {isa = PBXBuildFile; fileRef = E687B3D128B398E600A9551C /* String+Data.swift */; };
E687B3E328B398E600A9551C /* FetchSchema.swift in Sources */ = {isa = PBXBuildFile; fileRef = E687B3D428B398E600A9551C /* FetchSchema.swift */; };
Expand Down Expand Up @@ -1138,6 +1140,8 @@
54DDB0911EA045870009DD99 /* InMemoryNormalizedCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InMemoryNormalizedCache.swift; sourceTree = "<group>"; };
5AC6CA4222AAF7B200B7C94D /* GraphQLHTTPMethod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GraphQLHTTPMethod.swift; sourceTree = "<group>"; };
5BB2C0222380836100774170 /* VersionNumberTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionNumberTests.swift; sourceTree = "<group>"; };
662EA65D2A701483008A1931 /* GenerateOperationManifest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenerateOperationManifest.swift; sourceTree = "<group>"; };
662EA65F2A705BD7008A1931 /* GenerateOperationManifestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenerateOperationManifestTests.swift; sourceTree = "<group>"; };
66321AE62A126C4400CC35CB /* IR+Formatting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IR+Formatting.swift"; sourceTree = "<group>"; };
66B18E8E2A16BF9B00525DFB /* MockURLProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockURLProtocol.swift; sourceTree = "<group>"; };
90690D05224333DA00FC2E54 /* Apollo-Project-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Apollo-Project-Debug.xcconfig"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1957,7 +1961,7 @@
E687B3CA28B398E600A9551C /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
E687B3CC28B398E600A9551C /* InputOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputOptions.swift; sourceTree = "<group>"; };
E687B3CD28B398E600A9551C /* Error.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; };
E687B3CF28B398E600A9551C /* ParsableCommand+RootOutputURL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ParsableCommand+RootOutputURL.swift"; sourceTree = "<group>"; };
E687B3CF28B398E600A9551C /* ParsableCommand+Apollo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ParsableCommand+Apollo.swift"; sourceTree = "<group>"; };
E687B3D028B398E600A9551C /* FileManager+Data.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FileManager+Data.swift"; sourceTree = "<group>"; };
E687B3D128B398E600A9551C /* String+Data.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Data.swift"; sourceTree = "<group>"; };
E687B3D428B398E600A9551C /* FetchSchema.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FetchSchema.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4046,7 +4050,7 @@
E687B3CE28B398E600A9551C /* Extensions */ = {
isa = PBXGroup;
children = (
E687B3CF28B398E600A9551C /* ParsableCommand+RootOutputURL.swift */,
E687B3CF28B398E600A9551C /* ParsableCommand+Apollo.swift */,
DE2A20E729032E1F008ADE48 /* VersionChecker.swift */,
E687B3D028B398E600A9551C /* FileManager+Data.swift */,
E687B3D128B398E600A9551C /* String+Data.swift */,
Expand All @@ -4060,6 +4064,7 @@
E687B3D428B398E600A9551C /* FetchSchema.swift */,
E687B3D528B398E600A9551C /* Initialize.swift */,
E687B3D628B398E600A9551C /* Generate.swift */,
662EA65D2A701483008A1931 /* GenerateOperationManifest.swift */,
);
path = Commands;
sourceTree = "<group>";
Expand Down Expand Up @@ -4113,6 +4118,7 @@
E6DC0AD228B3AC490064A68F /* GenerateTests.swift */,
DE2A20EC29033ABE008ADE48 /* VersionCheckerTests.swift */,
E6DC0AD328B3AC490064A68F /* FetchSchemaTests.swift */,
662EA65F2A705BD7008A1931 /* GenerateOperationManifestTests.swift */,
);
path = Commands;
sourceTree = "<group>";
Expand Down Expand Up @@ -5833,10 +5839,11 @@
E687B3E528B398E600A9551C /* Generate.swift in Sources */,
E687B3DE28B398E600A9551C /* Error.swift in Sources */,
DE2A20E829032E1F008ADE48 /* VersionChecker.swift in Sources */,
E687B3DF28B398E600A9551C /* ParsableCommand+RootOutputURL.swift in Sources */,
E687B3DF28B398E600A9551C /* ParsableCommand+Apollo.swift in Sources */,
E687B3E028B398E600A9551C /* FileManager+Data.swift in Sources */,
E687B3E828B398E600A9551C /* SchemaDownloadProvider.swift in Sources */,
E64F226D28B8B3FE0011292F /* LogLevelSetter.swift in Sources */,
662EA65E2A701483008A1931 /* GenerateOperationManifest.swift in Sources */,
E687B3E428B398E600A9551C /* Initialize.swift in Sources */,
E687B3E128B398E600A9551C /* String+Data.swift in Sources */,
E687B3DD28B398E600A9551C /* InputOptions.swift in Sources */,
Expand All @@ -5853,6 +5860,7 @@
E64F227128B8BEE10011292F /* MockLogLevelSetter.swift in Sources */,
E6DC0ADA28B3AC490064A68F /* MockApolloSchemaDownloader.swift in Sources */,
E6DC0AD928B3AC490064A68F /* TestSupport.swift in Sources */,
662EA6602A705BD7008A1931 /* GenerateOperationManifestTests.swift in Sources */,
E6DC0AD728B3AC490064A68F /* MockApolloCodegen.swift in Sources */,
E6DC0ADC28B3AC490064A68F /* InitializeTests.swift in Sources */,
E6DC0AD828B3AC490064A68F /* MockApolloCodegenConfiguration.swift in Sources */,
Expand Down
31 changes: 31 additions & 0 deletions Sources/ApolloCodegenLib/ApolloCodegen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,37 @@ public class ApolloCodegen {
)
}
}

public static func generateOperationManifest(
with configuration: ApolloCodegenConfiguration,
withRootURL rootURL: URL? = nil,
fileManager: ApolloFileManager = .default
) throws {
let configContext = ConfigurationContext(
config: configuration,
rootURL: rootURL
)

try validate(configContext)

let compilationResult = try compileGraphQLResult(
configContext,
experimentalFeatures: configuration.experimentalFeatures
)

try validate(configContext, with: compilationResult)

let ir = IR(compilationResult: compilationResult)

var operationIDsFileGenerator = OperationManifestFileGenerator(config: configContext)

for operation in compilationResult.operations {
let irOperation = ir.build(operation: operation)
operationIDsFileGenerator?.collectOperationIdentifier(irOperation)
}

try operationIDsFileGenerator?.generate(fileManager: fileManager)
}

// MARK: Internal

Expand Down
40 changes: 3 additions & 37 deletions Sources/CodegenCLI/Commands/Generate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,6 @@ public struct Generate: ParsableCommand {
)
var fetchSchema: Bool = false

@Flag(
name: .long,
help: "Ignore Apollo version mismatch errors. Warning: This may lead to incompatible generated objects."
)
var ignoreVersionMismatch: Bool = false

// MARK: - Implementation

public init() { }
Expand All @@ -40,7 +34,9 @@ public struct Generate: ParsableCommand {
) throws {
logger.SetLoggingLevel(verbose: inputs.verbose)

try checkForCLIVersionMismatch()
try checkForCLIVersionMismatch(
with: inputs
)

switch (inputs.string, inputs.path) {
case let (.some(string), _):
Expand All @@ -60,36 +56,6 @@ public struct Generate: ParsableCommand {
}
}

private func checkForCLIVersionMismatch() throws {
if case let .versionMismatch(cliVersion, apolloVersion) =
try VersionChecker.matchCLIVersionToApolloVersion(projectRootURL: rootOutputURL(for: inputs)) {
let errorMessage = """
Apollo Version Mismatch
We've detected that the version of the Apollo Codegen CLI does not match the version of the
Apollo library used in your project. This may lead to incompatible generated objects.
Please update your version of the Codegen CLI by following the instructions at:
https://www.apollographql.com/docs/ios/code-generation/codegen-cli/#installation
CLI version: \(cliVersion)
Apollo version: \(apolloVersion)
"""

if ignoreVersionMismatch {
print("""
Warning: \(errorMessage)
""")
} else {

throw Error(errorDescription: """
Error: \(errorMessage)
To ignore this error during code generation, use the argument: --ignore-version-mismatch.
""")
}
}
}

private func generate(
data: Data,
codegenProvider: CodegenProvider.Type,
Expand Down
61 changes: 61 additions & 0 deletions Sources/CodegenCLI/Commands/GenerateOperationManifest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import Foundation
import ArgumentParser
import ApolloCodegenLib

public struct GenerateOperationManifest: ParsableCommand {

// MARK: - Configuration

public static var configuration = CommandConfiguration(
abstract: "Generate Persisted Queries operation manifest based on a code generation configuration."
)

@OptionGroup var inputs: InputOptions

// MARK: - Implementation

public init() { }

public func run() throws {
try _run()
}

func _run(
fileManager: FileManager = .default,
codegenProvider: CodegenProvider.Type = ApolloCodegen.self,
logger: LogLevelSetter.Type = CodegenLogger.self
) throws {
logger.SetLoggingLevel(verbose: inputs.verbose)

try checkForCLIVersionMismatch(
with: inputs
)

switch (inputs.string, inputs.path) {
case let (.some(string), _):
try generateManifest(
data: try string.asData(),
codegenProvider: codegenProvider
)
case let (nil, path):
try generateManifest(
data: try fileManager.unwrappedContents(atPath: path),
codegenProvider: codegenProvider
)
}
}

private func generateManifest(
data: Data,
codegenProvider: CodegenProvider.Type
) throws {
let configuration = try JSONDecoder().decode(ApolloCodegenConfiguration.self, from: data)

try codegenProvider.generateOperationManifest(
with: configuration,
withRootURL: rootOutputURL(for: inputs),
fileManager: .default
)
}

}
45 changes: 45 additions & 0 deletions Sources/CodegenCLI/Extensions/ParsableCommand+Apollo.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import Foundation
import ArgumentParser
import ApolloCodegenLib

extension ParsableCommand {
func rootOutputURL(for inputOptions: InputOptions) -> URL? {
if inputOptions.string != nil { return nil }
let rootURL = URL(fileURLWithPath: inputOptions.path).deletingLastPathComponent()
if rootURL.path == FileManager.default.currentDirectoryPath { return nil }
return rootURL
}

func checkForCLIVersionMismatch(
with inputs: InputOptions,
ignoreVersionMismatch: Bool = false
) throws {
if case let .versionMismatch(cliVersion, apolloVersion) =
try VersionChecker.matchCLIVersionToApolloVersion(projectRootURL: rootOutputURL(for: inputs)) {
let errorMessage = """
Apollo Version Mismatch
We've detected that the version of the Apollo Codegen CLI does not match the version of the
Apollo library used in your project. This may lead to incompatible generated objects.
Please update your version of the Codegen CLI by following the instructions at:
https://www.apollographql.com/docs/ios/code-generation/codegen-cli/#installation
CLI version: \(cliVersion)
Apollo version: \(apolloVersion)
"""

if inputs.ignoreVersionMismatch {
print("""
Warning: \(errorMessage)
""")
} else {

throw Error(errorDescription: """
Error: \(errorMessage)
To ignore this error during code generation, use the argument: --ignore-version-mismatch.
""")
}
}
}
}
12 changes: 0 additions & 12 deletions Sources/CodegenCLI/Extensions/ParsableCommand+RootOutputURL.swift

This file was deleted.

6 changes: 6 additions & 0 deletions Sources/CodegenCLI/OptionGroups/InputOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,10 @@ struct InputOptions: ParsableArguments {
help: "Increase verbosity to include debug output."
)
var verbose: Bool = false

@Flag(
name: .long,
help: "Ignore Apollo version mismatch errors. Warning: This may lead to incompatible generated objects."
)
var ignoreVersionMismatch: Bool = false
}
6 changes: 6 additions & 0 deletions Sources/CodegenCLI/Protocols/CodegenProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ public protocol CodegenProvider {
with configuration: ApolloCodegenConfiguration,
withRootURL rootURL: URL?
) throws

static func generateOperationManifest(
with configuration: ApolloCodegenConfiguration,
withRootURL rootURL: URL?,
fileManager: ApolloFileManager
) throws
}

extension ApolloCodegen: CodegenProvider { }
17 changes: 17 additions & 0 deletions Sources/apollo-ios-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ SUBCOMMANDS:
init Initialize a new configuration with defaults.
generate Generate Swift source code based on a code generation configuration.
fetch-schema Download a GraphQL schema from the Apollo Registry or GraphQL introspection.
generate-operation-manifest
Generate Persisted Queries operation manifest based on a code generation configuration.
See 'apollo-ios-cli help <subcommand>' for detailed help.
```
Expand Down Expand Up @@ -75,3 +77,18 @@ OPTIONS:
--version Show the version.
-h, --help Show help information.
```
## Generate Operation Manifest
```
OVERVIEW: Generate Persisted Queries operation manifest based on a code generation configuration.
USAGE: apollo-ios-cli generate-operation-manifest [--path <path>] [--string <string>] [--verbose] [--ignore-version-mismatch]
OPTIONS:
-p, --path <path> Read the configuration from a file at the path. --string overrides this option if used together. (default: ./apollo-codegen-config.json)
-s, --string <string> Configuration string in JSON format. This option overrides --path.
-v, --verbose Increase verbosity to include debug output.
--ignore-version-mismatch
Ignore Apollo version mismatch errors. Warning: This may lead to incompatible generated objects.
--version Show the version.
-h, --help Show help information.
```
1 change: 1 addition & 0 deletions Sources/apollo-ios-cli/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ struct Apollo_iOS_CLI: ParsableCommand {
CodegenCLI.Initialize.self,
CodegenCLI.Generate.self,
CodegenCLI.FetchSchema.self,
CodegenCLI.GenerateOperationManifest.self
]
)
}
Expand Down

0 comments on commit a47a8af

Please sign in to comment.