This commit is contained in:
Oliver Foggin
2023-12-14 17:48:20 +00:00
parent 50f602f3b9
commit 3382f48991
4 changed files with 193 additions and 18 deletions

113
Package.resolved Normal file
View File

@@ -0,0 +1,113 @@
{
"pins" : [
{
"identity" : "combine-schedulers",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/combine-schedulers",
"state" : {
"revision" : "9dc9cbe4bc45c65164fa653a563d8d8db61b09bb",
"version" : "1.0.0"
}
},
{
"identity" : "swift-case-paths",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-case-paths",
"state" : {
"revision" : "bba1111185863c9288c5f047770f421c3b7793a4",
"version" : "1.1.3"
}
},
{
"identity" : "swift-clocks",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-clocks",
"state" : {
"revision" : "a8421d68068d8f45fbceb418fbf22c5dad4afd33",
"version" : "1.0.2"
}
},
{
"identity" : "swift-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections",
"state" : {
"revision" : "a902f1823a7ff3c9ab2fba0f992396b948eda307",
"version" : "1.0.5"
}
},
{
"identity" : "swift-composable-architecture",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-composable-architecture",
"state" : {
"revision" : "cb9c1f845b3b981da787452beee893826210eb7a",
"version" : "1.5.5"
}
},
{
"identity" : "swift-concurrency-extras",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-concurrency-extras",
"state" : {
"revision" : "bb5059bde9022d69ac516803f4f227d8ac967f71",
"version" : "1.1.0"
}
},
{
"identity" : "swift-custom-dump",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-custom-dump",
"state" : {
"revision" : "aedcf6f4cd486ccef5b312ccac85d4b3f6e58605",
"version" : "1.1.2"
}
},
{
"identity" : "swift-dependencies",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-dependencies",
"state" : {
"revision" : "101ba87f8de2cb7a80e0c0551370f6981a03022a",
"version" : "1.1.4"
}
},
{
"identity" : "swift-identified-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-identified-collections",
"state" : {
"revision" : "d1e45f3e1eee2c9193f5369fa9d70a6ddad635e8",
"version" : "1.0.0"
}
},
{
"identity" : "swift-syntax",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-syntax",
"state" : {
"revision" : "6ad4ea24b01559dde0773e3d091f1b9e36175036",
"version" : "509.0.2"
}
},
{
"identity" : "swiftui-navigation",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swiftui-navigation",
"state" : {
"revision" : "78f9d72cf667adb47e2040aa373185c88c63f0dc",
"version" : "1.2.0"
}
},
{
"identity" : "xctest-dynamic-overlay",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
"state" : {
"revision" : "23cbf2294e350076ea4dbd7d5d047c1e76b03631",
"version" : "1.0.2"
}
}
],
"version" : 2
}

View File

@@ -5,19 +5,24 @@ import PackageDescription
let package = Package(
name: "swift-composable-subscriber",
platforms: [
.iOS(.v13),
.macOS(.v10_15),
.tvOS(.v13),
.watchOS(.v6),
],
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "swift-composable-subscriber",
targets: ["swift-composable-subscriber"]),
.library(name: "ComposableSubscriber", targets: ["ComposableSubscriber"]),
],
dependencies: [
.package(url: "https://github.com/pointfreeco/swift-composable-architecture", .upToNextMajor(from: "1.0.0")),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "swift-composable-subscriber"),
.testTarget(
name: "swift-composable-subscriberTests",
dependencies: ["swift-composable-subscriber"]),
name: "ComposableSubscriber",
dependencies: [
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
]
),
]
)

View File

@@ -0,0 +1,59 @@
import ComposableArchitecture
extension Reducer {
func subscribe<TriggerAction, T>(
on triggerAction: CaseKeyPath<Action, TriggerAction>,
to stream: @escaping () async throws -> AsyncStream<T>,
with responseAction: CaseKeyPath<Action, T>
) -> _SubscribeReducer<Self, TriggerAction, T> {
.init(
parent: self,
on: triggerAction,
to: stream,
with: responseAction
)
}
}
struct _SubscribeReducer<Parent: Reducer, TriggerAction, T>: Reducer {
@usableFromInline
let parent: Parent
@usableFromInline
let triggerAction: AnyCasePath<Parent.Action, TriggerAction>
@usableFromInline
let stream: () async throws -> AsyncStream<T>
@usableFromInline
let responseAction: AnyCasePath<Parent.Action, T>
init(
parent: Parent,
on triggerAction: CaseKeyPath<Parent.Action, TriggerAction>,
to stream: @escaping () async throws -> AsyncStream<T>,
with responseAction: CaseKeyPath<Parent.Action, T>
) {
self.parent = parent
self.triggerAction = AnyCasePath(triggerAction)
self.stream = stream
self.responseAction = AnyCasePath(responseAction)
}
func reduce(into state: inout Parent.State, action: Parent.Action) -> Effect<Parent.Action> {
let effects = parent.reduce(into: &state, action: action)
guard self.triggerAction.extract(from: action) != nil else {
return effects
}
return .merge(
effects,
.run { send in
for await value in try await stream() {
await send(responseAction.embed(value))
}
}
)
}
}

View File

@@ -1,2 +0,0 @@
// The Swift Programming Language
// https://docs.swift.org/swift-book