diff --git a/.changeset/hot-jokes-push.md b/.changeset/hot-jokes-push.md
new file mode 100644
index 0000000..e2914e1
--- /dev/null
+++ b/.changeset/hot-jokes-push.md
@@ -0,0 +1,6 @@
+---
+"@effect-rx/rx": minor
+"@effect-rx/rx-react": minor
+---
+
+consolidate Rx constructors
diff --git a/docs/rx-react/index.ts.md b/docs/rx-react/index.ts.md
index 26bceef..54f67fb 100644
--- a/docs/rx-react/index.ts.md
+++ b/docs/rx-react/index.ts.md
@@ -95,7 +95,7 @@ Added in v1.0.0
**Signature**
```ts
-export declare const useRxRefresh: (rx: any) => () => void
+export declare const useRxRefresh: (rx: Rx.Rx & Rx.Refreshable) => () => void
```
Added in v1.0.0
@@ -144,7 +144,7 @@ Added in v1.0.0
export declare const useRxSuspense: (
rx: Rx.Rx>,
options?: { readonly suspendOnWaiting?: boolean }
-) => any
+) => Result.Success | Result.Failure
```
Added in v1.0.0
@@ -181,7 +181,7 @@ Re-exports all named exports from the "@effect-rx/rx/Registry" module as `Regist
**Signature**
```ts
-export * as Registry from '@effect-rx/rx/Registry'
+export * as Registry from "@effect-rx/rx/Registry"
```
Added in v1.0.0
@@ -193,7 +193,7 @@ Re-exports all named exports from the "@effect-rx/rx/Result" module as `Result`.
**Signature**
```ts
-export * as Result from '@effect-rx/rx/Result'
+export * as Result from "@effect-rx/rx/Result"
```
Added in v1.0.0
@@ -205,7 +205,7 @@ Re-exports all named exports from the "@effect-rx/rx/Rx" module as `Rx`.
**Signature**
```ts
-export * as Rx from '@effect-rx/rx/Rx'
+export * as Rx from "@effect-rx/rx/Rx"
```
Added in v1.0.0
@@ -217,7 +217,7 @@ Re-exports all named exports from the "@effect-rx/rx/RxRef" module as `RxRef`.
**Signature**
```ts
-export * as RxRef from '@effect-rx/rx/RxRef'
+export * as RxRef from "@effect-rx/rx/RxRef"
```
Added in v1.0.0
diff --git a/docs/rx/Result.ts.md b/docs/rx/Result.ts.md
index 19cdb64..130310c 100644
--- a/docs/rx/Result.ts.md
+++ b/docs/rx/Result.ts.md
@@ -237,7 +237,7 @@ Added in v1.0.0
```ts
export interface Failure extends Result.Proto {
- readonly _tag: 'Failure'
+ readonly _tag: "Failure"
readonly cause: Cause.Cause
readonly previousValue: Option.Option
}
@@ -251,7 +251,7 @@ Added in v1.0.0
```ts
export interface Initial extends Result.Proto {
- readonly _tag: 'Initial'
+ readonly _tag: "Initial"
}
```
@@ -315,10 +315,10 @@ Added in v1.0.0
export type With, E, A> = R extends Initial
? Initial
: R extends Success
- ? Success
- : R extends Failure
- ? Failure
- : never
+ ? Success
+ : R extends Failure
+ ? Failure
+ : never
```
Added in v1.0.0
@@ -329,7 +329,7 @@ Added in v1.0.0
```ts
export interface Success extends Result.Proto {
- readonly _tag: 'Success'
+ readonly _tag: "Success"
readonly value: A
}
```
diff --git a/docs/rx/Rx.ts.md b/docs/rx/Rx.ts.md
index fe30f69..44fb8e9 100644
--- a/docs/rx/Rx.ts.md
+++ b/docs/rx/Rx.ts.md
@@ -24,23 +24,18 @@ Added in v1.0.0
- [withFallback](#withfallback)
- [withLabel](#withlabel)
- [constructors](#constructors)
- - [effect](#effect)
- - [effectFn](#effectfn)
- [family](#family)
- [fn](#fn)
+ - [fnSync](#fnsync)
+ - [make](#make)
+ - [pull](#pull)
- [readable](#readable)
- - [runtime](#runtime)
- - [scoped](#scoped)
- - [scopedFn](#scopedfn)
- - [state](#state)
- - [stream](#stream)
- - [streamFn](#streamfn)
- - [streamPull](#streampull)
- [writable](#writable)
- [context](#context)
- [Context (interface)](#context-interface)
- [WriteContext (interface)](#writecontext-interface)
- [models](#models)
+ - [PullResult (type alias)](#pullresult-type-alias)
- [Refreshable (interface)](#refreshable-interface)
- [Rx (interface)](#rx-interface)
- [Rx (namespace)](#rx-namespace)
@@ -59,7 +54,6 @@ Added in v1.0.0
- [Write (type alias)](#write-type-alias)
- [RxResultFn (interface)](#rxresultfn-interface)
- [RxRuntime (interface)](#rxruntime-interface)
- - [StreamPullResult (type alias)](#streampullresult-type-alias)
- [Writable (interface)](#writable-interface)
- [refinements](#refinements)
- [isWritable](#iswritable)
@@ -177,14 +171,17 @@ Added in v1.0.0
```ts
export declare const withFallback: {
- (fallback: Rx>): >>(
+ (
+ fallback: Rx>
+ ): >>(
self: R
) => [R] extends [Writable]
? Writable>, A2 | Result.Result.InferA>>, RW>
: Rx>, A2 | Result.Result.InferA>>>
- >, E2, A2>(self: R, fallback: Rx>): [R] extends [
- Writable
- ]
+ >, E2, A2>(
+ self: R,
+ fallback: Rx>
+ ): [R] extends [Writable]
? Writable>, A2 | Result.Result.InferA>>, RW>
: Rx>, A2 | Result.Result.InferA>>>
}
@@ -207,60 +204,41 @@ Added in v1.0.0
# constructors
-## effect
+## family
**Signature**
```ts
-export declare const effect: {
- (
- create: Rx.Read>,
- options?: { readonly initialValue?: A | undefined; readonly runtime?: undefined } | undefined
- ): Rx>
- (
- create: Rx.Read>,
- options: { readonly runtime: RxRuntime; readonly initialValue?: A | undefined }
- ): Rx>
-}
+export declare const family: >(f: (arg: Arg) => T) => (arg: Arg) => T
```
Added in v1.0.0
-## effectFn
+## fn
**Signature**
```ts
-export declare const effectFn: {
+export declare const fn: {
(
- fn: Rx.ReadFn>,
- options?: { readonly initialValue?: A | undefined; readonly runtime?: undefined } | undefined
+ fn: Rx.ReadFn>,
+ options?: { readonly initialValue?: A | undefined } | undefined
): RxResultFn
- (
- fn: Rx.ReadFn>,
- options: { readonly runtime: RxRuntime; readonly initialValue?: A | undefined }
- ): RxResultFn
+ (
+ fn: Rx.ReadFn>,
+ options?: { readonly initialValue?: A | undefined } | undefined
+ ): RxResultFn
}
```
Added in v1.0.0
-## family
-
-**Signature**
-
-```ts
-export declare const family: >(f: (arg: Arg) => T) => (arg: Arg) => T
-```
-
-Added in v1.0.0
-
-## fn
+## fnSync
**Signature**
```ts
-export declare const fn: {
+export declare const fnSync: {
(f: Rx.ReadFn): Writable, Arg>
(f: Rx.ReadFn, options: { readonly initialValue: A }): Writable
}
@@ -268,156 +246,58 @@ export declare const fn: {
Added in v1.0.0
-## readable
+## make
**Signature**
```ts
-export declare const readable: (read: Rx.Read, refresh?: Rx.Refresh) => Rx
-```
-
-Added in v1.0.0
-
-## runtime
-
-**Signature**
-
-```ts
-export declare const runtime: {
+export declare const make: {
(
- create: (get: Context) => Layer.Layer,
- options?: {
- readonly autoDispose?: boolean
- readonly idleTTL?: Duration.DurationInput
- readonly runtime?: undefined
- }
- ): RxRuntime
- (
- create: (get: Context) => Layer.Layer,
- options?:
- | {
- readonly autoDispose?: boolean | undefined
- readonly idleTTL?: Duration.DurationInput | undefined
- readonly runtime: RxRuntime
- }
- | undefined
- ): RxRuntime
-}
-```
-
-Added in v1.0.0
-
-## scoped
-
-**Signature**
-
-```ts
-export declare const scoped: {
+ effect: Effect.Effect,
+ options?: { readonly initialValue?: A | undefined } | undefined
+ ): Rx>
(
create: Rx.Read>,
- options?: { readonly initialValue?: A | undefined; readonly runtime?: undefined } | undefined
+ options?: { readonly initialValue?: A | undefined } | undefined
+ ): Rx>
+ (
+ stream: Stream.Stream,
+ options?: { readonly initialValue?: A | undefined } | undefined
): Rx>
- (
- create: Rx.Read>,
- options: { readonly initialValue?: A | undefined; readonly runtime: RxRuntime }
- ): Rx>
-}
-```
-
-Added in v1.0.0
-
-## scopedFn
-
-**Signature**
-
-```ts
-export declare const scopedFn: {
- (
- fn: Rx.ReadFn>,
- options?: { readonly initialValue?: A | undefined; readonly runtime?: undefined } | undefined
- ): RxResultFn
- (
- fn: Rx.ReadFn>,
- options: { readonly initialValue?: A | undefined; readonly runtime: RxRuntime }
- ): RxResultFn
-}
-```
-
-Added in v1.0.0
-
-## state
-
-**Signature**
-
-```ts
-export declare const state: (initialValue: A) => Writable
-```
-
-Added in v1.0.0
-
-## stream
-
-**Signature**
-
-```ts
-export declare const stream: {
(
create: Rx.Read>,
- options?: { readonly initialValue?: A | undefined; readonly runtime?: undefined } | undefined
- ): Rx>
- (
- create: Rx.Read>,
- options: { readonly initialValue?: A | undefined; readonly runtime: RxRuntime }
- ): Rx>
+ options?: { readonly initialValue?: A | undefined } | undefined
+ ): Rx>
+ (layer: Layer.Layer): RxRuntime
+ (create: Rx.Read>): RxRuntime
+ (create: Rx.Read): Rx
+ (initialValue: A): Writable
}
```
Added in v1.0.0
-## streamFn
+## pull
**Signature**
```ts
-export declare const streamFn: {
- (
- fn: Rx.ReadFn>,
- options?: { readonly initialValue?: A | undefined; readonly runtime?: undefined } | undefined
- ): RxResultFn
- (
- fn: Rx.ReadFn>,
- options: { readonly runtime: RxRuntime; readonly initialValue?: A | undefined }
- ): RxResultFn
-}
+export declare const pull: (
+ create: Stream.Stream | Rx.Read>,
+ options?:
+ | { readonly disableAccumulation?: boolean | undefined; readonly initialValue?: readonly A[] | undefined }
+ | undefined
+) => Writable, void>
```
Added in v1.0.0
-## streamPull
+## readable
**Signature**
```ts
-export declare const streamPull: {
- (
- create: Rx.Read>,
- options?:
- | {
- readonly disableAccumulation?: boolean | undefined
- readonly initialValue?: readonly A[] | undefined
- readonly runtime?: undefined
- }
- | undefined
- ): Writable, void>
- (
- create: Rx.Read>,
- options: {
- readonly runtime: RxRuntime
- readonly disableAccumulation?: boolean | undefined
- readonly initialValue?: readonly A[] | undefined
- }
- ): Writable, void>
-}
+export declare const readable: (read: Rx.Read, refresh?: Rx.Refresh) => Rx
```
Added in v1.0.0
@@ -484,6 +364,22 @@ Added in v1.0.0
# models
+## PullResult (type alias)
+
+**Signature**
+
+```ts
+export type PullResult = Result.Result<
+ E | NoSuchElementException,
+ {
+ readonly done: boolean
+ readonly items: Array
+ }
+>
+```
+
+Added in v1.0.0
+
## Refreshable (interface)
**Signature**
@@ -668,23 +564,59 @@ Added in v1.0.0
**Signature**
```ts
-export interface RxRuntime extends Rx>> {}
-```
-
-Added in v1.0.0
-
-## StreamPullResult (type alias)
-
-**Signature**
+export interface RxRuntime extends Rx>> {
+ readonly rx: {
+ (
+ effect: Effect.Effect,
+ options?: {
+ readonly initialValue?: A
+ }
+ ): Rx>
+ (
+ create: Rx.Read>,
+ options?: {
+ readonly initialValue?: A
+ }
+ ): Rx>
+ (
+ stream: Stream.Stream,
+ options?: {
+ readonly initialValue?: A
+ }
+ ): Rx>
+ (
+ create: Rx.Read>,
+ options?: {
+ readonly initialValue?: A
+ }
+ ): Rx>
+ (layer: Layer.Layer): RxRuntime
+ (create: Rx.Read>): RxRuntime
+ }
-```ts
-export type StreamPullResult = Result.Result<
- E | NoSuchElementException,
- {
- readonly done: boolean
- readonly items: Array
+ readonly fn: {
+ (
+ fn: Rx.ReadFn>,
+ options?: {
+ readonly initialValue?: A
+ }
+ ): RxResultFn
+ (
+ fn: Rx.ReadFn>,
+ options?: {
+ readonly initialValue?: A
+ }
+ ): RxResultFn
}
->
+
+ readonly pull: (
+ create: Rx.Read> | Stream.Stream,
+ options?: {
+ readonly disableAccumulation?: boolean
+ readonly initialValue?: ReadonlyArray
+ }
+ ) => Writable, void>
+}
```
Added in v1.0.0
diff --git a/docs/rx/index.ts.md b/docs/rx/index.ts.md
index 225c45f..4bf23e5 100644
--- a/docs/rx/index.ts.md
+++ b/docs/rx/index.ts.md
@@ -13,59 +13,59 @@ Added in v1.0.0
Table of contents
- [exports](#exports)
- - [From "@effect-rx/rx/Registry"](#from-effect-rxrxregistry)
- - [From "@effect-rx/rx/Result"](#from-effect-rxrxresult)
- - [From "@effect-rx/rx/Rx"](#from-effect-rxrxrx)
- - [From "@effect-rx/rx/RxRef"](#from-effect-rxrxrxref)
+ - [From "./Registry.js"](#from-registryjs)
+ - [From "./Result.js"](#from-resultjs)
+ - [From "./Rx.js"](#from-rxjs)
+ - [From "./RxRef.js"](#from-rxrefjs)
---
# exports
-## From "@effect-rx/rx/Registry"
+## From "./Registry.js"
-Re-exports all named exports from the "@effect-rx/rx/Registry" module as `Registry`.
+Re-exports all named exports from the "./Registry.js" module as `Registry`.
**Signature**
```ts
-export * as Registry from '@effect-rx/rx/Registry'
+export * as Registry from "./Registry.js"
```
Added in v1.0.0
-## From "@effect-rx/rx/Result"
+## From "./Result.js"
-Re-exports all named exports from the "@effect-rx/rx/Result" module as `Result`.
+Re-exports all named exports from the "./Result.js" module as `Result`.
**Signature**
```ts
-export * as Result from '@effect-rx/rx/Result'
+export * as Result from "./Result.js"
```
Added in v1.0.0
-## From "@effect-rx/rx/Rx"
+## From "./Rx.js"
-Re-exports all named exports from the "@effect-rx/rx/Rx" module as `Rx`.
+Re-exports all named exports from the "./Rx.js" module as `Rx`.
**Signature**
```ts
-export * as Rx from '@effect-rx/rx/Rx'
+export * as Rx from "./Rx.js"
```
Added in v1.0.0
-## From "@effect-rx/rx/RxRef"
+## From "./RxRef.js"
-Re-exports all named exports from the "@effect-rx/rx/RxRef" module as `RxRef`.
+Re-exports all named exports from the "./RxRef.js" module as `RxRef`.
**Signature**
```ts
-export * as RxRef from '@effect-rx/rx/RxRef'
+export * as RxRef from "./RxRef.js"
```
Added in v1.0.0
diff --git a/packages/rx/src/Rx.ts b/packages/rx/src/Rx.ts
index d789953..f165925 100644
--- a/packages/rx/src/Rx.ts
+++ b/packages/rx/src/Rx.ts
@@ -12,11 +12,11 @@ import * as Inspectable from "effect/Inspectable"
import * as Layer from "effect/Layer"
import * as Option from "effect/Option"
import { type Pipeable, pipeArguments } from "effect/Pipeable"
-import type * as Runtime from "effect/Runtime"
+import * as Runtime from "effect/Runtime"
import * as Scope from "effect/Scope"
import * as Stream from "effect/Stream"
import * as internalRegistry from "./internal/registry.js"
-import { runCallbackSync, runCallbackSyncDefault } from "./internal/runtime.js"
+import { runCallbackSync } from "./internal/runtime.js"
import * as Result from "./Result.js"
/**
@@ -211,7 +211,6 @@ const RxProto = {
pipe() {
return pipeArguments(this, arguments)
},
-
toJSON(this: Rx) {
return {
_id: "Rx",
@@ -224,6 +223,51 @@ const RxProto = {
},
[Inspectable.NodeInspectSymbol](this: Rx) {
return this.toJSON()
+ },
+
+ // runtime api
+ rx(this: RxRuntime, arg: any, options?: { readonly initialValue?: unknown }) {
+ const read = makeRead(arg, options)
+ return readable((get) => {
+ const previous = get.self>()
+ const runtimeResult = get(this)
+ if (runtimeResult._tag !== "Success") {
+ return Result.replacePrevious(runtimeResult, previous)
+ }
+ return read(runtimeResult.value)(get)
+ })
+ },
+
+ fn(this: RxRuntime, arg: any, options?: { readonly initialValue?: unknown }) {
+ const [makeRead, write] = makeResultFn(arg, options)
+ return writable((get) => {
+ const previous = get.self>()
+ const runtimeResult = get(this)
+ if (runtimeResult._tag !== "Success") {
+ return Result.replacePrevious(runtimeResult, previous)
+ }
+ return makeRead(runtimeResult.value)(get)
+ }, write)
+ },
+
+ pull(this: RxRuntime, arg: any, options?: {
+ readonly disableAccumulation?: boolean
+ readonly initialValue?: ReadonlyArray
+ }) {
+ const pullRx = readable((get) => {
+ const previous = get.self>()
+ const runtimeResult = get(this)
+ if (runtimeResult._tag !== "Success") {
+ return Result.replacePrevious(runtimeResult, previous)
+ }
+ return makeEffect(
+ get,
+ makeStreamPullEffect(get, arg, options, runtimeResult.value),
+ Result.initial(true),
+ runtimeResult.value
+ )
+ })
+ return makeStreamPull(pullRx as any, options)
}
} as const
@@ -274,27 +318,145 @@ function constSetSelf(ctx: WriteContext, value: A) {
ctx.setSelf(value)
}
+// -----------------------------------------------------------------------------
+// constructors
+// -----------------------------------------------------------------------------
+
/**
* @since 1.0.0
* @category constructors
*/
-export const state = (
+export const make: {
+ (effect: Effect.Effect, options?: {
+ readonly initialValue?: A
+ }): Rx>
+ (create: Rx.Read>, options?: {
+ readonly initialValue?: A
+ }): Rx>
+ (stream: Stream.Stream, options?: {
+ readonly initialValue?: A
+ }): Rx>
+ (create: Rx.Read>, options?: {
+ readonly initialValue?: A
+ }): Rx>
+ (layer: Layer.Layer): RxRuntime
+ (create: Rx.Read>): RxRuntime
+ (create: Rx.Read): Rx
+ (initialValue: A): Writable
+} = (arg: any, options?: { readonly initialValue?: unknown }) => {
+ const readOrRx = makeRead(arg, options)()
+ if (TypeId in readOrRx) {
+ return readOrRx as any
+ }
+ return readable(readOrRx)
+}
+
+// -----------------------------------------------------------------------------
+// constructors - effect
+// -----------------------------------------------------------------------------
+
+const makeRead: {
+ (effect: Effect.Effect, options?: {
+ readonly initialValue?: A
+ }): (runtime?: Runtime.Runtime) => Rx.Read>
+ (create: Rx.Read>, options?: {
+ readonly initialValue?: A
+ }): (runtime?: Runtime.Runtime) => Rx.Read>
+ (stream: Stream.Stream, options?: {
+ readonly initialValue?: A
+ }): (runtime?: Runtime.Runtime) => Rx.Read>
+ (create: Rx.Read>, options?: {
+ readonly initialValue?: A
+ }): (runtime?: Runtime.Runtime) => Rx.Read>
+ (
+ layer: Layer.Layer
+ ): (runtime?: Runtime.Runtime) => Rx.Read>>
+ (
+ create: Rx.Read>
+ ): (runtime?: Runtime.Runtime) => Rx.Read>>
+ (create: Rx.Read): (runtime?: Runtime.Runtime) => Rx.Read
+ (initialValue: A): (runtime?: Runtime.Runtime) => Writable
+} = (
+ arg:
+ | Effect.Effect
+ | Rx.Read>
+ | Stream.Stream
+ | Rx.Read>
+ | Layer.Layer
+ | Rx.Read>
+ | Rx.Read
+ | A,
+ options?: { readonly initialValue?: unknown }
+) =>
+(providedRuntime?: Runtime.Runtime) => {
+ if (typeof arg === "function") {
+ const create = arg as Rx.Read
+ return function(get: Context) {
+ const value = create(get)
+ if (Effect.EffectTypeId in value) {
+ return effect(get, value, options, providedRuntime)
+ } else if (Stream.StreamTypeId in value) {
+ return stream(get, value, options, providedRuntime)
+ } else if (Layer.LayerTypeId in value) {
+ return runtime(get, value, providedRuntime)
+ }
+ return value
+ }
+ } else if (typeof arg === "object" && arg !== null) {
+ if (Effect.EffectTypeId in arg) {
+ return function(get: Context) {
+ return effect(get, arg, options, providedRuntime)
+ }
+ } else if (Stream.StreamTypeId in arg) {
+ return function(get: Context) {
+ return stream(get, arg, options, providedRuntime)
+ }
+ } else if (Layer.LayerTypeId in arg) {
+ return function(get: Context) {
+ return runtime(get, arg, providedRuntime)
+ }
+ }
+ }
+
+ return state(arg) as any
+}
+
+const state = (
initialValue: A
): Writable =>
writable(function(_get) {
return initialValue
}, constSetSelf)
+const effect = (
+ get: Context,
+ effect: Effect.Effect,
+ options?: { readonly initialValue?: A },
+ runtime?: Runtime.Runtime
+): Result.Result => {
+ const initialValue = options?.initialValue !== undefined
+ ? Result.success(options.initialValue)
+ : Result.initial()
+ return makeEffect(get, effect, initialValue, runtime)
+}
+
function makeEffect(
ctx: Context,
- create: Rx.Read>,
+ effect: Effect.Effect,
initialValue: Result.Result,
- runCallback = runCallbackSyncDefault
+ runtime = Runtime.defaultRuntime
): Result.Result {
const previous = ctx.self>()
- const cancel = runCallback(
- create(ctx),
+ const scope = Effect.runSync(Scope.make())
+ ctx.addFinalizer(() => Effect.runFork(Scope.close(scope, Exit.unit)))
+ const scopedEffect = Effect.provideService(
+ effect,
+ Scope.Scope,
+ scope
+ )
+ const cancel = runCallbackSync(runtime)(
+ scopedEffect,
function(exit) {
if (!Exit.isInterrupted(exit)) {
ctx.setSelfSync(Result.fromExitWithPrevious(exit, previous))
@@ -311,284 +473,89 @@ function makeEffect(
return Result.waiting(initialValue)
}
-function makeEffectRuntime(
- ctx: Context,
- create: Rx.Read>,
- initialValue: Result.Result,
- runtime: RxRuntime
-): Result.Result