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
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
# Bricks
![237940157-f9e1d753-fed9-47c8-90b2-abc127e5c7d4](https://github.com/aniramskaya/bricks/assets/108326429/6688c16f-d99a-4f43-9c14-5f0fc5a13e78)

Эта библиотечка состоит из набора сущностей и декораторов (кирпичиков), с помощью которых можно строить различную логику загркзыи и кэширования данных.
В ее основе лежат два протокола: Query и FailableQuery. Остальные компоненты библиотеки реализуют один из них и предоставляют расширения этих протоколов для того чтобы можно было выстраивать сложные сервисы используя непрерывную dot-нотацию

Простой пример:
```swift
static func simpleModelLoader() -> any FailableQuery {
let dto = DTO(value: UUID())
// Загрузить DTO используя DTOLoader и выполнить маппинг DTO на модель
return DTOLoader(dto: dto).map(with: DTO.toModel)
}
```

Чуть сложнее:
```swift
static func modelLoaderWithInMemoryCache() -> any FailableQuery {
let dto = DTO(value: UUID())

let storage = InMemoryStorage<Model>().asQuery()

// Начинаем с получения данных из кэша в памяти (storage)
return storage
// Применяем к нему политику валидации TimeIntervalValidationPolicy
.expiring(validationPolicy: TimeIntervalValidationPolicy())
// Если кэш невалиден, запускается вторая ветка
.fallback(
// Загружается DTO
DTOLoader(dto: dto)
// DTO маппится в модель
.map(with: DTO.toModel)
// модель сохраняется в InMemoryStorage
.store(into: storage)
)
}
```
2 changes: 2 additions & 0 deletions bricks.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
CC27C14F2A3887E600AF020E /* ParallelPriority.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParallelPriority.swift; sourceTree = "<group>"; };
CC27C1532A38880A00AF020E /* ParallelPriorityLoaderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParallelPriorityLoaderTests.swift; sourceTree = "<group>"; };
CC4771462A28BAA2005AAE39 /* PaginatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginatorTests.swift; sourceTree = "<group>"; };
CC56EACF2F17B3730044956B /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
CC5CB3C82A2E0C4B00DCE080 /* Paginator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Paginator.swift; sourceTree = "<group>"; };
CC5CB3CA2A2E108700DCE080 /* Paginator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Paginator.swift; sourceTree = "<group>"; };
CC7141782A2721A3005DBA5F /* Command.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Command.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -140,6 +141,7 @@
CC86FB112A07A40300416227 = {
isa = PBXGroup;
children = (
CC56EACF2F17B3730044956B /* README.md */,
CC97021B2A417BA000918FC0 /* Bricks.podspec */,
CC7431D92A07B568004E0175 /* bricks.xctestplan */,
CC86FB1D2A07A40300416227 /* bricks */,
Expand Down
34 changes: 17 additions & 17 deletions bricks/source/AnyFailableQuery.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,25 @@

import Foundation

// Type erasing wrapper for FailableQuery
public struct AnyFailableQuery<Success, Failure: Error>: FailableQuery {
private class _AnyFailableQueryBox<Success, Failure: Error>: FailableQuery {
func load(completion: @escaping (Swift.Result<Success, Failure>) -> Void) {
fatalError("This method is abstract")
}
}

private class _FailableQueryBox<Base: FailableQuery>: _AnyFailableQueryBox<Base.Success, Base.Failure> {
private let _base: Base
init(_ base: Base) {
_base = base
}

override func load(completion: @escaping (Swift.Result<Success, Failure>) -> Void) {
return _base.load(completion: completion)
}
private class _AnyFailableQueryBox<Success, Failure: Error>: FailableQuery {
func load(completion: @escaping (Swift.Result<Success, Failure>) -> Void) {
fatalError("This method is abstract")
}
}

private class _FailableQueryBox<Base: FailableQuery>: _AnyFailableQueryBox<Base.Success, Base.Failure> {
private let _base: Base
init(_ base: Base) {
_base = base
}

override func load(completion: @escaping (Swift.Result<Success, Failure>) -> Void) {
return _base.load(completion: completion)
}
}

// Type erasing wrapper for FailableQuery
public struct AnyFailableQuery<Success, Failure: Error>: FailableQuery {
private let _box: _AnyFailableQueryBox<Success, Failure>

public init<Q>(_ wrappee: Q) where Q: FailableQuery, Q.Success == Success, Q.Failure == Failure {
Expand Down
2 changes: 1 addition & 1 deletion bricks/source/InMemoryStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Foundation

/// In-memory storage simply holds the data passed into `load` method
/// In-memory storage simply holds the data passed into `save` method
public final class InMemoryStorage<Stored>: SynchronousStorage {
private var stored: Stored?
public private(set) var timestamp: Date?
Expand Down