effect 3.10.0 → 3.10.2
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/GlobalValue.js +29 -0
- package/dist/cjs/GlobalValue.js.map +1 -1
- package/dist/cjs/internal/channel/channelExecutor.js +160 -161
- package/dist/cjs/internal/channel/channelExecutor.js.map +1 -1
- package/dist/cjs/internal/version.js +1 -1
- package/dist/dts/GlobalValue.d.ts +18 -0
- package/dist/dts/GlobalValue.d.ts.map +1 -1
- package/dist/dts/Match.d.ts +1 -4
- package/dist/dts/Match.d.ts.map +1 -1
- package/dist/dts/Types.d.ts +4 -8
- package/dist/dts/Types.d.ts.map +1 -1
- package/dist/dts/index.d.ts +11 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/esm/GlobalValue.js +29 -0
- package/dist/esm/GlobalValue.js.map +1 -1
- package/dist/esm/index.js +11 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/channel/channelExecutor.js +160 -161
- package/dist/esm/internal/channel/channelExecutor.js.map +1 -1
- package/dist/esm/internal/version.js +1 -1
- package/package.json +1 -1
- package/src/GlobalValue.ts +29 -0
- package/src/Match.ts +1 -5
- package/src/Types.ts +6 -14
- package/src/index.ts +11 -0
- package/src/internal/channel/channelExecutor.ts +213 -214
- package/src/internal/version.ts +1 -1
package/src/index.ts
CHANGED
|
@@ -323,6 +323,17 @@ export * as FiberStatus from "./FiberStatus.js"
|
|
|
323
323
|
export * as Function from "./Function.js"
|
|
324
324
|
|
|
325
325
|
/**
|
|
326
|
+
* The `GlobalValue` module ensures that a single instance of a value is created globally,
|
|
327
|
+
* even when modules are imported multiple times (e.g., due to mixing CommonJS and ESM builds)
|
|
328
|
+
* or during hot-reloading in development environments like Next.js or Remix.
|
|
329
|
+
*
|
|
330
|
+
* It achieves this by using a versioned global store, identified by a unique `Symbol` tied to
|
|
331
|
+
* the current version of the `effect` library. The store holds values that are keyed by an identifier,
|
|
332
|
+
* allowing the reuse of previously computed instances across imports or reloads.
|
|
333
|
+
*
|
|
334
|
+
* This pattern is particularly useful in scenarios where frequent reloading can cause services or
|
|
335
|
+
* single-instance objects to be recreated unnecessarily, such as in development environments with hot-reloading.
|
|
336
|
+
*
|
|
326
337
|
* @since 2.0.0
|
|
327
338
|
*/
|
|
328
339
|
export * as GlobalValue from "./GlobalValue.js"
|
|
@@ -101,247 +101,246 @@ export class ChannelExecutor<
|
|
|
101
101
|
} else {
|
|
102
102
|
if (Effect.isEffect(this._currentChannel)) {
|
|
103
103
|
this._currentChannel = core.fromEffect(this._currentChannel) as core.Primitive
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
104
|
+
}
|
|
105
|
+
switch (this._currentChannel._tag) {
|
|
106
|
+
case ChannelOpCodes.OP_BRACKET_OUT: {
|
|
107
|
+
result = this.runBracketOut(this._currentChannel)
|
|
108
|
+
break
|
|
109
|
+
}
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
case ChannelStateOpCodes.OP_READ: {
|
|
147
|
-
return readUpstream(
|
|
148
|
-
state,
|
|
149
|
-
() => drainer(),
|
|
150
|
-
(cause) => bridgeInput.error(cause)
|
|
151
|
-
)
|
|
152
|
-
}
|
|
111
|
+
case ChannelOpCodes.OP_BRIDGE: {
|
|
112
|
+
const bridgeInput = this._currentChannel.input
|
|
113
|
+
|
|
114
|
+
// PipeTo(left, Bridge(queue, channel))
|
|
115
|
+
// In a fiber: repeatedly run left and push its outputs to the queue
|
|
116
|
+
// Add a finalizer to interrupt the fiber and close the executor
|
|
117
|
+
this._currentChannel = this._currentChannel.channel as core.Primitive
|
|
118
|
+
|
|
119
|
+
if (this._input !== undefined) {
|
|
120
|
+
const inputExecutor = this._input
|
|
121
|
+
this._input = undefined
|
|
122
|
+
|
|
123
|
+
const drainer = (): Effect.Effect<unknown, never, Env> =>
|
|
124
|
+
Effect.flatMap(bridgeInput.awaitRead(), () =>
|
|
125
|
+
Effect.suspend(() => {
|
|
126
|
+
const state = inputExecutor.run() as ChannelState.Primitive
|
|
127
|
+
switch (state._tag) {
|
|
128
|
+
case ChannelStateOpCodes.OP_DONE: {
|
|
129
|
+
return Exit.match(inputExecutor.getDone(), {
|
|
130
|
+
onFailure: (cause) => bridgeInput.error(cause),
|
|
131
|
+
onSuccess: (value) => bridgeInput.done(value)
|
|
132
|
+
})
|
|
133
|
+
}
|
|
134
|
+
case ChannelStateOpCodes.OP_EMIT: {
|
|
135
|
+
return Effect.flatMap(
|
|
136
|
+
bridgeInput.emit(inputExecutor.getEmit()),
|
|
137
|
+
() => drainer()
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
case ChannelStateOpCodes.OP_FROM_EFFECT: {
|
|
141
|
+
return Effect.matchCauseEffect(state.effect, {
|
|
142
|
+
onFailure: (cause) => bridgeInput.error(cause),
|
|
143
|
+
onSuccess: () => drainer()
|
|
144
|
+
})
|
|
153
145
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
(fiber) =>
|
|
160
|
-
Effect.sync(() =>
|
|
161
|
-
this.addFinalizer((exit) =>
|
|
162
|
-
Effect.flatMap(Fiber.interrupt(fiber), () =>
|
|
163
|
-
Effect.suspend(() => {
|
|
164
|
-
const effect = this.restorePipe(exit, inputExecutor)
|
|
165
|
-
return effect !== undefined ? effect : Effect.void
|
|
166
|
-
}))
|
|
146
|
+
case ChannelStateOpCodes.OP_READ: {
|
|
147
|
+
return readUpstream(
|
|
148
|
+
state,
|
|
149
|
+
() => drainer(),
|
|
150
|
+
(cause) => bridgeInput.error(cause)
|
|
167
151
|
)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
})) as Effect.Effect<unknown, never, Env>
|
|
155
|
+
|
|
156
|
+
result = ChannelState.fromEffect(
|
|
157
|
+
Effect.flatMap(
|
|
158
|
+
Effect.forkDaemon(Effect.interruptible(drainer())),
|
|
159
|
+
(fiber) =>
|
|
160
|
+
Effect.sync(() =>
|
|
161
|
+
this.addFinalizer((exit) =>
|
|
162
|
+
Effect.flatMap(Fiber.interrupt(fiber), () =>
|
|
163
|
+
Effect.suspend(() => {
|
|
164
|
+
const effect = this.restorePipe(exit, inputExecutor)
|
|
165
|
+
return effect !== undefined ? effect : Effect.void
|
|
166
|
+
}))
|
|
168
167
|
)
|
|
169
|
-
|
|
168
|
+
)
|
|
170
169
|
)
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
break
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
case ChannelOpCodes.OP_CONCAT_ALL: {
|
|
177
|
-
const executor: ErasedExecutor<Env> = new ChannelExecutor(
|
|
178
|
-
this._currentChannel.value() as Channel.Channel<
|
|
179
|
-
never,
|
|
180
|
-
unknown,
|
|
181
|
-
never,
|
|
182
|
-
unknown,
|
|
183
|
-
never,
|
|
184
|
-
unknown,
|
|
185
|
-
Env
|
|
186
|
-
>,
|
|
187
|
-
this._providedEnv,
|
|
188
|
-
(effect) =>
|
|
189
|
-
Effect.sync(() => {
|
|
190
|
-
const prevLastClose = this._closeLastSubstream === undefined
|
|
191
|
-
? Effect.void
|
|
192
|
-
: this._closeLastSubstream
|
|
193
|
-
this._closeLastSubstream = pipe(prevLastClose, Effect.zipRight(effect))
|
|
194
|
-
})
|
|
195
|
-
)
|
|
196
|
-
executor._input = this._input
|
|
197
|
-
|
|
198
|
-
const channel = this._currentChannel
|
|
199
|
-
this._activeSubexecutor = new Subexecutor.PullFromUpstream(
|
|
200
|
-
executor,
|
|
201
|
-
(value) => channel.k(value),
|
|
202
|
-
undefined,
|
|
203
|
-
[],
|
|
204
|
-
(x, y) => channel.combineInners(x, y),
|
|
205
|
-
(x, y) => channel.combineAll(x, y),
|
|
206
|
-
(request) => channel.onPull(request),
|
|
207
|
-
(value) => channel.onEmit(value)
|
|
208
170
|
)
|
|
171
|
+
}
|
|
209
172
|
|
|
210
|
-
|
|
211
|
-
|
|
173
|
+
break
|
|
174
|
+
}
|
|
212
175
|
|
|
213
|
-
|
|
214
|
-
|
|
176
|
+
case ChannelOpCodes.OP_CONCAT_ALL: {
|
|
177
|
+
const executor: ErasedExecutor<Env> = new ChannelExecutor(
|
|
178
|
+
this._currentChannel.value() as Channel.Channel<
|
|
179
|
+
never,
|
|
180
|
+
unknown,
|
|
181
|
+
never,
|
|
182
|
+
unknown,
|
|
183
|
+
never,
|
|
184
|
+
unknown,
|
|
185
|
+
Env
|
|
186
|
+
>,
|
|
187
|
+
this._providedEnv,
|
|
188
|
+
(effect) =>
|
|
189
|
+
Effect.sync(() => {
|
|
190
|
+
const prevLastClose = this._closeLastSubstream === undefined
|
|
191
|
+
? Effect.void
|
|
192
|
+
: this._closeLastSubstream
|
|
193
|
+
this._closeLastSubstream = pipe(prevLastClose, Effect.zipRight(effect))
|
|
194
|
+
})
|
|
195
|
+
)
|
|
196
|
+
executor._input = this._input
|
|
197
|
+
|
|
198
|
+
const channel = this._currentChannel
|
|
199
|
+
this._activeSubexecutor = new Subexecutor.PullFromUpstream(
|
|
200
|
+
executor,
|
|
201
|
+
(value) => channel.k(value),
|
|
202
|
+
undefined,
|
|
203
|
+
[],
|
|
204
|
+
(x, y) => channel.combineInners(x, y),
|
|
205
|
+
(x, y) => channel.combineAll(x, y),
|
|
206
|
+
(request) => channel.onPull(request),
|
|
207
|
+
(value) => channel.onEmit(value)
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
this._closeLastSubstream = undefined
|
|
211
|
+
this._currentChannel = undefined
|
|
212
|
+
|
|
213
|
+
break
|
|
214
|
+
}
|
|
215
215
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
216
|
+
case ChannelOpCodes.OP_EMIT: {
|
|
217
|
+
this._emitted = this._currentChannel.out
|
|
218
|
+
this._currentChannel = (this._activeSubexecutor !== undefined ?
|
|
219
|
+
undefined :
|
|
220
|
+
core.void) as core.Primitive | undefined
|
|
221
|
+
result = ChannelState.Emit()
|
|
222
|
+
break
|
|
223
|
+
}
|
|
224
224
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
225
|
+
case ChannelOpCodes.OP_ENSURING: {
|
|
226
|
+
this.runEnsuring(this._currentChannel)
|
|
227
|
+
break
|
|
228
|
+
}
|
|
229
229
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
230
|
+
case ChannelOpCodes.OP_FAIL: {
|
|
231
|
+
result = this.doneHalt(this._currentChannel.error())
|
|
232
|
+
break
|
|
233
|
+
}
|
|
234
234
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
235
|
+
case ChannelOpCodes.OP_FOLD: {
|
|
236
|
+
this._doneStack.push(this._currentChannel.k as ErasedContinuation<Env>)
|
|
237
|
+
this._currentChannel = this._currentChannel.channel as core.Primitive
|
|
238
|
+
break
|
|
239
|
+
}
|
|
240
240
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
241
|
+
case ChannelOpCodes.OP_FROM_EFFECT: {
|
|
242
|
+
const effect = this._providedEnv === undefined ?
|
|
243
|
+
this._currentChannel.effect() :
|
|
244
|
+
pipe(
|
|
245
|
+
this._currentChannel.effect(),
|
|
246
|
+
Effect.provide(this._providedEnv)
|
|
247
|
+
)
|
|
248
248
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
249
|
+
result = ChannelState.fromEffect(
|
|
250
|
+
Effect.matchCauseEffect(effect, {
|
|
251
|
+
onFailure: (cause) => {
|
|
252
|
+
const state = this.doneHalt(cause)
|
|
253
|
+
return state !== undefined && ChannelState.isFromEffect(state) ?
|
|
254
|
+
state.effect :
|
|
255
|
+
Effect.void
|
|
256
|
+
},
|
|
257
|
+
onSuccess: (value) => {
|
|
258
|
+
const state = this.doneSucceed(value)
|
|
259
|
+
return state !== undefined && ChannelState.isFromEffect(state) ?
|
|
260
|
+
state.effect :
|
|
261
|
+
Effect.void
|
|
262
|
+
}
|
|
263
|
+
})
|
|
264
|
+
) as ChannelState.ChannelState<unknown, Env> | undefined
|
|
265
265
|
|
|
266
|
-
|
|
267
|
-
|
|
266
|
+
break
|
|
267
|
+
}
|
|
268
268
|
|
|
269
|
-
|
|
270
|
-
|
|
269
|
+
case ChannelOpCodes.OP_PIPE_TO: {
|
|
270
|
+
const previousInput = this._input
|
|
271
271
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
272
|
+
const leftExec: ErasedExecutor<Env> = new ChannelExecutor(
|
|
273
|
+
this._currentChannel.left() as Channel.Channel<never, unknown, never, unknown, never, unknown, Env>,
|
|
274
|
+
this._providedEnv,
|
|
275
|
+
(effect) => this._executeCloseLastSubstream(effect)
|
|
276
|
+
)
|
|
277
|
+
leftExec._input = previousInput
|
|
278
|
+
this._input = leftExec
|
|
279
279
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
280
|
+
this.addFinalizer((exit) => {
|
|
281
|
+
const effect = this.restorePipe(exit, previousInput)
|
|
282
|
+
return effect !== undefined ? effect : Effect.void
|
|
283
|
+
})
|
|
284
284
|
|
|
285
|
-
|
|
285
|
+
this._currentChannel = this._currentChannel.right() as core.Primitive
|
|
286
286
|
|
|
287
|
-
|
|
288
|
-
|
|
287
|
+
break
|
|
288
|
+
}
|
|
289
289
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
290
|
+
case ChannelOpCodes.OP_PROVIDE: {
|
|
291
|
+
const previousEnv = this._providedEnv
|
|
292
|
+
this._providedEnv = this._currentChannel.context()
|
|
293
|
+
this._currentChannel = this._currentChannel.inner as core.Primitive
|
|
294
|
+
this.addFinalizer(() =>
|
|
295
|
+
Effect.sync(() => {
|
|
296
|
+
this._providedEnv = previousEnv
|
|
297
|
+
})
|
|
298
|
+
)
|
|
299
|
+
break
|
|
300
|
+
}
|
|
301
301
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
}
|
|
313
|
-
return undefined
|
|
314
|
-
},
|
|
315
|
-
(exit) => {
|
|
316
|
-
const onExit = (exit: Exit.Exit<unknown, unknown>): core.Primitive => {
|
|
317
|
-
return read.done.onExit(exit) as core.Primitive
|
|
318
|
-
}
|
|
319
|
-
this._currentChannel = onExit(exit)
|
|
320
|
-
return undefined
|
|
302
|
+
case ChannelOpCodes.OP_READ: {
|
|
303
|
+
const read = this._currentChannel
|
|
304
|
+
result = ChannelState.Read(
|
|
305
|
+
this._input!,
|
|
306
|
+
identity,
|
|
307
|
+
(emitted) => {
|
|
308
|
+
try {
|
|
309
|
+
this._currentChannel = read.more(emitted) as core.Primitive
|
|
310
|
+
} catch (error) {
|
|
311
|
+
this._currentChannel = read.done.onExit(Exit.die(error)) as core.Primitive
|
|
321
312
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
313
|
+
return undefined
|
|
314
|
+
},
|
|
315
|
+
(exit) => {
|
|
316
|
+
const onExit = (exit: Exit.Exit<unknown, unknown>): core.Primitive => {
|
|
317
|
+
return read.done.onExit(exit) as core.Primitive
|
|
318
|
+
}
|
|
319
|
+
this._currentChannel = onExit(exit)
|
|
320
|
+
return undefined
|
|
321
|
+
}
|
|
322
|
+
)
|
|
323
|
+
break
|
|
324
|
+
}
|
|
325
325
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
326
|
+
case ChannelOpCodes.OP_SUCCEED: {
|
|
327
|
+
result = this.doneSucceed(this._currentChannel.evaluate())
|
|
328
|
+
break
|
|
329
|
+
}
|
|
330
330
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
331
|
+
case ChannelOpCodes.OP_SUCCEED_NOW: {
|
|
332
|
+
result = this.doneSucceed(this._currentChannel.terminal)
|
|
333
|
+
break
|
|
334
|
+
}
|
|
335
335
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
336
|
+
case ChannelOpCodes.OP_SUSPEND: {
|
|
337
|
+
this._currentChannel = this._currentChannel.channel() as core.Primitive
|
|
338
|
+
break
|
|
339
|
+
}
|
|
340
340
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
}
|
|
341
|
+
default: {
|
|
342
|
+
// @ts-expect-error
|
|
343
|
+
this._currentChannel._tag
|
|
345
344
|
}
|
|
346
345
|
}
|
|
347
346
|
}
|
package/src/internal/version.ts
CHANGED