Skip to content

Commit

Permalink
allow context in Rx.runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-smart committed Nov 9, 2023
1 parent 1495465 commit b00fa8d
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 53 deletions.
6 changes: 6 additions & 0 deletions .changeset/lemon-readers-tickle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@effect-rx/rx-react": minor
"@effect-rx/rx": minor
---

allow context in Rx.runtime
4 changes: 2 additions & 2 deletions docs/rx-react/index.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ Added in v1.0.0
export declare const useRxSuspense: <E, A>(
rx: Rx.Rx<Result.Result<E, A>>,
options?: { readonly suspendOnWaiting?: boolean }
) => { readonly isWaiting: boolean; readonly value: any }
) => any
```
Added in v1.0.0
Expand All @@ -157,7 +157,7 @@ Added in v1.0.0
export declare const useRxSuspenseSuccess: <E, A>(
rx: Rx.Rx<Result.Result<E, A>>,
options?: { readonly suspendOnWaiting?: boolean }
) => { readonly isWaiting: boolean; readonly value: A }
) => Result.Success<E, A>
```
Added in v1.0.0
Expand Down
22 changes: 11 additions & 11 deletions docs/rx/Rx.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,15 +285,15 @@ Added in v1.0.0
```ts
export declare const runtime: {
<E, A>(
layer: Layer.Layer<never, E, A>,
create: (get: Context) => Layer.Layer<never, E, A>,
options?: {
readonly autoDispose?: boolean
readonly idleTTL?: Duration.DurationInput
readonly runtime?: undefined
}
): RxRuntime<E, A>
<RR, R extends RR, E, A, RE>(
layer: Layer.Layer<R, E, A>,
create: (get: Context) => Layer.Layer<R, E, A>,
options?:
| {
readonly autoDispose?: boolean | undefined
Expand Down Expand Up @@ -441,20 +441,20 @@ Added in v1.0.0
```ts
export interface Context {
<A>(rx: Rx<A>): A
readonly get: Rx.Get
readonly result: Rx.GetResult
readonly once: Rx.Get
readonly get: <A>(rx: Rx<A>) => A
readonly result: <E, A>(rx: Rx<Result.Result<E, A>>) => Exit.Exit<E | NoSuchElementException, A>
readonly once: <A>(rx: Rx<A>) => A
readonly addFinalizer: (f: () => void) => void
readonly mount: <A>(rx: Rx<A>) => void
readonly refreshSync: Rx.RefreshRxSync
readonly refresh: Rx.RefreshRx
readonly refreshSync: <A>(rx: Rx<A> & Refreshable) => void
readonly refresh: <A>(rx: Rx<A> & Refreshable) => Effect.Effect<never, never, void>
readonly refreshSelfSync: () => void
readonly refreshSelf: Effect.Effect<never, never, void>
readonly self: <A>() => Option.Option<A>
readonly setSelfSync: <A>(a: A) => void
readonly setSelf: <A>(a: A) => Effect.Effect<never, never, void>
readonly setSync: Rx.Set
readonly set: Rx.SetEffect
readonly setSync: <R, W>(rx: Writable<R, W>, value: W) => void
readonly set: <R, W>(rx: Writable<R, W>, value: W) => Effect.Effect<never, never, void>
readonly subscribe: <A>(
rx: Rx<A>,
f: (_: A) => void,
Expand All @@ -473,10 +473,10 @@ Added in v1.0.0

```ts
export interface WriteContext<A> {
readonly get: Rx.Get
readonly get: <A>(rx: Rx<A>) => A
readonly refreshSelf: () => void
readonly setSelf: (a: A) => void
readonly set: Rx.Set
readonly set: <R, W>(rx: Writable<R, W>, value: W) => void
}
```

Expand Down
32 changes: 10 additions & 22 deletions packages/rx-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,35 +198,32 @@ type SuspenseResult<E, A> =
}
| {
readonly _tag: "Value"
readonly isWaiting: boolean
readonly value: Result.Success<E, A> | Result.Failure<E, A>
}

const suspenseRx = Rx.family((rx: Rx.Rx<Result.Result<any, any>>) =>
Rx.readable((get): SuspenseResult<any, any> => {
const result = get(rx)
const value = Result.noWaiting(result)
if (value._tag === "Initial") {
if (result._tag === "Initial") {
return {
_tag: "Suspended",
promise: new Promise<void>((resolve) => get.addFinalizer(resolve))
} as const
}
const isWaiting = Result.isWaiting(result)
return { _tag: "Value", isWaiting, value } as const
return { _tag: "Value", value: result } as const
})
)

const suspenseRxWaiting = Rx.family((rx: Rx.Rx<Result.Result<any, any>>) =>
Rx.readable((get): SuspenseResult<any, any> => {
const result = get(rx)
if (result._tag === "Waiting" || result._tag === "Initial") {
if (result.waiting || result._tag === "Initial") {
return {
_tag: "Suspended",
promise: new Promise<void>((resolve) => get.addFinalizer(resolve))
} as const
}
return { _tag: "Value", isWaiting: false, value: result } as const
return { _tag: "Value", value: result } as const
})
)

Expand All @@ -239,10 +236,7 @@ const suspenseMounts = globalValue("@effect-rx/rx-react/suspenseMounts", () => n
export const useRxSuspense = <E, A>(
rx: Rx.Rx<Result.Result<E, A>>,
options?: { readonly suspendOnWaiting?: boolean }
): {
readonly isWaiting: boolean
readonly value: Result.Success<E, A> | Result.Failure<E, A>
} => {
): Result.Success<E, A> | Result.Failure<E, A> => {
const registry = React.useContext(RegistryContext)
const resultRx = React.useMemo(
() => (options?.suspendOnWaiting ? suspenseRxWaiting(rx) : suspenseRx(rx)),
Expand All @@ -263,7 +257,7 @@ export const useRxSuspense = <E, A>(
throw result.promise
}

return result
return result.value
}

/**
Expand All @@ -273,18 +267,12 @@ export const useRxSuspense = <E, A>(
export const useRxSuspenseSuccess = <E, A>(
rx: Rx.Rx<Result.Result<E, A>>,
options?: { readonly suspendOnWaiting?: boolean }
): {
readonly isWaiting: boolean
readonly value: A
} => {
): Result.Success<E, A> => {
const result = useRxSuspense(rx, options)
if (result.value._tag === "Failure") {
throw Cause.squash(result.value.cause)
}
return {
isWaiting: result.isWaiting,
value: result.value.value
if (result._tag === "Failure") {
throw Cause.squash(result.cause)
}
return result
}

/**
Expand Down
30 changes: 15 additions & 15 deletions packages/rx/src/Rx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,20 +176,20 @@ export interface Writable<R, W> extends Rx<R> {
*/
export interface Context {
<A>(rx: Rx<A>): A
readonly get: Rx.Get
readonly result: Rx.GetResult
readonly once: Rx.Get
readonly get: <A>(rx: Rx<A>) => A
readonly result: <E, A>(rx: Rx<Result.Result<E, A>>) => Exit.Exit<E | NoSuchElementException, A>
readonly once: <A>(rx: Rx<A>) => A
readonly addFinalizer: (f: () => void) => void
readonly mount: <A>(rx: Rx<A>) => void
readonly refreshSync: Rx.RefreshRxSync
readonly refresh: Rx.RefreshRx
readonly refreshSync: <A>(rx: Rx<A> & Refreshable) => void
readonly refresh: <A>(rx: Rx<A> & Refreshable) => Effect.Effect<never, never, void>
readonly refreshSelfSync: () => void
readonly refreshSelf: Effect.Effect<never, never, void>
readonly self: <A>() => Option.Option<A>
readonly setSelfSync: <A>(a: A) => void
readonly setSelf: <A>(a: A) => Effect.Effect<never, never, void>
readonly setSync: Rx.Set
readonly set: Rx.SetEffect
readonly setSync: <R, W>(rx: Writable<R, W>, value: W) => void
readonly set: <R, W>(rx: Writable<R, W>, value: W) => Effect.Effect<never, never, void>
readonly subscribe: <A>(rx: Rx<A>, f: (_: A) => void, options?: {
readonly immediate?: boolean
}) => void
Expand All @@ -200,10 +200,10 @@ export interface Context {
* @category context
*/
export interface WriteContext<A> {
readonly get: Rx.Get
readonly get: <A>(rx: Rx<A>) => A
readonly refreshSelf: () => void
readonly setSelf: (a: A) => void
readonly set: Rx.Set
readonly set: <R, W>(rx: Writable<R, W>, value: W) => void
}

const RxProto = {
Expand Down Expand Up @@ -545,28 +545,28 @@ export interface RxRuntime<E, A> extends Rx<Result.Result<E, Runtime.Runtime<A>>
* @category constructors
*/
export const runtime: {
<E, A>(layer: Layer.Layer<never, E, A>, options?: {
<E, A>(create: (get: Context) => Layer.Layer<never, E, A>, options?: {
readonly autoDispose?: boolean
readonly idleTTL?: Duration.DurationInput
readonly runtime?: undefined
}): RxRuntime<E, A>
<RR, R extends RR, E, A, RE>(layer: Layer.Layer<R, E, A>, options?: {
<RR, R extends RR, E, A, RE>(create: (get: Context) => Layer.Layer<R, E, A>, options?: {
readonly autoDispose?: boolean
readonly idleTTL?: Duration.DurationInput
readonly runtime: RxRuntime<RE, RR>
}): RxRuntime<E, A | RR>
} = <R, E, A, RE>(layer: Layer.Layer<R, E, A>, options?: {
} = <R, E, A, RE>(create: (get: Context) => Layer.Layer<R, E, A>, options?: {
readonly autoDispose?: boolean
readonly idleTTL?: Duration.DurationInput
readonly runtime?: RxRuntime<RE, R>
}): RxRuntime<E | RE, A> => {
let rx = options?.runtime
? scoped(() =>
? scoped((get) =>
Effect.flatMap(
Layer.build(layer),
Layer.build(create(get)),
(context) => Effect.provide(Effect.runtime<A>(), context)
), { runtime: options.runtime })
: scoped(() => Layer.toRuntime(layer) as Effect.Effect<Scope.Scope, E, Runtime.Runtime<A>>)
: scoped((get) => Layer.toRuntime(create(get)) as Effect.Effect<Scope.Scope, E, Runtime.Runtime<A>>)

if (options?.idleTTL !== undefined) {
rx = setIdleTTL(rx, options.idleTTL)
Expand Down
6 changes: 3 additions & 3 deletions packages/rx/test/Rx.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -680,14 +680,14 @@ const MultiplierLive = Layer.effect(
})
)

const counterRuntime = Rx.runtime(CounterLive, {
const counterRuntime = Rx.runtime(() => CounterLive, {
autoDispose: true
})
const multiplierRuntime = Rx.runtime(MultiplierLive, {
const multiplierRuntime = Rx.runtime(() => MultiplierLive, {
runtime: counterRuntime,
autoDispose: true
})
const fiberRefRuntime = Rx.runtime(Layer.setRequestCaching(true), {
const fiberRefRuntime = Rx.runtime(() => Layer.setRequestCaching(true), {
runtime: counterRuntime,
autoDispose: true
})

0 comments on commit b00fa8d

Please sign in to comment.