0.2.0 #5

Merged
Thilawyn merged 59 commits from next into master 2026-05-30 06:10:54 +02:00
3 changed files with 91 additions and 1 deletions
Showing only changes of commit 31f275ec44 - Show all commits
+3
View File
@@ -241,8 +241,11 @@ Currently available:
| - | - | | - | - |
| `focusObjectOn` | Focuses to the field of an object | | `focusObjectOn` | Focuses to the field of an object |
| `focusArrayAt` | Focuses to an indexed entry of an array | | `focusArrayAt` | Focuses to an indexed entry of an array |
| `focusArrayLength` | Focuses to the length of an array |
| `focusTupleAt` | Focuses to an indexed entry of a tuple | | `focusTupleAt` | Focuses to an indexed entry of a tuple |
| `focusChunkAt` | Focuses to an indexed entry of a `Chunk` | | `focusChunkAt` | Focuses to an indexed entry of a `Chunk` |
| `focusChunkSize` | Focuses to the size of a `Chunk` |
| `focusIterableSize` | Focuses to the size of an iterable |
## Todo ## Todo
@@ -0,0 +1,66 @@
import { describe, expect, test } from "bun:test"
import { Chunk, Effect, SubscriptionRef } from "effect"
import * as Subscribable from "./Subscribable.js"
describe("Subscribable", () => {
test("focusArrayLength reads the current array length and reflects updates", async () => {
const result = await Effect.runPromise(
Effect.flatMap(
SubscriptionRef.make([1, 2, 3]),
parent => {
const sizeSub = Subscribable.focusArrayLength(parent)
return Effect.flatMap(
sizeSub.get,
initial => Effect.flatMap(
SubscriptionRef.set(parent, [1, 2, 3, 4, 5]),
() => Effect.map(sizeSub.get, next => [initial, next] as const),
),
)
},
),
)
expect(result).toEqual([3, 5])
})
test("focusChunkSize reads the current chunk size and reflects updates", async () => {
const result = await Effect.runPromise(
Effect.flatMap(
SubscriptionRef.make(Chunk.make(1, 2) as Chunk.Chunk<number>),
parent => {
const sizeSub = Subscribable.focusChunkSize(parent)
return Effect.flatMap(
sizeSub.get,
initial => Effect.flatMap(
SubscriptionRef.set(parent, Chunk.make(1, 2, 3, 4)),
() => Effect.map(sizeSub.get, next => [initial, next] as const),
),
)
},
),
)
expect(result).toEqual([2, 4])
})
test("focusIterableSize also works for array values", async () => {
const result = await Effect.runPromise(
Effect.flatMap(
SubscriptionRef.make([1, 2, 3]),
parent => {
const sizeSub = Subscribable.focusIterableSize(parent)
return Effect.flatMap(
sizeSub.get,
initial => Effect.flatMap(
SubscriptionRef.set(parent, [1, 2, 3, 4, 5]),
() => Effect.map(sizeSub.get, next => [initial, next] as const),
),
)
},
),
)
expect(result).toEqual([3, 5])
})
})
+22 -1
View File
@@ -1,4 +1,4 @@
import { Array, Chunk, Effect, Function, Option, Subscribable } from "effect" import { Array, Chunk, Effect, Function, Iterable, Option, Subscribable } from "effect"
import type { NoSuchElementException } from "effect/Cause" import type { NoSuchElementException } from "effect/Cause"
@@ -71,6 +71,13 @@ export const focusArrayAt: {
index: number, index: number,
): Subscribable.Subscribable<A[number], E | NoSuchElementException, R> => Subscribable.mapEffect(self, Array.get(index))) ): Subscribable.Subscribable<A[number], E | NoSuchElementException, R> => Subscribable.mapEffect(self, Array.get(index)))
/**
* Narrows the focus to the length of an array.
*/
export const focusArrayLength = <A extends readonly any[], E, R>(
self: Subscribable.Subscribable<A, E, R>,
): Subscribable.Subscribable<number, E, R> => Subscribable.map(self, a => a.length)
/** /**
* Narrows the focus to an indexed element of a readonly tuple. * Narrows the focus to an indexed element of a readonly tuple.
*/ */
@@ -102,3 +109,17 @@ export const focusChunkAt: {
self: Subscribable.Subscribable<Chunk.Chunk<A>, E, R>, self: Subscribable.Subscribable<Chunk.Chunk<A>, E, R>,
index: number, index: number,
): Subscribable.Subscribable<A, E | NoSuchElementException, R> => Subscribable.mapEffect(self, Chunk.get(index))) ): Subscribable.Subscribable<A, E | NoSuchElementException, R> => Subscribable.mapEffect(self, Chunk.get(index)))
/**
* Narrows the focus to the size of a `Chunk`.
*/
export const focusChunkSize = <A, E, R>(
self: Subscribable.Subscribable<Chunk.Chunk<A>, E, R>,
): Subscribable.Subscribable<number, E, R> => Subscribable.map(self, Chunk.size)
/**
* Narrows the focus to the size of a `Iterable`.
*/
export const focusIterableSize = <A, E, R>(
self: Subscribable.Subscribable<Iterable<A>, E, R>,
): Subscribable.Subscribable<number, E, R> => Subscribable.map(self, Iterable.size)