diff --git a/.changeset/ninety-schools-fail.md b/.changeset/ninety-schools-fail.md new file mode 100644 index 000000000..f2a61ce08 --- /dev/null +++ b/.changeset/ninety-schools-fail.md @@ -0,0 +1,5 @@ +--- +"@effect-app/prelude": patch +--- + +add basic fluent extensions for projects without tsplus diff --git a/packages/prelude/_src/fluent-extensions-ext.d.ts b/packages/prelude/_src/fluent-extensions-ext.d.ts new file mode 100644 index 000000000..ad5bb50d0 --- /dev/null +++ b/packages/prelude/_src/fluent-extensions-ext.d.ts @@ -0,0 +1,60 @@ +import type { NoInfer } from "effect/Types" +import type * as Cause from "effect/Cause" +import type * as Runtime from "effect/Runtime" + +// Put the following in the project, where RT is the default runtime context available +/* +import type * as Runtime from "effect/Runtime" +import type * as Fiber from "effect/Fiber" +declare module "effect/Effect" { + export interface Effect { + get runPromise(this: Effect): Promise + get runSync(this: Effect): A + runFork(this: Effect, options?: Runtime.RunForkOptions): Fiber.RuntimeFiber + } +} +*/ + +declare module "effect/Option" { + export interface None { + get value(this: None): A | undefined + } +} + +declare module "effect/Effect" { + export interface Effect { + andThen( + this: Effect, + f: (a: NoInfer) => X, + ): [X] extends [Effect] + ? Effect + : [X] extends [Promise] + ? Effect + : Effect + + andThen( + this: Effect, + f: X, + ): [X] extends [Effect] + ? Effect + : [X] extends [Promise] + ? Effect + : Effect + tap( + this: Effect, + f: (a: NoInfer) => X, + ): [X] extends [Effect] + ? Effect + : [X] extends [Promise] + ? Effect + : Effect + tap( + this: Effect, + f: X, + ): [X] extends [Effect] + ? Effect + : [X] extends [Promise] + ? Effect + : Effect + } +} diff --git a/packages/prelude/_src/fluent-extensions.ts b/packages/prelude/_src/fluent-extensions.ts new file mode 100644 index 000000000..1b516a643 --- /dev/null +++ b/packages/prelude/_src/fluent-extensions.ts @@ -0,0 +1,42 @@ +import type {} from "./fluent-extensions-ext.js" +import * as Effect from "effect/Effect" +import * as RT from "effect/Runtime" + +/** + * useful in e.g frontend projects that do not use tsplus, but still has the most useful extensions installed. + */ +export const installFluentExtensions = (runtime: Runtime) => { + const runPromise = RT.runPromise(runtime) + const runFork = RT.runFork(runtime) + const runSync = RT.runSync(runtime) + Object.defineProperty(Object.prototype, "runPromise", { + enumerable: false, + get() { + return runPromise(this) + } + }) + Object.defineProperty(Object.prototype, "runFork", { + enumerable: false, + value(arg: any) { + return runFork(this, arg) + } + }) + Object.defineProperty(Object.prototype, "runSync", { + enumerable: false, + get() { + return runSync(this) + } + }) + Object.defineProperty(Object.prototype, "andThen", { + enumerable: false, + value(arg: any) { + return Effect.andThen(this, arg) + } + }) + Object.defineProperty(Object.prototype, "tap", { + enumerable: false, + value(arg: any) { + return Effect.tap(this, arg) + } + }) +} diff --git a/packages/prelude/package.json b/packages/prelude/package.json index 758086791..e72d58aab 100644 --- a/packages/prelude/package.json +++ b/packages/prelude/package.json @@ -268,6 +268,26 @@ "default": "./_cjs/faker.cjs" } }, + "./fluent-extensions": { + "import": { + "types": "./dist/fluent-extensions.d.ts", + "default": "./dist/fluent-extensions.js" + }, + "require": { + "types": "./dist/fluent-extensions.d.ts", + "default": "./_cjs/fluent-extensions.cjs" + } + }, + "./fluent-extensions-ext.d": { + "import": { + "types": "./dist/fluent-extensions-ext.d.d.ts", + "default": "./dist/fluent-extensions-ext.d.js" + }, + "require": { + "types": "./dist/fluent-extensions-ext.d.d.ts", + "default": "./_cjs/fluent-extensions-ext.d.cjs" + } + }, "./ids": { "import": { "types": "./dist/ids.d.ts",