Skip to content

Commit

Permalink
Request : swap Error and Success type params + make Effect.request du…
Browse files Browse the repository at this point in the history
…al (#2238)
  • Loading branch information
JJayet authored Mar 4, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 781dc18 commit 6137533
Showing 6 changed files with 54 additions and 14 deletions.
5 changes: 5 additions & 0 deletions .changeset/few-islands-beg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

Request: swap Success and Error params
5 changes: 5 additions & 0 deletions .changeset/hip-berries-cheat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

make Effect.request dual
19 changes: 14 additions & 5 deletions packages/effect/src/Effect.ts
Original file line number Diff line number Diff line change
@@ -43,7 +43,7 @@ import type { Pipeable } from "./Pipeable.js"
import type { Predicate, Refinement } from "./Predicate.js"
import type * as Random from "./Random.js"
import type * as Ref from "./Ref.js"
import type * as Request from "./Request.js"
import * as Request from "./Request.js"
import type { RequestBlock } from "./RequestBlock.js"
import type { RequestResolver } from "./RequestResolver.js"
import type * as Runtime from "./Runtime.js"
@@ -4913,18 +4913,27 @@ export const step: <A, E, R>(self: Effect<A, E, R>) => Effect<Exit.Exit<A, E> |
* @category requests & batching
*/
export const request: {
<A extends Request.Request<any, any>, Ds extends RequestResolver<A> | Effect<RequestResolver<A>, any, any>>(
dataSource: Ds
): (
self: A
) => Effect<
Request.Request.Success<A>,
Request.Request.Error<A>,
[Ds] extends [Effect<any, any, any>] ? Effect.Context<Ds> : never
>
<
A extends Request.Request<any, any>,
Ds extends RequestResolver<A> | Effect<RequestResolver<A>, any, any>
Ds extends RequestResolver<A> | Effect<RequestResolver<A>, any, any>,
A extends Request.Request<any, any>
>(
request: A,
self: A,
dataSource: Ds
): Effect<
Request.Request.Success<A>,
Request.Request.Error<A>,
[Ds] extends [Effect<any, any, any>] ? Effect.Context<Ds> : never
>
} = query.fromRequest as any
} = dual((args) => Request.isRequest(args[0]), query.fromRequest)

/**
* @since 2.0.0
14 changes: 7 additions & 7 deletions packages/effect/src/Request.ts
Original file line number Diff line number Diff line change
@@ -57,7 +57,7 @@ export declare namespace Request {
* @category models
*/
export interface Constructor<R extends Request<any, any>, T extends keyof R = never> {
(args: Omit<R, T | keyof (Request.Variance<Request.Error<R>, Request.Success<R>>)>): R
(args: Omit<R, T | keyof (Request.Variance<Request.Success<R>, Request.Error<R>>)>): R
}

/**
@@ -127,17 +127,17 @@ export const tagged: <R extends Request<any, any> & { _tag: string }>(
* @example
* import * as Request from "effect/Request"
*
* type Error = never
* type Success = string
* type Error = never
*
* class MyRequest extends Request.Class<Error, Success, {
* class MyRequest extends Request.Class<Success, Error, {
* readonly id: string
* }> {}
*
* @since 2.0.0
* @category constructors
*/
export const Class: new<Error, Success, A extends Record<string, any>>(
export const Class: new<Success, Error, A extends Record<string, any>>(
args: Types.Equals<Omit<A, keyof Request<unknown, unknown>>, {}> extends true ? void
: { readonly [P in keyof A as P extends keyof Request<unknown, unknown> ? never : P]: A[P] }
) => Request<Success, Error> & Readonly<A> = internal.Class as any
@@ -148,10 +148,10 @@ export const Class: new<Error, Success, A extends Record<string, any>>(
* @example
* import * as Request from "effect/Request"
*
* type Error = never
* type Success = string
* type Error = never
*
* class MyRequest extends Request.TaggedClass("MyRequest")<Error, Success, {
* class MyRequest extends Request.TaggedClass("MyRequest")<Success, Error, {
* readonly name: string
* }> {}
*
@@ -160,7 +160,7 @@ export const Class: new<Error, Success, A extends Record<string, any>>(
*/
export const TaggedClass: <Tag extends string>(
tag: Tag
) => new<Error, Success, A extends Record<string, any>>(
) => new<Success, Error, A extends Record<string, any>>(
args: Types.Equals<Omit<A, keyof Request<unknown, unknown>>, {}> extends true ? void
: { readonly [P in keyof A as P extends "_tag" | keyof Request<unknown, unknown> ? never : P]: A[P] }
) => Request<Success, Error> & Readonly<A> & { readonly _tag: Tag } = internal.TaggedClass as any
4 changes: 2 additions & 2 deletions packages/effect/src/internal/request.ts
Original file line number Diff line number Diff line change
@@ -46,7 +46,7 @@ export const tagged = <R extends Request.Request<any, any> & { _tag: string }>(
}

/** @internal */
export const Class: new<Error, Success, A extends Record<string, any>>(
export const Class: new<Success, Error, A extends Record<string, any>>(
args: Types.Equals<Omit<A, keyof Request.Request<unknown, unknown>>, {}> extends true ? void
: { readonly [P in keyof A as P extends keyof Request.Request<unknown, unknown> ? never : P]: A[P] }
) => Request.Request<Success, Error> & Readonly<A> = (function() {
@@ -62,7 +62,7 @@ export const Class: new<Error, Success, A extends Record<string, any>>(
/** @internal */
export const TaggedClass = <Tag extends string>(
tag: Tag
): new<Error, Success, A extends Record<string, any>>(
): new<Success, Error, A extends Record<string, any>>(
args: Types.Equals<Omit<A, keyof Request.Request<unknown, unknown>>, {}> extends true ? void
: { readonly [P in keyof A as P extends "_tag" | keyof Request.Request<unknown, unknown> ? never : P]: A[P] }
) => Request.Request<Success, Error> & Readonly<A> & { readonly _tag: Tag } => {
21 changes: 21 additions & 0 deletions packages/effect/test/Effect/query.test.ts
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ import * as Resolver from "effect/RequestResolver"
import * as TestClock from "effect/TestClock"
import type { Concurrency } from "effect/Types"
import { describe, expect } from "vitest"
import { pipe } from "../../src/index.js"

interface Counter {
readonly _: unique symbol
@@ -69,14 +70,24 @@ export const interrupts = FiberRef.unsafeMake({ interrupts: 0 })

export const getUserNameById = (id: number) => Effect.request(new GetNameById({ id }), UserResolver)

export const getUserNameByIdPiped = (id: number) => pipe(new GetNameById({ id }), Effect.request(UserResolver))

export const getAllUserNamesN = (concurrency: Concurrency) =>
getAllUserIds.pipe(
Effect.flatMap(Effect.forEach(getUserNameById, { concurrency, batching: true })),
Effect.onInterrupt(() => FiberRef.getWith(interrupts, (i) => Effect.sync(() => i.interrupts++)))
)

export const getAllUserNamesPipedN = (concurrency: Concurrency) =>
getAllUserIds.pipe(
Effect.flatMap(Effect.forEach(getUserNameById, { concurrency, batching: true })),
Effect.onInterrupt(() => FiberRef.getWith(interrupts, (i) => Effect.sync(() => i.interrupts++)))
)

export const getAllUserNames = getAllUserNamesN("unbounded")

export const getAllUserNamesPiped = getAllUserNamesPipedN("unbounded")

export const print = (request: UserRequest): string => {
switch (request._tag) {
case "GetAllIds": {
@@ -159,6 +170,16 @@ describe("Effect", () => {
expect(names).toEqual(userIds.map((id) => userNames.get(id)))
})
))
it.effect("requests with dual syntax are executed correctly", () =>
provideEnv(
Effect.gen(function*($) {
const names = yield* $(getAllUserNamesPiped)
const count = yield* $(Counter)
expect(count.count).toEqual(3)
expect(names.length).toBeGreaterThan(2)
expect(names).toEqual(userIds.map((id) => userNames.get(id)))
})
))
it.effect("requests are executed correctly with fromEffectTagged", () =>
provideEnv(
Effect.gen(function*($) {

0 comments on commit 6137533

Please sign in to comment.