Add Effect v4 support, Fast Refresh tooling, and revamped docs (#56)
Lint / lint (push) Successful in 57s
Publish / publish (push) Failing after 57s

## Summary

- Add `effect-fc-next`, a React 19 integration targeting Effect v4 beta.
- Introduce component lifecycles, scoped resources, queries, mutations, forms, lenses, views, and refreshable components.
- Add `@effect-view/vite-plugin` for Vite Fast Refresh support.
- Add an Effect v4 example application covering the new APIs.
- Expand test coverage for both the existing and next-generation packages.
- Replace the starter Docusaurus content with complete Effect View documentation while preserving the Effect v3 docs as a versioned snapshot.
- Update the landing page, navigation, package scripts, and build output.
- Extend CI with linting, tests, package builds, Docker builds, and container publishing.

## Validation

- `bun lint:tsc`
- `bun lint:biome`
- `bun test`
- `bun run build`
- `bun pack`
- Docker image build

---------

Co-authored-by: Julien Valverdé <julien.valverde@mailo.com>
Reviewed-on: Thilawyn/effect-fc#56
This commit was merged in pull request #56.
This commit is contained in:
2026-07-26 02:32:59 +02:00
parent 721ab7d736
commit 4478598f15
138 changed files with 13360 additions and 1970 deletions
+7 -13
View File
@@ -1075,10 +1075,8 @@ export declare namespace useContext {
* ```tsx
* const MyLayer = Layer.succeed(MyService, new MyServiceImpl())
* const MyComponent = Component.make(function*() {
* const context = yield* Component.useContextFromLayer(MyLayer)
* const Sub = yield* SubComponent.use.pipe(
* Effect.provide(context)
* )
* const context = yield* Component.useLayer(MyLayer)
* const Sub = yield* Effect.provide(SubComponent.use, context)
*
* return <Sub />
* })
@@ -1087,12 +1085,10 @@ export declare namespace useContext {
* @example With memoized layer
* ```tsx
* const MyComponent = Component.make(function*(props: { id: string })) {
* const context = yield* Component.useContextFromLayer(
* const context = yield* Component.useLayer(
* React.useMemo(() => Layer.succeed(MyService, new MyServiceImpl(props.id)), [props.id])
* )
* const Sub = yield* SubComponent.use.pipe(
* Effect.provide(context)
* )
* const Sub = yield* Effect.provide(SubComponent.use, context)
*
* return <Sub />
* })
@@ -1102,17 +1098,15 @@ export declare namespace useContext {
* ```tsx
* const MyAsyncLayer = Layer.effect(MyService, someAsyncEffect)
* const MyComponent = Component.make(function*() {
* const context = yield* Component.useContextFromLayer(MyAsyncLayer)
* const Sub = yield* SubComponent.use.pipe(
* Effect.provide(context)
* )
* const context = yield* Component.useLayer(MyAsyncLayer)
* const Sub = yield* Effect.provide(SubComponent.use, context)
*
* return <Sub />
* }).pipe(
* Async.async // Required to handle async layer effects
* )
*/
export const useContextFromLayer = <ROut, E, RIn>(
export const useLayer = <ROut, E, RIn>(
layer: Layer.Layer<ROut, E, RIn>,
options?: useContext.Options,
): Effect.Effect<Context.Context<ROut>, E, RIn | Scope.Scope> => useOnChange(() => Effect.context<RIn>().pipe(