|
|
@@ -1,4 +1,4 @@
|
|
|
-import { Effect, ScopedCache, Scope, ServiceMap } from "effect"
|
|
|
+import { Effect, Fiber, ScopedCache, Scope, ServiceMap } from "effect"
|
|
|
import { Instance, type InstanceContext } from "@/project/instance"
|
|
|
import { registerDisposer } from "./instance-registry"
|
|
|
|
|
|
@@ -14,6 +14,16 @@ export interface InstanceState<A, E = never, R = never> {
|
|
|
}
|
|
|
|
|
|
export namespace InstanceState {
|
|
|
+ export const bind = <F extends (...args: any[]) => any>(fn: F): F => {
|
|
|
+ try {
|
|
|
+ return Instance.bind(fn)
|
|
|
+ } catch {}
|
|
|
+ const fiber = Fiber.getCurrent()
|
|
|
+ const ctx = fiber ? ServiceMap.getReferenceUnsafe(fiber.services, InstanceRef) : undefined
|
|
|
+ if (!ctx) return fn
|
|
|
+ return ((...args: any[]) => Instance.restore(ctx, () => fn(...args))) as F
|
|
|
+ }
|
|
|
+
|
|
|
export const context = Effect.gen(function* () {
|
|
|
const ref = yield* InstanceRef
|
|
|
return ref ?? Instance.current
|
|
|
@@ -30,7 +40,10 @@ export namespace InstanceState {
|
|
|
Effect.gen(function* () {
|
|
|
const cache = yield* ScopedCache.make<string, A, E, R>({
|
|
|
capacity: Number.POSITIVE_INFINITY,
|
|
|
- lookup: () => Effect.gen(function* () { return yield* init(yield* context) }),
|
|
|
+ lookup: () =>
|
|
|
+ Effect.gen(function* () {
|
|
|
+ return yield* init(yield* context)
|
|
|
+ }),
|
|
|
})
|
|
|
|
|
|
const off = registerDisposer((directory) => Effect.runPromise(ScopedCache.invalidate(cache, directory)))
|
|
|
@@ -43,7 +56,9 @@ export namespace InstanceState {
|
|
|
})
|
|
|
|
|
|
export const get = <A, E, R>(self: InstanceState<A, E, R>) =>
|
|
|
- Effect.gen(function* () { return yield* ScopedCache.get(self.cache, yield* directory) })
|
|
|
+ Effect.gen(function* () {
|
|
|
+ return yield* ScopedCache.get(self.cache, yield* directory)
|
|
|
+ })
|
|
|
|
|
|
export const use = <A, E, R, B>(self: InstanceState<A, E, R>, select: (value: A) => B) =>
|
|
|
Effect.map(get(self), select)
|
|
|
@@ -54,10 +69,14 @@ export namespace InstanceState {
|
|
|
) => Effect.flatMap(get(self), select)
|
|
|
|
|
|
export const has = <A, E, R>(self: InstanceState<A, E, R>) =>
|
|
|
- Effect.gen(function* () { return yield* ScopedCache.has(self.cache, yield* directory) })
|
|
|
+ Effect.gen(function* () {
|
|
|
+ return yield* ScopedCache.has(self.cache, yield* directory)
|
|
|
+ })
|
|
|
|
|
|
export const invalidate = <A, E, R>(self: InstanceState<A, E, R>) =>
|
|
|
- Effect.gen(function* () { return yield* ScopedCache.invalidate(self.cache, yield* directory) })
|
|
|
+ Effect.gen(function* () {
|
|
|
+ return yield* ScopedCache.invalidate(self.cache, yield* directory)
|
|
|
+ })
|
|
|
|
|
|
/** Run a sync function with Instance ALS restored from the InstanceRef. */
|
|
|
export const withALS = <T>(fn: () => T) => Effect.map(context, (ctx) => Instance.restore(ctx, fn))
|