diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index a23541f..f9a3e62 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -9,35 +9,28 @@ on: pull_request: branches: - main - push: - branches: - - main jobs: - swiftlint: - runs-on: ubuntu-latest - container: - image: swift:5.10-noble + lint: + runs-on: macos-latest steps: - - uses: actions/checkout@v2 - - name: Set Up swiftlint - run: | - sudo apt-get update && sudo apt-get install -y unzip curl - unzip ci/swiftlint.zip -d /usr/local/bin/ - chmod +x /usr/local/bin/swiftlint - - name: Lint Using swiftlint + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Set Up SwiftLint + run: brew install swiftlint + + - name: Lint Using SwiftLint run: swiftlint lint --strict . - swiftformat: - runs-on: ubuntu-latest - container: - image: swift:5.10-noble + format: + runs-on: macos-latest steps: - - uses: actions/checkout@v2 - - name: Set Up swiftformat - run: | - sudo apt-get update && sudo apt-get install -y unzip curl - unzip ci/swiftformat.zip -d /usr/local/bin/ - chmod +x /usr/local/bin/swiftformat - - name: Lint Using swiftformat - run: swiftformat --lint . + - name: Checkout Repository + uses: actions/checkout@v4 + + - name: Set Up swift-format + run: brew install swift-format + + - name: Lint Using swift-format + run: swift format lint -r . \ No newline at end of file diff --git a/.swift-format b/.swift-format new file mode 100644 index 0000000..ca3eb42 --- /dev/null +++ b/.swift-format @@ -0,0 +1,7 @@ +{ + "version": 1, + "lineLength": 120, + "indentation": { + "spaces": 4 + } +} \ No newline at end of file diff --git a/.swiftformat b/.swiftformat deleted file mode 100644 index b617f3f..0000000 --- a/.swiftformat +++ /dev/null @@ -1,2 +0,0 @@ ---disable wrapMultilineStatementBraces ---commas inline diff --git a/.swiftlint.yml b/.swiftlint.yml index 8fd1f55..31bfe38 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -6,5 +6,6 @@ disabled_rules: - function_body_length - file_length - non_optional_string_data_conversion + - trailing_comma excluded: - .build diff --git a/Package.swift b/Package.swift index 4192f0f..2182228 100644 --- a/Package.swift +++ b/Package.swift @@ -6,7 +6,7 @@ let package = Package( name: "VoltaserveCore", platforms: [ .iOS(.v13), - .macOS(.v12) + .macOS(.v12), ], products: [ .library( @@ -24,6 +24,6 @@ let package = Package( dependencies: ["VoltaserveCore"], path: "Tests", resources: [.process("Resources")] - ) + ), ] ) diff --git a/Sources/Account.swift b/Sources/Account.swift index 4dc43df..e3ca68c 100644 --- a/Sources/Account.swift +++ b/Sources/Account.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif diff --git a/Sources/Common/Error.swift b/Sources/Common/Error.swift index b4a344c..900a77b 100644 --- a/Sources/Common/Error.swift +++ b/Sources/Common/Error.swift @@ -21,7 +21,7 @@ public struct VOErrorResponse: Decodable, Error { } public enum Code: String, Codable, CaseIterable { - /* API */ + // API case groupNotFound = "group_not_found" case fileNotFound = "file_not_found" case invalidPath = "invalid_path" @@ -71,7 +71,7 @@ public struct VOErrorResponse: Decodable, Error { case invalidApiKey = "invalid_api_key" case pathVariablesAndBodyParametersNotConsistent = "path_variables_and_body_parameters_not_consistent" - /* IdP */ + // IdP case usernameUnavailable = "username_unavailable" case resourceNotFound = "resource_not_found" case invalidUsernameOrPassword = "invalid_username_or_password" @@ -84,11 +84,11 @@ public struct VOErrorResponse: Decodable, Error { case unsupportedGrantType = "unsupported_grant_type" case passwordValidationFailed = "password_validation_failed" - /* Common */ + // Common case internalServerError = "internal_server_error" case requestValidationError = "request_validation_error" - /* Unexpected */ + // Unexpected case unknown public init(rawValue: String) { diff --git a/Sources/Common/Request.swift b/Sources/Common/Request.swift index e716c20..f80aa53 100644 --- a/Sources/Common/Request.swift +++ b/Sources/Common/Request.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif @@ -30,7 +31,7 @@ func handleJSONResponse( return } let stringData = String(data: data, encoding: .utf8) - if (200 ... 299).contains(httpResponse.statusCode) { + if (200...299).contains(httpResponse.statusCode) { do { let result = try JSONDecoder().decode(T.self, from: data) continuation.resume(returning: result) @@ -44,6 +45,7 @@ func handleJSONResponse( } } else { if let stringData { + // swift-format-ignore // swiftlint:disable:next line_length print("Request to URL: \(httpResponse.url!), failed with status code: \(httpResponse.statusCode), data: \(stringData)") } else { @@ -71,7 +73,7 @@ func handleDataResponse( continuation.resume(throwing: VONoDataError()) return } - if (200 ... 299).contains(httpResponse.statusCode) { + if (200...299).contains(httpResponse.statusCode) { continuation.resume(returning: data) } else { handleErrorResponse(continuation: continuation, data: data) @@ -96,7 +98,7 @@ func handleEmptyResponse( continuation.resume(throwing: VONoDataError()) return } - if (200 ... 299).contains(httpResponse.statusCode) { + if (200...299).contains(httpResponse.statusCode) { continuation.resume() } else { handleErrorResponse(continuation: continuation, data: data) diff --git a/Sources/Common/URLRequest+AuthHeader.swift b/Sources/Common/URLRequest+AuthHeader.swift index 26e495f..cc99ee2 100644 --- a/Sources/Common/URLRequest+AuthHeader.swift +++ b/Sources/Common/URLRequest+AuthHeader.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif diff --git a/Sources/Common/URLRequest+JSON.swift b/Sources/Common/URLRequest+JSON.swift index 417fbc8..7b0a87c 100644 --- a/Sources/Common/URLRequest+JSON.swift +++ b/Sources/Common/URLRequest+JSON.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif diff --git a/Sources/File+Wait.swift b/Sources/File+Wait.swift index 43e00bb..63632f1 100644 --- a/Sources/File+Wait.swift +++ b/Sources/File+Wait.swift @@ -5,8 +5,8 @@ import Foundation -public extension VOFile { - func wait(_ id: String, sleepSeconds: UInt32 = 1) async throws -> Entity { +extension VOFile { + public func wait(_ id: String, sleepSeconds: UInt32 = 1) async throws -> Entity { var file: Entity repeat { file = try await fetch(id) diff --git a/Sources/File.swift b/Sources/File.swift index 71f7a76..9350691 100644 --- a/Sources/File.swift +++ b/Sources/File.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif @@ -132,11 +133,12 @@ public struct VOFile { public func fetchSegmentedThumbnail(_ id: String, page: Int, fileExtension: String) async throws -> Data { try await withCheckedThrowingContinuation { continuation in - var request = URLRequest(url: urlForSegmentedThumbnail( - id, - page: page, - fileExtension: String(fileExtension.dropFirst()) - )) + var request = URLRequest( + url: urlForSegmentedThumbnail( + id, + page: page, + fileExtension: String(fileExtension.dropFirst()) + )) request.httpMethod = "GET" request.appendAuthorizationHeader(accessToken) let task = URLSession.shared.dataTask(with: request) { data, response, error in @@ -526,7 +528,7 @@ public struct VOFile { urlComponents.queryItems = [ .init(name: "type", value: FileType.file.rawValue), .init(name: "workspace_id", value: options.workspaceID), - .init(name: "name", value: options.name) + .init(name: "name", value: options.name), ] if let parentID = options.parentID { urlComponents.queryItems?.append(.init(name: "parent_id", value: parentID)) @@ -540,7 +542,7 @@ public struct VOFile { urlComponents.queryItems = [ .init(name: "type", value: FileType.folder.rawValue), .init(name: "workspace_id", value: options.workspaceID), - .init(name: "name", value: options.name) + .init(name: "name", value: options.name), ] if let parentID = options.parentID { urlComponents.queryItems?.append(URLQueryItem(name: "parent_id", value: parentID)) @@ -550,28 +552,23 @@ public struct VOFile { } public func urlForOriginal(_ id: String, fileExtension: String) -> URL { - URL(string: "\(urlForID(id))/original.\(fileExtension)?" + - "access_token=\(accessToken)")! + URL(string: "\(urlForID(id))/original.\(fileExtension)?access_token=\(accessToken)")! } public func urlForPreview(_ id: String, fileExtension: String) -> URL { - URL(string: "\(urlForID(id))/preview.\(fileExtension)?" + - "access_token=\(accessToken)")! + URL(string: "\(urlForID(id))/preview.\(fileExtension)?access_token=\(accessToken)")! } public func urlForThumbnail(_ id: String, fileExtension: String) -> URL { - URL(string: "\(urlForID(id))/thumbnail.\(fileExtension)?" + - "access_token=\(accessToken)")! + URL(string: "\(urlForID(id))/thumbnail.\(fileExtension)?access_token=\(accessToken)")! } public func urlForSegmentedPage(_ id: String, page: Int, fileExtension: String) -> URL { - URL(string: "\(urlForID(id))/segmentation/pages/\(page).\(fileExtension)?" + - "access_token=\(accessToken)")! + URL(string: "\(urlForID(id))/segmentation/pages/\(page).\(fileExtension)?access_token=\(accessToken)")! } public func urlForSegmentedThumbnail(_ id: String, page: Int, fileExtension: String) -> URL { - URL(string: "\(urlForID(id))/segmentation/thumbnails/\(page).\(fileExtension)?" + - "access_token=\(accessToken)")! + URL(string: "\(urlForID(id))/segmentation/thumbnails/\(page).\(fileExtension)?access_token=\(accessToken)")! } public func urlForUserPermissions(_ id: String) -> URL { diff --git a/Sources/Group.swift b/Sources/Group.swift index 8a293ec..2207905 100644 --- a/Sources/Group.swift +++ b/Sources/Group.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif diff --git a/Sources/Insights.swift b/Sources/Insights.swift index 125b098..e495d49 100644 --- a/Sources/Insights.swift +++ b/Sources/Insights.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif diff --git a/Sources/Invitation.swift b/Sources/Invitation.swift index 78377c5..c879f50 100644 --- a/Sources/Invitation.swift +++ b/Sources/Invitation.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif diff --git a/Sources/Mosaic.swift b/Sources/Mosaic.swift index 0a2a913..301144b 100644 --- a/Sources/Mosaic.swift +++ b/Sources/Mosaic.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif @@ -44,13 +45,14 @@ public struct VOMosaic { fileExtension: String ) async throws -> Data { try await withCheckedThrowingContinuation { continuation in - var request = URLRequest(url: urlForTile( - id, - zoomLevel: zoomLevel, - row: row, - column: column, - fileExtension: fileExtension - )) + var request = URLRequest( + url: urlForTile( + id, + zoomLevel: zoomLevel, + row: row, + column: column, + fileExtension: fileExtension + )) request.httpMethod = "GET" request.appendAuthorizationHeader(accessToken) let task = URLSession.shared.dataTask(with: request) { data, response, error in @@ -122,9 +124,9 @@ public struct VOMosaic { column: Int, fileExtension: String ) -> URL { - URL(string: "\(urlForFile(id))/zoom_level/\(zoomLevel.index)" + - "/row/\(row)/column/\(column)/extension/\(fileExtension)?" + - "access_token=\(accessToken)")! + // swift-format-ignore + // swiftlint:disable:next line_length + URL(string: "\(urlForFile(id))/zoom_level/\(zoomLevel.index)/row/\(row)/column/\(column)/extension/\(fileExtension)?access_token=\(accessToken)")! } // MARK: - Types diff --git a/Sources/Organization.swift b/Sources/Organization.swift index 50a19b8..53e8f2c 100644 --- a/Sources/Organization.swift +++ b/Sources/Organization.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif diff --git a/Sources/Permission.swift b/Sources/Permission.swift index ecd61f3..ddf058f 100644 --- a/Sources/Permission.swift +++ b/Sources/Permission.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif diff --git a/Sources/Snapshot.swift b/Sources/Snapshot.swift index 1d99a14..f7fa9d5 100644 --- a/Sources/Snapshot.swift +++ b/Sources/Snapshot.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif diff --git a/Sources/Storage.swift b/Sources/Storage.swift index 1b30a64..7ffcb4e 100644 --- a/Sources/Storage.swift +++ b/Sources/Storage.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif diff --git a/Sources/Task+Wait.swift b/Sources/Task+Wait.swift index 65e686a..8361d08 100644 --- a/Sources/Task+Wait.swift +++ b/Sources/Task+Wait.swift @@ -5,8 +5,8 @@ import Foundation -public extension VOTask { - func wait(_ id: String, sleepSeconds: UInt32 = 1) async throws -> Entity? { +extension VOTask { + public func wait(_ id: String, sleepSeconds: UInt32 = 1) async throws -> Entity? { var task: Entity? repeat { do { @@ -30,7 +30,7 @@ public extension VOTask { return task } - enum RuntimeError: Error { + public enum RuntimeError: Error { case message(String) } } diff --git a/Sources/Task.swift b/Sources/Task.swift index c08e9f9..2eba0bd 100644 --- a/Sources/Task.swift +++ b/Sources/Task.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif diff --git a/Sources/Token.swift b/Sources/Token.swift index c5ecba0..213eb56 100644 --- a/Sources/Token.swift +++ b/Sources/Token.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif @@ -90,7 +91,8 @@ public struct VOToken { // Explicitly replace spaces with + and encode & characters var percentEncodedQuery = components.percentEncodedQuery ?? "" - percentEncodedQuery = percentEncodedQuery + percentEncodedQuery = + percentEncodedQuery .replacingOccurrences(of: "+", with: "%2B") .replacingOccurrences(of: "%20", with: "+") return percentEncodedQuery diff --git a/Sources/User.swift b/Sources/User.swift index e652db7..521f76b 100644 --- a/Sources/User.swift +++ b/Sources/User.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif diff --git a/Sources/Workspace.swift b/Sources/Workspace.swift index 20b650b..806b45b 100644 --- a/Sources/Workspace.swift +++ b/Sources/Workspace.swift @@ -4,6 +4,7 @@ // included in the file LICENSE in the root of this repository. import Foundation + #if canImport(FoundationNetworking) import FoundationNetworking #endif diff --git a/Tests/AccountTests.swift b/Tests/AccountTests.swift index b49518d..2d7130a 100644 --- a/Tests/AccountTests.swift +++ b/Tests/AccountTests.swift @@ -3,9 +3,10 @@ // Use of this software is governed by the MIT License // included in the file LICENSE in the root of this repository. -@testable import VoltaserveCore import XCTest +@testable import VoltaserveCore + final class AccountTests: XCTestCase { var factory: DisposableFactory? diff --git a/Tests/Common/TokenFactory.swift b/Tests/Common/TokenFactory.swift index 59a9921..e987438 100644 --- a/Tests/Common/TokenFactory.swift +++ b/Tests/Common/TokenFactory.swift @@ -14,12 +14,13 @@ class TokenFactory { } init(_ credentials: Config.Credentials) async throws { - value = try await VOToken(baseURL: config.idpURL).exchange(.init( - grantType: .password, - username: credentials.username, - password: credentials.password, - refreshToken: nil, - locale: nil - )) + value = try await VOToken(baseURL: config.idpURL).exchange( + .init( + grantType: .password, + username: credentials.username, + password: credentials.password, + refreshToken: nil, + locale: nil + )) } } diff --git a/Tests/Common/XCTestCase+Bundle.swift b/Tests/Common/XCTestCase+Bundle.swift index f0791d0..f15437e 100644 --- a/Tests/Common/XCTestCase+Bundle.swift +++ b/Tests/Common/XCTestCase+Bundle.swift @@ -11,10 +11,11 @@ extension XCTestCase { #if os(Linux) URL(fileURLWithPath: "Tests/Resources/\(resource).\(fileExtension)") #else - Bundle(url: Bundle(for: type(of: self)).url( - forResource: "VoltaserveCore_VoltaserveTests", - withExtension: "bundle" - )!)!.url(forResource: resource, withExtension: fileExtension) + Bundle( + url: Bundle(for: type(of: self)).url( + forResource: "VoltaserveCore_VoltaserveTests", + withExtension: "bundle" + )!)!.url(forResource: resource, withExtension: fileExtension) #endif } } diff --git a/Tests/FileTests.swift b/Tests/FileTests.swift index b7228b1..23cccf6 100644 --- a/Tests/FileTests.swift +++ b/Tests/FileTests.swift @@ -3,9 +3,10 @@ // Use of this software is governed by the MIT License // included in the file LICENSE in the root of this repository. -@testable import VoltaserveCore import XCTest +@testable import VoltaserveCore + final class FileTests: XCTestCase { var factory: DisposableFactory? var otherFactory: DisposableFactory? @@ -19,36 +20,38 @@ final class FileTests: XCTestCase { let client = factory.client.file let organization = try await factory.organization(.init(name: "Test Organization")) - let workspace = try await factory.workspace(.init( - name: "Test Workspace", - organizationID: organization.id, - storageCapacity: 100_000_000 - )) + let workspace = try await factory.workspace( + .init( + name: "Test Workspace", + organizationID: organization.id, + storageCapacity: 100_000_000 + )) - /* Create files */ + // Create files var options: [VOFile.CreateFileOptions] = [] - for index in 0 ..< 6 { - options.append(.init( - workspaceID: workspace.id, - name: "Test File \(index).txt", - data: Data("Test Content \(index)".utf8) - )) + for index in 0..<6 { + options.append( + .init( + workspaceID: workspace.id, + name: "Test File \(index).txt", + data: Data("Test Content \(index)".utf8) + )) } var files: [VOFile.Entity] = [] - for index in 0 ..< options.count { + for index in 0..