Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 8 additions & 14 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,28 +1,22 @@
// swift-tools-version: 5.7
// The swift-tools-version declares the minimum version of Swift required to build this package.
// swift-tools-version:5.7

import PackageDescription

let package = Package(
name: "CoreModule",
platforms: [
.iOS(.v14)
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "CoreModule",
targets: ["CoreModule"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
targets: ["CoreModule"]
)
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "CoreModule",
dependencies: []),
.testTarget(
name: "CoreModuleTests",
dependencies: ["CoreModule"]),
path: "Source"
)
]
)
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# CoreModule

A description of this package.
Core module for iOS projects.

Contents

* Core protocols
* Logging framework
* Some extensions for basic Swift types
* Some UIKit extensions
* HTTP client
17 changes: 17 additions & 0 deletions Source/Array+Core.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// Array+Core.swift
// ReTodoList
//
// Created by Maksim Ivanov on 21.02.2023.
//

extension Array {

public subscript(safeIndex index: Int) -> Element? {
guard index >= 0, index < endIndex else {
return nil
}

return self[index]
}
}
23 changes: 23 additions & 0 deletions Source/Builder.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// Builder.swift
// PersonalDictionary
//
// Created by Maxim Ivanov on 27.10.2022.
//

import UIKit

public protocol ViewBuilder {

func build() -> UIView
}

public protocol ViewControllerBuilder {

func build() -> UIViewController
}

public protocol SearchControllerBuilder {

func build() -> UISearchController
}
11 changes: 11 additions & 0 deletions Source/CoreRouter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//
// CoreRouter.swift
// CoreModule
//
// Created by Maxim Ivanov on 16.12.2021.
//

public protocol CoreRouter {

func navigate()
}
22 changes: 22 additions & 0 deletions Source/Date+Core.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// Date+Core.swift
// ReTodoList
//
// Created by Maksim Ivanov on 12.08.2022.
//

import Foundation

extension Date {

public var dMMMMyyyy: String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "d MMMM yyyy"

return dateFormatter.string(from: self)
}

public var integer: Int {
Int(timeIntervalSince1970)
}
}
13 changes: 13 additions & 0 deletions Source/Logger/LogLevel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// CoreRouter.swift
// CoreModule
//
// Created by Maxim Ivanov on 16.12.2021.
//

public enum LogLevel: String {
case debug = "DEBUG"
case info = "INFO"
case warn = "WARN ⚠️"
case error = "ALERT ❌"
}
81 changes: 81 additions & 0 deletions Source/Logger/Logger+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//
// CoreRouter.swift
// CoreModule
//
// Created by Maxim Ivanov on 16.12.2021.
//

import Foundation

extension Logger {

public func debug(_ message: String) {
log(message, level: .debug)
}

public func logWithContext(_ message: String,
level: LogLevel = .info,
file: String = #file,
function: String = #function,
line: Int = #line) {
guard isDevelopment() else { return }

log(message, level: level, file: file, function: function, line: line)
}

public func errorWithContext(_ error: Error,
file: String = #file,
function: String = #function,
line: Int = #line) {
guard isDevelopment() else { return }

log("\(error)", level: .error, file: file, function: function, line: line)
}

public func logState<State>(actionName: String,
_ state: State,
file: String = #file,
function: String = #function,
line: Int = #line) {
guard isDevelopment() else { return }
let text = "\(actionName) result:\n\(state)"

log(text, level: .info, file: file, function: function, line: line)
}

public func logSending<T>(_ object: T,
toModelStream modelStreamName: String,
file: String = #file,
function: String = #function,
line: Int = #line) {
guard isDevelopment() else { return }
let text = "Sending \(type(of: object)) = \(object) to the \(modelStreamName) model stream."

log(text, level: .info, file: file, function: function, line: line)
}

public func logReceiving<T>(_ object: T,
fromModelStream modelStreamName: String,
file: String = #file,
function: String = #function,
line: Int = #line) {
guard isDevelopment() else { return }
let text = "Received \(type(of: object)) = \(object) from the \(modelStreamName) model stream."

log(text, level: .info, file: file, function: function, line: line)
}

public func log(installedFeatureName: String) {
debug("The \(installedFeatureName) feature has been installed.")
}

public func log(dismissedFeatureName: String) {
debug("The \(dismissedFeatureName) feature has been dismissed.")
}

private func log(_ text: String, level: LogLevel, file: String, function: String, line: Int) {
let description = "\((file as NSString).lastPathComponent) line:\(line) \(function)"

log("\(text) -> \(description)", level: level)
}
}
11 changes: 11 additions & 0 deletions Source/Logger/Logger.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//
// Logger.swift
// CoreModule
//
// Created by Maxim Ivanov on 24.03.2023.
//

public protocol Logger {

func log(_ message: String, level: LogLevel)
}
42 changes: 42 additions & 0 deletions Source/Logger/LoggerImpl.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// LoggerImpl.swift
// CoreModule
//
// Created by Maxim Ivanov on 24.03.2023.
//

import os

public final class LoggerImpl: CoreModule.Logger {

private let logger: os.Logger

public init(category: String) {
logger = os.Logger(subsystem: "General", category: category)
}

public func log(_ message: String, level: LogLevel) {
guard isDevelopment() else { return }

logger.log(level: level.getOsLogLevel(), "[\(level.rawValue)] \(message)")
}
}

extension LogLevel {

func getOsLogLevel() -> OSLogType {
switch self {
case .debug:
return .debug

case .info:
return .default

case .warn:
return .error

case .error:
return .fault
}
}
}
33 changes: 33 additions & 0 deletions Source/Networking/HttpClient.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// CoreService.swift
// PersonalDictionary
//
// Created by Maxim Ivanov on 09.10.2021.
//

import Combine
import Foundation

public typealias RxHttpResponse = AnyPublisher<(response: HTTPURLResponse, data: Data), Error>

public struct Http {
public let urlString: String
public let method: String
public let headers: [String: String]?
public let body: Data?

public init(urlString: String = "",
method: String = "",
headers: [String: String]? = nil,
body: Data? = nil) {
self.urlString = urlString
self.method = method
self.headers = headers
self.body = body
}
}

public protocol HttpClient {

func send(_ http: Http) -> RxHttpResponse
}
53 changes: 53 additions & 0 deletions Source/Networking/HttpClientImpl.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// UrlSessionCoreService.swift
// PersonalDictionary
//
// Created by Maxim Ivanov on 09.10.2021.
//

import Combine
import Foundation

public class HttpClientImpl: HttpClient {

private let sessionConfiguration: URLSessionConfiguration

private lazy var session: URLSession = {
sessionConfiguration.timeoutIntervalForResource = 30.0
return URLSession(configuration: sessionConfiguration)
}()

public init(sessionConfiguration: URLSessionConfiguration = URLSessionConfiguration.default) {
self.sessionConfiguration = sessionConfiguration
}

public func send(_ http: Http) -> RxHttpResponse {
let urlString = http.urlString
guard let url = URL(string: urlString) else {
return Fail(error: URLError(.badURL))
.eraseToAnyPublisher()
}
var request = URLRequest(url: url)

request.httpMethod = http.method
request.httpBody = http.body

http.headers?.forEach { (key, value) in
request.addValue(value, forHTTPHeaderField: key)
}

return session.dataTaskPublisher(for: request)
.tryMap { value in
guard let httpURLResponse = value.response as? HTTPURLResponse else {
throw HttpClientError.nonHttpRequest
}

return (response: httpURLResponse, data: value.data)
}
.eraseToAnyPublisher()
}

enum HttpClientError: Error {
case nonHttpRequest
}
}
19 changes: 19 additions & 0 deletions Source/Tagged.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// Tagged.swift
// PersonalDictionary
//
// Created by Maxim Ivanov on 05.10.2021.
//

public struct Tagged<Tag, RawValue: Equatable>: Equatable {

public let raw: RawValue

public init(raw: RawValue) {
self.raw = raw
}

public static func == (_ lhs: Tagged, _ rhs: Tagged) -> Bool {
lhs.raw == rhs.raw
}
}
Loading