diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6cce070..24f7f18 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -26,7 +26,7 @@ concurrency:
cancel-in-progress: true
env:
- SCHEME_NAME: "NetworkLayer"
+ SCHEME_NAME: "NetworkLayer-Package"
jobs:
test-apple-platforms:
diff --git a/.gitignore b/.gitignore
index 5922fda..afe2bf9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@ DerivedData/
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
Package.resolved
+.swiftpm/
\ No newline at end of file
diff --git a/.swiftformat b/.swiftformat
index 13422b1..c8a9b34 100644
--- a/.swiftformat
+++ b/.swiftformat
@@ -1,6 +1,6 @@
# Stream rules
---swiftversion 5.3
+--swiftversion 5.10
# Use 'swiftformat --options' to list all of the possible options
diff --git a/.swiftlint.yml b/.swiftlint.yml
index ccb6b1f..e2e5644 100644
--- a/.swiftlint.yml
+++ b/.swiftlint.yml
@@ -1,10 +1,8 @@
excluded:
- Tests
- Package.swift
- - Package@swift-5.7.swift
- - Package@swift-5.8.swift
- - Package@swift-5.9.swift
- Package@swift-5.10.swift
+ - Package@swift-6.0.swift
- .build
# Rules
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NetworkLayer.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NetworkLayer.xcscheme
deleted file mode 100644
index a82d203..0000000
--- a/.swiftpm/xcode/xcshareddata/xcschemes/NetworkLayer.xcscheme
+++ /dev/null
@@ -1,102 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NetworkLayerInterfaces.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NetworkLayerInterfaces.xcscheme
deleted file mode 100644
index 2395097..0000000
--- a/.swiftpm/xcode/xcshareddata/xcschemes/NetworkLayerInterfaces.xcscheme
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/NetworkLayerTests.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/NetworkLayerTests.xcscheme
deleted file mode 100644
index af4fec8..0000000
--- a/.swiftpm/xcode/xcshareddata/xcschemes/NetworkLayerTests.xcscheme
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 856d64b..0000000
--- a/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-all: bootstrap
-
-bootstrap: hook
- mint bootstrap
-
-hook:
- ln -sf ../../hooks/pre-commit .git/hooks/pre-commit
- chmod +x .git/hooks/pre-commit
-
-mint:
- mint bootstrap
-
-lint:
- mint run swiftlint
-
-fmt:
- mint run swiftformat Sources Tests
-
-.PHONY: all bootstrap hook mint lint fmt
\ No newline at end of file
diff --git a/Package.swift b/Package.swift
index dd10ad4..2fc3efc 100644
--- a/Package.swift
+++ b/Package.swift
@@ -1,4 +1,4 @@
-// swift-tools-version: 6.0
+// swift-tools-version: 6.2
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
diff --git a/Package@swift-5.7.swift b/Package@swift-5.7.swift
deleted file mode 100644
index f462754..0000000
--- a/Package@swift-5.7.swift
+++ /dev/null
@@ -1,50 +0,0 @@
-// 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: "NetworkLayer",
- platforms: [
- .macOS(.v10_15),
- .iOS(.v13),
- .watchOS(.v7),
- .tvOS(.v13),
- ],
- products: [
- .library(name: "NetworkLayer", targets: ["NetworkLayer"]),
- .library(name: "NetworkLayerInterfaces", targets: ["NetworkLayerInterfaces"]),
- ],
- dependencies: [
- .package(url: "https://github.com/space-code/atomic", exact: "1.1.0"),
- .package(url: "https://github.com/space-code/typhoon", exact: "1.2.1"),
- .package(url: "https://github.com/WeTransfer/Mocker", exact: "3.0.1"),
- ],
- targets: [
- .target(
- name: "NetworkLayer",
- dependencies: [
- "NetworkLayerInterfaces",
- .product(name: "Atomic", package: "atomic"),
- .product(name: "Typhoon", package: "typhoon"),
- ]
- ),
- .target(
- name: "NetworkLayerInterfaces",
- dependencies: [
- .product(name: "Typhoon", package: "typhoon"),
- ]
- ),
- .testTarget(
- name: "NetworkLayerTests",
- dependencies: [
- "NetworkLayer",
- .product(name: "Mocker", package: "Mocker"),
- .product(name: "Typhoon", package: "typhoon"),
- ],
- resources: [
- .process("Resources"),
- ]
- ),
- ]
-)
diff --git a/Package@swift-5.8.swift b/Package@swift-5.8.swift
deleted file mode 100644
index a0ad70b..0000000
--- a/Package@swift-5.8.swift
+++ /dev/null
@@ -1,50 +0,0 @@
-// swift-tools-version: 5.8
-// The swift-tools-version declares the minimum version of Swift required to build this package.
-
-import PackageDescription
-
-let package = Package(
- name: "NetworkLayer",
- platforms: [
- .macOS(.v10_15),
- .iOS(.v13),
- .watchOS(.v7),
- .tvOS(.v13),
- ],
- products: [
- .library(name: "NetworkLayer", targets: ["NetworkLayer"]),
- .library(name: "NetworkLayerInterfaces", targets: ["NetworkLayerInterfaces"]),
- ],
- dependencies: [
- .package(url: "https://github.com/space-code/atomic", exact: "1.1.0"),
- .package(url: "https://github.com/space-code/typhoon", exact: "1.2.1"),
- .package(url: "https://github.com/WeTransfer/Mocker", exact: "3.0.1"),
- ],
- targets: [
- .target(
- name: "NetworkLayer",
- dependencies: [
- "NetworkLayerInterfaces",
- .product(name: "Atomic", package: "atomic"),
- .product(name: "Typhoon", package: "typhoon"),
- ]
- ),
- .target(
- name: "NetworkLayerInterfaces",
- dependencies: [
- .product(name: "Typhoon", package: "typhoon"),
- ]
- ),
- .testTarget(
- name: "NetworkLayerTests",
- dependencies: [
- "NetworkLayer",
- .product(name: "Mocker", package: "Mocker"),
- .product(name: "Typhoon", package: "typhoon"),
- ],
- resources: [
- .process("Resources"),
- ]
- ),
- ]
-)
diff --git a/Package@swift-5.9.swift b/Package@swift-6.0.swift
similarity index 98%
rename from Package@swift-5.9.swift
rename to Package@swift-6.0.swift
index 43d2dc8..382a9fb 100644
--- a/Package@swift-5.9.swift
+++ b/Package@swift-6.0.swift
@@ -1,4 +1,4 @@
-// swift-tools-version: 5.9
+// swift-tools-version: 6.0
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
diff --git a/Sources/NetworkLayer/Classes/Core/Authentification/AuthenticationInterceptor.swift b/Sources/NetworkLayer/Classes/Core/Authentification/AuthenticationInterceptor.swift
index e06a944..a548807 100644
--- a/Sources/NetworkLayer/Classes/Core/Authentification/AuthenticationInterceptor.swift
+++ b/Sources/NetworkLayer/Classes/Core/Authentification/AuthenticationInterceptor.swift
@@ -1,6 +1,6 @@
//
// network-layer
-// Copyright © 2024 Space Code. All rights reserved.
+// Copyright © 2023 Space Code. All rights reserved.
//
import Atomic
@@ -64,7 +64,7 @@ public final class AuthenticationInterceptor: IAu
return
}
- guard let credential = credential else {
+ guard let credential else {
throw AuthenticatorInterceptorError.missingCredential
}
diff --git a/Sources/NetworkLayer/Classes/Core/Services/DataRequestHandler/DataRequestHandler.swift b/Sources/NetworkLayer/Classes/Core/Services/DataRequestHandler/DataRequestHandler.swift
index b6fe0b9..bcabf22 100644
--- a/Sources/NetworkLayer/Classes/Core/Services/DataRequestHandler/DataRequestHandler.swift
+++ b/Sources/NetworkLayer/Classes/Core/Services/DataRequestHandler/DataRequestHandler.swift
@@ -1,6 +1,6 @@
//
// network-layer
-// Copyright © 2024 Space Code. All rights reserved.
+// Copyright © 2023 Space Code. All rights reserved.
//
import Atomic
@@ -91,7 +91,7 @@ extension DataRequestHandler {
userDataDelegate?.urlSession?(session, task: task, didCompleteWithError: error)
- if let error = error {
+ if let error {
handler.completion?(.failure(error))
} else {
if let response = task.response {
diff --git a/Sources/NetworkLayer/Classes/Core/Services/RequestProcessor/RequestProcessor.swift b/Sources/NetworkLayer/Classes/Core/Services/RequestProcessor/RequestProcessor.swift
index df5e5f7..794acbb 100644
--- a/Sources/NetworkLayer/Classes/Core/Services/RequestProcessor/RequestProcessor.swift
+++ b/Sources/NetworkLayer/Classes/Core/Services/RequestProcessor/RequestProcessor.swift
@@ -1,6 +1,6 @@
//
// network-layer
-// Copyright © 2025 Space Code. All rights reserved.
+// Copyright © 2023 Space Code. All rights reserved.
//
import Foundation
@@ -71,8 +71,8 @@ actor RequestProcessor {
/// - configure: A closure to configure the URLRequest.
///
/// - Returns: The response from the network request.
- private func performRequest(
- _ request: T,
+ private func performRequest(
+ _ request: some IRequest,
strategy: RetryPolicyStrategy? = nil,
delegate: URLSessionDelegate?,
configure: (@Sendable (inout URLRequest) throws -> Void)?
@@ -103,7 +103,7 @@ actor RequestProcessor {
}
}
- try await self.validate(response)
+ try await validate(response)
return response
} catch {
@@ -118,7 +118,7 @@ actor RequestProcessor {
/// - request: The request model.
/// - urlRequest: The request that needs to be authenticated.
/// - session: The URLSession for which the request is being refreshed.
- private func adapt(_ request: T, urlRequest: inout URLRequest, session: URLSession) async throws {
+ private func adapt(_ request: some IRequest, urlRequest: inout URLRequest, session: URLSession) async throws {
guard request.requiresAuthentication else { return }
try await interceptor?.adapt(request: &urlRequest, for: session)
}
@@ -131,9 +131,9 @@ actor RequestProcessor {
/// - session: The URLSession for which the request is being refreshed.
///
/// - Returns: `true` if the request's token is refreshed, false otherwise.
- private func refresh(
+ private func refresh(
urlRequest: URLRequest,
- response: Response,
+ response: Response,
session: URLSession
) async throws -> Bool {
guard let interceptor, let response = response.response as? HTTPURLResponse else { return false }
@@ -178,8 +178,8 @@ actor RequestProcessor {
// MARK: IRequestProcessor
extension RequestProcessor: IRequestProcessor {
- func send(
- _ request: T,
+ func send(
+ _ request: some IRequest,
strategy: RetryPolicyStrategy? = nil,
delegate: URLSessionDelegate? = nil,
configure: (@Sendable (inout URLRequest) throws -> Void)? = nil
diff --git a/Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticator.swift b/Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticator.swift
index 33f6f0b..f605fb1 100644
--- a/Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticator.swift
+++ b/Sources/NetworkLayerInterfaces/Classes/Core/Authenticator/IAuthenticator.swift
@@ -1,6 +1,6 @@
//
// network-layer
-// Copyright © 2024 Space Code. All rights reserved.
+// Copyright © 2023 Space Code. All rights reserved.
//
import Foundation
diff --git a/Sources/NetworkLayerInterfaces/Classes/Core/Models/IRequest.swift b/Sources/NetworkLayerInterfaces/Classes/Core/Models/IRequest.swift
index a109d00..2d2db89 100644
--- a/Sources/NetworkLayerInterfaces/Classes/Core/Models/IRequest.swift
+++ b/Sources/NetworkLayerInterfaces/Classes/Core/Models/IRequest.swift
@@ -1,6 +1,6 @@
//
// network-layer
-// Copyright © 2024 Space Code. All rights reserved.
+// Copyright © 2023 Space Code. All rights reserved.
//
import Foundation
diff --git a/Sources/NetworkLayerInterfaces/Classes/Core/Models/Response.swift b/Sources/NetworkLayerInterfaces/Classes/Core/Models/Response.swift
index d7b49aa..d162d03 100644
--- a/Sources/NetworkLayerInterfaces/Classes/Core/Models/Response.swift
+++ b/Sources/NetworkLayerInterfaces/Classes/Core/Models/Response.swift
@@ -35,6 +35,6 @@ public struct Response {
}
}
-// MARK: Sendable
+// MARK: @unchecked Sendable
extension Response: @unchecked Sendable where T: Sendable {}
diff --git a/Sources/NetworkLayerInterfaces/Classes/Core/Services/IRequestBuilder.swift b/Sources/NetworkLayerInterfaces/Classes/Core/Services/IRequestBuilder.swift
index b615596..beff9cd 100644
--- a/Sources/NetworkLayerInterfaces/Classes/Core/Services/IRequestBuilder.swift
+++ b/Sources/NetworkLayerInterfaces/Classes/Core/Services/IRequestBuilder.swift
@@ -1,6 +1,6 @@
//
// network-layer
-// Copyright © 2025 Space Code. All rights reserved.
+// Copyright © 2023 Space Code. All rights reserved.
//
import Foundation
diff --git a/Sources/NetworkLayerInterfaces/Classes/Core/Services/IRequestProcessor.swift b/Sources/NetworkLayerInterfaces/Classes/Core/Services/IRequestProcessor.swift
index 1800e40..c69d2d4 100644
--- a/Sources/NetworkLayerInterfaces/Classes/Core/Services/IRequestProcessor.swift
+++ b/Sources/NetworkLayerInterfaces/Classes/Core/Services/IRequestProcessor.swift
@@ -18,8 +18,8 @@ public protocol IRequestProcessor {
/// - configure: An optional closure that allows custom configuration of the URLRequest before sending the request.
/// Pass `nil` if not
/// needed.
- func send(
- _ request: T,
+ func send(
+ _ request: some IRequest,
strategy: RetryPolicyStrategy?,
delegate: URLSessionDelegate?,
configure: (@Sendable (inout URLRequest) throws -> Void)?
@@ -31,8 +31,8 @@ extension IRequestProcessor {
///
/// - Parameters:
/// - request: The request object conforming to the `IRequest` protocol, representing the network request to be sent.
- func send(
- _ request: T,
+ func send(
+ _ request: some IRequest,
strategy: RetryPolicyStrategy?
) async throws -> Response {
try await send(request, strategy: strategy, delegate: nil, configure: nil)
diff --git a/Tests/NetworkLayerTests/Classes/Helpers/Fakes/URLSessionDataTask+Fake.swift b/Tests/NetworkLayerTests/Classes/Helpers/Fakes/URLSessionDataTask+Fake.swift
index d289807..21e7071 100644
--- a/Tests/NetworkLayerTests/Classes/Helpers/Fakes/URLSessionDataTask+Fake.swift
+++ b/Tests/NetworkLayerTests/Classes/Helpers/Fakes/URLSessionDataTask+Fake.swift
@@ -6,8 +6,7 @@
import Foundation
extension URLSessionDataTask {
- @objc override dynamic
- class func fake() -> URLSessionDataTask {
+ @objc override dynamic class func fake() -> URLSessionDataTask {
URLSession.shared.dataTask(with: .fake())
}
}
diff --git a/Tests/NetworkLayerTests/Classes/Helpers/Fakes/URLSessionTask+Fake.swift b/Tests/NetworkLayerTests/Classes/Helpers/Fakes/URLSessionTask+Fake.swift
index 25801c3..004bf35 100644
--- a/Tests/NetworkLayerTests/Classes/Helpers/Fakes/URLSessionTask+Fake.swift
+++ b/Tests/NetworkLayerTests/Classes/Helpers/Fakes/URLSessionTask+Fake.swift
@@ -6,8 +6,7 @@
import Foundation
extension URLSessionTask {
- @objc dynamic
- class func fake() -> URLSessionTask {
+ @objc dynamic class func fake() -> URLSessionTask {
URLSession.shared.dataTask(with: .fake())
}
}
diff --git a/Tests/NetworkLayerTests/Classes/Helpers/Helpers/DynamicStubs.swift b/Tests/NetworkLayerTests/Classes/Helpers/Helpers/DynamicStubs.swift
index 20c7904..c1458b6 100644
--- a/Tests/NetworkLayerTests/Classes/Helpers/Helpers/DynamicStubs.swift
+++ b/Tests/NetworkLayerTests/Classes/Helpers/Helpers/DynamicStubs.swift
@@ -6,7 +6,7 @@
import Foundation
import Mocker
-final class DynamicStubs {
+enum DynamicStubs {
static func register(stubs: [StubResponse], prefix: String = "https://github.com", statusCode: Int = 200) {
for stub in stubs {
let mock = Mock(
diff --git a/Tests/NetworkLayerTests/Classes/Helpers/Mocks/AuthenticatorMock.swift b/Tests/NetworkLayerTests/Classes/Helpers/Mocks/AuthenticatorMock.swift
index d01a119..290dfc5 100644
--- a/Tests/NetworkLayerTests/Classes/Helpers/Mocks/AuthenticatorMock.swift
+++ b/Tests/NetworkLayerTests/Classes/Helpers/Mocks/AuthenticatorMock.swift
@@ -1,6 +1,6 @@
//
// network-layer
-// Copyright © 2024 Space Code. All rights reserved.
+// Copyright © 2023 Space Code. All rights reserved.
//
import Foundation
diff --git a/Tests/NetworkLayerTests/Classes/Tests/IntegrationTests/RequestProcessorAuthenticationTests.swift b/Tests/NetworkLayerTests/Classes/Tests/IntegrationTests/RequestProcessorAuthenticationTests.swift
index d45b568..f97cea0 100644
--- a/Tests/NetworkLayerTests/Classes/Tests/IntegrationTests/RequestProcessorAuthenticationTests.swift
+++ b/Tests/NetworkLayerTests/Classes/Tests/IntegrationTests/RequestProcessorAuthenticationTests.swift
@@ -1,6 +1,6 @@
//
// network-layer
-// Copyright © 2025 Space Code. All rights reserved.
+// Copyright © 2023 Space Code. All rights reserved.
//
import Foundation
@@ -88,12 +88,12 @@ final class RequestProcessorAuthenicationTests: XCTestCase {
}
func adapt(request _: inout URLRequest, for _: URLSession) async throws {
- guard let adaptError = adaptError else { return }
+ guard let adaptError else { return }
throw adaptError
}
func refresh(_: URLRequest, with _: HTTPURLResponse, for _: URLSession) async throws {
- guard let refreshError = refreshError else { return }
+ guard let refreshError else { return }
throw refreshError
}
diff --git a/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestBuilderTests.swift b/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestBuilderTests.swift
index 43dd0e0..2def897 100644
--- a/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestBuilderTests.swift
+++ b/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestBuilderTests.swift
@@ -86,10 +86,10 @@ private extension String {
static let domainName = "https://google.com"
}
-private extension Dictionary where Self.Key == String, Self.Value == String {
+private extension [String: String] {
static let contentType = ["Content-Type": "application/json"]
}
-private extension Dictionary where Self.Key == String, Self.Value == Any {
+private extension [String: Any] {
static let item = ["Content-Type": "application/json"]
}
diff --git a/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestParametersEncoderTests.swift b/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestParametersEncoderTests.swift
index d99165a..c63af39 100644
--- a/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestParametersEncoderTests.swift
+++ b/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestParametersEncoderTests.swift
@@ -1,6 +1,6 @@
//
// network-layer
-// Copyright © 2024 Space Code. All rights reserved.
+// Copyright © 2023 Space Code. All rights reserved.
//
import Foundation
@@ -63,6 +63,6 @@ private extension String {
static let domainName = "https://google.com"
}
-private extension Dictionary where Self.Key == String, Self.Value == String {
+private extension [String: String] {
static let parameters = ["id": "1"]
}
diff --git a/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestProcessorTests.swift b/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestProcessorTests.swift
index 9357595..e45cf25 100644
--- a/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestProcessorTests.swift
+++ b/Tests/NetworkLayerTests/Classes/Tests/UnitTests/RequestProcessorTests.swift
@@ -70,7 +70,7 @@ final class RequestProcessorTests: XCTestCase {
// when
do {
- let _ = try await sut.send(request) as Response
+ _ = try await sut.send(request) as Response
} catch {}
// then
@@ -88,7 +88,7 @@ final class RequestProcessorTests: XCTestCase {
// when
do {
- let _ = try await sut.send(request) as Response
+ _ = try await sut.send(request) as Response
} catch {}
// then
@@ -107,7 +107,7 @@ final class RequestProcessorTests: XCTestCase {
// when
do {
- let _ = try await sut.send(request) as Response
+ _ = try await sut.send(request) as Response
} catch {}
// then
@@ -125,7 +125,7 @@ final class RequestProcessorTests: XCTestCase {
// when
do {
- let _ = try await sut.send(request) as Response
+ _ = try await sut.send(request) as Response
} catch {}
// then
diff --git a/mise.toml b/mise.toml
new file mode 100644
index 0000000..2e45caf
--- /dev/null
+++ b/mise.toml
@@ -0,0 +1,10 @@
+[tools]
+git-cliff = "2.9.1"
+swiftlint = "0.62.2"
+swiftformat = "0.58.6"
+
+[settings]
+experimental = true
+
+[hooks]
+postinstall = "mise run install"
\ No newline at end of file
diff --git a/mise/tasks/install.sh b/mise/tasks/install.sh
new file mode 100755
index 0000000..aeba03b
--- /dev/null
+++ b/mise/tasks/install.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+
+set -e
+
+echo "🔧 Installing git hooks..."
+
+# Find git repository root
+GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
+
+if [ -z "$GIT_ROOT" ]; then
+ echo "❌ Error: Not a git repository"
+ exit 1
+fi
+
+echo "📁 Git root: $GIT_ROOT"
+
+# Create hooks directory if it doesn't exist
+mkdir -p "$GIT_ROOT/.git/hooks"
+
+# Create pre-commit hook
+cat > "$GIT_ROOT/.git/hooks/pre-commit" <<'HOOK_EOF'
+#!/bin/bash
+
+echo "🔍 Running linters..."
+
+echo "📝 Formatting staged Swift files..."
+git diff --diff-filter=d --staged --name-only | grep -e '\.swift$' | while read line; do
+ if [[ $line == *"/Generated"* ]]; then
+ echo "⏭️ Skipping generated file: $line"
+ else
+ echo "✨ Formatting: $line"
+ mise exec swiftformat -- swiftformat "${line}"
+ git add "$line"
+ fi
+done
+
+if ! mise run lint; then
+ echo "❌ Lint failed. Please fix the issues before committing."
+ echo "💡 Tip: Run 'mise run format' to auto-fix some issues"
+ echo "⚠️ To skip this hook, use: git commit --no-verify"
+ exit 1
+fi
+
+echo "✅ All checks passed!"
+exit 0
+HOOK_EOF
+
+chmod +x "$GIT_ROOT/.git/hooks/pre-commit"
+
+echo "✅ Git hooks installed successfully!"
+echo "📍 Hook location: $GIT_ROOT/.git/hooks/pre-commit"
+echo ""
+echo "Pre-commit hook will:"
+echo " 1. Format staged Swift files (except /Generated)"
+echo " 2. Run mise lint"
+echo ""
+echo "To skip the hook, use: git commit --no-verify"
\ No newline at end of file
diff --git a/mise/tasks/lint b/mise/tasks/lint
new file mode 100755
index 0000000..a00dbf4
--- /dev/null
+++ b/mise/tasks/lint
@@ -0,0 +1,13 @@
+#!/bin/bash
+#MISE description="Lint the network-layer package using SwiftLint and SwiftFormat"
+#MISE usage flag "-f --fix" help="Fix the fixable issues"
+
+set -eo pipefail
+
+if [ "$usage_fix" = "true" ]; then
+ swiftformat Sources Tests
+ swiftlint lint --fix --strict --config .swiftlint.yml Sources Tests
+else
+ swiftformat Sources Tests --lint
+ swiftlint lint --strict --config .swiftlint.yml Sources Tests
+fi
\ No newline at end of file