diff --git a/Documentation/ArchitecturalComparison.md b/Documentation/ArchitecturalComparison.md index 182acb5..fe04907 100644 --- a/Documentation/ArchitecturalComparison.md +++ b/Documentation/ArchitecturalComparison.md @@ -1,8 +1,8 @@ # Architectural Comparison -EffectView is not a new idea. It translates a family of well-established patterns — Elm, Redux, Elixir/GenServer — into idiomatic SwiftUI, using Swift's own concurrency model rather than fighting it. +EffectComponents is not a new idea. It translates a family of well-established patterns — Elm, Redux, Elixir/GenServer — into idiomatic SwiftUI, using Swift's own concurrency model rather than fighting it. -This document maps EffectView against the patterns iOS developers are most likely to know, across five dimensions that matter in practice: +This document maps EffectComponents against the patterns iOS developers are most likely to know, across five dimensions that matter in practice: 1. **State model** — what kinds of state exist, who owns each kind, and who can mutate it 2. **Effect/side-effect model** — how async work is described and executed @@ -52,7 +52,7 @@ A global store holds the entire application state. A single pure *reducer* funct ### The Composable Architecture (TCA) -The most direct comparison to EffectView. TCA targets SwiftUI with a Redux-shaped architecture: a `@Reducer` macro generates a store, actions map to state mutations and `Effect` return values. +The most direct comparison to EffectComponents. TCA targets SwiftUI with a Redux-shaped architecture: a `@Reducer` macro generates a store, actions map to state mutations and `Effect` return values. **State model:** Composable tree of child stores. Parent features compose child features using `Scope` and `IfLetStore`. Shared state is managed via `@Shared` property wrappers with explicit persistence strategies. @@ -86,7 +86,7 @@ The direct ancestor of all patterns in this family. An Elm application is define The most conceptually illuminating comparison. A `GenServer` is an actor with a single `handle_call` / `handle_cast` callback — the structural equivalent of `update`. State is private to the process; all mutations go through the callback; side effects are either synchronous return values or out-of-band messages sent to other processes. -Phoenix LiveView's `handle_event` maps almost directly to EffectView's `update`: it receives the current socket (state), an event name, and parameters, mutates the socket, and optionally pushes async work via `Task.async` or `send_update`. +Phoenix LiveView's `handle_event` maps almost directly to a transducer's `update`: it receives the current socket (state), an event name, and parameters, mutates the socket, and optionally pushes async work via `Task.async` or `send_update`. **State model:** Process-local. Each LiveView socket / GenServer process owns its own state exclusively. Shared state between processes requires explicit message passing or a shared ETS table — it is never implicit. @@ -100,9 +100,9 @@ Phoenix LiveView's `handle_event` maps almost directly to EffectView's `update`: --- -## EffectView +## EffectComponents -EffectView translates the Elm/GenServer model into idiomatic SwiftUI — using `@State`, structured concurrency, and `@MainActor` as the runtime rather than a custom one. +EffectComponents translates the Elm/GenServer model into idiomatic SwiftUI — using `@State`, structured concurrency, and `@MainActor` as the runtime rather than a custom one. **State model:** Three kinds of state are structurally distinct: @@ -198,7 +198,7 @@ This is a stronger encapsulation boundary than TCA's store, which is deliberatel ## Summary -| | MVVM | Redux | TCA | Elm | Elixir/GenServer | EffectView | +| | MVVM | Redux | TCA | Elm | Elixir/GenServer | EffectComponents | |---|---|---|---|---|---|---| | **Ephemeral state owner** | ViewModel class | Global store | Feature store | Model value | Process-local | `ViewState` value | | **Shared state access** | Direct reference | Global selector | `@Shared` wrapper | Message-passing only | Explicit IPC | Read-only slice via `.observe` | @@ -210,6 +210,6 @@ This is a stronger encapsulation boundary than TCA's store, which is deliberatel | **Dispatch levels** | Synchronous call | Fire-and-forget | Fire-and-forget (+ async `send` inside effects) | Fire-and-forget | `call` (sync) / `cast` (async) | `post` / `send` / `request` | | **Test surface** | Full class construction | Reducer pure function | `TestStore` harness | Pure `update` function | Process message passing | Static pure function | -The common thread in the well-designed patterns (Elm, GenServer, TCA, EffectView) is the same: a single authoritative transition function that owns all state mutations and returns effect descriptions. The differences are in scope (global vs. local), dispatch semantics, task lifecycle management, and how much framework ceremony is required to express the pattern. +The common thread in the well-designed patterns (Elm, GenServer, TCA, EffectComponents) is the same: a single authoritative transition function that owns all state mutations and returns effect descriptions. The differences are in scope (global vs. local), dispatch semantics, task lifecycle management, and how much framework ceremony is required to express the pattern. -EffectView's position is that the SwiftUI runtime already provides the scope, lifecycle, and concurrency model — the only missing piece is a structured way to describe and manage effects. The library adds that piece and nothing else. +EffectComponents' position is that the SwiftUI runtime already provides the scope, lifecycle, and concurrency model — the only missing piece is a structured way to describe and manage effects. The library adds that piece and nothing else. diff --git a/Documentation/CorrectByConstruction.md b/Documentation/CorrectByConstruction.md index c3537ec..cb77d26 100644 --- a/Documentation/CorrectByConstruction.md +++ b/Documentation/CorrectByConstruction.md @@ -1,4 +1,4 @@ -# Correct by Construction: State Machines and MVI with EffectView +# Correct by Construction: State Machines and MVI with EffectComponents The [previous article](TamingAsyncTasksInSwiftUIViews.md) solved a mechanical problem: `.task` doesn't give you the tools to manage task lifetimes properly. This article addresses a deeper one. @@ -11,13 +11,13 @@ When behaviour lives inside closures, async functions, and stored properties sca - Can two pieces of state ever be in contradiction with each other? - What happens if the user taps a button while something is already loading? -EffectView addresses this by pulling all logic into a single, pure function. +EffectComponents addresses this by pulling all logic into a single, pure function. --- ## The update function -The heart of EffectView is the update function: +The heart of EffectComponents is the update function: ```swift (inout State, Event) -> Effect? @@ -59,7 +59,7 @@ Without an FSM, a search screen typically accumulates state like this: There are immediately several illegal combinations: `isLoading == true && errorMessage != nil`. `results.isEmpty && !isLoading && errorMessage == nil` — is that idle, or empty results? Tests have to enumerate these combinations and hope they've covered the right ones. -With EffectView you model state as a Swift enum instead: +With EffectComponents you model state as a Swift enum instead: ```swift enum SearchState { @@ -246,9 +246,9 @@ Concurrency exists — tasks genuinely run in the background — but concurrency ## MVI in practice -EffectView implements the **Model–View–Intent** (MVI) pattern: +EffectComponents implements the **Model–View–Intent** (MVI) pattern: -| MVI concept | EffectView equivalent | +| MVI concept | EffectComponents equivalent | |---|---| | **Model** | `State` — the single source of truth | | **Intent** | `Event` — user actions and system callbacks | diff --git a/Documentation/GitWorkflow.md b/Documentation/GitWorkflow.md index ef385ca..19dc089 100644 --- a/Documentation/GitWorkflow.md +++ b/Documentation/GitWorkflow.md @@ -172,7 +172,7 @@ git push --force-with-lease origin feature/my-feature # after a rebase ## 7. Open a Pull Request ```bash -open https://github.com/couchdeveloper/EffectView/compare/main...feature/my-feature?expand=1 +open https://github.com/couchdeveloper/EffectComponents/compare/main...feature/my-feature?expand=1 ``` Fill in title and body, then click **Create pull request**. diff --git a/Documentation/Recipes.md b/Documentation/Recipes.md index 8863ddc..2908a6e 100644 --- a/Documentation/Recipes.md +++ b/Documentation/Recipes.md @@ -1,6 +1,6 @@ # Recipes -Short, practical snippets for common EffectView patterns. +Short, practical snippets for common EffectComponents patterns. ## Post an event from the view @@ -17,8 +17,8 @@ Button("Retry") { ``` Note: in this case it is safe to write `try?` since we can ignore the error when -attempting to dispatch an event when it happens within the button actions or -whithin the onChange closure. +attempting to dispatch an event when it happens within the button actions or +within the onChange closure. diff --git a/Documentation/RuntimeDesign.md b/Documentation/RuntimeDesign.md index b387a08..52a4a7b 100644 --- a/Documentation/RuntimeDesign.md +++ b/Documentation/RuntimeDesign.md @@ -9,7 +9,7 @@ In short, `EffectView` is an event-driven runtime built around a finite state ma At a high level, effects come in two forms: - Actions are inline effect steps in the current computation cycle. Unlike tasks, they remain part of the current event chain even when they suspend. -- tasks are managed asynchronous operations; they run outside the current reduction step, may be tracked by logical identifier, and can feed events back into the system later +- Tasks are managed asynchronous operations; they run outside the current reduction step, may be tracked by logical identifier, and can feed events back into the system later. Two earlier articles describe adjacent concerns from the public API side: @@ -162,7 +162,7 @@ A fire-and-forget call schedules work and returns immediately. The caller does n This is intentionally the weakest back pressure mode. It is useful, but it is also the deliberate escape hatch: callers can create pending work without themselves awaiting admission. -### Synchronous disaptch (`send`) +### Synchronous dispatch (`send`) A synchronous `send` means: @@ -377,6 +377,6 @@ The runtime is intentionally built around four ideas: 3. caller suspension provides the primary back pressure mechanism 4. `TaskManager` centralizes shutdown and task-lifecycle semantics -This gives `EffectView` a runtime that stays small in code size while still supporting async actions, request/response bridging, runtime-managed tasks, immediate interruption, and future runtime control features. +This gives EffectComponents a runtime that stays small in code size while still supporting async actions, request/response bridging, runtime-managed tasks, immediate interruption, and future runtime control features. The design is intentional, not accidental. diff --git a/Documentation/SwiftUIFirst.md b/Documentation/SwiftUIFirst.md index 4e4c78d..735ec9b 100644 --- a/Documentation/SwiftUIFirst.md +++ b/Documentation/SwiftUIFirst.md @@ -4,7 +4,7 @@ Modern SwiftUI development has accumulated a rich set of companion patterns: Vie These patterns all solve real problems. But they solve them *outside* SwiftUI — as a layer on top of it. The result is that every project ends up with two architectures: SwiftUI's own model and the one the team bolted on. -EffectView takes a different position. It asks: what if SwiftUI's own mechanisms are sufficient, and the only thing missing is structured effect management? +EffectComponents takes a different position. It asks: what if SwiftUI's own mechanisms are sufficient, and the only thing missing is structured effect management? --- @@ -22,7 +22,7 @@ SwiftUI is not a rendering library. It is an architecture. These are not implementation details. They are the intended architecture for SwiftUI applications. `Binding` is the dependency injection mechanism for state. `Environment` is the dependency injection mechanism for services. View identity is the lifecycle. All of these are first-class, framework-supported tools. -The only gap is **effect management**: triggering, naming, cancelling, and coordinating async tasks in response to logic rather than rendering. That is what EffectView adds. +The only gap is **effect management**: triggering, naming, cancelling, and coordinating async tasks in response to logic rather than rendering. That is what EffectComponents adds. --- @@ -53,7 +53,7 @@ This function is not an object. It has no stored properties, no lifecycle, and n Dependency injection frameworks exist to solve one problem: getting concrete implementations of services into the code that needs them, without coupling the two directly. SwiftUI's `@Environment` already does this. It is hierarchical, it propagates automatically, and it can be overridden at any level of the view tree. -EffectView connects to it through `EnvReader` — a four-line wrapper around `@Environment`. No registration, no container, no reflection, no macros. +EffectComponents connects to it through `EnvReader` — a four-line wrapper around `@Environment`. No registration, no container, no reflection, no macros. Dependencies are declared as structs of closures in the feature module. Concrete implementations are assigned in a single `EnvironmentValues` extension in the glue layer. Test doubles are struct literals. @@ -129,7 +129,7 @@ That function requires no framework to test, no mocking library, and no async te ## Getting started ```swift -.package(url: "https://github.com/couchdeveloper/EffectView", from: "0.1.0") +.package(url: "https://github.com/couchdeveloper/EffectComponents.git", from: "0.1.0") ``` Start with the simplest case — one state enum, one event enum, one `update` function — and expand from there. The pattern is the same at every scale. diff --git a/Documentation/TamingAsyncTasksInSwiftUIViews.md b/Documentation/TamingAsyncTasksInSwiftUIViews.md index 4e38a25..a8fa65b 100644 --- a/Documentation/TamingAsyncTasksInSwiftUIViews.md +++ b/Documentation/TamingAsyncTasksInSwiftUIViews.md @@ -203,11 +203,11 @@ case .queryChanged(let q): --- -## Adding `EffectView` to your project +## Adding EffectComponents to your project ```swift // Package.swift -.package(url: "https://github.com/couchdeveloper/EffectView.git", from: "0.1.0") +.package(url: "https://github.com/couchdeveloper/EffectComponents.git", from: "0.1.0") ``` The library is around 200 lines of source — a focused primitive, not a framework. diff --git a/Documentation/UsingEnvForDependencyInjection.md b/Documentation/UsingEnvForDependencyInjection.md index 0f3aeaa..99e3f94 100644 --- a/Documentation/UsingEnvForDependencyInjection.md +++ b/Documentation/UsingEnvForDependencyInjection.md @@ -172,7 +172,7 @@ struct MovieSearchView: View { } ``` -`EnvReader` is a thin wrapper around `@Environment`; it exists purely for ergonomics at the `EffectView` call site. The value it captures is passed to `initialEnv:`, and EffectView takes ownership from there — forwarding it to every `.run`, `.request`, and `.action` for the lifetime of the view. +`EnvReader` is a thin wrapper around `@Environment`; it exists purely for ergonomics at the `EffectView` call site. The value it captures is passed to `initialEnv:`, and `EffectView` takes ownership from there — forwarding it to every `.run`, `.request`, and `.action` for the lifetime of the view. Note that the transducer type (`MovieSearchLogic.self`) is passed directly rather than constructing an inline closure. This keeps the view body free of logic and makes the transition function easily findable and independently testable. @@ -228,4 +228,4 @@ The feature module declares *what* it needs (closure types). The glue layer deci This is dependency injection without a framework, without reflection, and without protocols. The only mechanism is function values — which Swift has had since day one. -*Next: [Testing EffectView end-to-end](TestingEffectView.md)* +*Next: [Bridging event-driven and imperative code](BridgingEventDrivenAndImperative.md)* diff --git a/Examples/EffectViewExample/EffectViewExample/App.swift b/Examples/EffectViewExample/EffectViewExample/App.swift index ec38b9a..e0e18cf 100644 --- a/Examples/EffectViewExample/EffectViewExample/App.swift +++ b/Examples/EffectViewExample/EffectViewExample/App.swift @@ -1,5 +1,5 @@ import SwiftUI -import EffectView +import EffectComponents @main struct EffectViewExampleApp: App { diff --git a/Examples/EffectViewExample/EffectViewExample/Counter.swift b/Examples/EffectViewExample/EffectViewExample/Counter.swift index 6f90cce..417e655 100644 --- a/Examples/EffectViewExample/EffectViewExample/Counter.swift +++ b/Examples/EffectViewExample/EffectViewExample/Counter.swift @@ -1,6 +1,6 @@ import SwiftUI import Foundation -import EffectView +import EffectComponents enum Counter { enum Views {} diff --git a/Examples/EffectViewExample/EffectViewExample/Movies.swift b/Examples/EffectViewExample/EffectViewExample/Movies.swift index b2b6957..3b8ba08 100644 --- a/Examples/EffectViewExample/EffectViewExample/Movies.swift +++ b/Examples/EffectViewExample/EffectViewExample/Movies.swift @@ -1,5 +1,5 @@ import SwiftUI -import EffectView +import EffectComponents import Foundation enum Movies { diff --git a/Examples/EffectViewExample/EffectViewExample/RemoteCounter.swift b/Examples/EffectViewExample/EffectViewExample/RemoteCounter.swift index b17e1e8..4f78362 100644 --- a/Examples/EffectViewExample/EffectViewExample/RemoteCounter.swift +++ b/Examples/EffectViewExample/EffectViewExample/RemoteCounter.swift @@ -1,6 +1,6 @@ import SwiftUI import Foundation -import EffectView +import EffectComponents @available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *) enum RemoteCounter { diff --git a/Package.swift b/Package.swift index f6f3e20..eb71082 100644 --- a/Package.swift +++ b/Package.swift @@ -4,7 +4,7 @@ import PackageDescription let package = Package( - name: "EffectView", + name: "EffectComponents", platforms: [ .iOS(.v15), .macOS(.v12), @@ -15,8 +15,8 @@ let package = Package( products: [ // Products define the executables and libraries a package produces, making them visible to other packages. .library( - name: "EffectView", - targets: ["EffectView"] + name: "EffectComponents", + targets: ["EffectComponents"] ), ], dependencies: [ @@ -26,7 +26,7 @@ let package = Package( // 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: "EffectView", + name: "EffectComponents", dependencies: [ .product(name: "Mutex", package: "swift-mutex"), ], @@ -34,9 +34,9 @@ let package = Package( ] ), .testTarget( - name: "EffectViewTests", + name: "EffectComponentsTests", dependencies: [ - "EffectView", + "EffectComponents", .product(name: "Mutex", package: "swift-mutex"), ], swiftSettings: [ diff --git a/README.md b/README.md index 9f288b1..1ae4a26 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,16 @@ -# EffectView +# EffectComponents -[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fcouchdeveloper%2FEffectView%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/couchdeveloper/EffectView) -[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fcouchdeveloper%2FEffectView%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/couchdeveloper/EffectView) +[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fcouchdeveloper%2FEffectComponents%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/couchdeveloper/EffectComponents) +[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fcouchdeveloper%2FEffectComponents%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/couchdeveloper/EffectComponents) -EffectView is a SwiftUI library for event-driven state management. +EffectComponents is a SwiftUI-first library for building composable finite-state components that emit and manage effects. Here, an *effect* means follow-up work caused by a state transition: starting a task, calling a service, waiting, cancelling, observing, or sending the next event back into the system. -You can think of it as SwiftUI's `task` modifier taken further. Instead of attaching async work ad hoc to views, you return effects from `update`, and the runtime tracks, replaces, cancels, and routes that work by event. +EffectComponents contains a SwiftUI view `EffectView` that is specifically useful for SwiftUI developers who are tired of ViewModels that keep absorbing async methods, loading flags, `Task` handles, cancellation logic, and UI glue. It gives your view one event-driven place where state changes are decided. + +You can think of `EffectView` as SwiftUI's `task` modifier taken further. Instead of attaching async work ad hoc to views, you return effects from `update`, and the runtime tracks, replaces, cancels, and routes that work by event. -EffectView is for SwiftUI developers who are tired of ViewModels that keep absorbing async methods, loading flags, `Task` handles, cancellation logic, and UI glue. It gives your view one event-driven place where state changes are decided. ## The problem @@ -26,18 +27,18 @@ The SwiftUI `task` modifier behavior is often surprising in practice. A timer st ## The solution -With EffectView, you move a feature's logic into a small stand-alone enum that declares `State`, `Event`, and one `update` function. +With `EffectView`, you move a feature's logic into a small stand-alone enum that declares `State`, `Event`, and one `update` function. `update` is a plain synchronous function: it receives the current state and an event, changes state, and decides what should happen next. It does not call services, start tasks, or cause side effects itself. If more work is needed, `update` returns an effect: just a function, possibly async, that the runtime executes one step later and where those side effects happen. That split keeps the logic easy to read and easy to test. -If you know Redux or TCA, a `Transducer` plays a similar role to what those architectures often call a reducer. EffectView uses "transducer" because `update` does more than reduce state from an event: it also emits the next effect for the runtime to execute. +If you know Redux or TCA, a `Transducer` plays a similar role to what those architectures often call a reducer. `EffectComponents` uses "transducer" because `update` does more than reduce state from an event: it also emits the next effect for the runtime to execute. The example below is a small debounced search feature. Read it as a transition table: query changes put the feature into a loading state and start a named search task; response events then settle the state back into either results or an error. ```swift -import EffectView +import EffectComponents import SwiftUI enum SearchFeature: Transducer { @@ -145,10 +146,10 @@ The view renders state and posts events. The feature logic stays in `update`. ## Installation ```swift -.package(url: "https://github.com/couchdeveloper/EffectView.git", from: "0.1.0") +.package(url: "https://github.com/couchdeveloper/EffectComponents.git", from: "0.1.0") ``` -Add `EffectView` to your target dependencies. +Add `EffectComponents` to your target dependencies. ## Learn more diff --git a/Sources/EffectView/EffectObservable/EffectObservable.Input.swift b/Sources/EffectComponents/EffectObservable/EffectObservable.Input.swift similarity index 100% rename from Sources/EffectView/EffectObservable/EffectObservable.Input.swift rename to Sources/EffectComponents/EffectObservable/EffectObservable.Input.swift diff --git a/Sources/EffectView/EffectObservable/EffectObservable.swift b/Sources/EffectComponents/EffectObservable/EffectObservable.swift similarity index 99% rename from Sources/EffectView/EffectObservable/EffectObservable.swift rename to Sources/EffectComponents/EffectObservable/EffectObservable.swift index 3470990..77a70ec 100644 --- a/Sources/EffectView/EffectObservable/EffectObservable.swift +++ b/Sources/EffectComponents/EffectObservable/EffectObservable.swift @@ -27,7 +27,7 @@ public final class EffectObservable< public typealias Effect = T.Effect typealias Storage = UnownedReferenceKeyPathStorage - typealias Send = EffectView::Send + typealias Send = EffectComponents::Send /// Current transducer state published through Swift Observation. diff --git a/Sources/EffectView/EffectObservable/Transducer.observe.swift b/Sources/EffectComponents/EffectObservable/Transducer.observe.swift similarity index 100% rename from Sources/EffectView/EffectObservable/Transducer.observe.swift rename to Sources/EffectComponents/EffectObservable/Transducer.observe.swift diff --git a/Sources/EffectView/EffectView/EffectView.swift b/Sources/EffectComponents/EffectView/EffectView.swift similarity index 100% rename from Sources/EffectView/EffectView/EffectView.swift rename to Sources/EffectComponents/EffectView/EffectView.swift diff --git a/Sources/EffectView/EffectView/EffectViewInput.swift b/Sources/EffectComponents/EffectView/EffectViewInput.swift similarity index 100% rename from Sources/EffectView/EffectView/EffectViewInput.swift rename to Sources/EffectComponents/EffectView/EffectViewInput.swift diff --git a/Sources/EffectView/Storage/ReferenceKeyPathStorage.swift b/Sources/EffectComponents/Storage/ReferenceKeyPathStorage.swift similarity index 100% rename from Sources/EffectView/Storage/ReferenceKeyPathStorage.swift rename to Sources/EffectComponents/Storage/ReferenceKeyPathStorage.swift diff --git a/Sources/EffectView/Storage/Storage.swift b/Sources/EffectComponents/Storage/Storage.swift similarity index 100% rename from Sources/EffectView/Storage/Storage.swift rename to Sources/EffectComponents/Storage/Storage.swift diff --git a/Sources/EffectView/Transducer/Errors.swift b/Sources/EffectComponents/Transducer/Errors.swift similarity index 100% rename from Sources/EffectView/Transducer/Errors.swift rename to Sources/EffectComponents/Transducer/Errors.swift diff --git a/Sources/EffectView/Transducer/SendFunc.swift b/Sources/EffectComponents/Transducer/SendFunc.swift similarity index 98% rename from Sources/EffectView/Transducer/SendFunc.swift rename to Sources/EffectComponents/Transducer/SendFunc.swift index 2f07677..bf0dcf9 100644 --- a/Sources/EffectView/Transducer/SendFunc.swift +++ b/Sources/EffectComponents/Transducer/SendFunc.swift @@ -6,7 +6,7 @@ import Foundation /// ``EffectView/Input-swift.struct`` or ``EffectObservable/Input-swift.struct``. public struct Send: Identifiable where Input: TransducerInput & Sendable { - typealias TaggedEvent = EffectView::TaggedEvent + typealias TaggedEvent = EffectComponents::TaggedEvent typealias SendFunc = (isolated any Actor, Event, Input?, Continuation?) async throws -> Void typealias ControlFunc = (isolated any Actor, ControlEvent) throws -> Void diff --git a/Sources/EffectView/Transducer/TaskManager.swift b/Sources/EffectComponents/Transducer/TaskManager.swift similarity index 100% rename from Sources/EffectView/Transducer/TaskManager.swift rename to Sources/EffectComponents/Transducer/TaskManager.swift diff --git a/Sources/EffectView/Transducer/Transducer.Effects.swift b/Sources/EffectComponents/Transducer/Transducer.Effects.swift similarity index 100% rename from Sources/EffectView/Transducer/Transducer.Effects.swift rename to Sources/EffectComponents/Transducer/Transducer.Effects.swift diff --git a/Sources/EffectView/Transducer/Transducer.run.swift b/Sources/EffectComponents/Transducer/Transducer.run.swift similarity index 100% rename from Sources/EffectView/Transducer/Transducer.run.swift rename to Sources/EffectComponents/Transducer/Transducer.run.swift diff --git a/Sources/EffectView/Transducer/Transducer.swift b/Sources/EffectComponents/Transducer/Transducer.swift similarity index 100% rename from Sources/EffectView/Transducer/Transducer.swift rename to Sources/EffectComponents/Transducer/Transducer.swift diff --git a/Sources/EffectView/Transducer/TransducerEffect.swift b/Sources/EffectComponents/Transducer/TransducerEffect.swift similarity index 100% rename from Sources/EffectView/Transducer/TransducerEffect.swift rename to Sources/EffectComponents/Transducer/TransducerEffect.swift diff --git a/Sources/EffectView/Transducer/TransducerInput.swift b/Sources/EffectComponents/Transducer/TransducerInput.swift similarity index 100% rename from Sources/EffectView/Transducer/TransducerInput.swift rename to Sources/EffectComponents/Transducer/TransducerInput.swift diff --git a/Sources/EffectView/Utilities/EnvReader.swift b/Sources/EffectComponents/Utilities/EnvReader.swift similarity index 100% rename from Sources/EffectView/Utilities/EnvReader.swift rename to Sources/EffectComponents/Utilities/EnvReader.swift diff --git a/Tests/EffectViewTests/AsyncActionRuntimeTests.swift b/Tests/EffectComponents/AsyncActionRuntimeTests.swift similarity index 99% rename from Tests/EffectViewTests/AsyncActionRuntimeTests.swift rename to Tests/EffectComponents/AsyncActionRuntimeTests.swift index e0ad75c..9d0e514 100644 --- a/Tests/EffectViewTests/AsyncActionRuntimeTests.swift +++ b/Tests/EffectComponents/AsyncActionRuntimeTests.swift @@ -1,5 +1,5 @@ import Testing -@testable import EffectView +@testable import EffectComponents #if canImport(Observation) diff --git a/Tests/EffectViewTests/EffectViewTests.swift b/Tests/EffectComponents/EffectViewTests.swift similarity index 99% rename from Tests/EffectViewTests/EffectViewTests.swift rename to Tests/EffectComponents/EffectViewTests.swift index ccb4f68..6f5e1a3 100644 --- a/Tests/EffectViewTests/EffectViewTests.swift +++ b/Tests/EffectComponents/EffectViewTests.swift @@ -2,7 +2,7 @@ import Foundation import Testing import SwiftUI -@testable import EffectView +@testable import EffectComponents #if canImport(Observation) import Observation #endif diff --git a/Tests/EffectViewTests/RunFailureLifecycleTests.swift b/Tests/EffectComponents/RunFailureLifecycleTests.swift similarity index 99% rename from Tests/EffectViewTests/RunFailureLifecycleTests.swift rename to Tests/EffectComponents/RunFailureLifecycleTests.swift index 46a514e..b43a36e 100644 --- a/Tests/EffectViewTests/RunFailureLifecycleTests.swift +++ b/Tests/EffectComponents/RunFailureLifecycleTests.swift @@ -1,6 +1,6 @@ import Foundation import Testing -import EffectView +import EffectComponents #if false // Feature run is not yet implemented @Suite("Run stub") diff --git a/Tests/EffectViewTests/RuntimeUnavailableTests.swift b/Tests/EffectComponents/RuntimeUnavailableTests.swift similarity index 99% rename from Tests/EffectViewTests/RuntimeUnavailableTests.swift rename to Tests/EffectComponents/RuntimeUnavailableTests.swift index b83421d..1d9285d 100644 --- a/Tests/EffectViewTests/RuntimeUnavailableTests.swift +++ b/Tests/EffectComponents/RuntimeUnavailableTests.swift @@ -1,5 +1,5 @@ import Testing -@testable import EffectView +@testable import EffectComponents #if canImport(Observation) diff --git a/Tests/EffectViewTests/TaskManagerTests.swift b/Tests/EffectComponents/TaskManagerTests.swift similarity index 99% rename from Tests/EffectViewTests/TaskManagerTests.swift rename to Tests/EffectComponents/TaskManagerTests.swift index 0494d36..e120783 100644 --- a/Tests/EffectViewTests/TaskManagerTests.swift +++ b/Tests/EffectComponents/TaskManagerTests.swift @@ -1,6 +1,6 @@ import Foundation import Testing -@testable import EffectView +@testable import EffectComponents private enum TaskManagerFailure: Error, Equatable { case boom diff --git a/Tests/EffectViewTests/TaskSubscriptionTests.swift b/Tests/EffectComponents/TaskSubscriptionTests.swift similarity index 99% rename from Tests/EffectViewTests/TaskSubscriptionTests.swift rename to Tests/EffectComponents/TaskSubscriptionTests.swift index 4174210..acf5355 100644 --- a/Tests/EffectViewTests/TaskSubscriptionTests.swift +++ b/Tests/EffectComponents/TaskSubscriptionTests.swift @@ -2,7 +2,7 @@ import Foundation import Testing import SwiftUI -import EffectView +import EffectComponents #if canImport(UIKit) import UIKit diff --git a/Tests/EffectViewTests/Utilities/Expectation.swift b/Tests/EffectComponents/Utilities/Expectation.swift similarity index 100% rename from Tests/EffectViewTests/Utilities/Expectation.swift rename to Tests/EffectComponents/Utilities/Expectation.swift diff --git a/Tests/EffectViewTests/Utilities/TestGlobalActor.swift b/Tests/EffectComponents/Utilities/TestGlobalActor.swift similarity index 100% rename from Tests/EffectViewTests/Utilities/TestGlobalActor.swift rename to Tests/EffectComponents/Utilities/TestGlobalActor.swift diff --git a/Tests/EffectViewTests/Utilities/TestView.swift b/Tests/EffectComponents/Utilities/TestView.swift similarity index 99% rename from Tests/EffectViewTests/Utilities/TestView.swift rename to Tests/EffectComponents/Utilities/TestView.swift index e70c563..fcc8995 100644 --- a/Tests/EffectViewTests/Utilities/TestView.swift +++ b/Tests/EffectComponents/Utilities/TestView.swift @@ -2,7 +2,7 @@ import Foundation import Testing import SwiftUI -@testable import EffectView +@testable import EffectComponents #if canImport(Observation) import Observation #endif