Created
September 29, 2021 23:57
-
-
Save djbe/1ce35bbd739521787ff10fc09c4d886d to your computer and use it in GitHub Desktop.
Migrate Alamofire5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -Eeuo pipefail | |
shopt -s extglob | |
update_swift_files() { | |
find . -name '*.swift' -print0 -o -type d \( -path .git -o -name Pods -o -name .build -o -name build -o -name Rome -o -name fastlane -o -name Generated \) -prune | xargs -0 perl -0pi -e "$@" | |
} | |
fix_dataresponse() { | |
echo "Fixing DataResponse..." | |
update_swift_files 's/DataResponse<([^,<>]+?)>/DataResponse<$1, Swift.Error>/g' | |
} | |
fix_result() { | |
echo "Fixing Result..." | |
update_swift_files 's/Result<([^,<>]+?<[^>]+?>[^,>]*?)>/Result<$1, Swift.Error>/g' | |
update_swift_files 's/Result<([^,<>]+?)>/Result<$1, Swift.Error>/g' | |
update_swift_files 's/Alamofire.Result/Result/g' | |
} | |
fix_request() { | |
echo "Fixing request calls..." | |
update_swift_files 's/requestJSONDecodable/requestDecodable/g' | |
update_swift_files 's/(?!func )requestInsert\((.+?),(\s+)type:(.+?),/requestInsert($1,$2of:$3,/gms' | |
update_swift_files 's/(?!func )requestInsert\(([^()]+?|[^()]+?\([^()]+?\)[^()]+?),(\s+db:([^()]+?|[^()]+?\([^()]+?\)[^()]+?),)?(\s+queue:([^()]+?|[^()]+?\([^()]+?\)[^()]+?),)?(\s+jsonSerializer:([^()]+?|[^()]+?\([^()]+?\)[^()]+?),)(\s+of:([^()]+?|[^()]+?\([^()]+?\)[^()]+?),)/requestInsert($1,$8$2$4\/* TODO: other params? *\//gms' | |
} | |
fix_api_client() { | |
echo "Fixing Client implementations..." | |
update_swift_files 's/\n([ \t]+)([^\n]*?(var|let)) sessionManager = SessionManager\(\)\n/\n$1$2 session = Session()\n/g' | |
update_swift_files 's/\n([ \t]+)([^\n]*?(var|let)) sessionManager = SessionManager\(\)\.then \{\n[^}]*?\}/\n$1private let interceptor = AuthenticationInterceptor(authenticator: OAuth2Authenticator(), credential: OAuth2Grant.grant)\n$1$2 session: Session = Session(interceptor: interceptor)/gms' | |
update_swift_files 's/NukeAlamofirePlugin\.AlamofireDataLoader\(manager: self\.sessionManager\)/NukeAlamofirePlugin.AlamofireDataLoader(session: self.session)/g' | |
update_swift_files 's/func nukeOptions.*? -> ImageLoadingOptions \{/func nukeOptions(placeholder: PlatformImage? = nil, transition: ImageLoadingOptions.Transition? = nil, failureImage: PlatformImage? = nil, failureImageTransition: ImageLoadingOptions.Transition? = nil, contentModes: ImageLoadingOptions.ContentModes? = nil) -> ImageLoadingOptions {/g' | |
update_swift_files 's/static func extract<T>\(from response: DataResponse<T>, error: Error\) -> Error \{/static func extract<T>(from response: DataResponse<T, Error>, error: Error) -> Error {/g' | |
update_swift_files 's/queue: DispatchQueue\? = nil,(\s*)jsonSerializer: DataResponseSerializer<Any> = DataRequest.jsonResponseSerializer\(\),/queue: DispatchQueue = .main,$1jsonOptions: JSONSerialization.ReadingOptions = .allowFragments,$1jsonTransformer: \@escaping (Any) throws -> Any = { \$0 },/gms' | |
} | |
fix_router() { | |
echo "Fixing Router implementations..." | |
update_swift_files 's/var headers: \[String: String\] \{/var headers: HTTPHeaders? \{/g' | |
} | |
fix_retry_handler() { | |
HANDLER_FILE="Application/Sources/Network/OAuth2RetryHandler.swift" | |
if [ ! -f "$HANDLER_FILE" ]; then return; fi | |
echo "Fixing retry handler..." | |
sed -i '' '/import p2_OAuth2/q' "$HANDLER_FILE" | |
cat >>"$HANDLER_FILE" <<EOL | |
extension OAuth2: AuthenticationCredential { | |
public var requiresRefresh: Bool { | |
!hasUnexpiredAccessToken() | |
} | |
} | |
final class OAuth2Authenticator: Authenticator { | |
func apply(_ credential: OAuth2, to urlRequest: inout URLRequest) { | |
try? urlRequest.sign(with: credential) | |
} | |
func refresh(_ credential: OAuth2, for session: Session, completion: @escaping (Result<OAuth2, Error>) -> Void) { | |
credential.authorize { _, error in | |
if let error = error { | |
completion(.failure(error)) | |
if error.isSessionExpired { | |
Notification.SessionExpired().post() | |
} | |
} else { | |
completion(.success(credential)) | |
} | |
} | |
} | |
func didRequest(_ urlRequest: URLRequest, with response: HTTPURLResponse, failDueToAuthenticationError error: Error) -> Bool { | |
response.statusCode == 401 | |
} | |
func isRequest(_ urlRequest: URLRequest, authenticatedWith credential: OAuth2) -> Bool { | |
urlRequest.headers["Authorization"] == credential.accessToken.flatMap { "Bearer \(\$0)" } | |
} | |
} | |
extension OAuth2Error { | |
var isSessionExpired: Bool { | |
switch self { | |
case .accessDenied, | |
.forbidden, | |
.invalidGrant, | |
.invalidScope, | |
.noPasswordGrantDelegate, | |
.unauthorizedClient: | |
return true | |
case .generic, | |
.nsError, | |
.invalidURLComponents, | |
.noClientId, | |
.noClientSecret, | |
.noRedirectURL, | |
.noUsername, | |
.noPassword, | |
.alreadyAuthorizing, | |
.noAuthorizationContext, | |
.invalidAuthorizationContext, | |
.invalidRedirectURL, | |
.noAccessToken, | |
.noRefreshToken, | |
.noRegistrationURL, | |
.invalidLoginController, | |
.notUsingTLS, | |
.unableToOpenAuthorizeURL, | |
.invalidRequest, | |
.requestCancelled, | |
.noTokenType, | |
.unsupportedTokenType, | |
.noDataInResponse, | |
.prerequisiteFailed, | |
.missingState, | |
.invalidState, | |
.jsonParserError, | |
.utf8EncodeError, | |
.utf8DecodeError, | |
.wrongUsernamePassword, | |
.unsupportedResponseType, | |
.serverError, | |
.temporarilyUnavailable, | |
.responseError: | |
return false | |
} | |
} | |
} | |
EOL | |
} | |
fix_then() { | |
echo "Fixing Then..." | |
update_swift_files 's/extension SessionManager: Then \{\}\n//gms' | |
} | |
fix_nuke() { | |
echo "Fixing Nuke..." | |
update_swift_files 's/(\.loadImage\(\s*with:[^{]+?\{[^}]*?)\s_,\s_\sin/$1 _ in/gms' | |
update_swift_files 's/(\.loadImage\(\s*with:[^{]+?\{[^}]*?)\s\w+,\s\w+\sin/$1 result in/gms' | |
update_swift_files 's/response\?\.image/result.value?.image/gms' | |
update_swift_files 's/if let key = cacheKey\(for: request\) \{[^}]*imageRequest[^}]*\}/imageRequest.options.filteredURL = cacheKey(for: request)/gms' | |
} | |
echo "Resetting git..." | |
git checkout -- Application | |
echo "Fixing project..." | |
fix_dataresponse | |
fix_result | |
fix_request | |
fix_api_client | |
fix_router | |
fix_retry_handler | |
fix_then | |
fix_nuke | |
echo "Done!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment