diff --git a/packages/effect-fc/src/types/Subscribable.ts b/packages/effect-fc/src/types/Subscribable.ts new file mode 100644 index 0000000..d622ec8 --- /dev/null +++ b/packages/effect-fc/src/types/Subscribable.ts @@ -0,0 +1,24 @@ +import { Effect, Effectable, Readable, Stream, Subscribable } from "effect" + + +class SubscribableImpl +extends Effectable.Class implements Subscribable.Subscribable { + readonly [Readable.TypeId]: Readable.TypeId = Readable.TypeId + readonly [Subscribable.TypeId]: Subscribable.TypeId = Subscribable.TypeId + + constructor( + readonly get: Effect.Effect, + readonly changes: Stream.Stream, + ) { + super() + } + + commit() { + return this.get + } +} + +export const make = (values: { + readonly get: Effect.Effect + readonly changes: Stream.Stream +}): Subscribable.Subscribable => new SubscribableImpl(values.get, values.changes) diff --git a/packages/effect-fc/src/types/index.ts b/packages/effect-fc/src/types/index.ts index e8b2633..6273110 100644 --- a/packages/effect-fc/src/types/index.ts +++ b/packages/effect-fc/src/types/index.ts @@ -1,3 +1,4 @@ export * as PropertyPath from "./PropertyPath.js" export * as SetStateAction from "./SetStateAction.js" +export * as Subscribable from "./Subscribable.js" export * as SubscriptionSubRef from "./SubscriptionSubRef.js" diff --git a/packages/example/src/todo/Todo.tsx b/packages/example/src/todo/Todo.tsx index f364ed1..40f3293 100644 --- a/packages/example/src/todo/Todo.tsx +++ b/packages/example/src/todo/Todo.tsx @@ -54,7 +54,7 @@ export class Todo extends Component.makeUntraced(function* Todo(props: TodoProps // eslint-disable-next-line react-hooks/exhaustive-deps ), [props._tag, props._tag === "edit" ? props.id : undefined]) - const [index, size] = yield* useSubscribe(indexRef, state.sizeRef) + const [index, size] = yield* useSubscribe(indexRef, state.sizeSubscribable) const StringTextAreaInputFC = yield* StringTextAreaInput const OptionalDateTimeInputFC = yield* OptionalDateTimeInput diff --git a/packages/example/src/todo/TodosState.service.ts b/packages/example/src/todo/TodosState.service.ts index 5b01c99..7fed39e 100644 --- a/packages/example/src/todo/TodosState.service.ts +++ b/packages/example/src/todo/TodosState.service.ts @@ -2,7 +2,7 @@ import { Todo } from "@/domain" import { KeyValueStore } from "@effect/platform" import { BrowserKeyValueStore } from "@effect/platform-browser" import { Chunk, Console, Effect, Option, Schema, Stream, SubscriptionRef } from "effect" -import { SubscriptionSubRef } from "effect-fc/types" +import { Subscribable } from "effect-fc/types" export class TodosState extends Effect.Service()("TodosState", { @@ -32,7 +32,11 @@ export class TodosState extends Effect.Service()("TodosState", { ) const ref = yield* SubscriptionRef.make(yield* readFromLocalStorage) - const sizeRef = SubscriptionSubRef.makeFromPath(ref, ["length"]) + + const sizeSubscribable = Subscribable.make({ + get: Effect.andThen(ref, Chunk.size), + get changes() { return Stream.map(ref.changes, Chunk.size) }, + }) yield* Effect.forkScoped(ref.changes.pipe( Stream.debounce("500 millis"), @@ -43,7 +47,7 @@ export class TodosState extends Effect.Service()("TodosState", { Effect.ignore, )) - return { ref, sizeRef } as const + return { ref, sizeSubscribable } as const }), dependencies: [BrowserKeyValueStore.layerLocalStorage],