Update dependency typescript to v7 - autoclosed #54
@@ -58,17 +58,18 @@
|
||||
"name": "effect-fc-next",
|
||||
"version": "0.1.0-beta.0",
|
||||
"dependencies": {
|
||||
"effect-lens": "2.0.0-beta.0",
|
||||
"effect-lens": "^2.0.0-beta.1",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@effect/platform-browser": "^4.0.0-beta.85",
|
||||
"@effect/platform-browser": "4.0.0-beta.98",
|
||||
"@testing-library/react": "^16.3.0",
|
||||
"effect": "4.0.0-beta.98",
|
||||
"jsdom": "^26.1.0",
|
||||
"vitest": "^3.2.4",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^19.2.0",
|
||||
"effect": "4.0.0-beta.85",
|
||||
"effect": "4.0.0-beta.98",
|
||||
"react": "^19.2.0",
|
||||
},
|
||||
},
|
||||
@@ -3063,11 +3064,11 @@
|
||||
|
||||
"dot-prop/is-obj": ["is-obj@2.0.0", "", {}, "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="],
|
||||
|
||||
"effect-fc-next/@effect/platform-browser": ["@effect/platform-browser@4.0.0-beta.87", "", { "dependencies": { "multipasta": "^0.2.7" }, "peerDependencies": { "effect": "^4.0.0-beta.87" } }, "sha512-sBUUdRt5PjFPLI7+ayxEX/jgnjCbOuc3I//98CmqiwhfgWbCMZ/rofYYb8Zk5tLpNsmdHnWgHWTsBLvH2SFrCw=="],
|
||||
"effect-fc-next/@effect/platform-browser": ["@effect/platform-browser@4.0.0-beta.98", "", { "dependencies": { "multipasta": "^0.2.8" }, "peerDependencies": { "effect": "^4.0.0-beta.98" } }, "sha512-Y0BEe0N8clKmJTHqmZpS85pLZbqAxP5uV3IYF0tDw/1dcs8AbTRHjbRmOLdyLtmU32NBVAiaUD3Vopb5Et5R/g=="],
|
||||
|
||||
"effect-fc-next/effect": ["effect@4.0.0-beta.85", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.8.0", "find-my-way-ts": "^0.1.6", "ini": "^7.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^2.0.1", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^14.0.0", "yaml": "^2.9.0" } }, "sha512-Cjv9YQyv4CiIccmRAQIWAoeESCpCpiuHYY8zb5vqiYs3Ac2yE5RQAnKq7z4Ir/3VJYZb8kxh6rS8czDDnpTdkQ=="],
|
||||
"effect-fc-next/effect": ["effect@4.0.0-beta.98", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.9.0", "find-my-way-ts": "^0.1.6", "ini": "^7.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^2.0.4", "multipasta": "^0.2.8", "toml": "^4.1.2", "uuid": "^14.0.1", "yaml": "^2.9.0" } }, "sha512-oz+bsG5h+6RNrw4t5GMfQrk/xBS8ROoqkYsuvRhBr5O7mCOrpvH/hbw+QrDzvKIpX4HJClwm86F94c87W0sJxg=="],
|
||||
|
||||
"effect-fc-next/effect-lens": ["effect-lens@2.0.0-beta.0", "", { "peerDependencies": { "effect": "4.0.0-beta.85" } }, "sha512-ntsRQSrzoX+GsNpkNVEGqebl/g1YOEDPIFRAHigf+4P6AtGnnOFcklqDHLrbm4zqnaxuWEgQvvn1J6S3eyC4yw=="],
|
||||
"effect-fc-next/effect-lens": ["effect-lens@2.0.0-beta.1", "", { "peerDependencies": { "effect": "4.0.0-beta.98" } }, "sha512-3MwsrezPczZHH4Tl2SvliZdiNRq9e/XbH+Vr1ckr/FPCEp6Wv8IYQL4Ie/hhI+XBiLlxbQERbgL8FlHW21avtw=="],
|
||||
|
||||
"esrecurse/estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
|
||||
|
||||
@@ -3373,10 +3374,16 @@
|
||||
|
||||
"csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="],
|
||||
|
||||
"effect-fc-next/effect/fast-check": ["fast-check@4.8.0", "", { "dependencies": { "pure-rand": "^8.0.0" } }, "sha512-GOJ158CUMnN6cSahsv4+ExARvIDuzzinFjkp0E9WtiBa5zcVeLozVkWaE4IzFcc+Y48Wp1EDlUZsXRyAztQcSg=="],
|
||||
"effect-fc-next/@effect/platform-browser/multipasta": ["multipasta@0.2.8", "", {}, "sha512-ZPWuMKyv0cSO29f7hozp+k6+crZbQijV8ipMvxNxRf2SwtYGTX1ZX89Kd20VV4H9Znonx+EQn+iy1wGQsJ+b+Q=="],
|
||||
|
||||
"effect-fc-next/effect/fast-check": ["fast-check@4.9.0", "", { "dependencies": { "pure-rand": "^8.0.0" } }, "sha512-7ms6T7SybUev/PQITciI0yLM2pOSFy5zpG8Ty7tQofcVaQUvrMXp6CBwqF6fThLCLOrfBtuHAtwq6Yu4XPCllg=="],
|
||||
|
||||
"effect-fc-next/effect/msgpackr": ["msgpackr@2.0.4", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.4" } }, "sha512-o1C5KRmuRt+apqMr1HuGSqWStZoRBUpEsCsl15uM9VdAF1qHLtvMOU2En747EnTyEl6c4pzPewRMFF31s1CNbA=="],
|
||||
|
||||
"effect-fc-next/effect/multipasta": ["multipasta@0.2.8", "", {}, "sha512-ZPWuMKyv0cSO29f7hozp+k6+crZbQijV8ipMvxNxRf2SwtYGTX1ZX89Kd20VV4H9Znonx+EQn+iy1wGQsJ+b+Q=="],
|
||||
|
||||
"effect-fc-next/effect/toml": ["toml@4.3.0", "", {}, "sha512-lVb8X9BsPVuH0M4BKeS91tXAmJvCjQ5UIyAbQFaxkKGyUFK2RPkhwaFSQH8vbpl1d23eu/IBH+dwVMHWaq9A5A=="],
|
||||
|
||||
"express/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||
|
||||
"file-loader/schema-utils/ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="],
|
||||
|
||||
@@ -39,17 +39,18 @@
|
||||
"clean:modules": "rm -rf node_modules"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@effect/platform-browser": "^4.0.0-beta.85",
|
||||
"@effect/platform-browser": "4.0.0-beta.98",
|
||||
"@testing-library/react": "^16.3.0",
|
||||
"effect": "4.0.0-beta.98",
|
||||
"jsdom": "^26.1.0",
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^19.2.0",
|
||||
"effect": "4.0.0-beta.85",
|
||||
"effect": "4.0.0-beta.98",
|
||||
"react": "^19.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"effect-lens": "2.0.0-beta.0"
|
||||
"effect-lens": "^2.0.0-beta.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Array, type Cause, Chunk, type Duration, Effect, Equal, Function, ident
|
||||
import type * as React from "react"
|
||||
import * as Component from "./Component.js"
|
||||
import * as Lens from "./Lens.js"
|
||||
import * as Subscribable from "./Subscribable.js"
|
||||
import * as View from "./View.js"
|
||||
|
||||
|
||||
export const FormTypeId: unique symbol = Symbol.for("@effect-fc/Form/Form")
|
||||
@@ -18,12 +18,12 @@ extends Pipeable.Pipeable {
|
||||
readonly [FormTypeId]: FormTypeId
|
||||
|
||||
readonly path: P
|
||||
readonly value: Subscribable.Subscribable<Option.Option<A>, ER, never>
|
||||
readonly value: View.View<Option.Option<A>, ER, never>
|
||||
readonly encodedValue: Lens.Lens<I, ER, EW, never, never>
|
||||
readonly issues: Subscribable.Subscribable<readonly FormIssue[], never, never>
|
||||
readonly isValidating: Subscribable.Subscribable<boolean, never, never>
|
||||
readonly canCommit: Subscribable.Subscribable<boolean, never, never>
|
||||
readonly isCommitting: Subscribable.Subscribable<boolean, never, never>
|
||||
readonly issues: View.View<readonly FormIssue[], never, never>
|
||||
readonly isValidating: View.View<boolean, never, never>
|
||||
readonly canCommit: View.View<boolean, never, never>
|
||||
readonly isCommitting: View.View<boolean, never, never>
|
||||
}
|
||||
|
||||
export class FormImpl<out P extends readonly PropertyKey[], in out A, in out I = A, in out ER = never, in out EW = never>
|
||||
@@ -32,12 +32,12 @@ extends Pipeable.Class implements Form<P, A, I, ER, EW> {
|
||||
|
||||
constructor(
|
||||
readonly path: P,
|
||||
readonly value: Subscribable.Subscribable<Option.Option<A>, ER, never>,
|
||||
readonly value: View.View<Option.Option<A>, ER, never>,
|
||||
readonly encodedValue: Lens.Lens<I, ER, EW, never, never>,
|
||||
readonly issues: Subscribable.Subscribable<readonly FormIssue[], never, never>,
|
||||
readonly isValidating: Subscribable.Subscribable<boolean, never, never>,
|
||||
readonly canCommit: Subscribable.Subscribable<boolean, never, never>,
|
||||
readonly isCommitting: Subscribable.Subscribable<boolean, never, never>,
|
||||
readonly issues: View.View<readonly FormIssue[], never, never>,
|
||||
readonly isValidating: View.View<boolean, never, never>,
|
||||
readonly canCommit: View.View<boolean, never, never>,
|
||||
readonly isCommitting: View.View<boolean, never, never>,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
@@ -71,9 +71,9 @@ export const focusObjectOn: {
|
||||
|
||||
return new FormImpl(
|
||||
path,
|
||||
Subscribable.mapOption(form.value, a => a[key]),
|
||||
View.mapOption(form.value, a => a[key]),
|
||||
Lens.focusObjectOn(form.encodedValue, key),
|
||||
Subscribable.map(form.issues, issues => filterIssuesByPath(issues, path)),
|
||||
View.map(form.issues, issues => filterIssuesByPath(issues, path)),
|
||||
form.isValidating,
|
||||
form.canCommit,
|
||||
form.isCommitting,
|
||||
@@ -97,9 +97,9 @@ export const focusArrayAt: {
|
||||
|
||||
return new FormImpl(
|
||||
path,
|
||||
Subscribable.mapOptionEffect(form.value, values => Effect.fromOption(Array.get(values, index))),
|
||||
View.mapOptionEffect(form.value, values => Effect.fromOption(Array.get(values, index))),
|
||||
Lens.focusArrayAt(form.encodedValue, index),
|
||||
Subscribable.map(form.issues, issues => filterIssuesByPath(issues, path)),
|
||||
View.map(form.issues, issues => filterIssuesByPath(issues, path)),
|
||||
form.isValidating,
|
||||
form.canCommit,
|
||||
form.isCommitting,
|
||||
@@ -123,9 +123,9 @@ export const focusTupleAt: {
|
||||
|
||||
return new FormImpl(
|
||||
path,
|
||||
Subscribable.mapOption(form.value, values => values[index]),
|
||||
View.mapOption(form.value, values => values[index]),
|
||||
Lens.focusTupleAt(form.encodedValue, index),
|
||||
Subscribable.map(form.issues, issues => filterIssuesByPath(issues, path)),
|
||||
View.map(form.issues, issues => filterIssuesByPath(issues, path)),
|
||||
form.isValidating,
|
||||
form.canCommit,
|
||||
form.isCommitting,
|
||||
@@ -149,9 +149,9 @@ export const focusChunkAt: {
|
||||
|
||||
return new FormImpl(
|
||||
path,
|
||||
Subscribable.mapOptionEffect(form.value, values => Effect.fromOption(Chunk.get(values, index))),
|
||||
View.mapOptionEffect(form.value, values => Effect.fromOption(Chunk.get(values, index))),
|
||||
Lens.focusChunkAt(form.encodedValue, index),
|
||||
Subscribable.map(form.issues, issues => filterIssuesByPath(issues, path)),
|
||||
View.map(form.issues, issues => filterIssuesByPath(issues, path)),
|
||||
form.isValidating,
|
||||
form.canCommit,
|
||||
form.isCommitting,
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
import { type Context, Effect, Equal, Exit, type Fiber, Option, Pipeable, Predicate, type Scope, Stream, SubscriptionRef } from "effect"
|
||||
import { AsyncResult } from "effect/unstable/reactivity"
|
||||
import * as Lens from "./Lens.js"
|
||||
import type * as Subscribable from "./Subscribable.js"
|
||||
import * as View from "./View.js"
|
||||
|
||||
|
||||
export const MutationTypeId: unique symbol = Symbol.for("@effect-fc/Mutation/Mutation")
|
||||
export type MutationTypeId = typeof MutationTypeId
|
||||
|
||||
export interface Mutation<in out K, in out A, in out E = never, in out R = never>
|
||||
export interface Mutation<in out K, out A, out E = never, in out R = never>
|
||||
extends Pipeable.Pipeable {
|
||||
readonly [MutationTypeId]: MutationTypeId
|
||||
|
||||
readonly context: Context.Context<Scope.Scope | R>
|
||||
readonly f: (key: K) => Effect.Effect<A, E, R>
|
||||
|
||||
readonly latestKey: Subscribable.Subscribable<Option.Option<K>>
|
||||
readonly fiber: Subscribable.Subscribable<Option.Option<Fiber.Fiber<A, E>>>
|
||||
readonly result: Subscribable.Subscribable<AsyncResult.AsyncResult<A, E>>
|
||||
readonly latestFinalResult: Subscribable.Subscribable<Option.Option<AsyncResult.Success<A, E> | AsyncResult.Failure<A, E>>>
|
||||
readonly latestKey: View.View<Option.Option<K>>
|
||||
readonly fiber: View.View<Option.Option<Fiber.Fiber<A, E>>>
|
||||
readonly state: View.View<AsyncResult.AsyncResult<A, E>>
|
||||
readonly latestFinalResult: View.View<Option.Option<AsyncResult.Success<A, E> | AsyncResult.Failure<A, E>>>
|
||||
|
||||
mutate(key: K): Effect.Effect<AsyncResult.Success<A, E> | AsyncResult.Failure<A, E>>
|
||||
mutateSubscribable(key: K): Effect.Effect<Subscribable.Subscribable<AsyncResult.AsyncResult<A, E>>>
|
||||
mutateView(key: K): Effect.Effect<View.View<AsyncResult.AsyncResult<A, E>>>
|
||||
}
|
||||
|
||||
export const isMutation = (u: unknown): u is Mutation<unknown, unknown, unknown, unknown> => Predicate.hasProperty(u, MutationTypeId)
|
||||
@@ -36,7 +36,7 @@ extends Pipeable.Class implements Mutation<K, A, E, R> {
|
||||
|
||||
readonly latestKey: Lens.Lens<Option.Option<K>>,
|
||||
readonly fiber: Lens.Lens<Option.Option<Fiber.Fiber<A, E>>>,
|
||||
readonly result: Lens.Lens<AsyncResult.AsyncResult<A, E>>,
|
||||
readonly state: Lens.Lens<AsyncResult.AsyncResult<A, E>>,
|
||||
readonly latestFinalResult: Lens.Lens<Option.Option<AsyncResult.Success<A, E> | AsyncResult.Failure<A, E>>>,
|
||||
) {
|
||||
super()
|
||||
@@ -49,7 +49,7 @@ extends Pipeable.Class implements Mutation<K, A, E, R> {
|
||||
Effect.provide(this.context),
|
||||
)
|
||||
}
|
||||
mutateSubscribable(key: K): Effect.Effect<Subscribable.Subscribable<AsyncResult.AsyncResult<A, E>>> {
|
||||
mutateView(key: K): Effect.Effect<View.View<AsyncResult.AsyncResult<A, E>>> {
|
||||
return Lens.set(this.latestKey, Option.some(key)).pipe(
|
||||
Effect.andThen(this.start(key)),
|
||||
Effect.tap(state => Effect.forkScoped(this.watch(state))),
|
||||
@@ -58,7 +58,7 @@ extends Pipeable.Class implements Mutation<K, A, E, R> {
|
||||
}
|
||||
|
||||
start(key: K): Effect.Effect<
|
||||
Subscribable.Subscribable<AsyncResult.AsyncResult<A, E>>,
|
||||
View.View<AsyncResult.AsyncResult<A, E>>,
|
||||
never,
|
||||
Scope.Scope | R
|
||||
> {
|
||||
@@ -114,13 +114,13 @@ extends Pipeable.Class implements Mutation<K, A, E, R> {
|
||||
}
|
||||
|
||||
watch(
|
||||
state: Subscribable.Subscribable<AsyncResult.AsyncResult<A, E>>
|
||||
state: View.View<AsyncResult.AsyncResult<A, E>>
|
||||
): Effect.Effect<AsyncResult.Success<A, E> | AsyncResult.Failure<A, E>> {
|
||||
return state.get.pipe(
|
||||
return View.get(state).pipe(
|
||||
Effect.andThen(initial => Stream.runFoldEffect(
|
||||
state.changes,
|
||||
View.changes(state),
|
||||
() => initial,
|
||||
(_, result) => Effect.as(Lens.set(this.result, result), result),
|
||||
(_, result) => Effect.as(Lens.set(this.state, result), result),
|
||||
) as Effect.Effect<AsyncResult.Success<A, E> | AsyncResult.Failure<A, E>>),
|
||||
Effect.tap(result => Lens.set(this.latestFinalResult, Option.some(result))),
|
||||
)
|
||||
|
||||
@@ -2,44 +2,44 @@ import { type Cause, type Context, Duration, Effect, Equal, type Equivalence, Ex
|
||||
import { AsyncResult } from "effect/unstable/reactivity"
|
||||
import * as Lens from "./Lens.js"
|
||||
import * as QueryClient from "./QueryClient.js"
|
||||
import * as Subscribable from "./Subscribable.js"
|
||||
import * as View from "./View.js"
|
||||
|
||||
|
||||
export const QueryTypeId: unique symbol = Symbol.for("@effect-fc/Query/Query")
|
||||
export type QueryTypeId = typeof QueryTypeId
|
||||
|
||||
export interface Query<in out K, in out A, in out E = never, in out R = never>
|
||||
export interface Query<in out K, out A, out E = never, in out R = never>
|
||||
extends Pipeable.Pipeable {
|
||||
readonly [QueryTypeId]: QueryTypeId
|
||||
|
||||
readonly context: Context.Context<Scope.Scope | QueryClient.QueryClient | R>
|
||||
readonly key: Subscribable.Subscribable<K>
|
||||
readonly key: View.View<K>
|
||||
readonly keyEquivalence: Equivalence.Equivalence<K>
|
||||
readonly f: (key: K) => Effect.Effect<A, E, R>
|
||||
|
||||
readonly staleTime: Duration.Duration
|
||||
readonly refreshOnWindowFocus: boolean
|
||||
|
||||
readonly fiber: Subscribable.Subscribable<Option.Option<Fiber.Fiber<A, E>>>
|
||||
readonly state: Subscribable.Subscribable<QueryState<K, A, E>>
|
||||
readonly latestFinalState: Subscribable.Subscribable<Option.Option<FinalQueryState<K, A, E>>>
|
||||
readonly fiber: View.View<Option.Option<Fiber.Fiber<A, E>>>
|
||||
readonly state: View.View<QueryState<K, A, E>>
|
||||
readonly latestFinalState: View.View<Option.Option<FinalQueryState<K, A, E>>>
|
||||
|
||||
readonly run: Effect.Effect<void>
|
||||
fetch(key: K): Effect.Effect<FinalQueryState<K, A, E>, Cause.NoSuchElementError>
|
||||
fetchSubscribable(key: K): Effect.Effect<Subscribable.Subscribable<QueryState<K, A, E>>, Cause.NoSuchElementError>
|
||||
fetchView(key: K): Effect.Effect<View.View<QueryState<K, A, E>>, Cause.NoSuchElementError>
|
||||
readonly refresh: Effect.Effect<FinalQueryState<K, A, E>, Cause.NoSuchElementError>
|
||||
readonly refreshSubscribable: Effect.Effect<Subscribable.Subscribable<QueryState<K, A, E>>, Cause.NoSuchElementError>
|
||||
readonly refreshView: Effect.Effect<View.View<QueryState<K, A, E>>, Cause.NoSuchElementError>
|
||||
|
||||
readonly invalidateCache: Effect.Effect<void>
|
||||
invalidateCacheEntry(key: K): Effect.Effect<void>
|
||||
}
|
||||
|
||||
export interface QueryState<in out K, in out A, in out E = never> {
|
||||
export interface QueryState<out K, out A, out E = never> {
|
||||
readonly key: K
|
||||
readonly result: AsyncResult.AsyncResult<A, E>
|
||||
}
|
||||
|
||||
export interface FinalQueryState<in out K, in out A, in out E = never> {
|
||||
export interface FinalQueryState<out K, out A, out E = never> {
|
||||
readonly key: K
|
||||
readonly result: AsyncResult.Success<A, E> | AsyncResult.Failure<A, E>
|
||||
}
|
||||
@@ -53,7 +53,7 @@ extends Pipeable.Class implements Query<K, A, E, R> {
|
||||
|
||||
constructor(
|
||||
readonly context: Context.Context<Scope.Scope | QueryClient.QueryClient | R>,
|
||||
readonly key: Subscribable.Subscribable<K>,
|
||||
readonly key: View.View<K>,
|
||||
readonly keyEquivalence: Equivalence.Equivalence<K>,
|
||||
readonly f: (key: K) => Effect.Effect<A, E, R>,
|
||||
|
||||
@@ -94,7 +94,7 @@ extends Pipeable.Class implements Query<K, A, E, R> {
|
||||
Effect.flatMap(({ BrowserStream }) => this.refreshOnWindowFocus
|
||||
? Stream.runForEach(
|
||||
BrowserStream.fromEventListenerWindow("focus"),
|
||||
() => this.refreshSubscribable,
|
||||
() => this.refreshView,
|
||||
)
|
||||
: Effect.void
|
||||
),
|
||||
@@ -127,8 +127,8 @@ extends Pipeable.Class implements Query<K, A, E, R> {
|
||||
)
|
||||
}
|
||||
|
||||
fetchSubscribable(key: K): Effect.Effect<
|
||||
Subscribable.Subscribable<QueryState<K, A, E>>,
|
||||
fetchView(key: K): Effect.Effect<
|
||||
View.View<QueryState<K, A, E>>,
|
||||
Cause.NoSuchElementError
|
||||
> {
|
||||
return Effect.gen({ self: this }, function*() {
|
||||
@@ -166,8 +166,8 @@ extends Pipeable.Class implements Query<K, A, E, R> {
|
||||
)
|
||||
}
|
||||
|
||||
get refreshSubscribable(): Effect.Effect<
|
||||
Subscribable.Subscribable<QueryState<K, A, E>>,
|
||||
get refreshView(): Effect.Effect<
|
||||
View.View<QueryState<K, A, E>>,
|
||||
Cause.NoSuchElementError
|
||||
> {
|
||||
return Effect.gen({ self: this }, function*() {
|
||||
@@ -194,7 +194,7 @@ extends Pipeable.Class implements Query<K, A, E, R> {
|
||||
startCached(
|
||||
previous: QueryState<K, A, E>,
|
||||
): Effect.Effect<
|
||||
Subscribable.Subscribable<QueryState<K, A, E>>,
|
||||
View.View<QueryState<K, A, E>>,
|
||||
Cause.NoSuchElementError,
|
||||
Scope.Scope | QueryClient.QueryClient | R
|
||||
> {
|
||||
@@ -206,7 +206,7 @@ extends Pipeable.Class implements Query<K, A, E, R> {
|
||||
key: previous.key,
|
||||
result: entry.result as AsyncResult.AsyncResult<A, E>,
|
||||
})
|
||||
: Effect.succeed(Subscribable.make({
|
||||
: Effect.succeed(View.make({
|
||||
get: Effect.succeed({
|
||||
key: previous.key,
|
||||
result: entry.result as AsyncResult.AsyncResult<A, E>,
|
||||
@@ -226,15 +226,15 @@ extends Pipeable.Class implements Query<K, A, E, R> {
|
||||
start(
|
||||
previous: QueryState<K, A, E>,
|
||||
): Effect.Effect<
|
||||
Subscribable.Subscribable<QueryState<K, A, E>>,
|
||||
View.View<QueryState<K, A, E>>,
|
||||
never,
|
||||
Scope.Scope | R
|
||||
> {
|
||||
return Effect.gen({ self: this }, function*() {
|
||||
const subscribable = Lens.fromSubscriptionRef(yield* SubscriptionRef.make(previous))
|
||||
const state = Lens.fromSubscriptionRef(yield* SubscriptionRef.make(previous))
|
||||
|
||||
const fiber = yield* Effect.forkScoped(Effect.andThen(
|
||||
Lens.update(subscribable, previous => AsyncResult.match(previous.result, {
|
||||
Lens.update(state, previous => AsyncResult.match(previous.result, {
|
||||
onInitial: () => ({
|
||||
key: previous.key,
|
||||
result: AsyncResult.initial(true),
|
||||
@@ -255,7 +255,7 @@ extends Pipeable.Class implements Query<K, A, E, R> {
|
||||
})),
|
||||
|
||||
Effect.onExit(this.f(previous.key), exit => Lens.update(
|
||||
subscribable,
|
||||
state,
|
||||
previous => Exit.match(exit, {
|
||||
onSuccess: v => ({
|
||||
key: previous.key,
|
||||
@@ -295,17 +295,17 @@ extends Pipeable.Class implements Query<K, A, E, R> {
|
||||
))
|
||||
|
||||
yield* Lens.set(this.fiber, Option.some(fiber))
|
||||
return subscribable
|
||||
return state
|
||||
})
|
||||
}
|
||||
|
||||
watch(
|
||||
subscribable: Subscribable.Subscribable<QueryState<K, A, E>>
|
||||
view: View.View<QueryState<K, A, E>>
|
||||
): Effect.Effect<FinalQueryState<K, A, E>, never, QueryClient.QueryClient> {
|
||||
return Effect.gen({ self: this }, function*() {
|
||||
const initial = yield* subscribable.get
|
||||
const initial = yield* View.get(view)
|
||||
const final = yield* Stream.runFoldEffect(
|
||||
subscribable.changes,
|
||||
View.changes(view),
|
||||
() => initial,
|
||||
(_, state) => Effect.as(Lens.set(this.state, state), state),
|
||||
) as Effect.Effect<FinalQueryState<K, A, E>>
|
||||
@@ -367,7 +367,7 @@ extends Pipeable.Class implements Query<K, A, E, R> {
|
||||
|
||||
export declare namespace make {
|
||||
export interface Options<K, A, E = never, R = never> {
|
||||
readonly key: Subscribable.Subscribable<K>,
|
||||
readonly key: View.View<K>,
|
||||
readonly keyEquivalence?: Equivalence.Equivalence<K>,
|
||||
readonly f: (key: K) => Effect.Effect<A, E, R>
|
||||
|
||||
@@ -396,7 +396,7 @@ export const make = Effect.fnUntraced(function* <K, A, E = never, R = never>(
|
||||
|
||||
Lens.fromSubscriptionRef(yield* SubscriptionRef.make(Option.none<Fiber.Fiber<A, E>>())),
|
||||
Lens.fromSubscriptionRef(yield* SubscriptionRef.make<QueryState<K, A, E>>({
|
||||
key: yield* options.key.get,
|
||||
key: yield* View.get(options.key),
|
||||
result: AsyncResult.initial(false),
|
||||
})),
|
||||
Lens.fromSubscriptionRef(yield* SubscriptionRef.make(Option.none<FinalQueryState<K, A, E>>())),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { type Cause, Context, DateTime, Duration, Effect, Equal, Equivalence, Hash, HashMap, type Option, Pipeable, Predicate, Schedule, type Scope, Semaphore, SubscriptionRef } from "effect"
|
||||
import type { AsyncResult } from "effect/unstable/reactivity"
|
||||
import * as Lens from "./Lens.js"
|
||||
import type * as Subscribable from "./Subscribable.js"
|
||||
import type * as View from "./View.js"
|
||||
|
||||
|
||||
export const QueryClientServiceTypeId: unique symbol = Symbol.for("@effect-fc/QueryClient/QueryClientService")
|
||||
@@ -10,7 +10,7 @@ export type QueryClientServiceTypeId = typeof QueryClientServiceTypeId
|
||||
export interface QueryClientService extends Pipeable.Pipeable {
|
||||
readonly [QueryClientServiceTypeId]: QueryClientServiceTypeId
|
||||
|
||||
readonly cache: Subscribable.Subscribable<HashMap.HashMap<QueryClientCacheKey, QueryClientCacheEntry>>
|
||||
readonly cache: View.View<HashMap.HashMap<QueryClientCacheKey, QueryClientCacheEntry>>
|
||||
readonly cacheGcTime: Duration.Duration
|
||||
readonly defaultStaleTime: Duration.Duration
|
||||
readonly defaultRefreshOnWindowFocus: boolean
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Cause, Context, Data, Effect, Equal, Exit, type Fiber, Hash, Layer, Match, Pipeable, Predicate, pipe, type Scope, SubscriptionRef } from "effect"
|
||||
import { Lens, Subscribable } from "effect-lens"
|
||||
import { Lens } from "effect-lens"
|
||||
import type { View } from "effect-lens/View"
|
||||
|
||||
|
||||
export const ResultTypeId: unique symbol = Symbol.for("@effect-fc/Result/Result")
|
||||
@@ -207,7 +208,7 @@ export const unsafeForkEffect = Effect.fnUntraced(function* <A, E, R, P = never>
|
||||
effect: Effect.Effect<A, E, R>,
|
||||
options?: unsafeForkEffect.Options<NoInfer<A>, NoInfer<E>, P>,
|
||||
): Effect.fn.Return<
|
||||
readonly [result: Subscribable.Subscribable<Result<A, E, P>, never, never>, fiber: Fiber.Fiber<A, E>],
|
||||
readonly [result: View<Result<A, E, P>, never, never>, fiber: Fiber.Fiber<A, E>],
|
||||
never,
|
||||
Scope.Scope | unsafeForkEffect.OutputContext<R, P>
|
||||
> {
|
||||
@@ -242,7 +243,7 @@ export const forkEffect: {
|
||||
effect: Effect.Effect<A, E, forkEffect.InputContext<R, NoInfer<P>>>,
|
||||
options?: forkEffect.Options<NoInfer<A>, NoInfer<E>, P>,
|
||||
): Effect.Effect<
|
||||
readonly [result: Subscribable.Subscribable<Result<A, E, P>, never, never>, fiber: Fiber.Fiber<A, E>],
|
||||
readonly [result: View<Result<A, E, P>, never, never>, fiber: Fiber.Fiber<A, E>],
|
||||
never,
|
||||
Scope.Scope | forkEffect.OutputContext<R, P>
|
||||
>
|
||||
|
||||
@@ -18,7 +18,7 @@ import * as Form from "./Form.js"
|
||||
import * as Lens from "./Lens.js"
|
||||
import * as Mutation from "./Mutation.js"
|
||||
import * as Result from "./Result.js"
|
||||
import * as Subscribable from "./Subscribable.js"
|
||||
import * as View from "./View.js"
|
||||
|
||||
|
||||
type FormSchema<A, I, R> = Schema.Top & {
|
||||
@@ -39,7 +39,7 @@ extends Form.Form<readonly [], A, I, never, never> {
|
||||
readonly [value: A, form: SubmittableForm<A, I, R, unknown, unknown, unknown>],
|
||||
MA, ME, MR, MP
|
||||
>
|
||||
readonly validationFiber: Subscribable.Subscribable<Option.Option<Fiber.Fiber<A, SchemaIssue.Issue>>, never, never>
|
||||
readonly validationFiber: View.View<Option.Option<Fiber.Fiber<A, SchemaIssue.Issue>>, never, never>
|
||||
readonly run: Effect.Effect<void>
|
||||
readonly submit: Effect.Effect<Option.Option<Result.Final<MA, ME, MP>>, Cause.NoSuchElementError>
|
||||
}
|
||||
@@ -50,9 +50,9 @@ extends Pipeable.Class implements SubmittableForm<A, I, R, MA, ME, MR, MP> {
|
||||
readonly [SubmittableFormTypeId]: SubmittableFormTypeId = SubmittableFormTypeId
|
||||
readonly path = [] as const
|
||||
readonly encodedValue: Lens.Lens<I, never, never, never, never>
|
||||
readonly isValidating: Subscribable.Subscribable<boolean, never, never>
|
||||
readonly canCommit: Subscribable.Subscribable<boolean, never, never>
|
||||
readonly isCommitting: Subscribable.Subscribable<boolean, never, never>
|
||||
readonly isValidating: View.View<boolean, never, never>
|
||||
readonly canCommit: View.View<boolean, never, never>
|
||||
readonly isCommitting: View.View<boolean, never, never>
|
||||
|
||||
constructor(
|
||||
readonly schema: FormSchema<A, I, R>,
|
||||
@@ -77,26 +77,26 @@ extends Pipeable.Class implements SubmittableForm<A, I, R, MA, ME, MR, MP> {
|
||||
),
|
||||
lock: Lens.asLensImpl(internalEncodedValue).lock,
|
||||
})
|
||||
this.isValidating = Subscribable.map(validationFiber, Option.isSome)
|
||||
const commitState = Subscribable.zipLatestAll(
|
||||
this.isValidating = View.map(validationFiber, Option.isSome)
|
||||
const commitState = View.zipLatestAll(
|
||||
value as any,
|
||||
issues as any,
|
||||
validationFiber as any,
|
||||
mutation.result as any,
|
||||
) as unknown as Subscribable.Subscribable<readonly [
|
||||
) as unknown as View.View<readonly [
|
||||
Option.Option<A>,
|
||||
readonly Form.FormIssue[],
|
||||
Option.Option<Fiber.Fiber<A, SchemaIssue.Issue>>,
|
||||
Result.Result<MA, ME, MP>,
|
||||
]>
|
||||
this.canCommit = Subscribable.map(
|
||||
this.canCommit = View.map(
|
||||
commitState,
|
||||
([current, currentIssues, fiber, result]: readonly [Option.Option<A>, readonly Form.FormIssue[], Option.Option<Fiber.Fiber<A, SchemaIssue.Issue>>, Result.Result<MA, ME, MP>]) => Option.isSome(current)
|
||||
&& currentIssues.length === 0
|
||||
&& Option.isNone(fiber)
|
||||
&& !(Result.isRunning(result) || Result.hasRefreshingFlag(result)),
|
||||
)
|
||||
this.isCommitting = Subscribable.map(
|
||||
this.isCommitting = View.map(
|
||||
mutation.result,
|
||||
result => Result.isRunning(result) || Result.hasRefreshingFlag(result),
|
||||
)
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
import { Effect, Equivalence, Stream } from "effect"
|
||||
import { Subscribable } from "effect-lens"
|
||||
import * as React from "react"
|
||||
import * as Component from "./Component.js"
|
||||
|
||||
|
||||
export * from "effect-lens/Subscribable"
|
||||
|
||||
export const zipLatestAll = <const T extends readonly Subscribable.Subscribable<any, any, any>[]>(
|
||||
...elements: T
|
||||
): Subscribable.Subscribable<
|
||||
[T[number]] extends [never]
|
||||
? never
|
||||
: { [K in keyof T]: T[K] extends Subscribable.Subscribable<infer A, infer _E, infer _R> ? A : never },
|
||||
[T[number]] extends [never] ? never : T[number] extends Subscribable.Subscribable<infer _A, infer E, infer _R> ? E : never,
|
||||
[T[number]] extends [never] ? never : T[number] extends Subscribable.Subscribable<infer _A, infer _E, infer R> ? R : never
|
||||
> => Subscribable.make({
|
||||
get: Effect.all(elements.map(v => v.get)),
|
||||
changes: Stream.zipLatestAll(...elements.map(v => v.changes)),
|
||||
}) as any
|
||||
|
||||
export declare namespace useAll {
|
||||
export type Success<T extends readonly Subscribable.Subscribable<any, any, any>[]> = [T[number]] extends [never]
|
||||
? never
|
||||
: { [K in keyof T]: T[K] extends Subscribable.Subscribable<infer A, infer _E, infer _R> ? A : never }
|
||||
|
||||
export interface Options<A> {
|
||||
readonly equivalence?: Equivalence.Equivalence<A>
|
||||
}
|
||||
}
|
||||
|
||||
export const useAll = Effect.fnUntraced(function* <const T extends readonly Subscribable.Subscribable<any, any, any>[]>(
|
||||
elements: T,
|
||||
options?: useAll.Options<useAll.Success<NoInfer<T>>>,
|
||||
): Effect.fn.Return<
|
||||
useAll.Success<T>,
|
||||
[T[number]] extends [never] ? never : T[number] extends Subscribable.Subscribable<infer _A, infer E, infer _R> ? E : never,
|
||||
[T[number]] extends [never] ? never : T[number] extends Subscribable.Subscribable<infer _A, infer _E, infer R> ? R : never
|
||||
> {
|
||||
const [reactStateValue, setReactStateValue] = React.useState(
|
||||
yield* Component.useOnMount(() => Effect.all(elements.map(v => v.get)))
|
||||
)
|
||||
|
||||
yield* Component.useReactEffect(() => Stream.zipLatestAll(...elements.map(ref => ref.changes)).pipe(
|
||||
Stream.changesWith((options?.equivalence as Equivalence.Equivalence<any[]> | undefined) ?? Equivalence.Array(Equivalence.strictEqual())),
|
||||
Stream.runForEach(v =>
|
||||
Effect.sync(() => setReactStateValue(v))
|
||||
),
|
||||
Effect.forkScoped,
|
||||
), elements)
|
||||
|
||||
return reactStateValue as any
|
||||
})
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
} from "effect"
|
||||
import * as Form from "./Form.js"
|
||||
import * as Lens from "./Lens.js"
|
||||
import * as Subscribable from "./Subscribable.js"
|
||||
import * as View from "./View.js"
|
||||
|
||||
|
||||
type FormSchema<A, I, R> = Schema.Top & {
|
||||
@@ -43,7 +43,7 @@ export interface SynchronizedForm<
|
||||
readonly schema: FormSchema<A, I, R>
|
||||
readonly context: Context.Context<Scope.Scope | R | TRR | TRW>
|
||||
readonly target: Lens.Lens<A, TER, TEW, TRR, TRW>
|
||||
readonly validationFiber: Subscribable.Subscribable<Option.Option<Fiber.Fiber<A, SchemaIssue.Issue>>, never, never>
|
||||
readonly validationFiber: View.View<Option.Option<Fiber.Fiber<A, SchemaIssue.Issue>>, never, never>
|
||||
readonly run: Effect.Effect<void, TER>
|
||||
}
|
||||
|
||||
@@ -59,10 +59,10 @@ export class SynchronizedFormImpl<
|
||||
readonly [Form.FormTypeId]: Form.FormTypeId = Form.FormTypeId
|
||||
readonly [SynchronizedFormTypeId]: SynchronizedFormTypeId = SynchronizedFormTypeId
|
||||
readonly path = [] as const
|
||||
readonly value: Subscribable.Subscribable<Option.Option<A>, TER, never>
|
||||
readonly value: View.View<Option.Option<A>, TER, never>
|
||||
readonly encodedValue: Lens.Lens<I, TER, TER | TEW, never, never>
|
||||
readonly isValidating: Subscribable.Subscribable<boolean, never, never>
|
||||
readonly canCommit: Subscribable.Subscribable<boolean, never, never>
|
||||
readonly isValidating: View.View<boolean, never, never>
|
||||
readonly canCommit: View.View<boolean, never, never>
|
||||
|
||||
constructor(
|
||||
readonly schema: FormSchema<A, I, R>,
|
||||
@@ -75,7 +75,7 @@ export class SynchronizedFormImpl<
|
||||
readonly runSemaphore: Semaphore.Semaphore,
|
||||
) {
|
||||
super()
|
||||
this.value = Subscribable.make({
|
||||
this.value = View.make({
|
||||
get: Effect.provide(Effect.map(target.get, Option.some), context),
|
||||
changes: Stream.provideContext(
|
||||
target.changes.pipe(
|
||||
@@ -94,13 +94,13 @@ export class SynchronizedFormImpl<
|
||||
),
|
||||
lock: Lens.asLensImpl(internalEncodedValue).lock,
|
||||
}) as unknown as Lens.Lens<I, TER, TER | TEW, never, never>
|
||||
this.isValidating = Subscribable.map(validationFiber, Option.isSome)
|
||||
const commitState = Subscribable.zipLatestAll(issues as any, validationFiber as any, isCommitting as any) as unknown as Subscribable.Subscribable<readonly [
|
||||
this.isValidating = View.map(validationFiber, Option.isSome)
|
||||
const commitState = View.zipLatestAll(issues as any, validationFiber as any, isCommitting as any) as unknown as View.View<readonly [
|
||||
readonly Form.FormIssue[],
|
||||
Option.Option<Fiber.Fiber<A, SchemaIssue.Issue>>,
|
||||
boolean,
|
||||
]>
|
||||
this.canCommit = Subscribable.map(
|
||||
this.canCommit = View.map(
|
||||
commitState,
|
||||
([currentIssues, fiber, committing]) => currentIssues.length === 0 && Option.isNone(fiber) && !committing,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Effect, Equivalence, Stream } from "effect"
|
||||
import { View } from "effect-lens"
|
||||
import * as React from "react"
|
||||
import * as Component from "./Component.js"
|
||||
|
||||
|
||||
export * from "effect-lens/View"
|
||||
|
||||
export declare namespace useAll {
|
||||
export type Success<T extends readonly View.View<any, any, any>[]> = [T[number]] extends [never]
|
||||
? never
|
||||
: { [K in keyof T]: T[K] extends View.View<infer A, infer _E, infer _R> ? A : never }
|
||||
|
||||
export interface Options<A> {
|
||||
readonly equivalence?: Equivalence.Equivalence<A>
|
||||
}
|
||||
}
|
||||
|
||||
export const useAll = Effect.fnUntraced(function* <const T extends readonly View.View<any, any, any>[]>(
|
||||
elements: T,
|
||||
options?: useAll.Options<useAll.Success<NoInfer<T>>>,
|
||||
): Effect.fn.Return<
|
||||
useAll.Success<T>,
|
||||
[T[number]] extends [never] ? never : T[number] extends View.View<infer _A, infer E, infer _R> ? E : never,
|
||||
[T[number]] extends [never] ? never : T[number] extends View.View<infer _A, infer _E, infer R> ? R : never
|
||||
> {
|
||||
const [reactStateValue, setReactStateValue] = React.useState(
|
||||
yield* Component.useOnMount(() => Effect.all(elements.map(View.get)))
|
||||
)
|
||||
|
||||
yield* Component.useReactEffect(() => View.changes(View.zipLatestAll(...elements)).pipe(
|
||||
Stream.changesWith((options?.equivalence as Equivalence.Equivalence<any[]> | undefined) ?? Equivalence.Array(Equivalence.strictEqual())),
|
||||
Stream.runForEach(v =>
|
||||
Effect.sync(() => setReactStateValue(v))
|
||||
),
|
||||
Effect.forkScoped,
|
||||
), elements)
|
||||
|
||||
return reactStateValue as any
|
||||
})
|
||||
@@ -13,5 +13,5 @@ export * as Result from "./Result.js"
|
||||
export * as SetStateAction from "./SetStateAction.js"
|
||||
export * as Stream from "./Stream.js"
|
||||
export * as SubmittableForm from "./SubmittableForm.js"
|
||||
export * as Subscribable from "./Subscribable.js"
|
||||
export * as SynchronizedForm from "./SynchronizedForm.js"
|
||||
export * as View from "./View.js"
|
||||
|
||||
+7
-42
@@ -1,10 +1,10 @@
|
||||
import { render, screen, waitFor } from "@testing-library/react"
|
||||
import { Effect, Fiber, Layer, Stream, SubscriptionRef } from "effect"
|
||||
import { Effect, Layer, SubscriptionRef } from "effect"
|
||||
import { Lens } from "effect-lens"
|
||||
import { describe, expect, it } from "vitest"
|
||||
import * as Component from "../src/Component.js"
|
||||
import * as ReactRuntime from "../src/ReactRuntime.js"
|
||||
import * as Subscribable from "../src/Subscribable.js"
|
||||
import * as View from "../src/View.js"
|
||||
|
||||
|
||||
const makeRuntime = async () => {
|
||||
@@ -18,42 +18,7 @@ const makeRuntime = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
describe("Subscribable", () => {
|
||||
it("zipLatestAll reads current values from all inputs", async () => {
|
||||
const leftRef = await Effect.runPromise(SubscriptionRef.make(1))
|
||||
const rightRef = await Effect.runPromise(SubscriptionRef.make("a"))
|
||||
const left = Lens.fromSubscriptionRef(leftRef)
|
||||
const right = Lens.fromSubscriptionRef(rightRef)
|
||||
|
||||
const zipped = Subscribable.zipLatestAll(left, right)
|
||||
|
||||
expect(await Effect.runPromise(zipped.get)).toEqual([1, "a"])
|
||||
})
|
||||
|
||||
it("zipLatestAll emits updates when any input changes", async () => {
|
||||
const leftRef = await Effect.runPromise(SubscriptionRef.make(1))
|
||||
const rightRef = await Effect.runPromise(SubscriptionRef.make("a"))
|
||||
const left = Lens.fromSubscriptionRef(leftRef)
|
||||
const right = Lens.fromSubscriptionRef(rightRef)
|
||||
|
||||
const zipped = Subscribable.zipLatestAll(left, right)
|
||||
const values: Array<readonly [number, string]> = []
|
||||
|
||||
const collector = Effect.runFork(Effect.scoped(zipped.changes.pipe(
|
||||
Stream.runForEach(value => Effect.sync(() => {
|
||||
values.push(value as readonly [number, string])
|
||||
})),
|
||||
)))
|
||||
|
||||
await Effect.runPromise(Lens.set(left, 2))
|
||||
await waitFor(() => expect(values).toContainEqual([2, "a"]))
|
||||
|
||||
await Effect.runPromise(Lens.set(right, "b"))
|
||||
await waitFor(() => expect(values).toContainEqual([2, "b"]))
|
||||
|
||||
await Effect.runPromise(Fiber.interrupt(collector))
|
||||
})
|
||||
|
||||
describe("View", () => {
|
||||
it("useAll returns the latest values and rerenders when any input changes", async () => {
|
||||
const { runtime, effectRuntime, dispose } = await makeRuntime()
|
||||
const countRef = await Effect.runPromise(SubscriptionRef.make(1))
|
||||
@@ -61,8 +26,8 @@ describe("Subscribable", () => {
|
||||
const count = Lens.fromSubscriptionRef(countRef)
|
||||
const label = Lens.fromSubscriptionRef(labelRef)
|
||||
|
||||
const Probe = Component.makeUntraced("SubscribableUseAllProbe")(function*() {
|
||||
const [currentCount, currentLabel] = yield* Subscribable.useAll([count, label])
|
||||
const Probe = Component.makeUntraced("ViewUseAllProbe")(function*() {
|
||||
const [currentCount, currentLabel] = yield* View.useAll([count, label])
|
||||
|
||||
return <div>{`${currentCount}:${currentLabel}`}</div>
|
||||
}).pipe(
|
||||
@@ -94,8 +59,8 @@ describe("Subscribable", () => {
|
||||
const item = Lens.fromSubscriptionRef(itemRef)
|
||||
const flag = Lens.fromSubscriptionRef(flagRef)
|
||||
|
||||
const Probe = Component.makeUntraced("SubscribableUseAllEquivalenceProbe")(function*() {
|
||||
const [currentItem, currentFlag] = yield* Subscribable.useAll([item, flag], {
|
||||
const Probe = Component.makeUntraced("ViewUseAllEquivalenceProbe")(function*() {
|
||||
const [currentItem, currentFlag] = yield* View.useAll([item, flag], {
|
||||
equivalence: ([selfItem, selfFlag], [thatItem, thatFlag]) =>
|
||||
selfItem.id === thatItem.id && selfFlag === thatFlag,
|
||||
})
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Effect, Layer, SubscriptionRef } from "effect"
|
||||
import { Component, Lens, ReactRuntime, Subscribable } from "effect-fc-next"
|
||||
import { Component, Lens, ReactRuntime, View } from "effect-fc-next"
|
||||
import { StrictMode } from "react"
|
||||
import { createRoot } from "react-dom/client"
|
||||
import "./index.css"
|
||||
@@ -10,7 +10,7 @@ const Counter = Component.make("Counter")(function*() {
|
||||
SubscriptionRef.make(0),
|
||||
Lens.fromSubscriptionRef,
|
||||
))
|
||||
const [value] = yield* Subscribable.useAll([count])
|
||||
const [value] = yield* View.useAll([count])
|
||||
const increment = yield* Component.useCallbackSync(
|
||||
() => Lens.update(count, n => n + 1),
|
||||
[count],
|
||||
|
||||
Reference in New Issue
Block a user