diff --git a/Sources/ApolloCodegenLib/ApolloSchemaOptions.swift b/Sources/ApolloCodegenLib/ApolloSchemaOptions.swift index 895cef027e..05cd300e3e 100644 --- a/Sources/ApolloCodegenLib/ApolloSchemaOptions.swift +++ b/Sources/ApolloCodegenLib/ApolloSchemaOptions.swift @@ -9,8 +9,48 @@ public struct ApolloSchemaOptions { case schemaDefinitionLanguage = "graphql" } - let apiKey: String? - let endpointURL: URL + /// How to attempt to download your schema + public enum DownloadMethod: Equatable { + + case registry(_ settings: RegistrySettings) + /// - endpointURL: The endpoint to hit to download your schema. + case introspection(endpointURL: URL) + + public struct RegistrySettings: Equatable { + public let apiKey: String + public let graphID: String + public let variant: String? + + /// Designated initializer + /// + /// - Parameters: + /// - apiKey: The API key to use when retrieving your schema. + /// - graphID: The identifier of the graph to fetch. Can be found in Apollo Studio. + /// - variant: [Optional] The variant of the graph to fetch. Defaults to nil, which will return whatever is set to the current variant. + public init(apiKey: String, + graphID: String, + variant: String? = nil) { + self.apiKey = apiKey + self.graphID = graphID + self.variant = variant + } + } + + public static func == (lhs: DownloadMethod, rhs: DownloadMethod) -> Bool { + switch (lhs, rhs) { + case (.introspection(let lhsURL), introspection(let rhsURL)): + return lhsURL == rhsURL + case (.registry(let lhsSettings), + .registry(let rhsSettings)): + return lhsSettings == rhsSettings + default: + return false + } + } + + } + + let downloadMethod: DownloadMethod let headers: [String] let outputURL: URL @@ -21,21 +61,18 @@ public struct ApolloSchemaOptions { /// - Parameters: /// - schemaFileName: The name, without an extension, for your schema file. Defaults to `"schema"` /// - schemaFileType: The `SchemaFileType` to download the schema as. Defaults to `.json`. - /// - apiKey: [optional] The API key to use when retrieving your schema. Defaults to nil. - /// - endpointURL: The endpoint to hit to download your schema. + /// - downloadMethod: How to download your schema. /// - headers: [optional] Any additional headers to include when retrieving your schema. Defaults to nil /// - outputFolderURL: The URL of the folder in which the downloaded schema should be written /// - downloadTimeout: The maximum time to wait before indicating that the download timed out, in seconds. Defaults to 30 seconds. public init(schemaFileName: String = "schema", schemaFileType: SchemaFileType = .json, - apiKey: String? = nil, - endpointURL: URL, + downloadMethod: DownloadMethod, headers: [String] = [], outputFolderURL: URL, downloadTimeout: Double = 30.0) { - self.apiKey = apiKey + self.downloadMethod = downloadMethod self.headers = headers - self.endpointURL = endpointURL self.outputURL = outputFolderURL.appendingPathComponent("\(schemaFileName).\(schemaFileType.rawValue)") self.downloadTimeout = downloadTimeout @@ -44,11 +81,17 @@ public struct ApolloSchemaOptions { var arguments: [String] { var arguments = [ "client:download-schema", - "--endpoint=\(self.endpointURL.absoluteString)" ] - if let key = self.apiKey { - arguments.append("--key=\(key)") + switch self.downloadMethod { + case .introspection(let endpointURL): + arguments.append("--endpoint=\(endpointURL.absoluteString)") + case .registry(let settings): + arguments.append("--key=\(settings.apiKey)") + arguments.append("--graph=\(settings.graphID)") + if let providedVariant = settings.variant { + arguments.append("--variant=\(providedVariant)") + } } arguments.append("'\(outputURL.path)'") diff --git a/SwiftScripts/Sources/SchemaDownload/main.swift b/SwiftScripts/Sources/SchemaDownload/main.swift index e134065073..d72627cada 100644 --- a/SwiftScripts/Sources/SchemaDownload/main.swift +++ b/SwiftScripts/Sources/SchemaDownload/main.swift @@ -20,10 +20,20 @@ let output = sourceRootURL .appendingPathComponent("Sources") .appendingPathComponent("UploadAPI") +// Introspection download: let options = ApolloSchemaOptions(schemaFileName: "schema", - endpointURL: endpoint, + downloadMethod: .introspection(endpointURL: endpoint), outputFolderURL: output) +// Registry download: +//let registrySettings = ApolloSchemaOptions.DownloadMethod.RegistrySettings(apiKey: <#Replace Me For Testing#>, +// graphID: "Apollo-Fullstack-8zo5jl") +// +//let options = ApolloSchemaOptions(schemaFileName: "schema", +// schemaFileType: .schemaDefinitionLanguage, +// downloadMethod: .registry(registrySettings), +// outputFolderURL: output) + do { try ApolloSchemaDownloader.run(with: cliFolderURL, options: options) diff --git a/Tests/ApolloCodegenTests/ApolloSchemaTests.swift b/Tests/ApolloCodegenTests/ApolloSchemaTests.swift index fb7552e2ad..433104762b 100644 --- a/Tests/ApolloCodegenTests/ApolloSchemaTests.swift +++ b/Tests/ApolloCodegenTests/ApolloSchemaTests.swift @@ -12,15 +12,16 @@ import ApolloTestSupport class ApolloSchemaTests: XCTestCase { - func testCreatingOptionsWithDefaultParameters() throws { + func testCreatingIntrospectionOptionsWithDefaultParameters() throws { let sourceRoot = CodegenTestHelper.sourceRootURL() - let options = ApolloSchemaOptions(endpointURL: TestURL.starWarsServer.url, + + let options = ApolloSchemaOptions(downloadMethod: .introspection(endpointURL: TestURL.starWarsServer.url), outputFolderURL: sourceRoot) let expectedOutputURL = sourceRoot.appendingPathComponent("schema.json") - XCTAssertEqual(options.endpointURL, TestURL.starWarsServer.url) + + XCTAssertEqual(options.downloadMethod, .introspection(endpointURL: TestURL.starWarsServer.url)) XCTAssertEqual(options.outputURL, expectedOutputURL) - XCTAssertNil(options.apiKey) XCTAssertTrue(options.headers.isEmpty) XCTAssertEqual(options.arguments, [ @@ -29,22 +30,49 @@ class ApolloSchemaTests: XCTestCase { "'\(expectedOutputURL.path)'" ]) } - - func testCreatingOptionsWithAllParameters() throws { + + func testCreatingRegistryOptionsWithDefaultParameters() throws { + let sourceRoot = CodegenTestHelper.sourceRootURL() + let apiKey = "Fake_API_Key" + let graphID = "Fake_Graph_ID" + + let settings = ApolloSchemaOptions.DownloadMethod.RegistrySettings(apiKey: apiKey, graphID: graphID) + + let options = ApolloSchemaOptions(downloadMethod: .registry(settings), + outputFolderURL: sourceRoot) + + let expectedOutputURL = sourceRoot.appendingPathComponent("schema.json") + + XCTAssertEqual(options.downloadMethod, .registry(settings)) + XCTAssertEqual(options.outputURL, expectedOutputURL) + XCTAssertTrue(options.headers.isEmpty) + + XCTAssertEqual(options.arguments, [ + "client:download-schema", + "--key=\(apiKey)", + "--graph=\(graphID)", + "'\(expectedOutputURL.path)'" + ]) + } + + func testCreatingRegistryOptionsWithAllParameters() throws { let sourceRoot = CodegenTestHelper.sourceRootURL() let apiKey = "Fake_API_Key" + let graphID = "Fake_Graph_ID" + let variant = "Fake_Variant" let firstHeader = "Authorization: Bearer tokenGoesHere" let secondHeader = "Custom-Header: Custom_Customer" let headers = [firstHeader, secondHeader] + let settings = ApolloSchemaOptions.DownloadMethod.RegistrySettings(apiKey: apiKey, + graphID: graphID, variant: variant) + let options = ApolloSchemaOptions(schemaFileName: "different_name", schemaFileType: .schemaDefinitionLanguage, - apiKey: apiKey, - endpointURL: TestURL.starWarsServer.url, + downloadMethod: .registry(settings), headers: headers, outputFolderURL: sourceRoot) - XCTAssertEqual(options.apiKey, apiKey) - XCTAssertEqual(options.endpointURL, TestURL.starWarsServer.url) + XCTAssertEqual(options.downloadMethod, .registry(settings)) XCTAssertEqual(options.headers, headers) let expectedOutputURL = sourceRoot.appendingPathComponent("different_name.graphql") @@ -52,8 +80,9 @@ class ApolloSchemaTests: XCTestCase { XCTAssertEqual(options.arguments, [ "client:download-schema", - "--endpoint=http://localhost:8080/graphql", "--key=\(apiKey)", + "--graph=\(graphID)", + "--variant=\(variant)", "'\(expectedOutputURL.path)'", "--header='\(firstHeader)'", "--header='\(secondHeader)'" @@ -63,7 +92,7 @@ class ApolloSchemaTests: XCTestCase { func testDownloadingSchemaAsJSON() throws { let testOutputFolderURL = CodegenTestHelper.outputFolderURL() - let options = ApolloSchemaOptions(endpointURL: TestURL.starWarsServer.url, + let options = ApolloSchemaOptions(downloadMethod: .introspection(endpointURL: TestURL.starWarsServer.url), outputFolderURL: testOutputFolderURL) // Delete anything existing at the output URL @@ -97,7 +126,7 @@ class ApolloSchemaTests: XCTestCase { let testOutputFolderURL = CodegenTestHelper.outputFolderURL() let options = ApolloSchemaOptions(schemaFileType: .schemaDefinitionLanguage, - endpointURL: TestURL.starWarsServer.url, + downloadMethod: .introspection(endpointURL: TestURL.starWarsServer.url), outputFolderURL: testOutputFolderURL) // Delete anything existing at the output URL