import { RpcStub, RpcTarget } from "cloudflare:workers"; import { Effect, type Scope } from "effect"; export { RpcStub, RpcTarget }; export type Stubable = Rpc.Stubable; export type Stub = Rpc.Stub; export type Provider = Rpc.Provider; type BaseType = | void | undefined | null | boolean | number | bigint | string | TypedArray | ArrayBuffer | DataView | Date | Error | RegExp | ReadableStream | WritableStream | Request | Response | Headers; export type Serializable = | BaseType | Map< T extends Map ? Serializable : never, T extends Map ? Serializable : never > | Set ? Serializable : never> | ReadonlyArray ? Serializable : never> | { [Key in keyof T]: Key extends number | string ? Serializable : never; } | Stub | Stubable; export type Stubify = T extends Stubable ? Stub : T extends Map ? Map, Stubify> : T extends Set ? Set> : T extends Array ? Array> : T extends ReadonlyArray ? ReadonlyArray> : T extends BaseType ? T : T extends { [key: string | number]: unknown; } ? { [Key in keyof T]: Stubify; } : T; type MaybeProvider = T extends object ? Provider : unknown; type MaybeDisposable = T extends object ? Disposable : unknown; export type Result = T extends Stubable ? Promise> & Provider : T extends Serializable ? Promise & MaybeDisposable> & MaybeProvider : never; export type MethodKey = { [Key in keyof Api]-?: Key extends string ? Api[Key] extends (...args: Array) => unknown ? Key : never : never; }[keyof Api]; export type MethodArgs = Api[Method] extends ( ...args: infer Args ) => unknown ? Args : never; export type MethodReturn = Api[Method] extends ( ...args: Array ) => infer Return ? Return : never; export type DisposableValue = { [Symbol.dispose](): void; }; export const isDisposable = (value: unknown): value is DisposableValue => (typeof value === "object" || typeof value === "function") && value !== null && Symbol.dispose in value && typeof (value as { readonly [Symbol.dispose]?: unknown })[Symbol.dispose] === "function"; export const dispose = (value: unknown): Effect.Effect => Effect.sync(() => { if (isDisposable(value)) { value[Symbol.dispose](); } }); export const resolve = (value: A): Effect.Effect, unknown> => isPromiseLike(value) ? Effect.tryPromise({ try: () => value, catch: (cause) => cause, }) : Effect.sync(() => value as Awaited); export const scoped = (value: A): Effect.Effect, unknown, Scope.Scope> => Effect.acquireRelease(resolve(value), (resolved) => dispose(resolved)); const isPromiseLike = (value: A): value is A & PromiseLike> => (typeof value === "object" || typeof value === "function") && value !== null && "then" in value && typeof (value as { readonly then?: unknown }).then === "function";