Skip to content

Commit

Permalink
Chore/Remove PovioKit dependency (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
borut-t authored Jun 5, 2024
1 parent b92c5f9 commit 86c0442
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 144 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
Package.resolved
68 changes: 0 additions & 68 deletions Package.resolved

This file was deleted.

14 changes: 4 additions & 10 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
// swift-tools-version: 5.8
// swift-tools-version: 5.7
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "PovioKitAuth",
platforms: [
.iOS(.v13),
.macOS(.v13)
.iOS(.v13)
],
products: [
.library(name: "PovioKitAuthCore", targets: ["PovioKitAuthCore"]),
Expand All @@ -17,16 +16,13 @@ let package = Package(
.library(name: "PovioKitAuthLinkedIn", targets: ["PovioKitAuthLinkedIn"])
],
dependencies: [
.package(url: "https://github.com/poviolabs/PovioKit", .upToNextMajor(from: "3.0.0")),
.package(url: "https://github.com/google/GoogleSignIn-iOS", .upToNextMajor(from: "7.0.0")),
.package(url: "https://github.com/facebook/facebook-ios-sdk", .upToNextMajor(from: "17.0.0")),
],
targets: [
.target(
name: "PovioKitAuthCore",
dependencies: [
.product(name: "PovioKitPromise", package: "PovioKit"),
],
dependencies: [],
path: "Sources/Core",
resources: [.copy("../../Resources/PrivacyInfo.xcprivacy")]
),
Expand All @@ -51,7 +47,6 @@ let package = Package(
name: "PovioKitAuthFacebook",
dependencies: [
"PovioKitAuthCore",
.product(name: "PovioKitCore", package: "PovioKit"),
.product(name: "FacebookLogin", package: "facebook-ios-sdk")
],
path: "Sources/Facebook",
Expand All @@ -60,8 +55,7 @@ let package = Package(
.target(
name: "PovioKitAuthLinkedIn",
dependencies: [
"PovioKitAuthCore",
.product(name: "PovioKitNetworking", package: "PovioKit")
"PovioKitAuthCore"
],
path: "Sources/LinkedIn",
resources: [.copy("../../Resources/PrivacyInfo.xcprivacy")]
Expand Down
3 changes: 1 addition & 2 deletions Sources/Facebook/FacebookAuthenticator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import Foundation
import FacebookLogin
import PovioKitCore
import PovioKitAuthCore

public final class FacebookAuthenticator {
Expand Down Expand Up @@ -106,7 +105,7 @@ private extension FacebookAuthenticator {

do {
let data = try JSONSerialization.data(withJSONObject: response, options: [])
let object = try data.decode(GraphResponse.self, with: decoder)
let object = try decoder.decode(GraphResponse.self, from: data)

let authResponse = Response(
userId: object.id,
Expand Down
23 changes: 0 additions & 23 deletions Sources/LinkedIn/API/EndpointEncodable.swift

This file was deleted.

5 changes: 2 additions & 3 deletions Sources/LinkedIn/API/LinkedInAPI+Endpoints.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,14 @@
//

import Foundation
import PovioKitNetworking

extension LinkedInAPI {
enum Endpoints: EndpointEncodable {
enum Endpoints {
case accessToken
case profile
case email

var path: Path {
var path: String {
switch self {
case .accessToken:
return "accessToken"
Expand Down
96 changes: 60 additions & 36 deletions Sources/LinkedIn/API/LinkedInAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,36 @@
//

import Foundation
import PovioKitNetworking

public final class LinkedInAPI {
private let client: AlamofireNetworkClient
public struct LinkedInAPI {
private let client: HttpClient = .init()

public init(client: AlamofireNetworkClient = .init()) {
self.client = client
}
public init() {}
}

public extension LinkedInAPI {
func login(with request: LinkedInAuthRequest) async throws -> LinkedInAuthResponse {
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
let jsonData = try encoder.encode(request)
let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: [])
guard let jsonDict = jsonObject as? [String: Any] else {
throw Error.invalidRequest
}

guard var components = URLComponents(string: Endpoints.accessToken.url) else {
throw Error.invalidUrl
}

let queryItems: [URLQueryItem] = jsonDict.compactMap { key, value in
(value as? String).map { .init(name: key, value: $0) }
}

components.queryItems = queryItems
guard let url = components.url else {
throw Error.invalidUrl
}

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
decoder.dateDecodingStrategy = .custom { decoder in
Expand All @@ -27,53 +45,59 @@ public extension LinkedInAPI {
return Date().addingTimeInterval(TimeInterval(secondsRemaining))
}

let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
let response = try await client.request(
method: "POST",
url: url,
headers: ["Content-Type": "application/x-www-form-urlencoded"],
decodeTo: LinkedInAuthResponse.self,
with: decoder
)

return try await client
.request(
method: .post,
endpoint: Endpoints.accessToken,
encode: request,
parameterEncoder: .urlEncoder(encoder: encoder)
)
.validate()
.decode(LinkedInAuthResponse.self, decoder: decoder)
.asAsync
return response
}

func loadProfile(with request: LinkedInProfileRequest) async throws -> LinkedInProfileResponse {
guard let url = URL(string: Endpoints.profile.url) else { throw Error.invalidUrl }

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
decoder.dateDecodingStrategy = .iso8601

return try await client
.request(
method: .get,
endpoint: Endpoints.profile,
headers: ["Authorization": "Bearer \(request.token)"]
)
.validate()
.decode(LinkedInProfileResponse.self, decoder: decoder)
.asAsync
let response = try await client.request(
method: "GET",
url: url,
headers: ["Authorization": "Bearer \(request.token)"],
decodeTo: LinkedInProfileResponse.self,
with: decoder
)

return response
}

func loadEmail(with request: LinkedInProfileRequest) async throws -> LinkedInEmailValueResponse {
return try await client
.request(
method: .get,
endpoint: Endpoints.email,
headers: ["Authorization": "Bearer \(request.token)"])
.validate()
.decode(LinkedInEmailResponse.self)
.compactMap { $0.elements.first?.handle }
.asAsync
guard let url = URL(string: Endpoints.email.url) else { throw Error.invalidUrl }

let response = try await client.request(
method: "GET",
url: url,
headers: ["Authorization": "Bearer \(request.token)"],
decodeTo: LinkedInEmailResponse.self
)

guard let emailObject = response.elements.first?.handle else {
throw Error.invalidResponse
}

return emailObject
}
}

// MARK: - Error
public extension LinkedInAPI {
enum Error: Swift.Error {
case missingParameters
case invalidUrl
case invalidRequest
case invalidResponse
}
}
32 changes: 32 additions & 0 deletions Sources/LinkedIn/Core/HttpClient.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// HttpClient.swift
// PovioKitAuth
//
// Created by Borut Tomazin on 22/05/2024.
// Copyright © 2024 Povio Inc. All rights reserved.
//

import Foundation

struct HttpClient {
func request<D: Decodable>(
method: String,
url: URL,
headers: [String: String]?,
decodeTo decode: D.Type,
with decoder: JSONDecoder = .init()
) async throws -> D {
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = method
urlRequest.allHTTPHeaderFields = headers

let (data, response) = try await URLSession.shared.data(for: urlRequest)

if let httpResponse = response as? HTTPURLResponse,
!(200...299).contains(httpResponse.statusCode) {
throw NSError(domain: "HTTP Error", code: httpResponse.statusCode, userInfo: nil)
}

return try decoder.decode(decode, from: data)
}
}
18 changes: 18 additions & 0 deletions Sources/LinkedIn/Core/URL+PovioKitAuth.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// URL+PovioKitAuth.swift
// PovioKitAuth
//
// Created by Borut Tomazin on 22/05/2024.
// Copyright © 2024 Povio Inc. All rights reserved.
//

import Foundation

extension URL: ExpressibleByStringLiteral {
public init(stringLiteral value: String) {
guard let url = URL(string: value) else {
fatalError("Invalid URL string!")
}
self = url
}
}
2 changes: 0 additions & 2 deletions Sources/LinkedIn/WebView/LinkedInWebView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
// Copyright © 2024 Povio Inc. All rights reserved.
//

import PovioKitCore
import SwiftUI
import WebKit

Expand Down Expand Up @@ -40,7 +39,6 @@ public struct LinkedInWebView: UIViewRepresentable {
public func updateUIView(_ uiView: UIViewType, context: Context) {
guard let webView = uiView as? WKWebView else { return }
guard let authURL = configuration.authorizationUrl(state: requestState) else {
Logger.error("Failed to geet auth url!")
dismiss()
return
}
Expand Down

0 comments on commit 86c0442

Please sign in to comment.