@pluv/client 0.7.0 → 0.8.1

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,5 +1,5 @@
1
1
 
2
- > @pluv/client@0.7.0 build /home/runner/work/pluv/pluv/packages/client
2
+ > @pluv/client@0.8.1 build /home/runner/work/pluv/pluv/packages/client
3
3
  > tsup src/index.ts --format esm,cjs --dts
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -8,10 +8,10 @@
8
8
  CLI Target: es6
9
9
  ESM Build start
10
10
  CJS Build start
11
- ESM dist/index.mjs 34.72 KB
12
- ESM ⚡️ Build success in 138ms
13
- CJS dist/index.js 35.86 KB
14
- CJS ⚡️ Build success in 138ms
11
+ ESM dist/index.mjs 35.08 KB
12
+ ESM ⚡️ Build success in 90ms
13
+ CJS dist/index.js 36.22 KB
14
+ CJS ⚡️ Build success in 92ms
15
15
  DTS Build start
16
- DTS ⚡️ Build success in 5111ms
17
- DTS dist/index.d.ts 11.71 KB
16
+ DTS ⚡️ Build success in 3816ms
17
+ DTS dist/index.d.ts 11.73 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @pluv/client
2
2
 
3
+ ## 0.8.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 2c9c5c3: changed my-presence to be non-nullable
8
+
9
+ ## 0.8.0
10
+
11
+ ### Minor Changes
12
+
13
+ - fde89cf: added defaults to the client to align it with createPluvClient by default
14
+
15
+ ### Patch Changes
16
+
17
+ - 5bbfb98: fix not properly handling unauthorized checks
18
+ - b85a232: bumped dependencies
19
+ - Updated dependencies [b85a232]
20
+ - @pluv/crdt-yjs@0.3.8
21
+ - @pluv/types@0.2.0
22
+
3
23
  ## 0.7.0
4
24
 
5
25
  ### Minor Changes
package/dist/index.d.ts CHANGED
@@ -53,7 +53,7 @@ declare abstract class AbstractRoom<TIO extends IOLike, TPresence extends JsonOb
53
53
  abstract broadcast<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>): void;
54
54
  abstract event<TEvent extends keyof InferIOOutput<TIO>>(event: TEvent, callback: EventNotifierSubscriptionCallback<TIO, TEvent>): () => void;
55
55
  abstract getConnection(): WebSocketConnection;
56
- abstract getMyPresence(): TPresence | null;
56
+ abstract getMyPresence(): TPresence;
57
57
  abstract getMyself(): Id<UserInfo<TIO, TPresence>> | null;
58
58
  abstract getOther(connectionId: string): Id<UserInfo<TIO, TPresence>> | null;
59
59
  abstract getOthers(): readonly Id<UserInfo<TIO, TPresence>>[];
@@ -81,18 +81,18 @@ declare global {
81
81
  };
82
82
  };
83
83
  }
84
- type AuthEndpoint = string | ((room: string) => FetchOptions);
84
+ type AuthEndpoint = string | ((room: string) => string | FetchOptions) | true;
85
85
  type WsEndpoint = string | ((room: string) => string);
86
- type FetchOptions = string | {
86
+ type FetchOptions = {
87
87
  url: string;
88
88
  options?: RequestInit;
89
89
  };
90
90
  type RoomEndpoints<TIO extends IOLike> = {
91
- wsEndpoint: WsEndpoint;
91
+ wsEndpoint?: WsEndpoint;
92
92
  } & (InferIOAuthorizeRequired<InferIOAuthorize<TIO>> extends true ? {
93
93
  authEndpoint: AuthEndpoint;
94
94
  } : {
95
- authEndpoint?: AuthEndpoint;
95
+ authEndpoint?: undefined;
96
96
  });
97
97
  type PluvRoomDebug<TIO extends IOLike> = Id<{
98
98
  output: readonly (keyof InferIOOutput<TIO>)[];
@@ -127,7 +127,7 @@ declare class PluvRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TS
127
127
  disconnect(): void;
128
128
  event: <TEvent extends keyof InferIOOutput<TIO>>(event: TEvent, callback: EventNotifierSubscriptionCallback<TIO, TEvent>) => (() => void);
129
129
  getConnection(): WebSocketConnection;
130
- getMyPresence: () => TPresence | null;
130
+ getMyPresence: () => TPresence;
131
131
  getMyself: () => Id<UserInfo<TIO, TPresence>> | null;
132
132
  getOther: (connectionId: string) => Id<UserInfo<TIO, TPresence>> | null;
133
133
  getOthers: () => readonly Id<UserInfo<TIO, TPresence>>[];
@@ -144,6 +144,7 @@ declare class PluvRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TS
144
144
  private _detachWindowListeners;
145
145
  private _detachWsListeners;
146
146
  private _getAuthorization;
147
+ private _getAuthFetchOptions;
147
148
  private _getWsEndpoint;
148
149
  private _handleExit;
149
150
  private _handlePresenceUpdatedMessage;
@@ -220,7 +221,7 @@ declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {},
220
221
  broadcast<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>): void;
221
222
  event: <TEvent extends keyof InferIOOutput<TIO>>(event: TEvent, callback: EventNotifierSubscriptionCallback<TIO, TEvent>) => (() => void);
222
223
  getConnection(): WebSocketConnection;
223
- getMyPresence: () => TPresence | null;
224
+ getMyPresence: () => TPresence;
224
225
  getMyself: () => Id<UserInfo<TIO, TPresence>> | null;
225
226
  getOther: (connectionId: string) => Id<UserInfo<TIO, TPresence>> | null;
226
227
  getOthers: () => readonly Id<UserInfo<TIO, TPresence>>[];
package/dist/index.js CHANGED
@@ -331,8 +331,7 @@ var PluvRoom = class extends AbstractRoom {
331
331
  return this._eventNotifier.subscribe(event, callback);
332
332
  };
333
333
  this.getMyPresence = () => {
334
- var _a, _b;
335
- return (_b = (_a = this._usersManager.myself) == null ? void 0 : _a.presence) != null ? _b : null;
334
+ return this._usersManager.myPresence;
336
335
  };
337
336
  this.getMyself = () => {
338
337
  return this._usersManager.myself;
@@ -369,10 +368,7 @@ var PluvRoom = class extends AbstractRoom {
369
368
  );
370
369
  };
371
370
  this._debug = debug;
372
- this._endpoints = {
373
- authEndpoint,
374
- wsEndpoint
375
- };
371
+ this._endpoints = { authEndpoint, wsEndpoint };
376
372
  this._listeners = {
377
373
  onAuthorizationFail: (error) => {
378
374
  this._clearTimeout(this._timeouts.reconnect);
@@ -585,24 +581,50 @@ var PluvRoom = class extends AbstractRoom {
585
581
  }
586
582
  _getAuthorization(room) {
587
583
  return __async(this, null, function* () {
588
- if (!this._endpoints.authEndpoint)
584
+ const fetchOptions = this._getAuthFetchOptions(room);
585
+ if (!fetchOptions)
589
586
  return null;
590
- if (typeof this._endpoints.authEndpoint === "string") {
591
- const token2 = yield fetch(this._endpoints.authEndpoint).then((res) => res.text()).then((text2) => text2.trim());
592
- return token2;
587
+ const { url, options } = fetchOptions;
588
+ const res = yield fetch(url, options);
589
+ if (!res.ok || res.status !== 200) {
590
+ throw new Error("Room is unauthorized");
591
+ }
592
+ try {
593
+ return yield res.text().then((text2) => text2.trim());
594
+ } catch (err) {
595
+ throw new Error(
596
+ err instanceof Error ? err.message : "Room is unauthorized"
597
+ );
593
598
  }
594
- const config = this._endpoints.authEndpoint(room);
595
- const endpoint = typeof config === "string" ? config : config.url;
596
- const options = typeof config === "string" ? void 0 : config.options;
597
- const token = yield fetch(endpoint, options).then((res) => res.text()).then((text2) => text2.trim());
598
- return token;
599
599
  });
600
600
  }
601
+ _getAuthFetchOptions(room) {
602
+ if (typeof this._endpoints.authEndpoint === "undefined")
603
+ return null;
604
+ if (this._endpoints.authEndpoint === true) {
605
+ return {
606
+ url: `/api/pluv/authorize?room=${room}`,
607
+ options: {}
608
+ };
609
+ }
610
+ if (typeof this._endpoints.authEndpoint === "string") {
611
+ return {
612
+ url: this._endpoints.authEndpoint,
613
+ options: {}
614
+ };
615
+ }
616
+ const result = this._endpoints.authEndpoint(room);
617
+ return typeof result === "string" ? { url: result, options: {} } : result;
618
+ }
601
619
  _getWsEndpoint(room) {
602
- if (typeof this._endpoints.wsEndpoint === "string") {
603
- return this._endpoints.wsEndpoint;
620
+ switch (typeof this._endpoints.wsEndpoint) {
621
+ case "undefined":
622
+ return `/api/pluv/room/${room}`;
623
+ case "string":
624
+ return this._endpoints.wsEndpoint;
625
+ default:
626
+ return this._endpoints.wsEndpoint(room);
604
627
  }
605
- return this._endpoints.wsEndpoint(room);
606
628
  }
607
629
  _handleExit(message) {
608
630
  const { connectionId } = message;
@@ -1083,8 +1105,7 @@ var MockedRoom = class extends AbstractRoom {
1083
1105
  return this._eventNotifier.subscribe(event, callback);
1084
1106
  };
1085
1107
  this.getMyPresence = () => {
1086
- var _a, _b;
1087
- return (_b = (_a = this._usersManager.myself) == null ? void 0 : _a.presence) != null ? _b : null;
1108
+ return this._usersManager.myPresence;
1088
1109
  };
1089
1110
  this.getMyself = () => {
1090
1111
  return this._usersManager.myself;
package/dist/index.mjs CHANGED
@@ -306,8 +306,7 @@ var PluvRoom = class extends AbstractRoom {
306
306
  return this._eventNotifier.subscribe(event, callback);
307
307
  };
308
308
  this.getMyPresence = () => {
309
- var _a, _b;
310
- return (_b = (_a = this._usersManager.myself) == null ? void 0 : _a.presence) != null ? _b : null;
309
+ return this._usersManager.myPresence;
311
310
  };
312
311
  this.getMyself = () => {
313
312
  return this._usersManager.myself;
@@ -344,10 +343,7 @@ var PluvRoom = class extends AbstractRoom {
344
343
  );
345
344
  };
346
345
  this._debug = debug;
347
- this._endpoints = {
348
- authEndpoint,
349
- wsEndpoint
350
- };
346
+ this._endpoints = { authEndpoint, wsEndpoint };
351
347
  this._listeners = {
352
348
  onAuthorizationFail: (error) => {
353
349
  this._clearTimeout(this._timeouts.reconnect);
@@ -560,24 +556,50 @@ var PluvRoom = class extends AbstractRoom {
560
556
  }
561
557
  _getAuthorization(room) {
562
558
  return __async(this, null, function* () {
563
- if (!this._endpoints.authEndpoint)
559
+ const fetchOptions = this._getAuthFetchOptions(room);
560
+ if (!fetchOptions)
564
561
  return null;
565
- if (typeof this._endpoints.authEndpoint === "string") {
566
- const token2 = yield fetch(this._endpoints.authEndpoint).then((res) => res.text()).then((text2) => text2.trim());
567
- return token2;
562
+ const { url, options } = fetchOptions;
563
+ const res = yield fetch(url, options);
564
+ if (!res.ok || res.status !== 200) {
565
+ throw new Error("Room is unauthorized");
566
+ }
567
+ try {
568
+ return yield res.text().then((text2) => text2.trim());
569
+ } catch (err) {
570
+ throw new Error(
571
+ err instanceof Error ? err.message : "Room is unauthorized"
572
+ );
568
573
  }
569
- const config = this._endpoints.authEndpoint(room);
570
- const endpoint = typeof config === "string" ? config : config.url;
571
- const options = typeof config === "string" ? void 0 : config.options;
572
- const token = yield fetch(endpoint, options).then((res) => res.text()).then((text2) => text2.trim());
573
- return token;
574
574
  });
575
575
  }
576
+ _getAuthFetchOptions(room) {
577
+ if (typeof this._endpoints.authEndpoint === "undefined")
578
+ return null;
579
+ if (this._endpoints.authEndpoint === true) {
580
+ return {
581
+ url: `/api/pluv/authorize?room=${room}`,
582
+ options: {}
583
+ };
584
+ }
585
+ if (typeof this._endpoints.authEndpoint === "string") {
586
+ return {
587
+ url: this._endpoints.authEndpoint,
588
+ options: {}
589
+ };
590
+ }
591
+ const result = this._endpoints.authEndpoint(room);
592
+ return typeof result === "string" ? { url: result, options: {} } : result;
593
+ }
576
594
  _getWsEndpoint(room) {
577
- if (typeof this._endpoints.wsEndpoint === "string") {
578
- return this._endpoints.wsEndpoint;
595
+ switch (typeof this._endpoints.wsEndpoint) {
596
+ case "undefined":
597
+ return `/api/pluv/room/${room}`;
598
+ case "string":
599
+ return this._endpoints.wsEndpoint;
600
+ default:
601
+ return this._endpoints.wsEndpoint(room);
579
602
  }
580
- return this._endpoints.wsEndpoint(room);
581
603
  }
582
604
  _handleExit(message) {
583
605
  const { connectionId } = message;
@@ -1058,8 +1080,7 @@ var MockedRoom = class extends AbstractRoom {
1058
1080
  return this._eventNotifier.subscribe(event, callback);
1059
1081
  };
1060
1082
  this.getMyPresence = () => {
1061
- var _a, _b;
1062
- return (_b = (_a = this._usersManager.myself) == null ? void 0 : _a.presence) != null ? _b : null;
1083
+ return this._usersManager.myPresence;
1063
1084
  };
1064
1085
  this.getMyself = () => {
1065
1086
  return this._usersManager.myself;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pluv/client",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
4
4
  "description": "@pluv/io frontend client",
5
5
  "author": "leedavidcs",
6
6
  "license": "MIT",
@@ -18,7 +18,7 @@
18
18
  },
19
19
  "dependencies": {
20
20
  "wonka": "^6.3.2",
21
- "@pluv/crdt-yjs": "^0.3.7",
21
+ "@pluv/crdt-yjs": "^0.3.8",
22
22
  "@pluv/types": "^0.2.0"
23
23
  },
24
24
  "peerDependencies": {
@@ -27,9 +27,9 @@
27
27
  "devDependencies": {
28
28
  "tsup": "^6.7.0",
29
29
  "typescript": "^5.0.4",
30
- "yjs": "^13.6.0",
30
+ "yjs": "^13.6.1",
31
31
  "@pluv/tsconfig": "^0.1.6",
32
- "eslint-config-pluv": "^0.1.11"
32
+ "eslint-config-pluv": "^0.1.12"
33
33
  },
34
34
  "scripts": {
35
35
  "build": "tsup src/index.ts --format esm,cjs --dts",
@@ -38,7 +38,7 @@ export abstract class AbstractRoom<
38
38
 
39
39
  public abstract getConnection(): WebSocketConnection;
40
40
 
41
- public abstract getMyPresence(): TPresence | null;
41
+ public abstract getMyPresence(): TPresence;
42
42
 
43
43
  public abstract getMyself(): Id<UserInfo<TIO, TPresence>> | null;
44
44
 
package/src/MockedRoom.ts CHANGED
@@ -131,8 +131,8 @@ export class MockedRoom<
131
131
  );
132
132
  }
133
133
 
134
- public getMyPresence = (): TPresence | null => {
135
- return this._usersManager.myself?.presence ?? null;
134
+ public getMyPresence = (): TPresence => {
135
+ return this._usersManager.myPresence;
136
136
  };
137
137
 
138
138
  public getMyself = (): Id<UserInfo<TIO, TPresence>> | null => {
package/src/PluvClient.ts CHANGED
@@ -5,6 +5,7 @@ import type {
5
5
  RoomEndpoints,
6
6
  PluvRoomOptions,
7
7
  WsEndpoint,
8
+ RoomConfig,
8
9
  } from "./PluvRoom";
9
10
  import { PluvRoom } from "./PluvRoom";
10
11
 
@@ -13,9 +14,9 @@ export type PluvClientOptions<TIO extends IOLike> = RoomEndpoints<TIO> & {
13
14
  };
14
15
 
15
16
  export class PluvClient<TIO extends IOLike = IOLike> {
16
- private _authEndpoint: AuthEndpoint;
17
+ private _authEndpoint: AuthEndpoint | undefined;
17
18
  private _debug: boolean;
18
- private _wsEndpoint: WsEndpoint;
19
+ private _wsEndpoint: WsEndpoint | undefined;
19
20
 
20
21
  private _rooms = new Map<string, PluvRoom<TIO, any, any>>();
21
22
 
@@ -45,7 +46,7 @@ export class PluvClient<TIO extends IOLike = IOLike> {
45
46
  initialStorage: options.initialStorage,
46
47
  onAuthorizationFail: options.onAuthorizationFail,
47
48
  wsEndpoint: this._wsEndpoint,
48
- });
49
+ } as RoomConfig<TIO, TPresence, TStorage>);
49
50
 
50
51
  this._rooms.set(room, newRoom);
51
52
 
package/src/PluvRoom.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { doc, InferYjsSharedTypeJson } from "@pluv/crdt-yjs";
1
+ import { InferYjsSharedTypeJson } from "@pluv/crdt-yjs";
2
2
  import type {
3
3
  BaseIOEventRecord,
4
4
  EventMessage,
@@ -70,21 +70,19 @@ interface TimeoutIds {
70
70
  reconnect: number | null;
71
71
  }
72
72
 
73
- export type AuthEndpoint = string | ((room: string) => FetchOptions);
73
+ export type AuthEndpoint =
74
+ | string
75
+ | ((room: string) => string | FetchOptions)
76
+ | true;
74
77
  export type WsEndpoint = string | ((room: string) => string);
75
78
 
76
- export interface RoomConfigOptions {
77
- authEndpoint?: AuthEndpoint;
78
- wsEndpoint: WsEndpoint;
79
- }
80
-
81
- type FetchOptions = string | { url: string; options?: RequestInit };
79
+ type FetchOptions = { url: string; options?: RequestInit };
82
80
 
83
81
  export type RoomEndpoints<TIO extends IOLike> = {
84
- wsEndpoint: WsEndpoint;
82
+ wsEndpoint?: WsEndpoint;
85
83
  } & (InferIOAuthorizeRequired<InferIOAuthorize<TIO>> extends true
86
84
  ? { authEndpoint: AuthEndpoint }
87
- : { authEndpoint?: AuthEndpoint });
85
+ : { authEndpoint?: undefined });
88
86
 
89
87
  interface InternalListeners {
90
88
  onAuthorizationFail: (error: Error) => void;
@@ -167,12 +165,7 @@ export class PluvRoom<
167
165
 
168
166
  this._debug = debug;
169
167
 
170
- this._endpoints = {
171
- authEndpoint: authEndpoint as
172
- | string
173
- | ((room: string) => FetchOptions),
174
- wsEndpoint,
175
- };
168
+ this._endpoints = { authEndpoint, wsEndpoint } as RoomEndpoints<TIO>;
176
169
 
177
170
  this._listeners = {
178
171
  onAuthorizationFail: (error) => {
@@ -310,8 +303,8 @@ export class PluvRoom<
310
303
  );
311
304
  }
312
305
 
313
- public getMyPresence = (): TPresence | null => {
314
- return this._usersManager.myself?.presence ?? null;
306
+ public getMyPresence = (): TPresence => {
307
+ return this._usersManager.myPresence;
315
308
  };
316
309
 
317
310
  public getMyself = (): Id<UserInfo<TIO, TPresence>> | null => {
@@ -494,33 +487,60 @@ export class PluvRoom<
494
487
  }
495
488
 
496
489
  private async _getAuthorization(room: string): Promise<string | null> {
497
- if (!this._endpoints.authEndpoint) return null;
490
+ const fetchOptions = this._getAuthFetchOptions(room);
498
491
 
499
- if (typeof this._endpoints.authEndpoint === "string") {
500
- const token = await fetch(this._endpoints.authEndpoint)
501
- .then((res) => res.text())
502
- .then((text) => text.trim());
492
+ if (!fetchOptions) return null;
493
+
494
+ const { url, options } = fetchOptions;
495
+
496
+ const res = await fetch(url, options);
497
+
498
+ if (!res.ok || res.status !== 200) {
499
+ throw new Error("Room is unauthorized");
500
+ }
501
+
502
+ try {
503
+ return await res.text().then((text) => text.trim());
504
+ } catch (err) {
505
+ throw new Error(
506
+ err instanceof Error ? err.message : "Room is unauthorized"
507
+ );
508
+ }
509
+ }
503
510
 
504
- return token;
511
+ private _getAuthFetchOptions(room: string): FetchOptions | null {
512
+ if (typeof this._endpoints.authEndpoint === "undefined") return null;
513
+
514
+ if (this._endpoints.authEndpoint === true) {
515
+ return {
516
+ url: `/api/pluv/authorize?room=${room}`,
517
+ options: {},
518
+ };
505
519
  }
506
520
 
507
- const config = this._endpoints.authEndpoint(room);
508
- const endpoint = typeof config === "string" ? config : config.url;
509
- const options = typeof config === "string" ? undefined : config.options;
521
+ if (typeof this._endpoints.authEndpoint === "string") {
522
+ return {
523
+ url: this._endpoints.authEndpoint,
524
+ options: {},
525
+ };
526
+ }
510
527
 
511
- const token = await fetch(endpoint, options)
512
- .then((res) => res.text())
513
- .then((text) => text.trim());
528
+ const result = this._endpoints.authEndpoint(room);
514
529
 
515
- return token;
530
+ return typeof result === "string"
531
+ ? { url: result, options: {} }
532
+ : result;
516
533
  }
517
534
 
518
535
  private _getWsEndpoint(room: string): string {
519
- if (typeof this._endpoints.wsEndpoint === "string") {
520
- return this._endpoints.wsEndpoint;
536
+ switch (typeof this._endpoints.wsEndpoint) {
537
+ case "undefined":
538
+ return `/api/pluv/room/${room}`;
539
+ case "string":
540
+ return this._endpoints.wsEndpoint;
541
+ default:
542
+ return this._endpoints.wsEndpoint(room);
521
543
  }
522
-
523
- return this._endpoints.wsEndpoint(room);
524
544
  }
525
545
 
526
546
  private _handleExit(message: IOEventMessage<TIO>): void {