Initial
This commit is contained in:
113
Package.resolved
Normal file
113
Package.resolved
Normal 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
|
||||||
|
}
|
||||||
@@ -4,20 +4,25 @@
|
|||||||
import PackageDescription
|
import PackageDescription
|
||||||
|
|
||||||
let package = Package(
|
let package = Package(
|
||||||
name: "swift-composable-subscriber",
|
name: "swift-composable-subscriber",
|
||||||
products: [
|
platforms: [
|
||||||
// Products define the executables and libraries a package produces, making them visible to other packages.
|
.iOS(.v13),
|
||||||
.library(
|
.macOS(.v10_15),
|
||||||
name: "swift-composable-subscriber",
|
.tvOS(.v13),
|
||||||
targets: ["swift-composable-subscriber"]),
|
.watchOS(.v6),
|
||||||
],
|
],
|
||||||
targets: [
|
products: [
|
||||||
// Targets are the basic building blocks of a package, defining a module or a test suite.
|
.library(name: "ComposableSubscriber", targets: ["ComposableSubscriber"]),
|
||||||
// Targets can depend on other targets in this package and products from dependencies.
|
],
|
||||||
.target(
|
dependencies: [
|
||||||
name: "swift-composable-subscriber"),
|
.package(url: "https://github.com/pointfreeco/swift-composable-architecture", .upToNextMajor(from: "1.0.0")),
|
||||||
.testTarget(
|
],
|
||||||
name: "swift-composable-subscriberTests",
|
targets: [
|
||||||
dependencies: ["swift-composable-subscriber"]),
|
.target(
|
||||||
]
|
name: "ComposableSubscriber",
|
||||||
|
dependencies: [
|
||||||
|
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|||||||
59
Sources/ComposableSubscriber/SubscriberReducer.swift
Normal file
59
Sources/ComposableSubscriber/SubscriberReducer.swift
Normal 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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
// The Swift Programming Language
|
|
||||||
// https://docs.swift.org/swift-book
|
|
||||||
Reference in New Issue
Block a user