cojson-transport-ws 0.7.23 → 0.7.27

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,8 +1,8 @@
1
1
 
2
- > cojson-transport-ws@0.7.22 build /Users/anselm/jazz/jazz/packages/cojson-transport-ws
2
+ > cojson-transport-ws@0.7.26 build /Users/anselm/jazz/jazz/packages/cojson-transport-ws
3
3
  > npm run lint && rm -rf ./dist && tsc --sourceMap --outDir dist
4
4
 
5
5
 
6
- > cojson-transport-ws@0.7.22 lint
6
+ > cojson-transport-ws@0.7.26 lint
7
7
  > eslint . --ext ts,tsx
8
8
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # cojson-transport-nodejs-ws
2
2
 
3
+ ## 0.7.27
4
+
5
+ ### Patch Changes
6
+
7
+ - Option to not expect pings
8
+
9
+ ## 0.7.26
10
+
11
+ ### Patch Changes
12
+
13
+ - Remove Effect from jazz/cojson internals
14
+ - Updated dependencies
15
+ - cojson@0.7.26
16
+
3
17
  ## 0.7.23
4
18
 
5
19
  ### Patch Changes
package/dist/index.js CHANGED
@@ -1,46 +1,58 @@
1
- import { DisconnectedError, PingTimeoutError } from "cojson";
2
- import { Stream, Queue, Effect, Console } from "effect";
1
+ import { cojsonInternals, } from "cojson";
3
2
  const g = globalThis;
4
- export function createWebSocketPeer(options) {
5
- return Effect.gen(function* () {
6
- const ws = options.websocket;
7
- const ws_ = ws;
8
- const outgoing = yield* Queue.unbounded();
9
- const closed = once(ws, "close").pipe(Effect.flatMap((event) => new DisconnectedError({
10
- message: `${event.code}: ${event.reason}`,
11
- })), Stream.fromEffect);
12
- const isSyncMessage = (msg) => {
13
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
- if (msg?.type === "ping") {
15
- const ping = msg;
16
- g.jazzPings || (g.jazzPings = []);
17
- g.jazzPings.push({
18
- received: Date.now(),
19
- sent: ping.time,
20
- dc: ping.dc,
21
- });
22
- return false;
23
- }
24
- return true;
25
- };
26
- yield* Effect.forkDaemon(Effect.gen(function* () {
27
- yield* once(ws, "open");
28
- yield* Queue.take(outgoing).pipe(Effect.andThen((message) => ws.send(JSON.stringify(message))), Effect.forever);
29
- }));
30
- const messages = Stream.fromEventListener(ws_, "message").pipe(Stream.timeoutFail(() => new PingTimeoutError(), "10 seconds"), Stream.tapError((_e) => Console.warn("Ping timeout").pipe(Effect.andThen(Effect.try(() => ws.close())), Effect.catchAll((e) => Console.error("Error while trying to close ws on ping timeout", e)))), Stream.mergeLeft(closed), Stream.map((_) => JSON.parse(_.data)), Stream.filter(isSyncMessage), Stream.buffer({ capacity: "unbounded" }), Stream.onDone(() => Queue.shutdown(outgoing)));
31
- return {
32
- id: options.id,
33
- incoming: messages,
34
- outgoing,
35
- role: options.role,
36
- };
3
+ export function createWebSocketPeer({ id, websocket, role, expectPings = true, }) {
4
+ const incoming = new cojsonInternals.Channel();
5
+ websocket.addEventListener("close", function handleClose() {
6
+ incoming
7
+ .push("Disconnected")
8
+ .catch((e) => console.error("Error while pushing disconnect msg", e));
37
9
  });
38
- }
39
- const once = (ws, event) => Effect.async((register) => {
40
- const cb = (msg) => {
41
- ws.removeEventListener(event, cb);
42
- register(Effect.succeed(msg));
10
+ let pingTimeout = null;
11
+ websocket.addEventListener("message", function handleIncomingMsg(event) {
12
+ const msg = JSON.parse(event.data);
13
+ pingTimeout && clearTimeout(pingTimeout);
14
+ if (msg?.type === "ping") {
15
+ const ping = msg;
16
+ g.jazzPings || (g.jazzPings = []);
17
+ g.jazzPings.push({
18
+ received: Date.now(),
19
+ sent: ping.time,
20
+ dc: ping.dc,
21
+ });
22
+ }
23
+ else {
24
+ incoming
25
+ .push(msg)
26
+ .catch((e) => console.error("Error while pushing incoming msg", e));
27
+ }
28
+ if (expectPings) {
29
+ pingTimeout = setTimeout(() => {
30
+ incoming
31
+ .push("PingTimeout")
32
+ .catch((e) => console.error("Error while pushing ping timeout", e));
33
+ }, 10000);
34
+ }
35
+ });
36
+ const websocketOpen = new Promise((resolve) => {
37
+ websocket.addEventListener("open", resolve, { once: true });
38
+ });
39
+ return {
40
+ id,
41
+ incoming,
42
+ outgoing: {
43
+ async push(msg) {
44
+ await websocketOpen;
45
+ if (websocket.readyState === 1) {
46
+ websocket.send(JSON.stringify(msg));
47
+ }
48
+ },
49
+ close() {
50
+ if (websocket.readyState === 1) {
51
+ websocket.close();
52
+ }
53
+ },
54
+ },
55
+ role,
43
56
  };
44
- ws.addEventListener(event, cb);
45
- });
57
+ }
46
58
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,eAAe,GAClB,MAAM,QAAQ,CAAC;AA2BhB,MAAM,CAAC,GAMH,UAAU,CAAC;AAEf,MAAM,UAAU,mBAAmB,CAAC,EAChC,EAAE,EACF,SAAS,EACT,IAAI,EACJ,WAAW,GAAG,IAAI,GAMrB;IACG,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,OAAO,EAEzC,CAAC;IAEJ,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE,SAAS,WAAW;QACpD,QAAQ;aACH,IAAI,CAAC,cAAc,CAAC;aACpB,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CACT,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,CAAC,CAAC,CACzD,CAAC;IACV,CAAC,CAAC,CAAC;IAEH,IAAI,WAAW,GAAyC,IAAI,CAAC;IAE7D,SAAS,CAAC,gBAAgB,CAAC,SAAS,EAAE,SAAS,iBAAiB,CAAC,KAAK;QAClE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAc,CAAC,CAAC;QAC7C,WAAW,IAAI,YAAY,CAAC,WAAW,CAAC,CAAC;QACzC,IAAI,GAAG,EAAE,IAAI,KAAK,MAAM,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,GAAc,CAAC;YAC5B,CAAC,CAAC,SAAS,KAAX,CAAC,CAAC,SAAS,GAAK,EAAE,EAAC;YACnB,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC;gBACb,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;gBACpB,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,EAAE,EAAE,IAAI,CAAC,EAAE;aACd,CAAC,CAAC;QACP,CAAC;aAAM,CAAC;YACJ,QAAQ;iBACH,IAAI,CAAC,GAAG,CAAC;iBACT,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CACT,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,CAAC,CAAC,CACvD,CAAC;QACV,CAAC;QACD,IAAI,WAAW,EAAE,CAAC;YACd,WAAW,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC1B,QAAQ;qBACH,IAAI,CAAC,aAAa,CAAC;qBACnB,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CACT,OAAO,CAAC,KAAK,CAAC,kCAAkC,EAAE,CAAC,CAAC,CACvD,CAAC;YACV,CAAC,EAAE,KAAM,CAAC,CAAC;QACf,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,aAAa,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAChD,SAAS,CAAC,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,OAAO;QACH,EAAE;QACF,QAAQ;QACR,QAAQ,EAAE;YACN,KAAK,CAAC,IAAI,CAAC,GAAG;gBACV,MAAM,aAAa,CAAC;gBACpB,IAAI,SAAS,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;oBAC7B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;gBACxC,CAAC;YACL,CAAC;YACD,KAAK;gBACD,IAAI,SAAS,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;oBAC7B,SAAS,CAAC,KAAK,EAAE,CAAC;gBACtB,CAAC;YACL,CAAC;SACJ;QACD,IAAI;KACP,CAAC;AACN,CAAC"}
package/package.json CHANGED
@@ -1,14 +1,13 @@
1
1
  {
2
2
  "name": "cojson-transport-ws",
3
3
  "type": "module",
4
- "version": "0.7.23",
4
+ "version": "0.7.27",
5
5
  "main": "dist/index.js",
6
6
  "types": "src/index.ts",
7
7
  "license": "MIT",
8
8
  "dependencies": {
9
- "effect": "^3.5.2",
10
9
  "typescript": "^5.1.6",
11
- "cojson": "0.7.23"
10
+ "cojson": "0.7.26"
12
11
  },
13
12
  "devDependencies": {
14
13
  "@types/ws": "^8.5.5"
package/src/index.ts CHANGED
@@ -1,5 +1,10 @@
1
- import { DisconnectedError, Peer, PingTimeoutError, SyncMessage } from "cojson";
2
- import { Stream, Queue, Effect, Console } from "effect";
1
+ import {
2
+ DisconnectedError,
3
+ Peer,
4
+ PingTimeoutError,
5
+ SyncMessage,
6
+ cojsonInternals,
7
+ } from "cojson";
3
8
 
4
9
  interface WebsocketEvents {
5
10
  close: { code: number; reason: string };
@@ -15,6 +20,7 @@ interface AnyWebSocket {
15
20
  addEventListener<K extends keyof WebsocketEvents>(
16
21
  type: K,
17
22
  listener: (event: WebsocketEvents[K]) => void,
23
+ options?: { once: boolean },
18
24
  ): void;
19
25
  removeEventListener<K extends keyof WebsocketEvents>(
20
26
  type: K,
@@ -22,6 +28,7 @@ interface AnyWebSocket {
22
28
  ): void;
23
29
  close(): void;
24
30
  send(data: string): void;
31
+ readyState: number;
25
32
  }
26
33
 
27
34
  const g: typeof globalThis & {
@@ -32,88 +39,80 @@ const g: typeof globalThis & {
32
39
  }[];
33
40
  } = globalThis;
34
41
 
35
- export function createWebSocketPeer(options: {
42
+ export function createWebSocketPeer({
43
+ id,
44
+ websocket,
45
+ role,
46
+ expectPings = true,
47
+ }: {
36
48
  id: string;
37
49
  websocket: AnyWebSocket;
38
50
  role: Peer["role"];
39
- }): Effect.Effect<Peer> {
40
- return Effect.gen(function* () {
41
- const ws = options.websocket;
42
- const ws_ = ws as unknown as Stream.EventListener<WebsocketEvents["message"]>;
51
+ expectPings?: boolean;
52
+ }): Peer {
53
+ const incoming = new cojsonInternals.Channel<
54
+ SyncMessage | DisconnectedError | PingTimeoutError
55
+ >();
43
56
 
44
- const outgoing = yield* Queue.unbounded<SyncMessage>();
45
-
46
- const closed = once(ws, "close").pipe(
47
- Effect.flatMap(
48
- (event) =>
49
- new DisconnectedError({
50
- message: `${event.code}: ${event.reason}`,
51
- }),
52
- ),
53
- Stream.fromEffect,
54
- );
55
-
56
- const isSyncMessage = (msg: unknown): msg is SyncMessage => {
57
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
58
- if ((msg as any)?.type === "ping") {
59
- const ping = msg as PingMsg;
60
- g.jazzPings ||= [];
61
- g.jazzPings.push({
62
- received: Date.now(),
63
- sent: ping.time,
64
- dc: ping.dc,
65
- });
66
- return false;
67
- }
68
- return true;
69
- };
70
-
71
- yield* Effect.forkDaemon(Effect.gen(function* () {
72
- yield* once(ws, "open");
73
- yield* Queue.take(outgoing).pipe(
74
- Effect.andThen((message) => ws.send(JSON.stringify(message))),
75
- Effect.forever,
57
+ websocket.addEventListener("close", function handleClose() {
58
+ incoming
59
+ .push("Disconnected")
60
+ .catch((e) =>
61
+ console.error("Error while pushing disconnect msg", e),
76
62
  );
77
- }));
63
+ });
78
64
 
79
- type E = WebsocketEvents["message"];
80
- const messages = Stream.fromEventListener<E>(ws_, "message").pipe(
81
- Stream.timeoutFail(() => new PingTimeoutError(), "10 seconds"),
82
- Stream.tapError((_e) =>
83
- Console.warn("Ping timeout").pipe(
84
- Effect.andThen(Effect.try(() => ws.close())),
85
- Effect.catchAll((e) =>
86
- Console.error(
87
- "Error while trying to close ws on ping timeout",
88
- e,
89
- ),
90
- ),
91
- ),
92
- ),
93
- Stream.mergeLeft(closed),
94
- Stream.map((_) => JSON.parse(_.data as string)),
95
- Stream.filter(isSyncMessage),
96
- Stream.buffer({ capacity: "unbounded" }),
97
- Stream.onDone(() => Queue.shutdown(outgoing)),
98
- );
65
+ let pingTimeout: ReturnType<typeof setTimeout> | null = null;
99
66
 
100
- return {
101
- id: options.id,
102
- incoming: messages,
103
- outgoing,
104
- role: options.role,
105
- };
67
+ websocket.addEventListener("message", function handleIncomingMsg(event) {
68
+ const msg = JSON.parse(event.data as string);
69
+ pingTimeout && clearTimeout(pingTimeout);
70
+ if (msg?.type === "ping") {
71
+ const ping = msg as PingMsg;
72
+ g.jazzPings ||= [];
73
+ g.jazzPings.push({
74
+ received: Date.now(),
75
+ sent: ping.time,
76
+ dc: ping.dc,
77
+ });
78
+ } else {
79
+ incoming
80
+ .push(msg)
81
+ .catch((e) =>
82
+ console.error("Error while pushing incoming msg", e),
83
+ );
84
+ }
85
+ if (expectPings) {
86
+ pingTimeout = setTimeout(() => {
87
+ incoming
88
+ .push("PingTimeout")
89
+ .catch((e) =>
90
+ console.error("Error while pushing ping timeout", e),
91
+ );
92
+ }, 10_000);
93
+ }
106
94
  });
107
- }
108
95
 
109
- const once = <Event extends keyof WebsocketEvents>(
110
- ws: AnyWebSocket,
111
- event: Event,
112
- ) =>
113
- Effect.async<WebsocketEvents[Event]>((register) => {
114
- const cb = (msg: WebsocketEvents[Event]) => {
115
- ws.removeEventListener(event, cb);
116
- register(Effect.succeed(msg));
117
- };
118
- ws.addEventListener(event, cb);
96
+ const websocketOpen = new Promise<void>((resolve) => {
97
+ websocket.addEventListener("open", resolve, { once: true });
119
98
  });
99
+
100
+ return {
101
+ id,
102
+ incoming,
103
+ outgoing: {
104
+ async push(msg) {
105
+ await websocketOpen;
106
+ if (websocket.readyState === 1) {
107
+ websocket.send(JSON.stringify(msg));
108
+ }
109
+ },
110
+ close() {
111
+ if (websocket.readyState === 1) {
112
+ websocket.close();
113
+ }
114
+ },
115
+ },
116
+ role,
117
+ };
118
+ }