@livestore/webmesh 0.0.0-snapshot-76bdaead452769e22fce7f5ec10482474416e04d → 0.0.0-snapshot-2da03812fc739d068b0e57f612c11fe4c4b28b0c

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.
@@ -1,6 +1,5 @@
1
1
  import type { HttpClient } from '@livestore/utils/effect';
2
- import { Effect, Schedule, Schema, Scope, WebChannel } from '@livestore/utils/effect';
3
- import type * as NodeWebSocket from 'ws';
2
+ import { Effect, Schema, Scope, Socket, WebChannel } from '@livestore/utils/effect';
4
3
  import * as WebmeshSchema from './mesh-schema.js';
5
4
  import type { MeshNode } from './node.js';
6
5
  declare const WSEdgeInit_base: Schema.TaggedStruct<"WSEdgeInit", {
@@ -38,12 +37,14 @@ export type SocketType = {
38
37
  } | {
39
38
  _tag: 'relay';
40
39
  };
41
- export declare const connectViaWebSocket: ({ node, url, reconnect, }: {
40
+ export declare const connectViaWebSocket: ({ node, url, }: {
42
41
  node: MeshNode;
43
42
  url: string;
44
- reconnect?: Schedule.Schedule<unknown> | false;
45
43
  }) => Effect.Effect<void, never, Scope.Scope | HttpClient.HttpClient>;
46
- export declare const makeWebSocketEdge: (socket: globalThis.WebSocket | NodeWebSocket.WebSocket, socketType: SocketType) => Effect.Effect<{
44
+ export declare const makeWebSocketEdge: ({ socket, socketType, }: {
45
+ socket: Socket.Socket;
46
+ socketType: SocketType;
47
+ }) => Effect.Effect<{
47
48
  webChannel: WebChannel.WebChannel<typeof WebmeshSchema.Packet.Type, typeof WebmeshSchema.Packet.Type>;
48
49
  from: string;
49
50
  }, never, Scope.Scope | HttpClient.HttpClient>;
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-edge.d.ts","sourceRoot":"","sources":["../src/websocket-edge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAEL,MAAM,EAIN,QAAQ,EACR,MAAM,EACN,KAAK,EAEL,UAAU,EAEX,MAAM,yBAAyB,CAAA;AAChC,OAAO,KAAK,KAAK,aAAa,MAAM,IAAI,CAAA;AAExC,OAAO,KAAK,aAAa,MAAM,kBAAkB,CAAA;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;;;;AAEzC,qBAAa,UAAW,SAAQ,eAE9B;CAAG;;;;;AAEL,qBAAa,aAAc,SAAQ,kBAGjC;CAAG;;AAEL,qBAAa,aAAc,SAAQ,kBAAuC;CAAG;AAE7E,eAAO,MAAM,cAAc;;;;;;;;;;;;;;UAAgC,CAAA;AAE3D,MAAM,MAAM,UAAU,GAClB;IACE,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,GACD;IACE,IAAI,EAAE,OAAO,CAAA;CACd,CAAA;AAEL,eAAO,MAAM,mBAAmB,GAAI,2BAIjC;IACD,IAAI,EAAE,QAAQ,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,KAAK,CAAA;CAC/C,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,UAAU,CAauB,CAAA;AAEzF,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,UAAU,CAAC,SAAS,GAAG,aAAa,CAAC,SAAS,EACtD,YAAY,UAAU,KACrB,MAAM,CAAC,MAAM,CACd;IACE,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,OAAO,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACrG,IAAI,EAAE,MAAM,CAAA;CACb,EACD,KAAK,EACL,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,UAAU,CAsFlC,CAAA"}
1
+ {"version":3,"file":"websocket-edge.d.ts","sourceRoot":"","sources":["../src/websocket-edge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAEL,MAAM,EAMN,MAAM,EACN,KAAK,EACL,MAAM,EAEN,UAAU,EACX,MAAM,yBAAyB,CAAA;AAEhC,OAAO,KAAK,aAAa,MAAM,kBAAkB,CAAA;AACjD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;;;;AAEzC,qBAAa,UAAW,SAAQ,eAE9B;CAAG;;;;;AAEL,qBAAa,aAAc,SAAQ,kBAGjC;CAAG;;AAEL,qBAAa,aAAc,SAAQ,kBAAuC;CAAG;AAE7E,eAAO,MAAM,cAAc;;;;;;;;;;;;;;UAAgC,CAAA;AAE3D,MAAM,MAAM,UAAU,GAClB;IACE,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,GACD;IACE,IAAI,EAAE,OAAO,CAAA;CACd,CAAA;AAEL,eAAO,MAAM,mBAAmB,GAAI,gBAGjC;IACD,IAAI,EAAE,QAAQ,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;CACZ,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,UAAU,CAcuB,CAAA;AAQzF,eAAO,MAAM,iBAAiB,GAAI,yBAG/B;IACD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAA;IACrB,UAAU,EAAE,UAAU,CAAA;CACvB,KAAG,MAAM,CAAC,MAAM,CACf;IACE,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,OAAO,aAAa,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACrG,IAAI,EAAE,MAAM,CAAA;CACb,EACD,KAAK,EACL,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,UAAU,CA6FlC,CAAA"}
@@ -1,4 +1,4 @@
1
- import { Deferred, Effect, Either, Exit, Queue, Schedule, Schema, Scope, Stream, WebChannel, WebSocket, } from '@livestore/utils/effect';
1
+ import { Deferred, Effect, Either, Exit, Layer, Queue, Schedule, Schema, Scope, Socket, Stream, WebChannel, } from '@livestore/utils/effect';
2
2
  import * as WebmeshSchema from './mesh-schema.js';
3
3
  export class WSEdgeInit extends Schema.TaggedStruct('WSEdgeInit', {
4
4
  from: Schema.String,
@@ -12,20 +12,38 @@ export class WSEdgePayload extends Schema.TaggedStruct('WSEdgePayload', {
12
12
  export class WSEdgeMessage extends Schema.Union(WSEdgeInit, WSEdgePayload) {
13
13
  }
14
14
  export const MessageMsgPack = Schema.MsgPack(WSEdgeMessage);
15
- export const connectViaWebSocket = ({ node, url, reconnect = Schedule.exponential(100), }) => Effect.gen(function* () {
15
+ export const connectViaWebSocket = ({ node, url, }) => Effect.gen(function* () {
16
16
  const disconnected = yield* Deferred.make();
17
- const socket = yield* WebSocket.makeWebSocket({ url, reconnect });
18
- socket.addEventListener('close', () => Deferred.unsafeDone(disconnected, Exit.void));
19
- const edgeChannel = yield* makeWebSocketEdge(socket, { _tag: 'leaf', from: node.nodeName });
17
+ const socket = yield* Socket.makeWebSocket(url, { openTimeout: 50 });
18
+ const edgeChannel = yield* makeWebSocketEdge({
19
+ socket,
20
+ socketType: { _tag: 'leaf', from: node.nodeName },
21
+ });
20
22
  yield* node.addEdge({ target: 'ws', edgeChannel: edgeChannel.webChannel, replaceIfExists: true });
21
23
  yield* disconnected;
22
- }).pipe(Effect.scoped, Effect.forever, Effect.catchTag('WebSocketError', Effect.orDie));
23
- export const makeWebSocketEdge = (socket, socketType) => Effect.scopeWithCloseable((scope) => Effect.gen(function* () {
24
+ }).pipe(Effect.scoped, Effect.forever, Effect.provide(binaryWebSocketConstructorLayer));
25
+ const binaryWebSocketConstructorLayer = Layer.succeed(Socket.WebSocketConstructor, (url, protocols) => {
26
+ const socket = new globalThis.WebSocket(url, protocols);
24
27
  socket.binaryType = 'arraybuffer';
28
+ return socket;
29
+ });
30
+ export const makeWebSocketEdge = ({ socket, socketType, }) => Effect.scopeWithCloseable((scope) => Effect.gen(function* () {
25
31
  const fromDeferred = yield* Deferred.make();
26
32
  const listenQueue = yield* Queue.unbounded().pipe(Effect.acquireRelease(Queue.shutdown));
27
33
  const schema = WebChannel.mapSchema(WebmeshSchema.Packet);
28
- yield* Stream.fromEventListener(socket, 'message').pipe(Stream.map((msg) => Schema.decodeUnknownEither(MessageMsgPack)(new Uint8Array(msg.data))), Stream.flatten(), Stream.tap((msg) => Effect.gen(function* () {
34
+ const isConnectedLatch = yield* Effect.makeLatch(true);
35
+ const closedDeferred = yield* Deferred.make().pipe(Effect.acquireRelease(Deferred.done(Exit.void)));
36
+ yield* Stream.never.pipe(Stream.pipeThroughChannel(Socket.toChannel(socket)), Stream.catchTag('SocketError', Effect.fn(function* (error) {
37
+ if (error.reason === 'Close') {
38
+ console.log('socket closed', error);
39
+ yield* isConnectedLatch.close;
40
+ yield* Deferred.succeed(closedDeferred, undefined);
41
+ return yield* Effect.interrupt;
42
+ }
43
+ else {
44
+ return yield* Effect.fail(error);
45
+ }
46
+ })), Stream.retry(Schedule.exponential(100).pipe(Schedule.whileInput((_) => _.reason === 'OpenTimeout'))), Stream.map((msg) => Schema.decodeUnknownEither(MessageMsgPack)(new Uint8Array(msg))), Stream.flatten(), Stream.tap((msg) => Effect.gen(function* () {
29
47
  if (msg._tag === 'WSEdgeInit') {
30
48
  yield* Deferred.succeed(fromDeferred, msg.from);
31
49
  }
@@ -33,27 +51,22 @@ export const makeWebSocketEdge = (socket, socketType) => Effect.scopeWithCloseab
33
51
  const decodedPayload = yield* Schema.decode(schema.listen)(msg.payload);
34
52
  yield* Queue.offer(listenQueue, decodedPayload);
35
53
  }
36
- })), Stream.runDrain, Effect.interruptible, Effect.tapCauseLogPretty, Effect.forkScoped);
37
- const initHandshake = (from) => socket.send(Schema.encodeSync(MessageMsgPack)({ _tag: 'WSEdgeInit', from }));
54
+ })), Stream.runDrain, Effect.interruptible, Effect.withSpan('makeWebSocketEdge:listen'), Effect.tapCauseLogPretty, Effect.forkScoped);
55
+ const sendToSocket = yield* socket.writer;
56
+ const initHandshake = (from) => sendToSocket(Schema.encodeSync(MessageMsgPack)({ _tag: 'WSEdgeInit', from }));
38
57
  if (socketType._tag === 'leaf') {
39
- initHandshake(socketType.from);
58
+ yield* initHandshake(socketType.from);
40
59
  }
41
60
  const deferredResult = yield* fromDeferred;
42
61
  const from = socketType._tag === 'leaf' ? socketType.from : deferredResult;
43
62
  if (socketType._tag === 'relay') {
44
- initHandshake(from);
63
+ yield* initHandshake(from);
45
64
  }
46
- const isConnectedLatch = yield* Effect.makeLatch(true);
47
- const closedDeferred = yield* Deferred.make().pipe(Effect.acquireRelease(Deferred.done(Exit.void)));
48
- yield* Effect.eventListener(socket, 'close', () => Effect.gen(function* () {
49
- yield* isConnectedLatch.close;
50
- yield* Deferred.succeed(closedDeferred, undefined);
51
- }), { once: true });
52
65
  const send = (message) => Effect.gen(function* () {
53
66
  yield* isConnectedLatch.await;
54
67
  const payload = yield* Schema.encode(schema.send)(message);
55
- socket.send(Schema.encodeSync(MessageMsgPack)({ _tag: 'WSEdgePayload', payload, from }));
56
- });
68
+ yield* sendToSocket(Schema.encodeSync(MessageMsgPack)({ _tag: 'WSEdgePayload', payload, from }));
69
+ }).pipe(Effect.orDie);
57
70
  const listen = Stream.fromQueue(listenQueue).pipe(Stream.map(Either.right), WebChannel.listenToDebugPing('websocket-edge'));
58
71
  const webChannel = {
59
72
  [WebChannel.WebChannelSymbol]: WebChannel.WebChannelSymbol,
@@ -65,5 +78,5 @@ export const makeWebSocketEdge = (socket, socketType) => Effect.scopeWithCloseab
65
78
  shutdown: Scope.close(scope, Exit.void),
66
79
  };
67
80
  return { webChannel, from };
68
- }).pipe(Effect.withSpanScoped('makeWebSocketEdge')));
81
+ }).pipe(Effect.withSpanScoped('makeWebSocketEdge'), Effect.orDie));
69
82
  //# sourceMappingURL=websocket-edge.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-edge.js","sourceRoot":"","sources":["../src/websocket-edge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"websocket-edge.js","sourceRoot":"","sources":["../src/websocket-edge.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livestore/webmesh",
3
- "version": "0.0.0-snapshot-76bdaead452769e22fce7f5ec10482474416e04d",
3
+ "version": "0.0.0-snapshot-2da03812fc739d068b0e57f612c11fe4c4b28b0c",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -15,12 +15,10 @@
15
15
  },
16
16
  "types": "./dist/mod.d.ts",
17
17
  "dependencies": {
18
- "ws": "8.18.0",
19
- "@livestore/common": "0.0.0-snapshot-76bdaead452769e22fce7f5ec10482474416e04d",
20
- "@livestore/utils": "0.0.0-snapshot-76bdaead452769e22fce7f5ec10482474416e04d"
18
+ "@livestore/common": "0.0.0-snapshot-2da03812fc739d068b0e57f612c11fe4c4b28b0c",
19
+ "@livestore/utils": "0.0.0-snapshot-2da03812fc739d068b0e57f612c11fe4c4b28b0c"
21
20
  },
22
21
  "devDependencies": {
23
- "@types/ws": "^8.18.0",
24
22
  "vitest": "^3.0.8"
25
23
  },
26
24
  "publishConfig": {
@@ -4,15 +4,15 @@ import {
4
4
  Effect,
5
5
  Either,
6
6
  Exit,
7
+ Layer,
7
8
  Queue,
8
9
  Schedule,
9
10
  Schema,
10
11
  Scope,
12
+ Socket,
11
13
  Stream,
12
14
  WebChannel,
13
- WebSocket,
14
15
  } from '@livestore/utils/effect'
15
- import type * as NodeWebSocket from 'ws'
16
16
 
17
17
  import * as WebmeshSchema from './mesh-schema.js'
18
18
  import type { MeshNode } from './node.js'
@@ -42,30 +42,38 @@ export type SocketType =
42
42
  export const connectViaWebSocket = ({
43
43
  node,
44
44
  url,
45
- reconnect = Schedule.exponential(100),
46
45
  }: {
47
46
  node: MeshNode
48
47
  url: string
49
- reconnect?: Schedule.Schedule<unknown> | false
50
48
  }): Effect.Effect<void, never, Scope.Scope | HttpClient.HttpClient> =>
51
49
  Effect.gen(function* () {
52
50
  const disconnected = yield* Deferred.make<void>()
53
51
 
54
- const socket = yield* WebSocket.makeWebSocket({ url, reconnect })
52
+ const socket = yield* Socket.makeWebSocket(url, { openTimeout: 50 })
55
53
 
56
- socket.addEventListener('close', () => Deferred.unsafeDone(disconnected, Exit.void))
57
-
58
- const edgeChannel = yield* makeWebSocketEdge(socket, { _tag: 'leaf', from: node.nodeName })
54
+ const edgeChannel = yield* makeWebSocketEdge({
55
+ socket,
56
+ socketType: { _tag: 'leaf', from: node.nodeName },
57
+ })
59
58
 
60
59
  yield* node.addEdge({ target: 'ws', edgeChannel: edgeChannel.webChannel, replaceIfExists: true })
61
60
 
62
61
  yield* disconnected
63
- }).pipe(Effect.scoped, Effect.forever, Effect.catchTag('WebSocketError', Effect.orDie))
62
+ }).pipe(Effect.scoped, Effect.forever, Effect.provide(binaryWebSocketConstructorLayer))
63
+
64
+ const binaryWebSocketConstructorLayer = Layer.succeed(Socket.WebSocketConstructor, (url, protocols) => {
65
+ const socket = new globalThis.WebSocket(url, protocols)
66
+ socket.binaryType = 'arraybuffer'
67
+ return socket
68
+ })
64
69
 
65
- export const makeWebSocketEdge = (
66
- socket: globalThis.WebSocket | NodeWebSocket.WebSocket,
67
- socketType: SocketType,
68
- ): Effect.Effect<
70
+ export const makeWebSocketEdge = ({
71
+ socket,
72
+ socketType,
73
+ }: {
74
+ socket: Socket.Socket
75
+ socketType: SocketType
76
+ }): Effect.Effect<
69
77
  {
70
78
  webChannel: WebChannel.WebChannel<typeof WebmeshSchema.Packet.Type, typeof WebmeshSchema.Packet.Type>
71
79
  from: string
@@ -75,8 +83,6 @@ export const makeWebSocketEdge = (
75
83
  > =>
76
84
  Effect.scopeWithCloseable((scope) =>
77
85
  Effect.gen(function* () {
78
- socket.binaryType = 'arraybuffer'
79
-
80
86
  const fromDeferred = yield* Deferred.make<string>()
81
87
 
82
88
  const listenQueue = yield* Queue.unbounded<typeof WebmeshSchema.Packet.Type>().pipe(
@@ -85,8 +91,29 @@ export const makeWebSocketEdge = (
85
91
 
86
92
  const schema = WebChannel.mapSchema(WebmeshSchema.Packet)
87
93
 
88
- yield* Stream.fromEventListener<MessageEvent>(socket as any, 'message').pipe(
89
- Stream.map((msg) => Schema.decodeUnknownEither(MessageMsgPack)(new Uint8Array(msg.data))),
94
+ const isConnectedLatch = yield* Effect.makeLatch(true)
95
+
96
+ const closedDeferred = yield* Deferred.make<void>().pipe(Effect.acquireRelease(Deferred.done(Exit.void)))
97
+
98
+ yield* Stream.never.pipe(
99
+ Stream.pipeThroughChannel(Socket.toChannel(socket)),
100
+ Stream.catchTag(
101
+ 'SocketError',
102
+ Effect.fn(function* (error) {
103
+ if (error.reason === 'Close') {
104
+ console.log('socket closed', error)
105
+ yield* isConnectedLatch.close
106
+ yield* Deferred.succeed(closedDeferred, undefined)
107
+ return yield* Effect.interrupt
108
+ } else {
109
+ return yield* Effect.fail(error)
110
+ }
111
+ }),
112
+ ),
113
+ Stream.retry(
114
+ Schedule.exponential(100).pipe(Schedule.whileInput((_: Socket.SocketError) => _.reason === 'OpenTimeout')),
115
+ ),
116
+ Stream.map((msg) => Schema.decodeUnknownEither(MessageMsgPack)(new Uint8Array(msg))),
90
117
  Stream.flatten(),
91
118
  Stream.tap((msg) =>
92
119
  Effect.gen(function* () {
@@ -100,45 +127,33 @@ export const makeWebSocketEdge = (
100
127
  ),
101
128
  Stream.runDrain,
102
129
  Effect.interruptible,
130
+ Effect.withSpan('makeWebSocketEdge:listen'),
103
131
  Effect.tapCauseLogPretty,
104
132
  Effect.forkScoped,
105
133
  )
106
134
 
135
+ const sendToSocket = yield* socket.writer
136
+
107
137
  const initHandshake = (from: string) =>
108
- socket.send(Schema.encodeSync(MessageMsgPack)({ _tag: 'WSEdgeInit', from }))
138
+ sendToSocket(Schema.encodeSync(MessageMsgPack)({ _tag: 'WSEdgeInit', from }))
109
139
 
110
140
  if (socketType._tag === 'leaf') {
111
- initHandshake(socketType.from)
141
+ yield* initHandshake(socketType.from)
112
142
  }
113
143
 
114
144
  const deferredResult = yield* fromDeferred
115
145
  const from = socketType._tag === 'leaf' ? socketType.from : deferredResult
116
146
 
117
147
  if (socketType._tag === 'relay') {
118
- initHandshake(from)
148
+ yield* initHandshake(from)
119
149
  }
120
150
 
121
- const isConnectedLatch = yield* Effect.makeLatch(true)
122
-
123
- const closedDeferred = yield* Deferred.make<void>().pipe(Effect.acquireRelease(Deferred.done(Exit.void)))
124
-
125
- yield* Effect.eventListener<any>(
126
- socket,
127
- 'close',
128
- () =>
129
- Effect.gen(function* () {
130
- yield* isConnectedLatch.close
131
- yield* Deferred.succeed(closedDeferred, undefined)
132
- }),
133
- { once: true },
134
- )
135
-
136
151
  const send = (message: typeof WebmeshSchema.Packet.Type) =>
137
152
  Effect.gen(function* () {
138
153
  yield* isConnectedLatch.await
139
154
  const payload = yield* Schema.encode(schema.send)(message)
140
- socket.send(Schema.encodeSync(MessageMsgPack)({ _tag: 'WSEdgePayload', payload, from }))
141
- })
155
+ yield* sendToSocket(Schema.encodeSync(MessageMsgPack)({ _tag: 'WSEdgePayload', payload, from }))
156
+ }).pipe(Effect.orDie)
142
157
 
143
158
  const listen = Stream.fromQueue(listenQueue).pipe(
144
159
  Stream.map(Either.right),
@@ -156,5 +171,5 @@ export const makeWebSocketEdge = (
156
171
  } satisfies WebChannel.WebChannel<typeof WebmeshSchema.Packet.Type, typeof WebmeshSchema.Packet.Type>
157
172
 
158
173
  return { webChannel, from }
159
- }).pipe(Effect.withSpanScoped('makeWebSocketEdge')),
174
+ }).pipe(Effect.withSpanScoped('makeWebSocketEdge'), Effect.orDie),
160
175
  )
@@ -1,7 +0,0 @@
1
- import type { HttpClient, Scope } from '@livestore/utils/effect';
2
- import { Effect } from '@livestore/utils/effect';
3
- import * as WebSocket from 'ws';
4
- export declare const makeWebSocketServer: ({ relayNodeName, }: {
5
- relayNodeName: string;
6
- }) => Effect.Effect<WebSocket.WebSocketServer, never, Scope.Scope | HttpClient.HttpClient>;
7
- //# sourceMappingURL=websocket-server.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"websocket-server.d.ts","sourceRoot":"","sources":["../src/websocket-server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAChE,OAAO,EAAE,MAAM,EAAY,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,SAAS,MAAM,IAAI,CAAA;AAK/B,eAAO,MAAM,mBAAmB,GAAI,oBAEjC;IACD,aAAa,EAAE,MAAM,CAAA;CACtB,KAAG,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,UAAU,CA4CnF,CAAA"}
@@ -1,38 +0,0 @@
1
- import { UnexpectedError } from '@livestore/common';
2
- import { Effect, FiberSet } from '@livestore/utils/effect';
3
- import * as WebSocket from 'ws';
4
- import { makeMeshNode } from './node.js';
5
- import { makeWebSocketEdge } from './websocket-edge.js';
6
- export const makeWebSocketServer = ({ relayNodeName, }) => Effect.gen(function* () {
7
- const server = new WebSocket.WebSocketServer({ noServer: true });
8
- yield* Effect.addFinalizer(() => Effect.async((cb) => {
9
- server.close((cause) => {
10
- if (cause) {
11
- cb(Effect.fail(UnexpectedError.make({ cause })));
12
- }
13
- else {
14
- server.removeAllListeners();
15
- server.clients.forEach((client) => client.terminate());
16
- cb(Effect.succeed(undefined));
17
- }
18
- });
19
- }).pipe(Effect.orDie));
20
- const node = yield* makeMeshNode(relayNodeName);
21
- const runtime = yield* Effect.runtime();
22
- const fiberSet = yield* FiberSet.make();
23
- // TODO handle node disconnects (i.e. remove respective connection)
24
- server.on('connection', (socket) => {
25
- Effect.gen(function* () {
26
- const { webChannel, from } = yield* makeWebSocketEdge(socket, { _tag: 'relay' });
27
- yield* node.addEdge({ target: from, edgeChannel: webChannel, replaceIfExists: true });
28
- yield* Effect.log(`WS Relay ${relayNodeName}: added edge from '${from}'`);
29
- socket.addEventListener('close', () => Effect.gen(function* () {
30
- yield* node.removeEdge(from);
31
- yield* Effect.log(`WS Relay ${relayNodeName}: removed edge from '${from}'`);
32
- }).pipe(Effect.provide(runtime), Effect.tapCauseLogPretty, Effect.runFork));
33
- yield* Effect.never;
34
- }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.provide(runtime), FiberSet.run(fiberSet), Effect.runFork);
35
- });
36
- return server;
37
- });
38
- //# sourceMappingURL=websocket-server.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"websocket-server.js","sourceRoot":"","sources":["../src/websocket-server.ts"],"names":[],"mappings":"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"}
@@ -1,57 +0,0 @@
1
- import { UnexpectedError } from '@livestore/common'
2
- import type { HttpClient, Scope } from '@livestore/utils/effect'
3
- import { Effect, FiberSet } from '@livestore/utils/effect'
4
- import * as WebSocket from 'ws'
5
-
6
- import { makeMeshNode } from './node.js'
7
- import { makeWebSocketEdge } from './websocket-edge.js'
8
-
9
- export const makeWebSocketServer = ({
10
- relayNodeName,
11
- }: {
12
- relayNodeName: string
13
- }): Effect.Effect<WebSocket.WebSocketServer, never, Scope.Scope | HttpClient.HttpClient> =>
14
- Effect.gen(function* () {
15
- const server = new WebSocket.WebSocketServer({ noServer: true })
16
-
17
- yield* Effect.addFinalizer(() =>
18
- Effect.async<void, UnexpectedError>((cb) => {
19
- server.close((cause) => {
20
- if (cause) {
21
- cb(Effect.fail(UnexpectedError.make({ cause })))
22
- } else {
23
- server.removeAllListeners()
24
- server.clients.forEach((client) => client.terminate())
25
- cb(Effect.succeed(undefined))
26
- }
27
- })
28
- }).pipe(Effect.orDie),
29
- )
30
-
31
- const node = yield* makeMeshNode(relayNodeName)
32
-
33
- const runtime = yield* Effect.runtime<HttpClient.HttpClient>()
34
-
35
- const fiberSet = yield* FiberSet.make()
36
-
37
- // TODO handle node disconnects (i.e. remove respective connection)
38
- server.on('connection', (socket) => {
39
- Effect.gen(function* () {
40
- const { webChannel, from } = yield* makeWebSocketEdge(socket, { _tag: 'relay' })
41
-
42
- yield* node.addEdge({ target: from, edgeChannel: webChannel, replaceIfExists: true })
43
- yield* Effect.log(`WS Relay ${relayNodeName}: added edge from '${from}'`)
44
-
45
- socket.addEventListener('close', () =>
46
- Effect.gen(function* () {
47
- yield* node.removeEdge(from)
48
- yield* Effect.log(`WS Relay ${relayNodeName}: removed edge from '${from}'`)
49
- }).pipe(Effect.provide(runtime), Effect.tapCauseLogPretty, Effect.runFork),
50
- )
51
-
52
- yield* Effect.never
53
- }).pipe(Effect.scoped, Effect.tapCauseLogPretty, Effect.provide(runtime), FiberSet.run(fiberSet), Effect.runFork)
54
- })
55
-
56
- return server
57
- })