Skip to content

Commit

Permalink
Release queue: minor (#2690)
Browse files Browse the repository at this point in the history
Co-authored-by: Maxim Khramtsov <khraks.mamtsov@gmail.com>
Co-authored-by: maksim.khramtsov <maksim.khramtsov@btsdigital.kz>
Co-authored-by: Tim <hello@timsmart.co>
Co-authored-by: Giulio Canti <giulio.canti@gmail.com>
Co-authored-by: Milan Suk <Milansuk@email.cz>
Co-authored-by: Michael Arnaldi <michael.arnaldi@effectful.co>
Co-authored-by: Bodhi <106667397+RareBodhi@users.noreply.github.com>
  • Loading branch information
8 people authored May 20, 2024
1 parent ed96531 commit 76efa47
Show file tree
Hide file tree
Showing 50 changed files with 1,355 additions and 485 deletions.
5 changes: 5 additions & 0 deletions .changeset/bright-apricots-sit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": minor
---

Add Stream.toReadableStreamEffect / .toReadableStreamRuntime
7 changes: 7 additions & 0 deletions .changeset/cyan-kiwis-juggle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"effect": minor
---

add Cause.prettyErrors api

You can use this to extract `Error` instances from a `Cause`, that have clean stack traces and have had span information added to them.
5 changes: 5 additions & 0 deletions .changeset/few-bikes-cheer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

add span stack trace to rendered causes
5 changes: 5 additions & 0 deletions .changeset/four-garlics-wonder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": minor
---

add Chunk.difference & Chunk.differenceWith
6 changes: 6 additions & 0 deletions .changeset/gorgeous-students-jog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"effect": minor
"@effect/vitest": minor
---

Improve causal rendering in vitest by rethrowing pretty errors
19 changes: 19 additions & 0 deletions .changeset/lovely-frogs-scream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
"effect": minor
---

add Effect.functionWithSpan

Allows you to define an effectful function that is wrapped with a span.

```ts
import { Effect } from "effect"

const getTodo = Effect.functionWithSpan({
body: (id: number) => Effect.succeed(`Got todo ${id}!`),
options: (id) => ({
name: `getTodo-${id}`,
attributes: { id }
})
})
```
5 changes: 5 additions & 0 deletions .changeset/metal-balloons-play.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": minor
---

Add do notation for Array
5 changes: 5 additions & 0 deletions .changeset/quiet-ladybugs-fly.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": minor
---

support $is & $match for Data.TaggedEnum with generics
5 changes: 5 additions & 0 deletions .changeset/seven-cougars-jump.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@effect/platform": patch
---

Run client request stream with a current runtime.
5 changes: 5 additions & 0 deletions .changeset/soft-moons-raise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@effect/vitest": patch
---

Throw plain error object derived from fiber failure
9 changes: 9 additions & 0 deletions .changeset/tiny-zebras-work.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"effect": minor
"@effect/experimental": patch
"@effect/platform": patch
"@effect/rpc": patch
"@effect/sql": patch
---

capture stack trace for tracing spans
5 changes: 5 additions & 0 deletions .changeset/tough-buses-brush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

Consider Generator.next a cutpoint
5 changes: 5 additions & 0 deletions .changeset/warm-clouds-matter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@effect/opentelemetry": patch
---

properly record exceptions in otel spans
214 changes: 214 additions & 0 deletions packages/effect/src/Array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type { LazyArg } from "./Function.js"
import { dual, identity } from "./Function.js"
import type { TypeLambda } from "./HKT.js"
import * as readonlyArray from "./internal/array.js"
import * as doNotation from "./internal/doNotation.js"
import * as EffectIterable from "./Iterable.js"
import type { Option } from "./Option.js"
import * as O from "./Option.js"
Expand Down Expand Up @@ -2111,3 +2112,216 @@ export const cartesian: {
2,
<A, B>(self: ReadonlyArray<A>, that: ReadonlyArray<B>): Array<[A, B]> => cartesianWith(self, that, (a, b) => [a, b])
)

// -------------------------------------------------------------------------------------
// do notation
// -------------------------------------------------------------------------------------

/**
* The "do simulation" for array allows you to sequentially apply operations to the elements of arrays, just as nested loops allow you to go through all combinations of elements in an arrays.
*
* It can be used to simulate "array comprehension".
* It's a technique that allows you to create new arrays by iterating over existing ones and applying specific **conditions** or **transformations** to the elements. It's like assembling a new collection from pieces of other collections based on certain rules.
*
* Here's how the do simulation works:
*
* 1. Start the do simulation using the `Do` value
* 2. Within the do simulation scope, you can use the `bind` function to define variables and bind them to `Array` values
* 3. You can accumulate multiple `bind` statements to define multiple variables within the scope
* 4. Inside the do simulation scope, you can also use the `let` function to define variables and bind them to simple values
* 5. Regular `Option` functions like `map` and `filter` can still be used within the do simulation. These functions will receive the accumulated variables as arguments within the scope
*
* @see {@link bindTo}
* @see {@link bind}
* @see {@link let_ let}
*
* @example
* import { Array as Arr, pipe } from "effect"
* const doResult = pipe(
* Arr.Do,
* Arr.bind("x", () => [1, 3, 5]),
* Arr.bind("y", () => [2, 4, 6]),
* Arr.filter(({ x, y }) => x < y), // condition
* Arr.map(({ x, y }) => [x, y] as const) // transformation
* )
* assert.deepStrictEqual(doResult, [[1, 2], [1, 4], [1, 6], [3, 4], [3, 6], [5, 6]])
*
* // equivalent
* const x = [1, 3, 5],
* y = [2, 4, 6],
* result = [];
* for(let i = 0; i < x.length; i++) {
* for(let j = 0; j < y.length; j++) {
* const _x = x[i], _y = y[j];
* if(_x < _y) result.push([_x, _y] as const)
* }
* }
*
* @category do notation
* @since 3.2.0
*/
export const Do: ReadonlyArray<{}> = of({})

/**
* The "do simulation" for array allows you to sequentially apply operations to the elements of arrays, just as nested loops allow you to go through all combinations of elements in an arrays.
*
* It can be used to simulate "array comprehension".
* It's a technique that allows you to create new arrays by iterating over existing ones and applying specific **conditions** or **transformations** to the elements. It's like assembling a new collection from pieces of other collections based on certain rules.
*
* Here's how the do simulation works:
*
* 1. Start the do simulation using the `Do` value
* 2. Within the do simulation scope, you can use the `bind` function to define variables and bind them to `Array` values
* 3. You can accumulate multiple `bind` statements to define multiple variables within the scope
* 4. Inside the do simulation scope, you can also use the `let` function to define variables and bind them to simple values
* 5. Regular `Option` functions like `map` and `filter` can still be used within the do simulation. These functions will receive the accumulated variables as arguments within the scope
*
* @see {@link bindTo}
* @see {@link Do}
* @see {@link let_ let}
*
* @example
* import { Array as Arr, pipe } from "effect"
* const doResult = pipe(
* Arr.Do,
* Arr.bind("x", () => [1, 3, 5]),
* Arr.bind("y", () => [2, 4, 6]),
* Arr.filter(({ x, y }) => x < y), // condition
* Arr.map(({ x, y }) => [x, y] as const) // transformation
* )
* assert.deepStrictEqual(doResult, [[1, 2], [1, 4], [1, 6], [3, 4], [3, 6], [5, 6]])
*
* // equivalent
* const x = [1, 3, 5],
* y = [2, 4, 6],
* result = [];
* for(let i = 0; i < x.length; i++) {
* for(let j = 0; j < y.length; j++) {
* const _x = x[i], _y = y[j];
* if(_x < _y) result.push([_x, _y] as const)
* }
* }
*
* @category do notation
* @since 3.2.0
*/
export const bind: {
<A extends object, N extends string, B>(
tag: Exclude<N, keyof A>,
f: (a: A) => ReadonlyArray<B>
): (
self: ReadonlyArray<A>
) => Array<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }>
<A extends object, N extends string, B>(
self: ReadonlyArray<A>,
tag: Exclude<N, keyof A>,
f: (a: A) => ReadonlyArray<B>
): Array<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }>
} = doNotation.bind<ReadonlyArrayTypeLambda>(map, flatMap) as any

/**
* The "do simulation" for array allows you to sequentially apply operations to the elements of arrays, just as nested loops allow you to go through all combinations of elements in an arrays.
*
* It can be used to simulate "array comprehension".
* It's a technique that allows you to create new arrays by iterating over existing ones and applying specific **conditions** or **transformations** to the elements. It's like assembling a new collection from pieces of other collections based on certain rules.
*
* Here's how the do simulation works:
*
* 1. Start the do simulation using the `Do` value
* 2. Within the do simulation scope, you can use the `bind` function to define variables and bind them to `Array` values
* 3. You can accumulate multiple `bind` statements to define multiple variables within the scope
* 4. Inside the do simulation scope, you can also use the `let` function to define variables and bind them to simple values
* 5. Regular `Option` functions like `map` and `filter` can still be used within the do simulation. These functions will receive the accumulated variables as arguments within the scope
*
* @see {@link bindTo}
* @see {@link Do}
* @see {@link let_ let}
*
* @example
* import { Array as Arr, pipe } from "effect"
* const doResult = pipe(
* Arr.Do,
* Arr.bind("x", () => [1, 3, 5]),
* Arr.bind("y", () => [2, 4, 6]),
* Arr.filter(({ x, y }) => x < y), // condition
* Arr.map(({ x, y }) => [x, y] as const) // transformation
* )
* assert.deepStrictEqual(doResult, [[1, 2], [1, 4], [1, 6], [3, 4], [3, 6], [5, 6]])
*
* // equivalent
* const x = [1, 3, 5],
* y = [2, 4, 6],
* result = [];
* for(let i = 0; i < x.length; i++) {
* for(let j = 0; j < y.length; j++) {
* const _x = x[i], _y = y[j];
* if(_x < _y) result.push([_x, _y] as const)
* }
* }
*
* @category do notation
* @since 3.2.0
*/
export const bindTo: {
<N extends string>(tag: N): <A>(self: ReadonlyArray<A>) => Array<{ [K in N]: A }>
<A, N extends string>(self: ReadonlyArray<A>, tag: N): Array<{ [K in N]: A }>
} = doNotation.bindTo<ReadonlyArrayTypeLambda>(map) as any

const let_: {
<N extends string, B, A extends object>(
tag: Exclude<N, keyof A>,
f: (a: A) => B
): (self: ReadonlyArray<A>) => Array<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }>
<N extends string, A extends object, B>(
self: ReadonlyArray<A>,
tag: Exclude<N, keyof A>,
f: (a: A) => B
): Array<{ [K in N | keyof A]: K extends keyof A ? A[K] : B }>
} = doNotation.let_<ReadonlyArrayTypeLambda>(map) as any

export {
/**
* The "do simulation" for array allows you to sequentially apply operations to the elements of arrays, just as nested loops allow you to go through all combinations of elements in an arrays.
*
* It can be used to simulate "array comprehension".
* It's a technique that allows you to create new arrays by iterating over existing ones and applying specific **conditions** or **transformations** to the elements. It's like assembling a new collection from pieces of other collections based on certain rules.
*
* Here's how the do simulation works:
*
* 1. Start the do simulation using the `Do` value
* 2. Within the do simulation scope, you can use the `bind` function to define variables and bind them to `Array` values
* 3. You can accumulate multiple `bind` statements to define multiple variables within the scope
* 4. Inside the do simulation scope, you can also use the `let` function to define variables and bind them to simple values
* 5. Regular `Option` functions like `map` and `filter` can still be used within the do simulation. These functions will receive the accumulated variables as arguments within the scope
*
* @see {@link bindTo}
* @see {@link bind}
* @see {@link Do}
*
* @example
* import { Array as Arr, pipe } from "effect"
* const doResult = pipe(
* Arr.Do,
* Arr.bind("x", () => [1, 3, 5]),
* Arr.bind("y", () => [2, 4, 6]),
* Arr.filter(({ x, y }) => x < y), // condition
* Arr.map(({ x, y }) => [x, y] as const) // transformation
* )
* assert.deepStrictEqual(doResult, [[1, 2], [1, 4], [1, 6], [3, 4], [3, 6], [5, 6]])
*
* // equivalent
* const x = [1, 3, 5],
* y = [2, 4, 6],
* result = [];
* for(let i = 0; i < x.length; i++) {
* for(let j = 0; j < y.length; j++) {
* const _x = x[i], _y = y[j];
* if(_x < _y) result.push([_x, _y] as const)
* }
* }
*
* @category do notation
* @since 3.2.0
*/
let_ as let
}
17 changes: 17 additions & 0 deletions packages/effect/src/Cause.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import type { Pipeable } from "./Pipeable.js"
import type { Predicate, Refinement } from "./Predicate.js"
import type * as Sink from "./Sink.js"
import type * as Stream from "./Stream.js"
import type { Span } from "./Tracer.js"
import type { Covariant, NoInfer } from "./Types.js"

/**
Expand Down Expand Up @@ -914,6 +915,22 @@ export const isUnknownException: (u: unknown) => u is UnknownException = core.is
*/
export const pretty: <E>(cause: Cause<E>) => string = internal.pretty

/**
* @since 3.2.0
* @category models
*/
export interface PrettyError extends Error {
readonly span: Span | undefined
}

/**
* Returns the specified `Cause` as a pretty-printed string.
*
* @since 3.2.0
* @category rendering
*/
export const prettyErrors: <E>(cause: Cause<E>) => Array<PrettyError> = internal.prettyErrors

/**
* Returns the original, unproxied, instance of a thrown error
*
Expand Down
30 changes: 30 additions & 0 deletions packages/effect/src/Chunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1387,3 +1387,33 @@ export const reduceRight: {
<B, A>(b: B, f: (b: B, a: A, i: number) => B): (self: Chunk<A>) => B
<A, B>(self: Chunk<A>, b: B, f: (b: B, a: A, i: number) => B): B
} = RA.reduceRight

/**
* Creates a `Chunk` of values not included in the other given `Chunk` using the provided `isEquivalent` function.
* The order and references of result values are determined by the first `Chunk`.
*
* @since 3.2.0
*/
export const differenceWith = <A>(isEquivalent: (self: A, that: A) => boolean): {
(that: Chunk<A>): (self: Chunk<A>) => Chunk<A>
(self: Chunk<A>, that: Chunk<A>): Chunk<A>
} => {
return dual(
2,
(self: Chunk<A>, that: Chunk<A>): Chunk<A> => unsafeFromArray(RA.differenceWith(isEquivalent)(that, self))
)
}

/**
* Creates a `Chunk` of values not included in the other given `Chunk`.
* The order and references of result values are determined by the first `Chunk`.
*
* @since 3.2.0
*/
export const difference: {
<A>(that: Chunk<A>): (self: Chunk<A>) => Chunk<A>
<A>(self: Chunk<A>, that: Chunk<A>): Chunk<A>
} = dual(
2,
<A>(self: Chunk<A>, that: Chunk<A>): Chunk<A> => unsafeFromArray(RA.difference(that, self))
)
Loading

0 comments on commit 76efa47

Please sign in to comment.