diff --git a/Apollo.xcodeproj/project.pbxproj b/Apollo.xcodeproj/project.pbxproj index a30b8855c1..e441f32894 100644 --- a/Apollo.xcodeproj/project.pbxproj +++ b/Apollo.xcodeproj/project.pbxproj @@ -14,12 +14,16 @@ 9B0E471A240AFA060093BDA7 /* VariableToSwiftTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B0E4719240AFA060093BDA7 /* VariableToSwiftTypeTests.swift */; }; 9B0E471C240B167C0093BDA7 /* String+Apollo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B0E471B240B167C0093BDA7 /* String+Apollo.swift */; }; 9B0E471E240B239D0093BDA7 /* ASTEnumValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B0E471D240B239D0093BDA7 /* ASTEnumValue.swift */; }; - 9B1A38532332AF6F00325FB4 /* String+SHA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B1A38522332AF6F00325FB4 /* String+SHA.swift */; }; 9B1CCDD92360F02C007C9032 /* Bundle+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B1CCDD82360F02C007C9032 /* Bundle+Helpers.swift */; }; 9B21FD752422C29D00998B5C /* GraphQLFileTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B21FD742422C29D00998B5C /* GraphQLFileTests.swift */; }; 9B21FD772422C8CC00998B5C /* TestFileHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B21FD762422C8CC00998B5C /* TestFileHelper.swift */; }; 9B21FD782424305700998B5C /* ExpectedEnumWithDifferentCases.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B68F05F2416F80C00E97318 /* ExpectedEnumWithDifferentCases.swift */; }; 9B21FD792424305E00998B5C /* ExpectedEnumWithSanitizedCases.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B68F063241703B200E97318 /* ExpectedEnumWithSanitizedCases.swift */; }; + 9B455CDF2492D05E002255A9 /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B6CB23D238077B60007259D /* Atomic.swift */; }; + 9B455CE52492D0A3002255A9 /* ApolloExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B455CE22492D0A3002255A9 /* ApolloExtension.swift */; }; + 9B455CE62492D0A3002255A9 /* OptionalBoolean.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B455CE32492D0A3002255A9 /* OptionalBoolean.swift */; }; + 9B455CE72492D0A3002255A9 /* Collection+Apollo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B455CE42492D0A3002255A9 /* Collection+Apollo.swift */; }; + 9B455CEB2492FB03002255A9 /* String+SHA.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B455CEA2492FB03002255A9 /* String+SHA.swift */; }; 9B4F453F244A27B900C2CF7D /* URLSessionClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B4F453E244A27B900C2CF7D /* URLSessionClient.swift */; }; 9B4F4541244A2A9200C2CF7D /* HTTPBinAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B4F4540244A2A9200C2CF7D /* HTTPBinAPI.swift */; }; 9B4F4543244A2AD300C2CF7D /* URLSessionClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B4F4542244A2AD300C2CF7D /* URLSessionClientTests.swift */; }; @@ -51,7 +55,6 @@ 9B68F05D2416BDCF00E97318 /* ExpectedEnumWithDeprecatedCases.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B68F05C2416BDCF00E97318 /* ExpectedEnumWithDeprecatedCases.swift */; }; 9B68F06524198D1000E97318 /* InputObjectGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B68F0612417002900E97318 /* InputObjectGenerator.swift */; }; 9B68F068241ADA9D00E97318 /* Dictionary+Apollo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B68F066241AD98C00E97318 /* Dictionary+Apollo.swift */; }; - 9B6CB23E238077B70007259D /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B6CB23D238077B60007259D /* Atomic.swift */; }; 9B708AAD2305884500604A11 /* ApolloClientProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B708AAC2305884500604A11 /* ApolloClientProtocol.swift */; }; 9B78C71E2326E86E000C8C32 /* ErrorGenerationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B78C71B2326E859000C8C32 /* ErrorGenerationTests.swift */; }; 9B7B6F59233C287200F32205 /* ApolloCodegen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B7B6F57233C287100F32205 /* ApolloCodegen.swift */; }; @@ -84,6 +87,8 @@ 9B7BDB1523FDF09600ACD198 /* ApolloTestSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F8A95781EC0FC1200304A2D /* ApolloTestSupport.framework */; }; 9B7BDB1A23FDF12000ACD198 /* ApolloSQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B7BDABF23FDEBB600ACD198 /* ApolloSQLite.framework */; }; 9B7BDB1D23FDF22300ACD198 /* StarWarsAPI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9FCE2CFA1E6C213D00E34457 /* StarWarsAPI.framework */; }; + 9B8C3FB3248DA2FE00707B13 /* URL+Apollo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B8C3FB1248DA2EA00707B13 /* URL+Apollo.swift */; }; + 9B8C3FB5248DA3E000707B13 /* URLExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B8C3FB4248DA3E000707B13 /* URLExtensionsTests.swift */; }; 9B95EDC022CAA0B000702BB2 /* GETTransformerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B95EDBF22CAA0AF00702BB2 /* GETTransformerTests.swift */; }; 9BA1244A22D8A8EA00BF1D24 /* JSONSerialization+Sorting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BA1244922D8A8EA00BF1D24 /* JSONSerialization+Sorting.swift */; }; 9BA1245E22DE116B00BF1D24 /* Result+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BA1245D22DE116B00BF1D24 /* Result+Helpers.swift */; }; @@ -102,7 +107,6 @@ 9BAEEC17234C275600808306 /* ApolloSchemaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BAEEC16234C275600808306 /* ApolloSchemaTests.swift */; }; 9BAEEC19234C297800808306 /* ApolloCodegenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BAEEC18234C297800808306 /* ApolloCodegenTests.swift */; }; 9BC2D9D3233C6EF0007BD083 /* Basher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BC2D9D1233C6DC0007BD083 /* Basher.swift */; }; - 9BCB58602407593C002F766E /* OptionalBoolean.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BCB585E240758C8002F766E /* OptionalBoolean.swift */; }; 9BCF0CE023FC9CA50031D2A2 /* TestCacheProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BCF0CD923FC9CA50031D2A2 /* TestCacheProvider.swift */; }; 9BCF0CE223FC9CA50031D2A2 /* XCTestCase+Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BCF0CDB23FC9CA50031D2A2 /* XCTestCase+Promise.swift */; }; 9BCF0CE323FC9CA50031D2A2 /* XCTAssertHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BCF0CDC23FC9CA50031D2A2 /* XCTAssertHelpers.swift */; }; @@ -192,7 +196,6 @@ 9FF90A6F1DDDEB420034C3B6 /* InputValueEncodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF90A6A1DDDEB420034C3B6 /* InputValueEncodingTests.swift */; }; 9FF90A711DDDEB420034C3B6 /* ReadFieldValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF90A6B1DDDEB420034C3B6 /* ReadFieldValueTests.swift */; }; 9FF90A731DDDEB420034C3B6 /* ParseQueryResponseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF90A6C1DDDEB420034C3B6 /* ParseQueryResponseTests.swift */; }; - AE1CFBD0245EBA25002C8CEE /* ApolloExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AE1CFBCE245EB998002C8CEE /* ApolloExtension.swift */; }; C3279FC72345234D00224790 /* TestCustomRequestCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3279FC52345233000224790 /* TestCustomRequestCreator.swift */; }; C338DF1722DD9DE9006AF33E /* RequestCreatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C338DF1622DD9DE9006AF33E /* RequestCreatorTests.swift */; }; C35D43C222DDD4AC00BCBABE /* b.txt in Resources */ = {isa = PBXBuildFile; fileRef = C35D43BE22DDD3C100BCBABE /* b.txt */; }; @@ -291,6 +294,13 @@ remoteGlobalIDString = 9FCE2CF91E6C213D00E34457; remoteInfo = StarWarsAPI; }; + 9B8C3FBB248DAA0400707B13 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9FC7503B1D2A532C00458D91 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 9B68353D2463481A00337AE6; + remoteInfo = ApolloCore; + }; 9BAD16B723FE361F00007BEF /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 9FC7503B1D2A532C00458D91 /* Project object */; @@ -389,10 +399,13 @@ 9B0E4719240AFA060093BDA7 /* VariableToSwiftTypeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VariableToSwiftTypeTests.swift; sourceTree = ""; }; 9B0E471B240B167C0093BDA7 /* String+Apollo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Apollo.swift"; sourceTree = ""; }; 9B0E471D240B239D0093BDA7 /* ASTEnumValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASTEnumValue.swift; sourceTree = ""; }; - 9B1A38522332AF6F00325FB4 /* String+SHA.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+SHA.swift"; sourceTree = ""; }; 9B1CCDD82360F02C007C9032 /* Bundle+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+Helpers.swift"; sourceTree = ""; }; 9B21FD742422C29D00998B5C /* GraphQLFileTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphQLFileTests.swift; sourceTree = ""; }; 9B21FD762422C8CC00998B5C /* TestFileHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestFileHelper.swift; sourceTree = ""; }; + 9B455CE22492D0A3002255A9 /* ApolloExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApolloExtension.swift; sourceTree = ""; }; + 9B455CE32492D0A3002255A9 /* OptionalBoolean.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptionalBoolean.swift; sourceTree = ""; }; + 9B455CE42492D0A3002255A9 /* Collection+Apollo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Collection+Apollo.swift"; sourceTree = ""; }; + 9B455CEA2492FB03002255A9 /* String+SHA.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+SHA.swift"; sourceTree = ""; }; 9B4AA8AD239EFDC9003E1300 /* Apollo-Target-CodegenTests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Apollo-Target-CodegenTests.xcconfig"; sourceTree = ""; }; 9B4F453E244A27B900C2CF7D /* URLSessionClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionClient.swift; sourceTree = ""; }; 9B4F4540244A2A9200C2CF7D /* HTTPBinAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPBinAPI.swift; sourceTree = ""; }; @@ -474,6 +487,8 @@ 9B7BDAED23FDED9700ACD198 /* ApolloSQLiteTestSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ApolloSQLiteTestSupport.h; sourceTree = ""; }; 9B7BDAEE23FDED9700ACD198 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 9B8110A723A1995D00688AC4 /* .keep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .keep; sourceTree = ""; }; + 9B8C3FB1248DA2EA00707B13 /* URL+Apollo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Apollo.swift"; sourceTree = ""; }; + 9B8C3FB4248DA3E000707B13 /* URLExtensionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLExtensionsTests.swift; sourceTree = ""; }; 9B95EDBF22CAA0AF00702BB2 /* GETTransformerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GETTransformerTests.swift; sourceTree = ""; }; 9BA1244922D8A8EA00BF1D24 /* JSONSerialization+Sorting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSONSerialization+Sorting.swift"; sourceTree = ""; }; 9BA1245D22DE116B00BF1D24 /* Result+Helpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Result+Helpers.swift"; sourceTree = ""; }; @@ -494,7 +509,6 @@ 9BAEEC18234C297800808306 /* ApolloCodegenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApolloCodegenTests.swift; sourceTree = ""; }; 9BC2D9CE233C3531007BD083 /* Apollo-Target-ApolloCodegen.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Apollo-Target-ApolloCodegen.xcconfig"; sourceTree = ""; }; 9BC2D9D1233C6DC0007BD083 /* Basher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Basher.swift; sourceTree = ""; }; - 9BCB585E240758C8002F766E /* OptionalBoolean.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptionalBoolean.swift; sourceTree = ""; }; 9BCF0CD923FC9CA50031D2A2 /* TestCacheProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestCacheProvider.swift; sourceTree = ""; }; 9BCF0CDA23FC9CA50031D2A2 /* ApolloTestSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ApolloTestSupport.h; sourceTree = ""; }; 9BCF0CDB23FC9CA50031D2A2 /* XCTestCase+Promise.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "XCTestCase+Promise.swift"; sourceTree = ""; }; @@ -610,7 +624,6 @@ 9FF90A6A1DDDEB420034C3B6 /* InputValueEncodingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputValueEncodingTests.swift; sourceTree = ""; }; 9FF90A6B1DDDEB420034C3B6 /* ReadFieldValueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReadFieldValueTests.swift; sourceTree = ""; }; 9FF90A6C1DDDEB420034C3B6 /* ParseQueryResponseTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParseQueryResponseTests.swift; sourceTree = ""; }; - AE1CFBCE245EB998002C8CEE /* ApolloExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApolloExtension.swift; sourceTree = ""; }; C304EBD322DDC7B200748F72 /* a.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = a.txt; sourceTree = ""; }; C3279FC52345233000224790 /* TestCustomRequestCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestCustomRequestCreator.swift; sourceTree = ""; }; C338DF1622DD9DE9006AF33E /* RequestCreatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestCreatorTests.swift; sourceTree = ""; }; @@ -786,10 +799,23 @@ name = TestHelpers; sourceTree = ""; }; + 9B455CE82492D0A7002255A9 /* Extensions */ = { + isa = PBXGroup; + children = ( + 9B455CE22492D0A3002255A9 /* ApolloExtension.swift */, + 9B455CE42492D0A3002255A9 /* Collection+Apollo.swift */, + 9B455CE32492D0A3002255A9 /* OptionalBoolean.swift */, + 9B455CEA2492FB03002255A9 /* String+SHA.swift */, + ); + name = Extensions; + sourceTree = ""; + }; 9B6835472463486200337AE6 /* ApolloCore */ = { isa = PBXGroup; children = ( + 9B6CB23D238077B60007259D /* Atomic.swift */, 9B68F06E241C649E00E97318 /* GraphQLOptional.swift */, + 9B455CE82492D0A7002255A9 /* Extensions */, ); name = ApolloCore; path = Sources/ApolloCore; @@ -945,6 +971,7 @@ 9B68F0512415B17B00E97318 /* ExpectedOutputs */, 9B8110A623A1994000688AC4 /* SourcePackages */, 9BAEEC11234BBA9200808306 /* CodegenTestHelper.swift */, + 9B6835322460B32A00337AE6 /* ASTVariableType+TestHelpers.swift */, 9BD681372405F7F6000874CB /* JSONTestHelpers.swift */, 9BD681412406F516000874CB /* ASTParsingTests.swift */, 9BAEEC16234C275600808306 /* ApolloSchemaTests.swift */, @@ -957,9 +984,9 @@ 9BAEEC0D234BB95B00808306 /* FileManagerExtensionsTests.swift */, 9B68F0542416B33300E97318 /* LineByLineComparison.swift */, 9BD681352405F725000874CB /* JSONTests.swift */, + 9B8C3FB4248DA3E000707B13 /* URLExtensionsTests.swift */, 9B0E4719240AFA060093BDA7 /* VariableToSwiftTypeTests.swift */, 9BAEEC0C234BB95B00808306 /* Info.plist */, - 9B6835322460B32A00337AE6 /* ASTVariableType+TestHelpers.swift */, ); path = ApolloCodegenTests; sourceTree = ""; @@ -967,12 +994,11 @@ 9BCB585D240758B2002F766E /* Extensions */ = { isa = PBXGroup; children = ( - AE1CFBCE245EB998002C8CEE /* ApolloExtension.swift */, 9B68F066241AD98C00E97318 /* Dictionary+Apollo.swift */, 9B7B6F68233C2C0C00F32205 /* FileManager+Apollo.swift */, - 9BCB585E240758C8002F766E /* OptionalBoolean.swift */, 9BAEEBF62346F0A000808306 /* StaticString+Apollo.swift */, 9B0E471B240B167C0093BDA7 /* String+Apollo.swift */, + 9B8C3FB1248DA2EA00707B13 /* URL+Apollo.swift */, ); name = Extensions; sourceTree = ""; @@ -1298,7 +1324,6 @@ isa = PBXGroup; children = ( 9FCDFD221E33A0D8007519DC /* AsynchronousOperation.swift */, - 9B6CB23D238077B60007259D /* Atomic.swift */, 9B1CCDD82360F02C007C9032 /* Bundle+Helpers.swift */, 9BE071AC2368D08700FA5952 /* Collection+Helpers.swift */, 9BE071B02368D3F500FA5952 /* Dictionary+Helpers.swift */, @@ -1309,7 +1334,6 @@ 9FE941CF1E62C771007CDD89 /* Promise.swift */, 9BA1245D22DE116B00BF1D24 /* Result+Helpers.swift */, 9F19D8431EED568200C57247 /* ResultOrPromise.swift */, - 9B1A38522332AF6F00325FB4 /* String+SHA.swift */, ); name = Utilities; sourceTree = ""; @@ -1648,6 +1672,7 @@ buildRules = ( ); dependencies = ( + 9B8C3FBC248DAA0400707B13 /* PBXTargetDependency */, ); name = Apollo; packageProductDependencies = ( @@ -1931,6 +1956,11 @@ buildActionMask = 2147483647; files = ( 9B68354E24634A3C00337AE6 /* GraphQLOptional.swift in Sources */, + 9B455CE52492D0A3002255A9 /* ApolloExtension.swift in Sources */, + 9B455CEB2492FB03002255A9 /* String+SHA.swift in Sources */, + 9B455CE62492D0A3002255A9 /* OptionalBoolean.swift in Sources */, + 9B455CDF2492D05E002255A9 /* Atomic.swift in Sources */, + 9B455CE72492D0A3002255A9 /* Collection+Apollo.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1942,6 +1972,7 @@ 9B68F03D240ED3B300E97318 /* ASTCondition.swift in Sources */, 9BD681402406F31A000874CB /* FlexibleDecoder.swift in Sources */, 9BC2D9D3233C6EF0007BD083 /* Basher.swift in Sources */, + 9B8C3FB3248DA2FE00707B13 /* URL+Apollo.swift in Sources */, 9BAEEBEF2346644B00808306 /* ApolloSchemaDownloader.swift in Sources */, 9BAEEBF72346F0A000808306 /* StaticString+Apollo.swift in Sources */, 9B68F03F240F3B0E00E97318 /* CodeGenerator.swift in Sources */, @@ -1955,7 +1986,6 @@ 9B68F04A24130D6500E97318 /* EnumGenerator.swift in Sources */, 9B68F06524198D1000E97318 /* InputObjectGenerator.swift in Sources */, 9B7B6F69233C2C0C00F32205 /* FileManager+Apollo.swift in Sources */, - AE1CFBD0245EBA25002C8CEE /* ApolloExtension.swift in Sources */, 9BE74D3D23FB4A8E006D354F /* FileFinder.swift in Sources */, 9B68F068241ADA9D00E97318 /* Dictionary+Apollo.swift in Sources */, 9B7B6F59233C287200F32205 /* ApolloCodegen.swift in Sources */, @@ -1964,7 +1994,6 @@ 9B0E471E240B239D0093BDA7 /* ASTEnumValue.swift in Sources */, 9B7B6F5A233C287200F32205 /* ApolloCodegenOptions.swift in Sources */, 9BAEEBF52346E90700808306 /* CLIExtractor.swift in Sources */, - 9BCB58602407593C002F766E /* OptionalBoolean.swift in Sources */, 9BD6813B2405FA56000874CB /* ASTOperation.swift in Sources */, 9BD681292405F149000874CB /* ASTTypeUsed.swift in Sources */, 9BD6812F2405F665000874CB /* JSON.swift in Sources */, @@ -2037,6 +2066,7 @@ 9BAEEC17234C275600808306 /* ApolloSchemaTests.swift in Sources */, 9B5A1EFC243528AA00F066BB /* InputObjectGenerationTests.swift in Sources */, 9B0E471A240AFA060093BDA7 /* VariableToSwiftTypeTests.swift in Sources */, + 9B8C3FB5248DA3E000707B13 /* URLExtensionsTests.swift in Sources */, 9BAEEC12234BBA9200808306 /* CodegenTestHelper.swift in Sources */, 9B5A1EFD24352AC100F066BB /* ExpectedReviewInput.swift in Sources */, 9B68F0592416BA7700E97318 /* ExpectedEnumWithNoCases.swift in Sources */, @@ -2097,7 +2127,6 @@ C377CCAB22D7992E00572E03 /* MultipartFormData.swift in Sources */, 9FCE2CEE1E6BE2D900E34457 /* NormalizedCache.swift in Sources */, 9F8F334C229044A200C0E83B /* Decoding.swift in Sources */, - 9B6CB23E238077B70007259D /* Atomic.swift in Sources */, 9FADC84A1E6B0B2300C677E6 /* Locking.swift in Sources */, 9F295E381E277B2A00A24949 /* GraphQLResultNormalizer.swift in Sources */, 9F86B68B1E6438D700B885FF /* GraphQLSelectionSetMapper.swift in Sources */, @@ -2130,7 +2159,6 @@ 9FADC84F1E6B865E00C677E6 /* DataLoader.swift in Sources */, 9FF90A611DDDEB100034C3B6 /* GraphQLResponse.swift in Sources */, 9F27D4641D40379500715680 /* JSONStandardTypeConversions.swift in Sources */, - 9B1A38532332AF6F00325FB4 /* String+SHA.swift in Sources */, 9BEDC79E22E5D2CF00549BF6 /* RequestCreator.swift in Sources */, 9BE071AD2368D08700FA5952 /* Collection+Helpers.swift in Sources */, 9FA6F3681E65DF4700BF8D73 /* GraphQLResultAccumulator.swift in Sources */, @@ -2260,6 +2288,11 @@ target = 9FCE2CF91E6C213D00E34457 /* StarWarsAPI */; targetProxy = 9B7BDB1B23FDF22000ACD198 /* PBXContainerItemProxy */; }; + 9B8C3FBC248DAA0400707B13 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 9B68353D2463481A00337AE6 /* ApolloCore */; + targetProxy = 9B8C3FBB248DAA0400707B13 /* PBXContainerItemProxy */; + }; 9BAD16B823FE361F00007BEF /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 9F8A95771EC0FC1200304A2D /* ApolloTestSupport */; diff --git a/Sources/Apollo/ApolloStore.swift b/Sources/Apollo/ApolloStore.swift index 719dcb4bb9..fd26ac0915 100644 --- a/Sources/Apollo/ApolloStore.swift +++ b/Sources/Apollo/ApolloStore.swift @@ -57,7 +57,7 @@ public final class ApolloStore { self.cacheLock.withWriteLock { self.cache.clearPromise() }.andThen { - DispatchQueue.apollo_returnResultAsyncIfNeeded(on: callbackQueue, + DispatchQueue.apollo.returnResultAsyncIfNeeded(on: callbackQueue, action: completion, result: .success(())) } @@ -115,12 +115,12 @@ public final class ApolloStore { Promise(fulfilled: try body($0)) } .andThen { object in - DispatchQueue.apollo_returnResultAsyncIfNeeded(on: callbackQueue, + DispatchQueue.apollo.returnResultAsyncIfNeeded(on: callbackQueue, action: completion, result: .success(object)) } .catch { error in - DispatchQueue.apollo_returnResultAsyncIfNeeded(on: callbackQueue, + DispatchQueue.apollo.returnResultAsyncIfNeeded(on: callbackQueue, action: completion, result: .failure(error)) } @@ -153,12 +153,12 @@ public final class ApolloStore { Promise(fulfilled: try body($0)) } .andThen { object in - DispatchQueue.apollo_returnResultAsyncIfNeeded(on: callbackQueue, + DispatchQueue.apollo.returnResultAsyncIfNeeded(on: callbackQueue, action: completion, result: .success(object)) } .catch { error in - DispatchQueue.apollo_returnResultAsyncIfNeeded(on: callbackQueue, + DispatchQueue.apollo.returnResultAsyncIfNeeded(on: callbackQueue, action: completion, result: .failure(error)) } diff --git a/Sources/Apollo/Bundle+Helpers.swift b/Sources/Apollo/Bundle+Helpers.swift index 7d94864f69..26baead4df 100644 --- a/Sources/Apollo/Bundle+Helpers.swift +++ b/Sources/Apollo/Bundle+Helpers.swift @@ -1,13 +1,16 @@ import Foundation +import ApolloCore -extension Bundle { +extension Bundle: ApolloCompatible {} + +extension ApolloExtension where Base == Bundle { /// Type-safe getter for info dictionary key objects /// /// - Parameter key: The key to try to grab an object for /// - Returns: The object of the desired type, or nil if it is not present or of the incorrect type. func bundleValue(forKey key: String) -> T? { - return object(forInfoDictionaryKey: key) as? T + return base.object(forInfoDictionaryKey: key) as? T } /// The bundle identifier of this bundle, or nil if not present. diff --git a/Sources/Apollo/Collection+Helpers.swift b/Sources/Apollo/Collection+Helpers.swift index 86ed5dd2c4..9046b4b950 100644 --- a/Sources/Apollo/Collection+Helpers.swift +++ b/Sources/Apollo/Collection+Helpers.swift @@ -1,40 +1,5 @@ import Foundation -// MARK: - Emptiness + Optionality - -extension Collection { - - /// Convenience helper to make `guard` statements more readable - /// - /// - returns: `true` if the collection has contents. - var isNotEmpty: Bool { - return !self.isEmpty - } -} - -extension Optional where Wrapped: Collection { - - /// - returns: `true` if the collection is empty or nil - var isEmptyOrNil: Bool { - switch self { - case .none: - return true - case .some(let collection): - return collection.isEmpty - } - } - - /// - returns: `true` if the collection is non-nil AND has contents. - var isNotEmpty: Bool { - switch self { - case .none: - return false - case .some(let collection): - return collection.isNotEmpty - } - } -} - // MARK: - Unzipping // MARK: Arrays of tuples to tuples of arrays diff --git a/Sources/Apollo/DispatchQueue+Optional.swift b/Sources/Apollo/DispatchQueue+Optional.swift index 310fe32279..ca13b06ae0 100644 --- a/Sources/Apollo/DispatchQueue+Optional.swift +++ b/Sources/Apollo/DispatchQueue+Optional.swift @@ -1,8 +1,11 @@ import Foundation +import ApolloCore -public extension DispatchQueue { +extension DispatchQueue: ApolloCompatible {} - static func apollo_performAsyncIfNeeded(on callbackQueue: DispatchQueue?, action: @escaping () -> Void) { +public extension ApolloExtension where Base == DispatchQueue { + + static func performAsyncIfNeeded(on callbackQueue: DispatchQueue?, action: @escaping () -> Void) { if let callbackQueue = callbackQueue { // A callback queue was provided, perform the action on that queue callbackQueue.async { @@ -14,14 +17,14 @@ public extension DispatchQueue { } } - static func apollo_returnResultAsyncIfNeeded(on callbackQueue: DispatchQueue?, - action: ((Result) -> Void)?, - result: Result) { + static func returnResultAsyncIfNeeded(on callbackQueue: DispatchQueue?, + action: ((Result) -> Void)?, + result: Result) { guard let action = action else { return } - self.apollo_performAsyncIfNeeded(on: callbackQueue) { + self.performAsyncIfNeeded(on: callbackQueue) { action(result) } } diff --git a/Sources/Apollo/GraphQLHTTPResponseError.swift b/Sources/Apollo/GraphQLHTTPResponseError.swift index 5ac8955ec0..f0f2f3488f 100644 --- a/Sources/Apollo/GraphQLHTTPResponseError.swift +++ b/Sources/Apollo/GraphQLHTTPResponseError.swift @@ -55,7 +55,7 @@ public struct GraphQLHTTPResponseError: Error, LocalizedError { return "[Empty response body]" } - guard let description = String(data: body, encoding: response.textEncoding ?? .utf8) else { + guard let description = String(data: body, encoding: response.apollo.textEncoding ?? .utf8) else { return "[Unreadable response body]" } @@ -69,7 +69,7 @@ public struct GraphQLHTTPResponseError: Error, LocalizedError { return "\(kind.description): \(description)" } else { - return "\(kind.description) (\(response.statusCode) \(response.statusCodeDescription)): \(bodyDescription)" + return "\(kind.description) (\(response.statusCode) \(response.apollo.statusCodeDescription)): \(bodyDescription)" } } } diff --git a/Sources/Apollo/GraphQLSelectionSet.swift b/Sources/Apollo/GraphQLSelectionSet.swift index 30ae00a041..6afbc6ff61 100644 --- a/Sources/Apollo/GraphQLSelectionSet.swift +++ b/Sources/Apollo/GraphQLSelectionSet.swift @@ -1,3 +1,5 @@ +import ApolloCore + public typealias ResultMap = [String: Any?] public protocol GraphQLSelectionSet { @@ -56,7 +58,7 @@ public struct GraphQLField: GraphQLSelection { func cacheKey(with variables: [String: JSONEncodable]?) throws -> String { if let argumentValues = try arguments?.evaluate(with: variables), - argumentValues.isNotEmpty { + argumentValues.apollo.isNotEmpty { let argumentsKey = orderIndependentKey(for: argumentValues) return "\(name)(\(argumentsKey))" } else { diff --git a/Sources/Apollo/HTTPNetworkTransport.swift b/Sources/Apollo/HTTPNetworkTransport.swift index ad38789c74..42bd1043fd 100644 --- a/Sources/Apollo/HTTPNetworkTransport.swift +++ b/Sources/Apollo/HTTPNetworkTransport.swift @@ -173,7 +173,7 @@ public class HTTPNetworkTransport { response: nil, completionHandler: completionHandler) case .success(let (data, httpResponse)): - guard httpResponse.isSuccessful == true else { + guard httpResponse.apollo.isSuccessful == true else { let unsuccessfulError = GraphQLHTTPResponseError(body: data, response: httpResponse, kind: .errorResponse) @@ -226,7 +226,7 @@ public class HTTPNetworkTransport { guard let delegate = self.delegate as? HTTPNetworkTransportGraphQLErrorDelegate, let graphQLErrors = response.parseErrorsOnlyFast(), - graphQLErrors.isNotEmpty else { + graphQLErrors.apollo.isNotEmpty else { completionHandler(.success(response)) return } @@ -391,7 +391,7 @@ public class HTTPNetworkTransport { do { if let files = files, - files.isNotEmpty { + files.apollo.isNotEmpty { let formData = try requestCreator.requestMultipartFormData( for: operation, files: files, diff --git a/Sources/Apollo/HTTPURLResponse+Helpers.swift b/Sources/Apollo/HTTPURLResponse+Helpers.swift index 128e7f60ca..3d845392ee 100644 --- a/Sources/Apollo/HTTPURLResponse+Helpers.swift +++ b/Sources/Apollo/HTTPURLResponse+Helpers.swift @@ -1,16 +1,19 @@ import Foundation +import ApolloCore -extension HTTPURLResponse { +extension HTTPURLResponse: ApolloCompatible {} + +extension ApolloExtension where Base == HTTPURLResponse { var isSuccessful: Bool { - return (200..<300).contains(statusCode) + return (200..<300).contains(base.statusCode) } var statusCodeDescription: String { - return HTTPURLResponse.localizedString(forStatusCode: statusCode) + return HTTPURLResponse.localizedString(forStatusCode: base.statusCode) } var textEncoding: String.Encoding? { - guard let encodingName = textEncodingName else { return nil } + guard let encodingName = base.textEncodingName else { return nil } return String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding(encodingName as CFString))) } diff --git a/Sources/Apollo/InMemoryNormalizedCache.swift b/Sources/Apollo/InMemoryNormalizedCache.swift index 0a840188b9..0e7821e9ec 100644 --- a/Sources/Apollo/InMemoryNormalizedCache.swift +++ b/Sources/Apollo/InMemoryNormalizedCache.swift @@ -14,7 +14,7 @@ public final class InMemoryNormalizedCache: NormalizedCache { self.recordsLock.lock() let records = keys.map { self.records[$0] } self.recordsLock.unlock() - DispatchQueue.apollo_returnResultAsyncIfNeeded(on: callbackQueue, + DispatchQueue.apollo.returnResultAsyncIfNeeded(on: callbackQueue, action: completion, result: .success(records)) } @@ -25,7 +25,7 @@ public final class InMemoryNormalizedCache: NormalizedCache { self.recordsLock.lock() let cacheKeys = self.records.merge(records: records) self.recordsLock.unlock() - DispatchQueue.apollo_returnResultAsyncIfNeeded(on: callbackQueue, + DispatchQueue.apollo.returnResultAsyncIfNeeded(on: callbackQueue, action: completion, result: .success(cacheKeys)) } @@ -38,7 +38,7 @@ public final class InMemoryNormalizedCache: NormalizedCache { return } - DispatchQueue.apollo_returnResultAsyncIfNeeded(on: callbackQueue, + DispatchQueue.apollo.returnResultAsyncIfNeeded(on: callbackQueue, action: completion, result: .success(())) } diff --git a/Sources/Apollo/NetworkTransport.swift b/Sources/Apollo/NetworkTransport.swift index 1584845add..337bb1906f 100644 --- a/Sources/Apollo/NetworkTransport.swift +++ b/Sources/Apollo/NetworkTransport.swift @@ -48,11 +48,11 @@ public extension NetworkTransport { /// The default client version to use when setting up the `clientVersion` property. static var defaultClientVersion: String { var version = String() - if let shortVersion = Bundle.main.shortVersion { + if let shortVersion = Bundle.main.apollo.shortVersion { version.append(shortVersion) } - if let buildNumber = Bundle.main.buildNumber { + if let buildNumber = Bundle.main.apollo.buildNumber { if version.isEmpty { version.append(buildNumber) } else { diff --git a/Sources/Apollo/Promise.swift b/Sources/Apollo/Promise.swift index 28ca10d284..9d829b8153 100644 --- a/Sources/Apollo/Promise.swift +++ b/Sources/Apollo/Promise.swift @@ -19,7 +19,7 @@ func whenAll(_ promises: [Promise], notifyOn queue: DispatchQueue group.notify(queue: queue) { if !rejected { - fulfill(promises.map { $0.result!.value! }) + fulfill(promises.map { $0.result!.apollo.value! }) } } } diff --git a/Sources/Apollo/RequestCreator.swift b/Sources/Apollo/RequestCreator.swift index e607479829..022b3fb8ff 100644 --- a/Sources/Apollo/RequestCreator.swift +++ b/Sources/Apollo/RequestCreator.swift @@ -1,4 +1,5 @@ import Foundation +import ApolloCore public protocol RequestCreator { /// Creates a `GraphQLMap` out of the passed-in operation @@ -70,7 +71,7 @@ extension RequestCreator { hash = operationIdentifier } else { // The codegen needed more info for the correct hash - regenerate it. - hash = operation.queryDocument.sha256Hash + hash = operation.queryDocument.apollo.sha256Hash } body["extensions"] = [ diff --git a/Sources/Apollo/Result+Helpers.swift b/Sources/Apollo/Result+Helpers.swift index 1324c81536..c661310108 100644 --- a/Sources/Apollo/Result+Helpers.swift +++ b/Sources/Apollo/Result+Helpers.swift @@ -1,10 +1,13 @@ import Foundation +import ApolloCore -extension Result { +extension Result: ApolloCompatible {} + +extension ApolloExtension where Base: ResultType, Base.SuccessType: Any { /// Converts the result into an optional value. Returns the value for a `success` case and nil for a `failure` case. - var value: Success? { - switch self { + var value: Base.SuccessType? { + switch base.underlying { case .success(let value): return value case .failure: @@ -14,8 +17,8 @@ extension Result { /// Converts the result into an optional error. Returns the error for a `failure` case and nil for a `success` case. /// Mostly useful for testing to make sure appropriate errors are received. - var error: Failure? { - switch self { + var error: Base.FailureType? { + switch base.underlying { case .success: return nil case .failure(let error): diff --git a/Sources/Apollo/ResultOrPromise.swift b/Sources/Apollo/ResultOrPromise.swift index c2814ecaa2..4bb7b70195 100644 --- a/Sources/Apollo/ResultOrPromise.swift +++ b/Sources/Apollo/ResultOrPromise.swift @@ -35,7 +35,7 @@ func whenAll(_ resultsOrPromises: [ResultOrPromise], notifyOn queu group.notify(queue: queue) { if !rejected { - fulfill(resultsOrPromises.map { $0.result!.value! }) + fulfill(resultsOrPromises.map { $0.result!.apollo.value! }) } } }) diff --git a/Sources/Apollo/URLSessionClient.swift b/Sources/Apollo/URLSessionClient.swift index 565d2da8ab..7476e46a14 100644 --- a/Sources/Apollo/URLSessionClient.swift +++ b/Sources/Apollo/URLSessionClient.swift @@ -1,4 +1,5 @@ import Foundation +import ApolloCore /// A class to handle URL Session calls that will support background execution, /// but still (mostly) use callbacks for its primary method of communication. diff --git a/Sources/ApolloCodegenLib/ApolloExtension.swift b/Sources/ApolloCodegenLib/ApolloExtension.swift deleted file mode 100644 index 4d816c4915..0000000000 --- a/Sources/ApolloCodegenLib/ApolloExtension.swift +++ /dev/null @@ -1,35 +0,0 @@ -import Foundation - -/// Wrapper to allow calls to extended methods and vars as object.apollo.method -public struct ApolloExtension { - - /// The base type in the extension - public let base: Base -} - -/// Protocol to allow calls to extended methods and vars as object.apollo.method -/// -/// NOTE: This does not work with a bunch of stuff involving generic types - those -/// still need to use old-school `apollo_method` naming conventions. -public protocol ApolloCompatible { - /// The base type being extended - associatedtype Base - - /// The `ApolloExtension` object for an instance - var apollo: ApolloExtension { get } - - /// The `ApolloExtension` object for a type - static var apollo: ApolloExtension.Type { get } -} - -// MARK: - Default implementation - -extension ApolloCompatible { - public var apollo: ApolloExtension { - ApolloExtension(base: self) - } - - public static var apollo: ApolloExtension.Type { - ApolloExtension.self - } -} diff --git a/Sources/ApolloCodegenLib/Dictionary+Apollo.swift b/Sources/ApolloCodegenLib/Dictionary+Apollo.swift index 4cf7449a6f..265adb857d 100644 --- a/Sources/ApolloCodegenLib/Dictionary+Apollo.swift +++ b/Sources/ApolloCodegenLib/Dictionary+Apollo.swift @@ -1,12 +1,13 @@ import Foundation +import ApolloCore + +public extension ApolloExtension where Base: DictionaryType, Base.KeyType: RawRepresentable, Base.KeyType.RawValue == String, Base.ValueType: Any { -public extension Dictionary where Key: RawRepresentable, Key.RawValue == String, Value: Any { - /// Transforms a dictionary keyed by a String enum into a dictionary keyed by the /// string values of that enum. - var apollo_toStringKeyedDict: [String: Any] { + var toStringKeyedDict: [String: Any] { var updatedDict = [String: Any]() - for (_, (key, value)) in self.enumerated() { + for (_, (key, value)) in base.underlying.enumerated() { updatedDict[key.rawValue] = value } return updatedDict diff --git a/Sources/ApolloCodegenLib/EnumGenerator.swift b/Sources/ApolloCodegenLib/EnumGenerator.swift index 8753a39a1b..b1dd994b71 100644 --- a/Sources/ApolloCodegenLib/EnumGenerator.swift +++ b/Sources/ApolloCodegenLib/EnumGenerator.swift @@ -76,7 +76,7 @@ public class EnumGenerator { .cases: cases.map { SanitizedEnumValue(astEnumValue: $0) } ] - return try Environment().renderTemplate(string: self.enumTemplate, context: context.apollo_toStringKeyedDict) + return try Environment().renderTemplate(string: self.enumTemplate, context: context.apollo.toStringKeyedDict) } /// A stencil template to use to render enums. diff --git a/Sources/ApolloCodegenLib/FileManager+Apollo.swift b/Sources/ApolloCodegenLib/FileManager+Apollo.swift index 29d3ce0e57..c4e84cbba1 100644 --- a/Sources/ApolloCodegenLib/FileManager+Apollo.swift +++ b/Sources/ApolloCodegenLib/FileManager+Apollo.swift @@ -1,5 +1,6 @@ import Foundation import CommonCrypto +import ApolloCore extension FileManager: ApolloCompatible {} diff --git a/Sources/ApolloCodegenLib/InputObjectGenerator.swift b/Sources/ApolloCodegenLib/InputObjectGenerator.swift index 0935109502..a3c6be034e 100644 --- a/Sources/ApolloCodegenLib/InputObjectGenerator.swift +++ b/Sources/ApolloCodegenLib/InputObjectGenerator.swift @@ -71,7 +71,7 @@ public class InputObjectGenerator { .hasOptionalFields: hasOptionalFields, ] - return try Environment().renderTemplate(string: self.inputObjectTemplate, context: context.apollo_toStringKeyedDict) + return try Environment().renderTemplate(string: self.inputObjectTemplate, context: context.apollo.toStringKeyedDict) } /// A stencil template to use to render enums. diff --git a/Sources/ApolloCodegenLib/StaticString+Apollo.swift b/Sources/ApolloCodegenLib/StaticString+Apollo.swift index 8bd53f3c6e..16cdbd9fb1 100644 --- a/Sources/ApolloCodegenLib/StaticString+Apollo.swift +++ b/Sources/ApolloCodegenLib/StaticString+Apollo.swift @@ -1,4 +1,5 @@ import Foundation +import ApolloCore extension StaticString: ApolloCompatible {} diff --git a/Sources/ApolloCodegenLib/String+Apollo.swift b/Sources/ApolloCodegenLib/String+Apollo.swift index 96df1a317c..807ad004d2 100644 --- a/Sources/ApolloCodegenLib/String+Apollo.swift +++ b/Sources/ApolloCodegenLib/String+Apollo.swift @@ -1,11 +1,10 @@ import Foundation +import ApolloCore enum ApolloStringError: Error { case expectedSuffixMissing(_ suffix: String) } -extension String: ApolloCompatible {} - extension ApolloExtension where Base == String { func droppingSuffix(_ suffix: String) throws -> String { diff --git a/Sources/ApolloCodegenLib/URL+Apollo.swift b/Sources/ApolloCodegenLib/URL+Apollo.swift new file mode 100644 index 0000000000..23723233c6 --- /dev/null +++ b/Sources/ApolloCodegenLib/URL+Apollo.swift @@ -0,0 +1,43 @@ +import Foundation +import ApolloCore + +extension URL: ApolloCompatible {} + +public enum ApolloURLError: Error, LocalizedError { + case fileNameIsEmpty + + public var errorDescription: String? { + switch self { + case .fileNameIsEmpty: + return "The file name for this file URL was empty. Please pass a non-empty string." + } + } +} + +extension ApolloExtension where Base == URL { + + /// - Returns: the URL to the parent folder of the current URL. + public func parentFolderURL() -> URL { + base.deletingLastPathComponent() + } + + /// - Parameter folderName: The name of the child folder to append to the current URL + /// - Returns: The full URL including the appended child folder. + public func childFolderURL(folderName: String) -> URL { + base.appendingPathComponent(folderName, isDirectory: true) + } + + /// Adds the filename to the caller to get the full URL of a file + /// + /// - Parameters: + /// - fileName: The name of the child file, with an extension, for example `"API.swift"`. Note: For hidden files just pass `".filename"`. + /// - Returns: The full URL including the full file. + public func childFileURL(fileName: String) throws -> URL { + guard fileName.apollo.isNotEmpty else { + throw ApolloURLError.fileNameIsEmpty + } + + return base + .appendingPathComponent(fileName, isDirectory: false) + } +} diff --git a/Sources/ApolloCore/ApolloExtension.swift b/Sources/ApolloCore/ApolloExtension.swift new file mode 100644 index 0000000000..3f102ee5e6 --- /dev/null +++ b/Sources/ApolloCore/ApolloExtension.swift @@ -0,0 +1,76 @@ +import Foundation + +/// Wrapper to allow calls to extended methods and vars as object.apollo.method +public struct ApolloExtension { + + /// The base type in the extension + public let base: Base +} + +/// Protocol to allow calls to extended methods and vars as object.apollo.method +/// +/// NOTE: This does not work with a bunch of stuff involving generic types - those +/// still need to use old-school `apollo_method` naming conventions. +public protocol ApolloCompatible { + /// The base type being extended + associatedtype Base + + /// The `ApolloExtension` object for an instance + var apollo: ApolloExtension { get } + + /// The `ApolloExtension` object for a type + static var apollo: ApolloExtension.Type { get } +} + +// MARK: - Default implementation + +extension ApolloCompatible { + public var apollo: ApolloExtension { + ApolloExtension(base: self) + } + + public static var apollo: ApolloExtension.Type { + ApolloExtension.self + } +} + +// MARK: - PAT Wrappers + +/// Provides a PAT interface to `Optional` +public protocol OptionalType: ExpressibleByNilLiteral { + associatedtype WrappedType + var underlying: WrappedType? { get } +} + +extension Optional: OptionalType { + /// Return the value if it exists, otherwise `nil` + public var underlying: Wrapped? { self } +} + +/// Provides a PAT interface to `Result` +public protocol ResultType { + associatedtype SuccessType + associatedtype FailureType: Error + + var underlying: Result { get } +} + +extension Result: ResultType { + + public var underlying: Result { self } +} + + +/// Provides a PAT interface to `Dictionary` +public protocol DictionaryType: ExpressibleByDictionaryLiteral { + associatedtype KeyType: Hashable + associatedtype ValueType + + var underlying: [KeyType: ValueType] { get } +} + +extension Dictionary: DictionaryType { + public var underlying: [Key: Value] { + self + } +} diff --git a/Sources/Apollo/Atomic.swift b/Sources/ApolloCore/Atomic.swift similarity index 100% rename from Sources/Apollo/Atomic.swift rename to Sources/ApolloCore/Atomic.swift diff --git a/Sources/ApolloCore/Collection+Apollo.swift b/Sources/ApolloCore/Collection+Apollo.swift new file mode 100644 index 0000000000..0fedaaebef --- /dev/null +++ b/Sources/ApolloCore/Collection+Apollo.swift @@ -0,0 +1,40 @@ +import Foundation + +// MARK: - Emptiness + Optionality + +public extension ApolloExtension where Base: Collection { + + /// Convenience helper to make `guard` statements more readable + /// + /// - returns: `true` if the collection has contents. + var isNotEmpty: Bool { + return !base.isEmpty + } +} + +extension Array: ApolloCompatible {} +extension Dictionary: ApolloCompatible {} + +public extension ApolloExtension where Base: OptionalType, Base.WrappedType: Collection { + + /// - returns: `true` if the collection is empty or nil + var isEmptyOrNil: Bool { + switch base.underlying { + case .none: + return true + case .some(let collection): + return collection.isEmpty + } + } + + /// - returns: `true` if the collection is non-nil AND has contents. + var isNotEmpty: Bool { + switch base.underlying { + case .none: + return false + case .some(let collection): + return !collection.isEmpty + } + } +} + diff --git a/Sources/ApolloCodegenLib/OptionalBoolean.swift b/Sources/ApolloCore/OptionalBoolean.swift similarity index 56% rename from Sources/ApolloCodegenLib/OptionalBoolean.swift rename to Sources/ApolloCore/OptionalBoolean.swift index 86114d1812..5c0f1359cd 100644 --- a/Sources/ApolloCodegenLib/OptionalBoolean.swift +++ b/Sources/ApolloCore/OptionalBoolean.swift @@ -1,10 +1,12 @@ import Foundation -extension Optional where Wrapped == Bool { +extension Optional: ApolloCompatible {} + +public extension ApolloExtension where Base == Optional { /// The value of the unwrapped `Bool`, or false if optional value is `.none` - var apollo_boolValue: Bool { - switch self { + var boolValue: Bool { + switch base { case .none: return false case .some(let actual): @@ -12,3 +14,4 @@ extension Optional where Wrapped == Bool { } } } + diff --git a/Sources/Apollo/String+SHA.swift b/Sources/ApolloCore/String+SHA.swift similarity index 62% rename from Sources/Apollo/String+SHA.swift rename to Sources/ApolloCore/String+SHA.swift index 3d2b04c687..08a4b7835e 100644 --- a/Sources/Apollo/String+SHA.swift +++ b/Sources/ApolloCore/String+SHA.swift @@ -1,10 +1,13 @@ import Foundation import CommonCrypto -extension String { +extension String: ApolloCompatible {} - var sha256Hash: String { - let data = self.data(using: .utf8)! +extension ApolloExtension where Base == String { + + /// The SHA256 hash of the current string. + public var sha256Hash: String { + let data = base.data(using: .utf8)! var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH)) data.withUnsafeBytes { _ = CC_SHA256($0.baseAddress, CC_LONG(data.count), &hash) diff --git a/Sources/ApolloSQLite/SQLiteNormalizedCache.swift b/Sources/ApolloSQLite/SQLiteNormalizedCache.swift index 2ed9a8ad03..1633f04aa2 100644 --- a/Sources/ApolloSQLite/SQLiteNormalizedCache.swift +++ b/Sources/ApolloSQLite/SQLiteNormalizedCache.swift @@ -117,7 +117,7 @@ extension SQLiteNormalizedCache: NormalizedCache { result = .failure(error) } - DispatchQueue.apollo_returnResultAsyncIfNeeded(on: callbackQueue, + DispatchQueue.apollo.returnResultAsyncIfNeeded(on: callbackQueue, action: completion, result: result) } @@ -140,7 +140,7 @@ extension SQLiteNormalizedCache: NormalizedCache { result = .failure(error) } - DispatchQueue.apollo_returnResultAsyncIfNeeded(on: callbackQueue, + DispatchQueue.apollo.returnResultAsyncIfNeeded(on: callbackQueue, action: completion, result: result) } @@ -154,7 +154,7 @@ extension SQLiteNormalizedCache: NormalizedCache { result = .failure(error) } - DispatchQueue.apollo_returnResultAsyncIfNeeded(on: callbackQueue, + DispatchQueue.apollo.returnResultAsyncIfNeeded(on: callbackQueue, action: completion, result: result) } diff --git a/Sources/ApolloWebSocket/WebSocketTransport.swift b/Sources/ApolloWebSocket/WebSocketTransport.swift index d73049ccde..1558743d94 100644 --- a/Sources/ApolloWebSocket/WebSocketTransport.swift +++ b/Sources/ApolloWebSocket/WebSocketTransport.swift @@ -1,6 +1,7 @@ #if !COCOAPODS import Apollo #endif +import ApolloCore import Starscream import Foundation diff --git a/SwiftScripts/Sources/Codegen/ArgumentSetup.swift b/SwiftScripts/Sources/Codegen/ArgumentSetup.swift index dc084ea425..d5ddb473a7 100644 --- a/SwiftScripts/Sources/Codegen/ArgumentSetup.swift +++ b/SwiftScripts/Sources/Codegen/ArgumentSetup.swift @@ -21,12 +21,12 @@ enum Target { switch self { case .gitHub: return sourceRootURL - .appendingPathComponent("Sources") - .appendingPathComponent("GitHubAPI") + .apollo.childFolderURL(folderName: "Sources") + .apollo.childFolderURL(folderName: "GitHubAPI") case .starWars: return sourceRootURL - .appendingPathComponent("Sources") - .appendingPathComponent("StarWarsAPI") + .apollo.childFolderURL(folderName: "Sources") + .apollo.childFolderURL(folderName: "StarWarsAPI") } } @@ -36,9 +36,9 @@ enum Target { case .starWars: return ApolloCodegenOptions(targetRootURL: targetRootURL) case .gitHub: - let json = targetRootURL.appendingPathComponent("schema.json") - let outputFileURL = targetRootURL.appendingPathComponent("API.swift") - let operationIDsURL = targetRootURL.appendingPathComponent("operationIDs.json") + let json = try! targetRootURL.apollo.childFileURL(fileName: "schema.json") + let outputFileURL = try! targetRootURL.apollo.childFileURL(fileName: "API.swift") + let operationIDsURL = try! targetRootURL.apollo.childFileURL(fileName: "operationIDs.json") return ApolloCodegenOptions(mergeInFieldsFromFragmentSpreads: true, operationIDsURL: operationIDsURL, diff --git a/SwiftScripts/Sources/Codegen/main.swift b/SwiftScripts/Sources/Codegen/main.swift index 2d8b623205..833068a4a5 100644 --- a/SwiftScripts/Sources/Codegen/main.swift +++ b/SwiftScripts/Sources/Codegen/main.swift @@ -7,9 +7,9 @@ let parentFolderOfScriptFile = FileFinder.findParentFolder() // Use that to calculate the source root let sourceRootURL = parentFolderOfScriptFile - .deletingLastPathComponent() // Sources - .deletingLastPathComponent() // SwiftScripts - .deletingLastPathComponent() // apollo-ios + .apollo.parentFolderURL() // Sources + .apollo.parentFolderURL() // SwiftScripts + .apollo.parentFolderURL() // apollo-ios // In a typical app, you'll only need to do this for one target, so you'd // set these up directly within this file. Here, we're using more than one @@ -25,8 +25,8 @@ try FileManager.default.apollo.createFolderIfNeeded(at: targetURL) // Calculate where you want to download the CLI folder. let cliFolderURL = sourceRootURL - .appendingPathComponent("SwiftScripts") - .appendingPathComponent("ApolloCLI") + .apollo.childFolderURL(folderName: "SwiftScripts") + .apollo.childFolderURL(folderName: "ApolloCLI") do { // Actually attempt to generate code. diff --git a/Tests/ApolloCacheDependentTests/FetchQueryTests.swift b/Tests/ApolloCacheDependentTests/FetchQueryTests.swift index 3eaed01fe6..fe2444a56a 100644 --- a/Tests/ApolloCacheDependentTests/FetchQueryTests.swift +++ b/Tests/ApolloCacheDependentTests/FetchQueryTests.swift @@ -438,7 +438,7 @@ class FetchQueryTests: XCTestCase, CacheTesting { let watcher = client1.watch( query: HeroAndFriendsNamesWithIDsQuery(), cachePolicy: .returnCacheDataAndFetch) { result in - if result.value?.source == .some(.server) { + if result.apollo.value?.source == .some(.server) { group.leave() } } @@ -453,7 +453,7 @@ class FetchQueryTests: XCTestCase, CacheTesting { let watcher = client2.watch( query: HeroAndFriendsNamesWithIDsQuery(), cachePolicy: .returnCacheDataAndFetch) { result in - if result.value?.source == .some(.server) { + if result.apollo.value?.source == .some(.server) { group.leave() } } diff --git a/Tests/ApolloCodegenTests/ASTParsingTests.swift b/Tests/ApolloCodegenTests/ASTParsingTests.swift index c3a0c7552c..1c32e36614 100644 --- a/Tests/ApolloCodegenTests/ASTParsingTests.swift +++ b/Tests/ApolloCodegenTests/ASTParsingTests.swift @@ -174,7 +174,7 @@ mutation CreateAwesomeReview {\n createReview(episode: JEDI, review: {stars: 10 XCTAssertEqual(outerField.responseName, "createReview") XCTAssertEqual(outerField.fieldName, "createReview") XCTAssertEqual(outerField.typeNode, .named("Review")) - XCTAssertFalse(outerField.isDeprecated.apollo_boolValue) + XCTAssertFalse(outerField.isDeprecated.apollo.boolValue) XCTAssertFalse(outerField.isConditional) let fragmentSpreads = try XCTUnwrap(outerField.fragmentSpreads) XCTAssertTrue(fragmentSpreads.isEmpty) diff --git a/Tests/ApolloCodegenTests/CodegenExtensionTests.swift b/Tests/ApolloCodegenTests/CodegenExtensionTests.swift index 01a3e14845..0678406856 100644 --- a/Tests/ApolloCodegenTests/CodegenExtensionTests.swift +++ b/Tests/ApolloCodegenTests/CodegenExtensionTests.swift @@ -15,13 +15,13 @@ class CodegenExtensionTests: XCTestCase { func testOptionalBoolean() { var optionalBoolean: Bool? = nil - XCTAssertFalse(optionalBoolean.apollo_boolValue) + XCTAssertFalse(optionalBoolean.apollo.boolValue) optionalBoolean = true - XCTAssertTrue(optionalBoolean.apollo_boolValue) + XCTAssertTrue(optionalBoolean.apollo.boolValue) optionalBoolean = false - XCTAssertFalse(optionalBoolean.apollo_boolValue) + XCTAssertFalse(optionalBoolean.apollo.boolValue) } // MARK: String diff --git a/Tests/ApolloCodegenTests/URLExtensionsTests.swift b/Tests/ApolloCodegenTests/URLExtensionsTests.swift new file mode 100644 index 0000000000..dc746056cc --- /dev/null +++ b/Tests/ApolloCodegenTests/URLExtensionsTests.swift @@ -0,0 +1,71 @@ +// +// URLExtensionsTests.swift +// ApolloCodegenTests +// +// Created by Ellen Shapiro on 6/7/20. +// Copyright © 2020 Apollo GraphQL. All rights reserved. +// + +import Foundation +import XCTest +import ApolloCodegenLib +import ApolloCore + +class URLExtensionsTests: XCTestCase { + + func testGettingParentFolderURL() { + let apolloCodegenTests = FileFinder.findParentFolder() + + let expectedParent = CodegenTestHelper.sourceRootURL() + .appendingPathComponent("Tests") + + let parent = apolloCodegenTests.apollo.parentFolderURL() + XCTAssertEqual(parent, expectedParent) + } + + func testGettingChildFolderURL() { + let testsFolderURL = CodegenTestHelper.sourceRootURL() + .appendingPathComponent("Tests") + + let expectedChild = FileFinder.findParentFolder() + + let child = testsFolderURL.apollo.childFolderURL(folderName: "ApolloCodegenTests") + XCTAssertEqual(child, expectedChild) + } + + func testGettingChildFileURL() throws { + let apolloCodegenTests = FileFinder.findParentFolder() + + let expectedFileURL = URL(fileURLWithPath: #file) + + let fileURL = try apolloCodegenTests.apollo.childFileURL(fileName: "URLExtensionsTests.swift") + + XCTAssertEqual(fileURL, expectedFileURL) + } + + func testGettingChildFileURLWithEmptyFilenameThrows() { + let starWars = CodegenTestHelper.starWarsFolderURL() + + do { + _ = try starWars.apollo.childFileURL(fileName: "") + XCTFail("That should have thrown") + } catch { + switch error { + case ApolloURLError.fileNameIsEmpty: + // This is what we want + break + default: + XCTFail("Unexpected error: \(error)") + } + } + } + + func testGettingHiddenChildFileURL() throws { + let url = CodegenTestHelper.apolloFolderURL() + + let expectedFile = CodegenTestHelper.shasumFileURL() + let child = try url.apollo.childFileURL(fileName: ".shasum") + + XCTAssertEqual(child, expectedFile) + } +} diff --git a/Tests/ApolloTests/BatchedLoadTests.swift b/Tests/ApolloTests/BatchedLoadTests.swift index 2f040c1bcf..8e3a812a38 100644 --- a/Tests/ApolloTests/BatchedLoadTests.swift +++ b/Tests/ApolloTests/BatchedLoadTests.swift @@ -19,7 +19,7 @@ private final class MockBatchedNormalizedCache: NormalizedCache { DispatchQueue.global().asyncAfter(deadline: .now() + .milliseconds(1)) { let records = keys.map { self.records[$0] } - DispatchQueue.apollo_returnResultAsyncIfNeeded(on: callbackQueue, + DispatchQueue.apollo.returnResultAsyncIfNeeded(on: callbackQueue, action: completion, result: .success(records)) } @@ -30,7 +30,7 @@ private final class MockBatchedNormalizedCache: NormalizedCache { completion: @escaping (Result, Error>) -> Void) { DispatchQueue.global().asyncAfter(deadline: .now() + .milliseconds(1)) { let changedKeys = self.records.merge(records: records) - DispatchQueue.apollo_returnResultAsyncIfNeeded(on: callbackQueue, + DispatchQueue.apollo.returnResultAsyncIfNeeded(on: callbackQueue, action: completion, result: .success(changedKeys)) } @@ -39,7 +39,7 @@ private final class MockBatchedNormalizedCache: NormalizedCache { func clear(callbackQueue: DispatchQueue?, completion: ((Result) -> Void)?) { DispatchQueue.global().asyncAfter(deadline: .now() + .milliseconds(1)) { self.records.clear() - DispatchQueue.apollo_returnResultAsyncIfNeeded(on: callbackQueue, + DispatchQueue.apollo.returnResultAsyncIfNeeded(on: callbackQueue, action: completion, result: .success(())) } diff --git a/Tests/ApolloTests/PromiseTests.swift b/Tests/ApolloTests/PromiseTests.swift index a601a2c803..cebfca278f 100644 --- a/Tests/ApolloTests/PromiseTests.swift +++ b/Tests/ApolloTests/PromiseTests.swift @@ -10,14 +10,14 @@ class PromiseTests: XCTestCase { func testResultOfFulfilledPromise() { let promise = Promise(fulfilled: "foo") - XCTAssertEqual(promise.result?.value, "foo") + XCTAssertEqual(promise.result?.apollo.value, "foo") } func testResultOfRejectedPromise() { let promise = Promise(rejected: TestError()) - XCTAssertNil(promise.result?.value) - XCTAssert(promise.result?.error is TestError) + XCTAssertNil(promise.result?.apollo.value) + XCTAssert(promise.result?.apollo.error is TestError) } func testWaitForResultOfFulfilledPromise() throws { @@ -65,7 +65,7 @@ class PromiseTests: XCTestCase { fulfill("foo") } - XCTAssertEqual(promise.result?.value, "foo") + XCTAssertEqual(promise.result?.apollo.value, "foo") } func testWaitForResultOfImmediatelyFulfilledPromise() throws { @@ -81,7 +81,7 @@ class PromiseTests: XCTestCase { reject(TestError()) } - XCTAssert(promise.result?.error is TestError) + XCTAssert(promise.result?.apollo.error is TestError) } func testWaitForResultOfImmediatelyRejectedPromise() { diff --git a/Tests/ApolloTests/ResultOrPromiseTests.swift b/Tests/ApolloTests/ResultOrPromiseTests.swift index 09603e44d7..67cfbac88f 100644 --- a/Tests/ApolloTests/ResultOrPromiseTests.swift +++ b/Tests/ApolloTests/ResultOrPromiseTests.swift @@ -10,27 +10,27 @@ class ResultOrPromiseTests: XCTestCase { func testSuccessResult() { let resultOrPromise = ResultOrPromise.result(.success("foo")) - XCTAssertEqual(resultOrPromise.result?.value, "foo") + XCTAssertEqual(resultOrPromise.result?.apollo.value, "foo") } func testFailureResult() { let resultOrPromise = ResultOrPromise.result(.failure(TestError())) - XCTAssertNil(resultOrPromise.result?.value) - XCTAssert(resultOrPromise.result?.error is TestError) + XCTAssertNil(resultOrPromise.result?.apollo.value) + XCTAssert(resultOrPromise.result?.apollo.error is TestError) } func testResultOfFulfilledPromise() { let resultOrPromise = ResultOrPromise.promise(Promise(fulfilled: "foo")) - XCTAssertEqual(resultOrPromise.result?.value, "foo") + XCTAssertEqual(resultOrPromise.result?.apollo.value, "foo") } func testResultOfRejectedPromise() { let resultOrPromise = ResultOrPromise.promise(Promise(rejected: TestError())) - XCTAssertNil(resultOrPromise.result?.value) - XCTAssert(resultOrPromise.result?.error is TestError) + XCTAssertNil(resultOrPromise.result?.apollo.value) + XCTAssert(resultOrPromise.result?.apollo.error is TestError) } func testWaitForSuccessResult() throws { diff --git a/Tests/ApolloTests/URLSessionClientTests.swift b/Tests/ApolloTests/URLSessionClientTests.swift index 9b690f075e..59002cf2c6 100644 --- a/Tests/ApolloTests/URLSessionClientTests.swift +++ b/Tests/ApolloTests/URLSessionClientTests.swift @@ -1,5 +1,6 @@ import XCTest @testable import Apollo +import ApolloCore class URLSessionClientLiveTests: XCTestCase {