@typed/fx 1.12.2 → 1.12.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.d.ts +2 -2
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/keyed.d.ts +2 -2
- package/dist/cjs/keyed.d.ts.map +1 -1
- package/dist/cjs/keyed.js +26 -21
- package/dist/cjs/keyed.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/keyed.d.ts +2 -2
- package/dist/keyed.d.ts.map +1 -1
- package/dist/keyed.js +26 -21
- package/dist/keyed.js.map +1 -1
- package/dist/tsconfig.cjs.build.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/index.ts +10 -10
- package/src/keyed.test.ts +9 -5
- package/src/keyed.ts +45 -35
- package/tsconfig.build.tsbuildinfo +1 -1
package/src/keyed.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as MutableHashMap from '@effect/data/MutableHashMap'
|
|
2
2
|
import * as Option from '@effect/data/Option'
|
|
3
3
|
import * as ReadonlyArray from '@effect/data/ReadonlyArray'
|
|
4
|
-
import
|
|
4
|
+
import * as Equivalence from '@effect/data/typeclass/Equivalence'
|
|
5
5
|
import * as Effect from '@effect/io/Effect'
|
|
6
6
|
import * as Fiber from '@effect/io/Fiber'
|
|
7
7
|
import fastDeepEqual from 'fast-deep-equal'
|
|
@@ -12,18 +12,19 @@ import { Subject, makeHoldSubject } from './Subject.js'
|
|
|
12
12
|
import { Cause } from './externals.js'
|
|
13
13
|
import { ScopedFork, withScopedFork } from './helpers.js'
|
|
14
14
|
|
|
15
|
-
export function keyed<R, E, A, R2, E2, B>(
|
|
15
|
+
export function keyed<R, E, A, R2, E2, B, C>(
|
|
16
16
|
fx: Fx<R, E, readonly A[]>,
|
|
17
|
-
f: (
|
|
18
|
-
|
|
17
|
+
f: (fx: RefSubject<never, A>) => Fx<R2, E2, B>,
|
|
18
|
+
getKey: (a: A) => C,
|
|
19
19
|
): Fx<R | R2, E | E2, readonly B[]> {
|
|
20
20
|
return Fx(<R3>(sink: Sink<R3, E | E2, readonly B[]>) =>
|
|
21
21
|
withScopedFork((fork) =>
|
|
22
22
|
Effect.gen(function* ($) {
|
|
23
|
-
const state = createKeyedState<A, B>()
|
|
23
|
+
const state = createKeyedState<A, B, C>()
|
|
24
|
+
const eq = Equivalence.make((x: A, y: A) => fastDeepEqual(getKey(x), getKey(y)))
|
|
24
25
|
const difference = ReadonlyArray.difference(eq)
|
|
25
26
|
const intersection = ReadonlyArray.intersection(eq)
|
|
26
|
-
const emit = emitWhenReady(state)
|
|
27
|
+
const emit = emitWhenReady(state, getKey)
|
|
27
28
|
|
|
28
29
|
// Let output emit to the sink
|
|
29
30
|
const fiber = yield* $(fork(state.output.run(sink)))
|
|
@@ -36,6 +37,7 @@ export function keyed<R, E, A, R2, E2, B>(
|
|
|
36
37
|
updateState({
|
|
37
38
|
state,
|
|
38
39
|
updated: as,
|
|
40
|
+
getKey,
|
|
39
41
|
f,
|
|
40
42
|
fork,
|
|
41
43
|
difference,
|
|
@@ -60,17 +62,17 @@ export function keyed<R, E, A, R2, E2, B>(
|
|
|
60
62
|
)
|
|
61
63
|
}
|
|
62
64
|
|
|
63
|
-
type KeyedState<A, B> = {
|
|
65
|
+
type KeyedState<A, B, C> = {
|
|
64
66
|
previous: readonly A[]
|
|
65
67
|
ended: boolean
|
|
66
68
|
|
|
67
|
-
readonly subjects: MutableHashMap.MutableHashMap<
|
|
68
|
-
readonly fibers: MutableHashMap.MutableHashMap<
|
|
69
|
-
readonly values: MutableHashMap.MutableHashMap<
|
|
69
|
+
readonly subjects: MutableHashMap.MutableHashMap<C, Subject<never, A>>
|
|
70
|
+
readonly fibers: MutableHashMap.MutableHashMap<C, Fiber.RuntimeFiber<never, void>>
|
|
71
|
+
readonly values: MutableHashMap.MutableHashMap<C, B>
|
|
70
72
|
readonly output: Subject<never, readonly B[]>
|
|
71
73
|
}
|
|
72
74
|
|
|
73
|
-
function createKeyedState<A, B>(): KeyedState<A, B> {
|
|
75
|
+
function createKeyedState<A, B, C>(): KeyedState<A, B, C> {
|
|
74
76
|
return {
|
|
75
77
|
previous: [],
|
|
76
78
|
ended: false,
|
|
@@ -81,7 +83,7 @@ function createKeyedState<A, B>(): KeyedState<A, B> {
|
|
|
81
83
|
}
|
|
82
84
|
}
|
|
83
85
|
|
|
84
|
-
function updateState<A, B, R2, E2, R3>({
|
|
86
|
+
function updateState<A, B, C, R2, E2, R3>({
|
|
85
87
|
state,
|
|
86
88
|
updated,
|
|
87
89
|
f,
|
|
@@ -90,15 +92,17 @@ function updateState<A, B, R2, E2, R3>({
|
|
|
90
92
|
intersection,
|
|
91
93
|
emit,
|
|
92
94
|
error,
|
|
95
|
+
getKey,
|
|
93
96
|
}: {
|
|
94
|
-
state: KeyedState<A, B>
|
|
97
|
+
state: KeyedState<A, B, C>
|
|
95
98
|
updated: readonly A[]
|
|
96
|
-
f: (
|
|
99
|
+
f: (fx: RefSubject<never, A>) => Fx<R2, E2, B>
|
|
97
100
|
fork: ScopedFork
|
|
98
101
|
difference: (self: Iterable<A>, that: Iterable<A>) => A[]
|
|
99
102
|
intersection: (self: Iterable<A>, that: Iterable<A>) => A[]
|
|
100
103
|
emit: Effect.Effect<never, never, void>
|
|
101
104
|
error: (e: Cause.Cause<E2>) => Effect.Effect<R3, never, void>
|
|
105
|
+
getKey: (a: A) => C
|
|
102
106
|
}) {
|
|
103
107
|
return Effect.gen(function* ($) {
|
|
104
108
|
const added = difference(updated, state.previous)
|
|
@@ -108,15 +112,17 @@ function updateState<A, B, R2, E2, R3>({
|
|
|
108
112
|
state.previous = updated
|
|
109
113
|
|
|
110
114
|
// Remove values that are no longer in the stream
|
|
111
|
-
yield* $(Effect.forEachParDiscard(removed, (value) => removeValue(state, value)))
|
|
115
|
+
yield* $(Effect.forEachParDiscard(removed, (value) => removeValue(state, value, getKey)))
|
|
112
116
|
|
|
113
117
|
// Add values that are new to the stream
|
|
114
118
|
yield* $(
|
|
115
|
-
Effect.forEachParDiscard(added, (value) =>
|
|
119
|
+
Effect.forEachParDiscard(added, (value) =>
|
|
120
|
+
addValue({ state, value, f, fork, emit, error, getKey }),
|
|
121
|
+
),
|
|
116
122
|
)
|
|
117
123
|
|
|
118
124
|
// Update values that are still in the stream
|
|
119
|
-
yield* $(Effect.forEachParDiscard(unchanged, (value) => updateValue(state, value)))
|
|
125
|
+
yield* $(Effect.forEachParDiscard(unchanged, (value) => updateValue(state, value, getKey)))
|
|
120
126
|
|
|
121
127
|
// If nothing was added or removed, emit the current values
|
|
122
128
|
if (added.length === 0 && removed.length === 0) {
|
|
@@ -125,47 +131,51 @@ function updateState<A, B, R2, E2, R3>({
|
|
|
125
131
|
})
|
|
126
132
|
}
|
|
127
133
|
|
|
128
|
-
function removeValue<A, B>(state: KeyedState<A, B>, value: A) {
|
|
134
|
+
function removeValue<A, B, C>(state: KeyedState<A, B, C>, value: A, getKey: (a: A) => C) {
|
|
129
135
|
return Effect.gen(function* ($) {
|
|
130
|
-
const
|
|
136
|
+
const key = getKey(value)
|
|
137
|
+
const subject = MutableHashMap.get(state.subjects, key)
|
|
131
138
|
|
|
132
139
|
if (Option.isSome(subject)) yield* $(subject.value.end())
|
|
133
140
|
|
|
134
|
-
const fiber = MutableHashMap.get(state.fibers,
|
|
141
|
+
const fiber = MutableHashMap.get(state.fibers, key)
|
|
135
142
|
|
|
136
143
|
if (Option.isSome(fiber)) yield* $(Fiber.interrupt(fiber.value))
|
|
137
144
|
|
|
138
|
-
MutableHashMap.remove(state.values,
|
|
139
|
-
MutableHashMap.remove(state.subjects,
|
|
140
|
-
MutableHashMap.remove(state.fibers,
|
|
145
|
+
MutableHashMap.remove(state.values, key)
|
|
146
|
+
MutableHashMap.remove(state.subjects, key)
|
|
147
|
+
MutableHashMap.remove(state.fibers, key)
|
|
141
148
|
})
|
|
142
149
|
}
|
|
143
150
|
|
|
144
|
-
function addValue<A, B, R2, E2, R3>({
|
|
151
|
+
function addValue<A, B, C, R2, E2, R3>({
|
|
145
152
|
state,
|
|
146
153
|
value,
|
|
147
154
|
f,
|
|
148
155
|
fork,
|
|
149
156
|
emit,
|
|
150
157
|
error,
|
|
158
|
+
getKey,
|
|
151
159
|
}: {
|
|
152
|
-
state: KeyedState<A, B>
|
|
160
|
+
state: KeyedState<A, B, C>
|
|
153
161
|
value: A
|
|
154
|
-
f: (
|
|
162
|
+
f: (fx: RefSubject<never, A>) => Fx<R2, E2, B>
|
|
155
163
|
fork: ScopedFork
|
|
156
164
|
emit: Effect.Effect<never, never, void>
|
|
157
165
|
error: (e: Cause.Cause<E2>) => Effect.Effect<R3, never, void>
|
|
166
|
+
getKey: (a: A) => C
|
|
158
167
|
}) {
|
|
159
168
|
return Effect.gen(function* ($) {
|
|
169
|
+
const key = getKey(value)
|
|
160
170
|
const subject = RefSubject.unsafeMake<never, A>(Effect.succeed(value))
|
|
161
|
-
const fx = f(subject
|
|
171
|
+
const fx = f(subject)
|
|
162
172
|
const fiber = yield* $(
|
|
163
173
|
fork(
|
|
164
174
|
fx.run(
|
|
165
175
|
Sink(
|
|
166
176
|
(b: B) =>
|
|
167
177
|
Effect.suspend(() => {
|
|
168
|
-
MutableHashMap.set(state.values,
|
|
178
|
+
MutableHashMap.set(state.values, key, b)
|
|
169
179
|
return emit
|
|
170
180
|
}),
|
|
171
181
|
error,
|
|
@@ -174,14 +184,14 @@ function addValue<A, B, R2, E2, R3>({
|
|
|
174
184
|
),
|
|
175
185
|
)
|
|
176
186
|
|
|
177
|
-
MutableHashMap.set(state.subjects,
|
|
178
|
-
MutableHashMap.set(state.fibers,
|
|
187
|
+
MutableHashMap.set(state.subjects, key, subject)
|
|
188
|
+
MutableHashMap.set(state.fibers, key, fiber)
|
|
179
189
|
})
|
|
180
190
|
}
|
|
181
191
|
|
|
182
|
-
function updateValue<A, B>(state: KeyedState<A, B>, value: A) {
|
|
192
|
+
function updateValue<A, B, C>(state: KeyedState<A, B, C>, value: A, getKey: (a: A) => C) {
|
|
183
193
|
return Effect.gen(function* ($) {
|
|
184
|
-
const subject = MutableHashMap.get(state.subjects, value)
|
|
194
|
+
const subject = MutableHashMap.get(state.subjects, getKey(value))
|
|
185
195
|
|
|
186
196
|
// Send the current value
|
|
187
197
|
if (Option.isSome(subject)) {
|
|
@@ -190,10 +200,10 @@ function updateValue<A, B>(state: KeyedState<A, B>, value: A) {
|
|
|
190
200
|
})
|
|
191
201
|
}
|
|
192
202
|
|
|
193
|
-
function emitWhenReady<A, B>(state: KeyedState<A, B
|
|
203
|
+
function emitWhenReady<A, B, C>(state: KeyedState<A, B, C>, getKey: (a: A) => C) {
|
|
194
204
|
return Effect.suspend(() => {
|
|
195
205
|
const values = ReadonlyArray.filterMap(state.previous, (value) =>
|
|
196
|
-
MutableHashMap.get(state.values, value),
|
|
206
|
+
MutableHashMap.get(state.values, getKey(value)),
|
|
197
207
|
)
|
|
198
208
|
|
|
199
209
|
// When all of the values have resolved at least once, emit the output
|
|
@@ -205,7 +215,7 @@ function emitWhenReady<A, B>(state: KeyedState<A, B>) {
|
|
|
205
215
|
})
|
|
206
216
|
}
|
|
207
217
|
|
|
208
|
-
function endAll<A, B>(state: KeyedState<A, B>) {
|
|
218
|
+
function endAll<A, B, C>(state: KeyedState<A, B, C>) {
|
|
209
219
|
return Effect.gen(function* ($) {
|
|
210
220
|
yield* $(Effect.forEachParDiscard(state.subjects, ([, subject]) => subject.end()))
|
|
211
221
|
})
|