@livestore/utils 0.4.0-dev.2 → 0.4.0-dev.20
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/.tsbuildinfo.json +1 -1
- package/dist/NoopTracer.d.ts.map +1 -1
- package/dist/NoopTracer.js +1 -0
- package/dist/NoopTracer.js.map +1 -1
- package/dist/browser/Opfs/Opfs.d.ts +51 -0
- package/dist/browser/Opfs/Opfs.d.ts.map +1 -0
- package/dist/browser/Opfs/Opfs.js +345 -0
- package/dist/browser/Opfs/Opfs.js.map +1 -0
- package/dist/browser/Opfs/debug-utils.d.ts +20 -0
- package/dist/browser/Opfs/debug-utils.d.ts.map +1 -0
- package/dist/browser/Opfs/debug-utils.js +94 -0
- package/dist/browser/Opfs/debug-utils.js.map +1 -0
- package/dist/browser/Opfs/mod.d.ts +4 -0
- package/dist/browser/Opfs/mod.d.ts.map +1 -0
- package/dist/browser/Opfs/mod.js +4 -0
- package/dist/browser/Opfs/mod.js.map +1 -0
- package/dist/browser/Opfs/utils.d.ts +68 -0
- package/dist/browser/Opfs/utils.d.ts.map +1 -0
- package/dist/browser/Opfs/utils.js +206 -0
- package/dist/browser/Opfs/utils.js.map +1 -0
- package/dist/browser/QuotaExceededError.d.ts +59 -0
- package/dist/browser/QuotaExceededError.d.ts.map +1 -0
- package/dist/browser/QuotaExceededError.js +2 -0
- package/dist/browser/QuotaExceededError.js.map +1 -0
- package/dist/browser/WebChannelBrowser.d.ts +22 -0
- package/dist/browser/WebChannelBrowser.d.ts.map +1 -0
- package/dist/browser/WebChannelBrowser.js +76 -0
- package/dist/browser/WebChannelBrowser.js.map +1 -0
- package/dist/browser/WebError.d.ts +425 -0
- package/dist/browser/WebError.d.ts.map +1 -0
- package/dist/browser/WebError.js +414 -0
- package/dist/browser/WebError.js.map +1 -0
- package/dist/browser/WebError.test.d.ts +2 -0
- package/dist/browser/WebError.test.d.ts.map +1 -0
- package/dist/browser/WebError.test.js +46 -0
- package/dist/browser/WebError.test.js.map +1 -0
- package/dist/browser/WebLock.d.ts.map +1 -0
- package/dist/browser/WebLock.js.map +1 -0
- package/dist/{browser.d.ts → browser/detect.d.ts} +1 -1
- package/dist/browser/detect.d.ts.map +1 -0
- package/dist/{browser.js → browser/detect.js} +1 -1
- package/dist/browser/detect.js.map +1 -0
- package/dist/browser/mod.d.ts +8 -0
- package/dist/browser/mod.d.ts.map +1 -0
- package/dist/browser/mod.js +8 -0
- package/dist/browser/mod.js.map +1 -0
- package/dist/effect/Debug.d.ts +38 -0
- package/dist/effect/Debug.d.ts.map +1 -0
- package/dist/effect/Debug.js +287 -0
- package/dist/effect/Debug.js.map +1 -0
- package/dist/effect/Effect.d.ts +9 -3
- package/dist/effect/Effect.d.ts.map +1 -1
- package/dist/effect/Effect.js +4 -2
- package/dist/effect/Effect.js.map +1 -1
- package/dist/effect/Error.d.ts +1 -1
- package/dist/effect/Error.js.map +1 -1
- package/dist/effect/Logger.d.ts +4 -1
- package/dist/effect/Logger.d.ts.map +1 -1
- package/dist/effect/Logger.js +12 -3
- package/dist/effect/Logger.js.map +1 -1
- package/dist/effect/OtelTracer.d.ts +5 -0
- package/dist/effect/OtelTracer.d.ts.map +1 -0
- package/dist/effect/OtelTracer.js +8 -0
- package/dist/effect/OtelTracer.js.map +1 -0
- package/dist/effect/RpcClient.d.ts +32 -0
- package/dist/effect/RpcClient.d.ts.map +1 -0
- package/dist/effect/RpcClient.js +149 -0
- package/dist/effect/RpcClient.js.map +1 -0
- package/dist/effect/Schema/index.d.ts +2 -2
- package/dist/effect/Schema/index.d.ts.map +1 -1
- package/dist/effect/Schema/index.js +12 -2
- package/dist/effect/Schema/index.js.map +1 -1
- package/dist/effect/Stream.d.ts +73 -2
- package/dist/effect/Stream.d.ts.map +1 -1
- package/dist/effect/Stream.js +68 -1
- package/dist/effect/Stream.js.map +1 -1
- package/dist/effect/Stream.test.d.ts +2 -0
- package/dist/effect/Stream.test.d.ts.map +1 -0
- package/dist/effect/Stream.test.js +84 -0
- package/dist/effect/Stream.test.js.map +1 -0
- package/dist/effect/SubscriptionRef.d.ts +2 -2
- package/dist/effect/SubscriptionRef.d.ts.map +1 -1
- package/dist/effect/SubscriptionRef.js +6 -1
- package/dist/effect/SubscriptionRef.js.map +1 -1
- package/dist/effect/WebChannel/WebChannel.d.ts +2 -21
- package/dist/effect/WebChannel/WebChannel.d.ts.map +1 -1
- package/dist/effect/WebChannel/WebChannel.js +5 -81
- package/dist/effect/WebChannel/WebChannel.js.map +1 -1
- package/dist/effect/WebChannel/WebChannel.test.js +1 -1
- package/dist/effect/WebChannel/WebChannel.test.js.map +1 -1
- package/dist/effect/WebChannel/common.d.ts +1 -1
- package/dist/effect/WebChannel/common.d.ts.map +1 -1
- package/dist/effect/WebSocket.d.ts.map +1 -1
- package/dist/effect/WebSocket.js +12 -12
- package/dist/effect/WebSocket.js.map +1 -1
- package/dist/effect/mod.d.ts +32 -0
- package/dist/effect/mod.d.ts.map +1 -0
- package/dist/effect/mod.js +35 -0
- package/dist/effect/mod.js.map +1 -0
- package/dist/global.d.ts +1 -0
- package/dist/global.d.ts.map +1 -1
- package/dist/global.js.map +1 -1
- package/dist/misc.js +1 -1
- package/dist/misc.js.map +1 -1
- package/dist/mod.d.ts +3 -1
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +5 -1
- package/dist/mod.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunner.d.ts.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunner.js +66 -10
- package/dist/node/ChildProcessRunner/ChildProcessRunner.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js +177 -3
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.d.ts +14 -5
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.d.ts.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.js +7 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/schema.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.js +13 -3
- package/dist/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.js.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessWorker.d.ts +16 -0
- package/dist/node/ChildProcessRunner/ChildProcessWorker.d.ts.map +1 -1
- package/dist/node/ChildProcessRunner/ChildProcessWorker.js +98 -2
- package/dist/node/ChildProcessRunner/ChildProcessWorker.js.map +1 -1
- package/dist/node/mod.d.ts +8 -2
- package/dist/node/mod.d.ts.map +1 -1
- package/dist/node/mod.js +11 -3
- package/dist/node/mod.js.map +1 -1
- package/dist/qr.d.ts +38 -0
- package/dist/qr.d.ts.map +1 -0
- package/dist/qr.js +109 -0
- package/dist/qr.js.map +1 -0
- package/package.json +54 -44
- package/src/NoopTracer.ts +1 -0
- package/src/browser/Opfs/Opfs.ts +428 -0
- package/src/browser/Opfs/debug-utils.ts +151 -0
- package/src/browser/Opfs/mod.ts +3 -0
- package/src/browser/Opfs/utils.ts +270 -0
- package/src/browser/QuotaExceededError.ts +59 -0
- package/src/browser/WebChannelBrowser.ts +131 -0
- package/src/browser/WebError.test.ts +66 -0
- package/src/browser/WebError.ts +599 -0
- package/src/browser/mod.ts +8 -0
- package/src/effect/Debug.ts +375 -0
- package/src/effect/Effect.ts +31 -4
- package/src/effect/Error.ts +1 -1
- package/src/effect/Logger.ts +14 -4
- package/src/effect/OtelTracer.ts +11 -0
- package/src/effect/RpcClient.ts +212 -0
- package/src/effect/Schema/index.ts +17 -3
- package/src/effect/Stream.test.ts +127 -0
- package/src/effect/Stream.ts +111 -2
- package/src/effect/SubscriptionRef.ts +14 -2
- package/src/effect/WebChannel/WebChannel.test.ts +1 -1
- package/src/effect/WebChannel/WebChannel.ts +13 -135
- package/src/effect/WebChannel/common.ts +1 -1
- package/src/effect/WebSocket.ts +11 -10
- package/src/effect/{index.ts → mod.ts} +42 -15
- package/src/global.ts +1 -0
- package/src/misc.ts +1 -1
- package/src/mod.ts +10 -1
- package/src/node/ChildProcessRunner/ChildProcessRunner.ts +71 -10
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/ChildProcessRunner.test.ts +258 -3
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/schema.ts +14 -1
- package/src/node/ChildProcessRunner/ChildProcessRunnerTest/serializedWorker.ts +16 -3
- package/src/node/ChildProcessRunner/ChildProcessWorker.ts +111 -3
- package/src/node/mod.ts +13 -6
- package/src/qr.ts +125 -0
- package/dist/browser.d.ts.map +0 -1
- package/dist/browser.js.map +0 -1
- package/dist/effect/Schema/msgpack.d.ts +0 -3
- package/dist/effect/Schema/msgpack.d.ts.map +0 -1
- package/dist/effect/Schema/msgpack.js +0 -7
- package/dist/effect/Schema/msgpack.js.map +0 -1
- package/dist/effect/WebLock.d.ts.map +0 -1
- package/dist/effect/WebLock.js.map +0 -1
- package/dist/effect/index.d.ts +0 -27
- package/dist/effect/index.d.ts.map +0 -1
- package/dist/effect/index.js +0 -31
- package/dist/effect/index.js.map +0 -1
- package/src/effect/Schema/msgpack.ts +0 -8
- /package/dist/{effect → browser}/WebLock.d.ts +0 -0
- /package/dist/{effect → browser}/WebLock.js +0 -0
- /package/src/{effect → browser}/WebLock.ts +0 -0
- /package/src/{browser.ts → browser/detect.ts} +0 -0
|
@@ -38,127 +38,6 @@ export const noopChannel = <MsgListen, MsgSend>(): Effect.Effect<WebChannel<MsgL
|
|
|
38
38
|
}).pipe(Effect.withSpan(`WebChannel:noopChannel`)),
|
|
39
39
|
)
|
|
40
40
|
|
|
41
|
-
/** Only works in browser environments */
|
|
42
|
-
export const broadcastChannel = <MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded>({
|
|
43
|
-
channelName,
|
|
44
|
-
schema: inputSchema,
|
|
45
|
-
}: {
|
|
46
|
-
channelName: string
|
|
47
|
-
schema: InputSchema<MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded>
|
|
48
|
-
}): Effect.Effect<WebChannel<MsgListen, MsgSend>, never, Scope.Scope> =>
|
|
49
|
-
Effect.scopeWithCloseable((scope) =>
|
|
50
|
-
Effect.gen(function* () {
|
|
51
|
-
const schema = mapSchema(inputSchema)
|
|
52
|
-
|
|
53
|
-
const channel = new BroadcastChannel(channelName)
|
|
54
|
-
|
|
55
|
-
yield* Effect.addFinalizer(() => Effect.try(() => channel.close()).pipe(Effect.ignoreLogged))
|
|
56
|
-
|
|
57
|
-
const send = (message: MsgSend) =>
|
|
58
|
-
Effect.gen(function* () {
|
|
59
|
-
const messageEncoded = yield* Schema.encode(schema.send)(message)
|
|
60
|
-
channel.postMessage(messageEncoded)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
// TODO also listen to `messageerror` in parallel
|
|
64
|
-
const listen = Stream.fromEventListener<MessageEvent>(channel, 'message').pipe(
|
|
65
|
-
Stream.map((_) => Schema.decodeEither(schema.listen)(_.data)),
|
|
66
|
-
listenToDebugPing(channelName),
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
const closedDeferred = yield* Deferred.make<void>().pipe(Effect.acquireRelease(Deferred.done(Exit.void)))
|
|
70
|
-
const supportsTransferables = false
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
[WebChannelSymbol]: WebChannelSymbol,
|
|
74
|
-
send,
|
|
75
|
-
listen,
|
|
76
|
-
closedDeferred,
|
|
77
|
-
shutdown: Scope.close(scope, Exit.succeed('shutdown')),
|
|
78
|
-
schema,
|
|
79
|
-
supportsTransferables,
|
|
80
|
-
}
|
|
81
|
-
}).pipe(Effect.withSpan(`WebChannel:broadcastChannel(${channelName})`)),
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* NOTE the `listenName` and `sendName` is needed for cases where both sides are using the same window
|
|
86
|
-
* e.g. for a browser extension, so we need a way to know for which side a message is intended for.
|
|
87
|
-
*/
|
|
88
|
-
export const windowChannel = <MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded>({
|
|
89
|
-
listenWindow,
|
|
90
|
-
sendWindow,
|
|
91
|
-
targetOrigin = '*',
|
|
92
|
-
ids,
|
|
93
|
-
schema: inputSchema,
|
|
94
|
-
}: {
|
|
95
|
-
listenWindow: Window
|
|
96
|
-
sendWindow: Window
|
|
97
|
-
targetOrigin?: string
|
|
98
|
-
ids: { own: string; other: string }
|
|
99
|
-
schema: InputSchema<MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded>
|
|
100
|
-
}): Effect.Effect<WebChannel<MsgListen, MsgSend>, never, Scope.Scope> =>
|
|
101
|
-
Effect.scopeWithCloseable((scope) =>
|
|
102
|
-
Effect.gen(function* () {
|
|
103
|
-
const schema = mapSchema(inputSchema)
|
|
104
|
-
|
|
105
|
-
const debugInfo = {
|
|
106
|
-
sendTotal: 0,
|
|
107
|
-
listenTotal: 0,
|
|
108
|
-
targetOrigin,
|
|
109
|
-
ids,
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const WindowMessageListen = Schema.Struct({
|
|
113
|
-
message: schema.listen,
|
|
114
|
-
from: Schema.Literal(ids.other),
|
|
115
|
-
to: Schema.Literal(ids.own),
|
|
116
|
-
}).annotations({ title: 'webmesh.WindowMessageListen' })
|
|
117
|
-
|
|
118
|
-
const WindowMessageSend = Schema.Struct({
|
|
119
|
-
message: schema.send,
|
|
120
|
-
from: Schema.Literal(ids.own),
|
|
121
|
-
to: Schema.Literal(ids.other),
|
|
122
|
-
}).annotations({ title: 'webmesh.WindowMessageSend' })
|
|
123
|
-
|
|
124
|
-
const send = (message: MsgSend) =>
|
|
125
|
-
Effect.gen(function* () {
|
|
126
|
-
debugInfo.sendTotal++
|
|
127
|
-
|
|
128
|
-
const [messageEncoded, transferables] = yield* Schema.encodeWithTransferables(WindowMessageSend)({
|
|
129
|
-
message,
|
|
130
|
-
from: ids.own,
|
|
131
|
-
to: ids.other,
|
|
132
|
-
})
|
|
133
|
-
sendWindow.postMessage(messageEncoded, targetOrigin, transferables)
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
const listen = Stream.fromEventListener<MessageEvent>(listenWindow, 'message').pipe(
|
|
137
|
-
// Stream.tap((_) => Effect.log(`${ids.other}→${ids.own}:message`, _.data)),
|
|
138
|
-
Stream.filter((_) => Schema.is(Schema.encodedSchema(WindowMessageListen))(_.data)),
|
|
139
|
-
Stream.map((_) => {
|
|
140
|
-
debugInfo.listenTotal++
|
|
141
|
-
return Schema.decodeEither(schema.listen)(_.data.message)
|
|
142
|
-
}),
|
|
143
|
-
listenToDebugPing('window'),
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
const closedDeferred = yield* Deferred.make<void>().pipe(Effect.acquireRelease(Deferred.done(Exit.void)))
|
|
147
|
-
const supportsTransferables = true
|
|
148
|
-
|
|
149
|
-
return {
|
|
150
|
-
[WebChannelSymbol]: WebChannelSymbol,
|
|
151
|
-
send,
|
|
152
|
-
listen,
|
|
153
|
-
closedDeferred,
|
|
154
|
-
shutdown: Scope.close(scope, Exit.succeed('shutdown')),
|
|
155
|
-
schema,
|
|
156
|
-
supportsTransferables,
|
|
157
|
-
debugInfo,
|
|
158
|
-
}
|
|
159
|
-
}).pipe(Effect.withSpan(`WebChannel:windowChannel`)),
|
|
160
|
-
)
|
|
161
|
-
|
|
162
41
|
export const messagePortChannel: <MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded>(args: {
|
|
163
42
|
port: MessagePort
|
|
164
43
|
schema: InputSchema<MsgListen, MsgSend, MsgListenEncoded, MsgSendEncoded>
|
|
@@ -225,10 +104,7 @@ export const sameThreadChannel = <MsgListen, MsgSend, MsgListenEncoded, MsgSendE
|
|
|
225
104
|
|
|
226
105
|
const schema = mapSchema(inputSchema)
|
|
227
106
|
|
|
228
|
-
const send = (message: MsgSend) =>
|
|
229
|
-
Effect.gen(function* () {
|
|
230
|
-
yield* PubSub.publish(pubSub, message)
|
|
231
|
-
})
|
|
107
|
+
const send = (message: MsgSend) => PubSub.publish(pubSub, message)
|
|
232
108
|
|
|
233
109
|
const listen = Stream.fromPubSub(pubSub).pipe(Stream.map(Either.right), listenToDebugPing(channelName))
|
|
234
110
|
|
|
@@ -408,8 +284,8 @@ export const queueChannelProxy = <MsgListen, MsgSend>({
|
|
|
408
284
|
/**
|
|
409
285
|
* Eagerly starts listening to a channel by buffering incoming messages in a queue.
|
|
410
286
|
*/
|
|
411
|
-
export const toOpenChannel = (
|
|
412
|
-
channel: WebChannel<
|
|
287
|
+
export const toOpenChannel = <MsgListen, MsgSend>(
|
|
288
|
+
channel: WebChannel<MsgListen, MsgSend>,
|
|
413
289
|
options?: {
|
|
414
290
|
/**
|
|
415
291
|
* Sends a heartbeat message to the other end of the channel every `interval`.
|
|
@@ -420,9 +296,14 @@ export const toOpenChannel = (
|
|
|
420
296
|
timeout: DurationInput
|
|
421
297
|
}
|
|
422
298
|
},
|
|
423
|
-
): Effect.Effect<WebChannel<
|
|
299
|
+
): Effect.Effect<WebChannel<MsgListen, MsgSend>, never, Scope.Scope> =>
|
|
424
300
|
Effect.gen(function* () {
|
|
425
|
-
const queue = yield* Queue.unbounded<Either.Either<
|
|
301
|
+
const queue = yield* Queue.unbounded<Either.Either<MsgListen, any>>().pipe(Effect.acquireRelease(Queue.shutdown))
|
|
302
|
+
|
|
303
|
+
const heartbeatChannel = channel as WebChannel<
|
|
304
|
+
MsgListen | typeof WebChannelHeartbeat.Type,
|
|
305
|
+
MsgSend | typeof WebChannelHeartbeat.Type
|
|
306
|
+
>
|
|
426
307
|
|
|
427
308
|
const pendingPingDeferredRef = {
|
|
428
309
|
current: undefined as { deferred: Deferred.Deferred<void>; requestId: string } | undefined,
|
|
@@ -435,7 +316,7 @@ export const toOpenChannel = (
|
|
|
435
316
|
Effect.fn(function* (msg) {
|
|
436
317
|
if (msg._tag === 'Right' && Schema.is(WebChannelHeartbeat)(msg.right)) {
|
|
437
318
|
if (msg.right._tag === 'WebChannel.Ping') {
|
|
438
|
-
yield*
|
|
319
|
+
yield* heartbeatChannel.send(WebChannelPong.make({ requestId: msg.right.requestId }))
|
|
439
320
|
} else {
|
|
440
321
|
const { deferred, requestId } = pendingPingDeferredRef.current ?? shouldNeverHappen('No pending ping')
|
|
441
322
|
if (requestId !== msg.right.requestId) {
|
|
@@ -461,7 +342,7 @@ export const toOpenChannel = (
|
|
|
461
342
|
while (true) {
|
|
462
343
|
yield* Effect.sleep(interval)
|
|
463
344
|
const requestId = crypto.randomUUID()
|
|
464
|
-
yield*
|
|
345
|
+
yield* heartbeatChannel.send(WebChannelPing.make({ requestId }))
|
|
465
346
|
const deferred = yield* Deferred.make<void>()
|
|
466
347
|
pendingPingDeferredRef.current = { deferred, requestId }
|
|
467
348
|
yield* deferred.pipe(
|
|
@@ -492,7 +373,4 @@ export const toOpenChannel = (
|
|
|
492
373
|
}
|
|
493
374
|
})
|
|
494
375
|
|
|
495
|
-
export const sendDebugPing = (channel: WebChannel<any, any>) =>
|
|
496
|
-
Effect.gen(function* () {
|
|
497
|
-
yield* channel.send(DebugPingMessage.make({ message: 'ping' }))
|
|
498
|
-
})
|
|
376
|
+
export const sendDebugPing = (channel: WebChannel<any, any>) => channel.send(DebugPingMessage.make({ message: 'ping' }))
|
|
@@ -15,7 +15,7 @@ export interface WebChannel<MsgListen, MsgSend, E = never> {
|
|
|
15
15
|
closedDeferred: Deferred.Deferred<void>
|
|
16
16
|
shutdown: Effect.Effect<void>
|
|
17
17
|
schema: { listen: Schema.Schema<MsgListen, any>; send: Schema.Schema<MsgSend, any> }
|
|
18
|
-
debugInfo?: Record<string, any>
|
|
18
|
+
debugInfo?: Record<string, any> | undefined
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export const DebugPingMessage = Schema.TaggedStruct('WebChannel.DebugPing', {
|
package/src/effect/WebSocket.ts
CHANGED
|
@@ -81,16 +81,17 @@ export const makeWebSocket = ({
|
|
|
81
81
|
*/
|
|
82
82
|
yield* Effect.addFinalizer(
|
|
83
83
|
Effect.fn(function* (exit) {
|
|
84
|
-
try
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
84
|
+
yield* Effect.try({
|
|
85
|
+
try: () => {
|
|
86
|
+
if (Exit.isFailure(exit)) {
|
|
87
|
+
socket.close(3000)
|
|
88
|
+
} else {
|
|
89
|
+
socket.close(1000)
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
catch: (error) => new WebSocketError({ cause: error }),
|
|
93
|
+
})
|
|
94
|
+
}, Effect.orDie),
|
|
94
95
|
)
|
|
95
96
|
|
|
96
97
|
return socket
|
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
import '../global.ts'
|
|
2
2
|
|
|
3
|
-
export
|
|
3
|
+
export {
|
|
4
|
+
AiError,
|
|
5
|
+
LanguageModel,
|
|
6
|
+
LanguageModel as AiLanguageModel,
|
|
7
|
+
McpSchema,
|
|
8
|
+
McpServer,
|
|
9
|
+
Model,
|
|
10
|
+
Model as AiModel,
|
|
11
|
+
Prompt,
|
|
12
|
+
Tool,
|
|
13
|
+
Tool as AiTool,
|
|
14
|
+
Toolkit,
|
|
15
|
+
Toolkit as AiToolkit,
|
|
16
|
+
} from '@effect/ai'
|
|
17
|
+
// export { DevTools as EffectDevtools } from '@effect/experimental'
|
|
18
|
+
export { Sse } from '@effect/experimental'
|
|
19
|
+
export * as Otlp from '@effect/opentelemetry/Otlp'
|
|
4
20
|
export {
|
|
5
21
|
Command,
|
|
6
22
|
CommandExecutor,
|
|
@@ -8,6 +24,11 @@ export {
|
|
|
8
24
|
FetchHttpClient,
|
|
9
25
|
FileSystem,
|
|
10
26
|
Headers,
|
|
27
|
+
HttpApi,
|
|
28
|
+
HttpApiClient,
|
|
29
|
+
HttpApiEndpoint,
|
|
30
|
+
HttpApiGroup,
|
|
31
|
+
HttpApp,
|
|
11
32
|
HttpClient,
|
|
12
33
|
HttpClientError,
|
|
13
34
|
HttpClientRequest,
|
|
@@ -18,6 +39,7 @@ export {
|
|
|
18
39
|
HttpServerRequest,
|
|
19
40
|
HttpServerResponse,
|
|
20
41
|
KeyValueStore,
|
|
42
|
+
MsgPack,
|
|
21
43
|
Socket,
|
|
22
44
|
Terminal,
|
|
23
45
|
Transferable,
|
|
@@ -26,10 +48,10 @@ export {
|
|
|
26
48
|
WorkerError,
|
|
27
49
|
WorkerRunner,
|
|
28
50
|
} from '@effect/platform'
|
|
29
|
-
export { BrowserWorker, BrowserWorkerRunner } from '@effect/platform-browser'
|
|
30
51
|
export {
|
|
31
52
|
Rpc,
|
|
32
|
-
RpcClient,
|
|
53
|
+
// RpcClient, // TODO bring back "original" RpcClient from effect/rpc
|
|
54
|
+
RpcClientError,
|
|
33
55
|
RpcGroup,
|
|
34
56
|
RpcMessage,
|
|
35
57
|
RpcMiddleware,
|
|
@@ -47,8 +69,9 @@ export {
|
|
|
47
69
|
Cause,
|
|
48
70
|
Channel,
|
|
49
71
|
Chunk,
|
|
50
|
-
// Logger,
|
|
51
72
|
Config,
|
|
73
|
+
ConfigError,
|
|
74
|
+
ConfigProvider,
|
|
52
75
|
Console,
|
|
53
76
|
Context,
|
|
54
77
|
Data,
|
|
@@ -58,6 +81,7 @@ export {
|
|
|
58
81
|
Equal,
|
|
59
82
|
ExecutionStrategy,
|
|
60
83
|
Exit,
|
|
84
|
+
FastCheck,
|
|
61
85
|
Fiber,
|
|
62
86
|
FiberHandle,
|
|
63
87
|
FiberId,
|
|
@@ -84,6 +108,7 @@ export {
|
|
|
84
108
|
MutableHashMap,
|
|
85
109
|
MutableHashSet,
|
|
86
110
|
Option,
|
|
111
|
+
Order,
|
|
87
112
|
ParseResult,
|
|
88
113
|
Predicate,
|
|
89
114
|
Pretty,
|
|
@@ -98,6 +123,8 @@ export {
|
|
|
98
123
|
Runtime,
|
|
99
124
|
RuntimeFlags,
|
|
100
125
|
Scope,
|
|
126
|
+
ScopedRef,
|
|
127
|
+
Sink,
|
|
101
128
|
SortedMap,
|
|
102
129
|
STM,
|
|
103
130
|
SynchronizedRef,
|
|
@@ -107,26 +134,26 @@ export {
|
|
|
107
134
|
Tracer,
|
|
108
135
|
Types,
|
|
109
136
|
} from 'effect'
|
|
110
|
-
export {
|
|
137
|
+
export type { NonEmptyArray } from 'effect/Array'
|
|
138
|
+
export { constVoid, dual } from 'effect/Function'
|
|
139
|
+
export * as Graph from 'effect/Graph'
|
|
111
140
|
export { TreeFormatter } from 'effect/ParseResult'
|
|
112
141
|
export type { Serializable, SerializableWithResult } from 'effect/Schema'
|
|
113
|
-
|
|
114
142
|
export * as SchemaAST from 'effect/SchemaAST'
|
|
115
143
|
export * as BucketQueue from './BucketQueue.ts'
|
|
144
|
+
export * as Debug from './Debug.ts'
|
|
145
|
+
export * as Effect from './Effect.ts'
|
|
146
|
+
export * from './Error.ts'
|
|
116
147
|
export * as Logger from './Logger.ts'
|
|
148
|
+
export * as OtelTracer from './OtelTracer.ts'
|
|
149
|
+
export * as RpcClient from './RpcClient.ts'
|
|
150
|
+
export * as Schedule from './Schedule.ts'
|
|
151
|
+
export * as Scheduler from './Scheduler.ts'
|
|
117
152
|
export * as Schema from './Schema/index.ts'
|
|
153
|
+
export * as ServiceContext from './ServiceContext.ts'
|
|
118
154
|
export * as Stream from './Stream.ts'
|
|
119
155
|
export * as Subscribable from './Subscribable.ts'
|
|
120
156
|
export * as SubscriptionRef from './SubscriptionRef.ts'
|
|
121
157
|
export * as TaskTracing from './TaskTracing.ts'
|
|
122
158
|
export * as WebChannel from './WebChannel/mod.ts'
|
|
123
159
|
export * as WebSocket from './WebSocket.ts'
|
|
124
|
-
|
|
125
|
-
// export { DevTools as EffectDevtools } from '@effect/experimental'
|
|
126
|
-
|
|
127
|
-
export * as Effect from './Effect.ts'
|
|
128
|
-
export * from './Error.ts'
|
|
129
|
-
export * as Schedule from './Schedule.ts'
|
|
130
|
-
export * as Scheduler from './Scheduler.ts'
|
|
131
|
-
export * as ServiceContext from './ServiceContext.ts'
|
|
132
|
-
export * as WebLock from './WebLock.ts'
|
package/src/global.ts
CHANGED
package/src/misc.ts
CHANGED
package/src/mod.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { default as prettyBytes } from 'pretty-bytes'
|
|
2
2
|
export * as base64 from './base64.ts'
|
|
3
3
|
export * from './binary.ts'
|
|
4
|
-
export * from './browser.ts'
|
|
5
4
|
export * from './Deferred.ts'
|
|
6
5
|
export * from './env.ts'
|
|
7
6
|
export * from './fast-deep-equal.ts'
|
|
@@ -10,6 +9,7 @@ export * from './misc.ts'
|
|
|
10
9
|
export * from './NoopTracer.ts'
|
|
11
10
|
export * from './object/index.ts'
|
|
12
11
|
export * from './promise.ts'
|
|
12
|
+
export * as QR from './qr.ts'
|
|
13
13
|
export * from './set.ts'
|
|
14
14
|
export * from './string.ts'
|
|
15
15
|
export * from './time.ts'
|
|
@@ -234,4 +234,13 @@ export const isPromise = (value: any): value is Promise<unknown> => typeof value
|
|
|
234
234
|
|
|
235
235
|
export const isIterable = <T>(value: any): value is Iterable<T> => typeof value?.[Symbol.iterator] === 'function'
|
|
236
236
|
|
|
237
|
+
/** This utility "lies" as a means of compat with libs that don't explicitly type optionals as unioned with `undefined`. */
|
|
238
|
+
export const omitUndefineds = <T extends Record<keyof any, unknown>>(
|
|
239
|
+
rec: T,
|
|
240
|
+
): {
|
|
241
|
+
[K in keyof T]: Exclude<T[K], undefined>
|
|
242
|
+
} => {
|
|
243
|
+
return rec as never
|
|
244
|
+
}
|
|
245
|
+
|
|
237
246
|
export { objectToString as errorToString } from './misc.ts'
|
|
@@ -13,6 +13,53 @@ import * as Layer from 'effect/Layer'
|
|
|
13
13
|
import * as Runtime from 'effect/Runtime'
|
|
14
14
|
import * as Scope from 'effect/Scope'
|
|
15
15
|
|
|
16
|
+
// Parent death monitoring setup
|
|
17
|
+
let parentDeathDetectionEnabled = false
|
|
18
|
+
let parentDeathTimer: NodeJS.Timeout | null = null
|
|
19
|
+
|
|
20
|
+
const stopParentDeathMonitoring = () => {
|
|
21
|
+
parentDeathDetectionEnabled = false
|
|
22
|
+
if (parentDeathTimer) {
|
|
23
|
+
clearTimeout(parentDeathTimer)
|
|
24
|
+
parentDeathTimer = null
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const setupParentDeathMonitoring = (parentPid: number) => {
|
|
29
|
+
if (parentDeathDetectionEnabled) return
|
|
30
|
+
parentDeathDetectionEnabled = true
|
|
31
|
+
|
|
32
|
+
let consecutiveFailures = 0
|
|
33
|
+
const maxFailures = 3 // Require 3 consecutive failures before self-terminating
|
|
34
|
+
|
|
35
|
+
// Check if parent is still alive every 2 seconds (more conservative)
|
|
36
|
+
const checkParentAlive = () => {
|
|
37
|
+
if (!parentDeathDetectionEnabled) return
|
|
38
|
+
try {
|
|
39
|
+
// Send signal 0 to check if process exists (doesn't actually send signal)
|
|
40
|
+
process.kill(parentPid, 0)
|
|
41
|
+
// If we reach here, parent is still alive, reset failure counter and check again later
|
|
42
|
+
consecutiveFailures = 0
|
|
43
|
+
parentDeathTimer = setTimeout(checkParentAlive, 2000)
|
|
44
|
+
} catch {
|
|
45
|
+
consecutiveFailures++
|
|
46
|
+
console.warn(`[Worker ${process.pid}] Parent check failed (${consecutiveFailures}/${maxFailures})`)
|
|
47
|
+
|
|
48
|
+
if (consecutiveFailures >= maxFailures) {
|
|
49
|
+
// Parent process has been gone for multiple checks, self-terminate
|
|
50
|
+
console.error(`[Worker ${process.pid}] Parent process ${parentPid} confirmed dead, self-terminating`)
|
|
51
|
+
process.exit(0)
|
|
52
|
+
} else {
|
|
53
|
+
// Try again sooner on failure
|
|
54
|
+
parentDeathTimer = setTimeout(checkParentAlive, 1000)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Start monitoring after a longer initial delay to let things settle
|
|
60
|
+
parentDeathTimer = setTimeout(checkParentAlive, 5000)
|
|
61
|
+
}
|
|
62
|
+
|
|
16
63
|
const platformRunnerImpl = Runner.PlatformRunner.of({
|
|
17
64
|
[Runner.PlatformRunnerTypeId]: Runner.PlatformRunnerTypeId,
|
|
18
65
|
start<I, O>(closeLatch: typeof CloseLatch.Service) {
|
|
@@ -43,18 +90,32 @@ const platformRunnerImpl = Runner.PlatformRunner.of({
|
|
|
43
90
|
Deferred.unsafeDone(closeLatch, Exit.die(exit.cause))
|
|
44
91
|
}
|
|
45
92
|
}
|
|
46
|
-
port.on('message', (message: Runner.BackingRunner.Message<I>) => {
|
|
93
|
+
port.on('message', (message: Runner.BackingRunner.Message<I> | any) => {
|
|
47
94
|
// console.log('message', message)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
95
|
+
|
|
96
|
+
// Handle parent death detection setup messages
|
|
97
|
+
if (Array.isArray(message) && message[0] === 'setup-parent-death-detection' && message[1]?.parentPid) {
|
|
98
|
+
const parentPid = message[1].parentPid
|
|
99
|
+
// console.log(`[Worker ${process.pid}] Setting up parent death detection for parent ${parentPid}`)
|
|
100
|
+
setupParentDeathMonitoring(parentPid)
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Handle normal Effect worker messages
|
|
105
|
+
if (Array.isArray(message) && typeof message[0] === 'number') {
|
|
106
|
+
if (message[0] === 0) {
|
|
107
|
+
const result = handler(0, message[1])
|
|
108
|
+
if (Effect.isEffect(result)) {
|
|
109
|
+
const fiber = runFork(result)
|
|
110
|
+
fiber.addObserver(onExit)
|
|
111
|
+
FiberSet.unsafeAdd(fiberSet, fiber)
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
// Graceful shutdown requested by parent: stop monitoring and close port
|
|
115
|
+
stopParentDeathMonitoring()
|
|
116
|
+
Deferred.unsafeDone(closeLatch, Exit.void)
|
|
117
|
+
port.close()
|
|
54
118
|
}
|
|
55
|
-
} else {
|
|
56
|
-
Deferred.unsafeDone(closeLatch, Exit.void)
|
|
57
|
-
port.close()
|
|
58
119
|
}
|
|
59
120
|
})
|
|
60
121
|
port.on('messageerror', (cause) => {
|