@pluv/io 0.38.14 → 0.39.0
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/.turbo/turbo-build.log +9 -9
- package/CHANGELOG.md +9 -0
- package/dist/index.d.mts +4 -5
- package/dist/index.d.ts +4 -5
- package/dist/index.js +48 -54
- package/dist/index.mjs +48 -54
- package/eslint.config.mjs +4 -0
- package/package.json +7 -7
- package/src/AbstractPersistence.ts +2 -2
- package/src/AbstractPlatform.ts +1 -1
- package/src/AbstractWebSocket.ts +0 -1
- package/src/IORoom.ts +60 -68
- package/src/PluvIO.ts +2 -2
- package/src/PluvServer.ts +4 -6
- package/src/types.ts +1 -0
- package/src/version.generated.ts +1 -1
- package/src/version.ts +1 -0
- package/.eslintrc.js +0 -4
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
> @pluv/io@0.
|
|
2
|
+
> @pluv/io@0.39.0 build /home/runner/work/pluv/pluv/packages/io
|
|
3
3
|
> pnpm run version && tsup src/index.ts --format esm,cjs --dts
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> @pluv/io@0.
|
|
6
|
+
> @pluv/io@0.39.0 version /home/runner/work/pluv/pluv/packages/io
|
|
7
7
|
> genversion ./src/version.generated.ts --esm
|
|
8
8
|
|
|
9
9
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
[34mCLI[39m Target: es6
|
|
13
13
|
[34mESM[39m Build start
|
|
14
14
|
[34mCJS[39m Build start
|
|
15
|
-
[
|
|
16
|
-
[
|
|
17
|
-
[
|
|
18
|
-
[
|
|
15
|
+
[32mCJS[39m [1mdist/index.js [22m[32m46.56 KB[39m
|
|
16
|
+
[32mCJS[39m ⚡️ Build success in 147ms
|
|
17
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m44.38 KB[39m
|
|
18
|
+
[32mESM[39m ⚡️ Build success in 148ms
|
|
19
19
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[32m30.
|
|
22
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m30.
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 2394ms
|
|
21
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m30.93 KB[39m
|
|
22
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m30.93 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @pluv/io
|
|
2
2
|
|
|
3
|
+
## 0.39.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- fe6e239: Broadcast the quitting user when the server receives an abnormal message event from a session that was marked as having quit.
|
|
8
|
+
- 737d508: Fix not always fully running clean-up effects on the `IORoom` after websocket sessions are closed.
|
|
9
|
+
- @pluv/crdt@0.39.0
|
|
10
|
+
- @pluv/types@0.39.0
|
|
11
|
+
|
|
3
12
|
## 0.38.14
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -7,10 +7,10 @@ declare abstract class AbstractPersistence {
|
|
|
7
7
|
abstract deleteStorageState(room: string): Promise<void>;
|
|
8
8
|
abstract deleteUser(room: string, connectionId: string): Promise<void>;
|
|
9
9
|
abstract deleteUsers(room: string): Promise<void>;
|
|
10
|
-
abstract getSize(room: string): Promise<number>;
|
|
11
10
|
abstract getStorageState(room: string): Promise<string | null>;
|
|
12
11
|
abstract getUser(room: string, connectionId: string): Promise<JsonObject | null>;
|
|
13
12
|
abstract getUsers(room: string): Promise<readonly (JsonObject | null)[]>;
|
|
13
|
+
abstract getUsersSize(room: string): Promise<number>;
|
|
14
14
|
abstract setStorageState(room: string, state: string): Promise<void>;
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -72,7 +72,6 @@ declare abstract class AbstractWebSocket<TWebSocket = any> {
|
|
|
72
72
|
* method, because the implementing class might have to transform the
|
|
73
73
|
* listener, and removing the same listener might be complicated as a
|
|
74
74
|
* result.
|
|
75
|
-
* @author leedavidcs
|
|
76
75
|
* @date August 28, 2022
|
|
77
76
|
*/
|
|
78
77
|
abstract addEventListener<TType extends EventType>(type: TType, handler: AbstractListener<TType>): void;
|
|
@@ -330,7 +329,7 @@ type IORoomConfig<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any
|
|
|
330
329
|
roomContext: InferRoomContextType<TPlatform>;
|
|
331
330
|
router: PluvRouter<TPlatform, TAuthorize, TContext, TEvents>;
|
|
332
331
|
};
|
|
333
|
-
type
|
|
332
|
+
type WebSocketRegisterConfig<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>> = {
|
|
334
333
|
token?: string | null;
|
|
335
334
|
} & InferInitContextType<TPlatform>;
|
|
336
335
|
declare class IORoom<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, InferInitContextType<TPlatform>> | null = null, TContext extends Record<string, any> = {}, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {}> implements IOLike<TAuthorize, TEvents> {
|
|
@@ -375,12 +374,12 @@ declare class IORoom<TPlatform extends AbstractPlatform<any> = AbstractPlatform<
|
|
|
375
374
|
onMessage(webSocket: WebSocketType<TPlatform>): (event: AbstractMessageEvent) => Promise<void>;
|
|
376
375
|
register(webSocket: InferPlatformWebSocketSource<TPlatform>, ...options: keyof InferInitContextType<TPlatform> extends never ? [{
|
|
377
376
|
token?: string;
|
|
378
|
-
}?] : [
|
|
377
|
+
}?] : [WebSocketRegisterConfig<TPlatform>]): Promise<void>;
|
|
379
378
|
private _broadcast;
|
|
379
|
+
private _closeWebSockets;
|
|
380
380
|
private _emitQuitters;
|
|
381
381
|
private _emitRegistered;
|
|
382
382
|
private _ensureDetached;
|
|
383
|
-
private _exitWebsocket;
|
|
384
383
|
private _getAbstractWs;
|
|
385
384
|
private _getAuthorizedUser;
|
|
386
385
|
private _getInitialDoc;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,10 +7,10 @@ declare abstract class AbstractPersistence {
|
|
|
7
7
|
abstract deleteStorageState(room: string): Promise<void>;
|
|
8
8
|
abstract deleteUser(room: string, connectionId: string): Promise<void>;
|
|
9
9
|
abstract deleteUsers(room: string): Promise<void>;
|
|
10
|
-
abstract getSize(room: string): Promise<number>;
|
|
11
10
|
abstract getStorageState(room: string): Promise<string | null>;
|
|
12
11
|
abstract getUser(room: string, connectionId: string): Promise<JsonObject | null>;
|
|
13
12
|
abstract getUsers(room: string): Promise<readonly (JsonObject | null)[]>;
|
|
13
|
+
abstract getUsersSize(room: string): Promise<number>;
|
|
14
14
|
abstract setStorageState(room: string, state: string): Promise<void>;
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -72,7 +72,6 @@ declare abstract class AbstractWebSocket<TWebSocket = any> {
|
|
|
72
72
|
* method, because the implementing class might have to transform the
|
|
73
73
|
* listener, and removing the same listener might be complicated as a
|
|
74
74
|
* result.
|
|
75
|
-
* @author leedavidcs
|
|
76
75
|
* @date August 28, 2022
|
|
77
76
|
*/
|
|
78
77
|
abstract addEventListener<TType extends EventType>(type: TType, handler: AbstractListener<TType>): void;
|
|
@@ -330,7 +329,7 @@ type IORoomConfig<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any
|
|
|
330
329
|
roomContext: InferRoomContextType<TPlatform>;
|
|
331
330
|
router: PluvRouter<TPlatform, TAuthorize, TContext, TEvents>;
|
|
332
331
|
};
|
|
333
|
-
type
|
|
332
|
+
type WebSocketRegisterConfig<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>> = {
|
|
334
333
|
token?: string | null;
|
|
335
334
|
} & InferInitContextType<TPlatform>;
|
|
336
335
|
declare class IORoom<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, InferInitContextType<TPlatform>> | null = null, TContext extends Record<string, any> = {}, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {}> implements IOLike<TAuthorize, TEvents> {
|
|
@@ -375,12 +374,12 @@ declare class IORoom<TPlatform extends AbstractPlatform<any> = AbstractPlatform<
|
|
|
375
374
|
onMessage(webSocket: WebSocketType<TPlatform>): (event: AbstractMessageEvent) => Promise<void>;
|
|
376
375
|
register(webSocket: InferPlatformWebSocketSource<TPlatform>, ...options: keyof InferInitContextType<TPlatform> extends never ? [{
|
|
377
376
|
token?: string;
|
|
378
|
-
}?] : [
|
|
377
|
+
}?] : [WebSocketRegisterConfig<TPlatform>]): Promise<void>;
|
|
379
378
|
private _broadcast;
|
|
379
|
+
private _closeWebSockets;
|
|
380
380
|
private _emitQuitters;
|
|
381
381
|
private _emitRegistered;
|
|
382
382
|
private _ensureDetached;
|
|
383
|
-
private _exitWebsocket;
|
|
384
383
|
private _getAbstractWs;
|
|
385
384
|
private _getAuthorizedUser;
|
|
386
385
|
private _getInitialDoc;
|
package/dist/index.js
CHANGED
|
@@ -220,7 +220,7 @@ var AbstractPlatform = class {
|
|
|
220
220
|
this._initialized = false;
|
|
221
221
|
const { roomContext, persistence, pubSub } = config;
|
|
222
222
|
this._meta = config._meta;
|
|
223
|
-
roomContext
|
|
223
|
+
if (!!roomContext) this._roomContext = roomContext;
|
|
224
224
|
this.persistence = persistence != null ? persistence : new Persistence();
|
|
225
225
|
this.pubSub = pubSub != null ? pubSub : new PubSub();
|
|
226
226
|
}
|
|
@@ -594,19 +594,53 @@ var IORoom = class {
|
|
|
594
594
|
}, message));
|
|
595
595
|
});
|
|
596
596
|
}
|
|
597
|
+
_closeWebSockets(webSockets) {
|
|
598
|
+
return __async(this, null, function* () {
|
|
599
|
+
const closeWebSocket = (webSocket) => __async(this, null, function* () {
|
|
600
|
+
webSocket.state = __spreadProps(__spreadValues({}, webSocket.state), { quit: true });
|
|
601
|
+
const sessionId = webSocket.sessionId;
|
|
602
|
+
this._logDebug(`${import_kleur.default.blue(`Unregistering connection for room ${this.id}:`)} ${sessionId}`);
|
|
603
|
+
this._sessions.delete(sessionId);
|
|
604
|
+
yield this._platform.persistence.deleteUser(this.id, sessionId).catch(() => null);
|
|
605
|
+
yield this._broadcast({
|
|
606
|
+
message: { type: "$exit", data: { sessionId } },
|
|
607
|
+
senderId: sessionId
|
|
608
|
+
});
|
|
609
|
+
try {
|
|
610
|
+
const [session, doc] = yield Promise.all([webSocket.getSession(), this._doc]);
|
|
611
|
+
const encodedState = doc.getEncodedState();
|
|
612
|
+
yield Promise.resolve(
|
|
613
|
+
this._listeners.onUserDisconnected({
|
|
614
|
+
context: this._context,
|
|
615
|
+
encodedState,
|
|
616
|
+
room: this.id,
|
|
617
|
+
user: session.user
|
|
618
|
+
})
|
|
619
|
+
);
|
|
620
|
+
} catch (error) {
|
|
621
|
+
console.error(error);
|
|
622
|
+
}
|
|
623
|
+
this._logDebug(`${import_kleur.default.blue(`Unregistered connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
624
|
+
});
|
|
625
|
+
const promises = webSockets.map((webSocket) => __async(this, null, function* () {
|
|
626
|
+
yield closeWebSocket(webSocket).catch(() => null);
|
|
627
|
+
}));
|
|
628
|
+
yield Promise.all(promises).catch(() => null);
|
|
629
|
+
const size = this.getSize();
|
|
630
|
+
this._logDebug(`${import_kleur.default.blue(`Room ${this.id} size:`)} ${size}`);
|
|
631
|
+
if (!!size) return;
|
|
632
|
+
if (!this._uninitialize) return;
|
|
633
|
+
const uninitialize = (yield this._uninitialize).bind(this);
|
|
634
|
+
yield uninitialize();
|
|
635
|
+
});
|
|
636
|
+
}
|
|
597
637
|
_emitQuitters() {
|
|
598
638
|
return __async(this, null, function* () {
|
|
599
639
|
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
600
640
|
const quitters = Array.from(this._sessions.values()).filter(
|
|
601
641
|
(pluvWs) => pluvWs.state.quit || currentTime - pluvWs.state.timers.ping > PING_TIMEOUT_MS
|
|
602
642
|
);
|
|
603
|
-
|
|
604
|
-
this._sessions.delete(pluvWs.sessionId);
|
|
605
|
-
});
|
|
606
|
-
const promises = quitters.map((quitter) => __async(this, null, function* () {
|
|
607
|
-
yield this._exitWebsocket(quitter);
|
|
608
|
-
}));
|
|
609
|
-
yield Promise.all(promises);
|
|
643
|
+
this._closeWebSockets(quitters);
|
|
610
644
|
});
|
|
611
645
|
}
|
|
612
646
|
_emitRegistered(pluvWs) {
|
|
@@ -636,32 +670,6 @@ var IORoom = class {
|
|
|
636
670
|
if (this._platform._config.registrationMode === "detached") return;
|
|
637
671
|
throw new Error("Platform must use detached mode");
|
|
638
672
|
}
|
|
639
|
-
_exitWebsocket(webSocket) {
|
|
640
|
-
return __async(this, null, function* () {
|
|
641
|
-
const session = yield webSocket.getSession();
|
|
642
|
-
yield this._broadcast({
|
|
643
|
-
message: {
|
|
644
|
-
type: "$exit",
|
|
645
|
-
data: { sessionId: session.id }
|
|
646
|
-
},
|
|
647
|
-
senderId: session.id
|
|
648
|
-
});
|
|
649
|
-
try {
|
|
650
|
-
const doc = yield this._doc;
|
|
651
|
-
const encodedState = doc.getEncodedState();
|
|
652
|
-
yield Promise.resolve(
|
|
653
|
-
this._listeners.onUserDisconnected({
|
|
654
|
-
context: this._context,
|
|
655
|
-
encodedState,
|
|
656
|
-
room: this.id,
|
|
657
|
-
user: session.user
|
|
658
|
-
})
|
|
659
|
-
);
|
|
660
|
-
} catch (err) {
|
|
661
|
-
console.error(err);
|
|
662
|
-
}
|
|
663
|
-
});
|
|
664
|
-
}
|
|
665
673
|
_getAbstractWs(webSocket) {
|
|
666
674
|
var _a, _b;
|
|
667
675
|
if (webSocket instanceof AbstractWebSocket) return webSocket;
|
|
@@ -796,25 +804,12 @@ var IORoom = class {
|
|
|
796
804
|
return { doc: this._doc, uninitialize: this._uninitialize };
|
|
797
805
|
}
|
|
798
806
|
_logDebug(...data) {
|
|
799
|
-
this._debug
|
|
807
|
+
if (this._debug) console.log(...data);
|
|
800
808
|
}
|
|
801
809
|
_onClose(webSocket) {
|
|
802
810
|
return () => __async(this, null, function* () {
|
|
803
811
|
if (!(yield this._initialized)) return;
|
|
804
|
-
|
|
805
|
-
this._logDebug(`${import_kleur.default.blue(`Unregistering connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
806
|
-
this._sessions.delete(webSocket.sessionId);
|
|
807
|
-
this._platform.persistence.deleteUser(this.id, webSocket.sessionId).finally(() => __async(this, null, function* () {
|
|
808
|
-
yield this._exitWebsocket(webSocket);
|
|
809
|
-
const size = this.getSize();
|
|
810
|
-
this._logDebug(`${import_kleur.default.blue(`Unregistered connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
811
|
-
this._logDebug(`${import_kleur.default.blue(`Room ${this.id} size:`)} ${size}`);
|
|
812
|
-
if (size) return;
|
|
813
|
-
if (this._uninitialize) {
|
|
814
|
-
const uninitialize = (yield this._uninitialize).bind(this);
|
|
815
|
-
yield uninitialize();
|
|
816
|
-
}
|
|
817
|
-
}));
|
|
812
|
+
yield this._closeWebSockets([webSocket]);
|
|
818
813
|
});
|
|
819
814
|
}
|
|
820
815
|
_onMessage(webSocket) {
|
|
@@ -836,6 +831,7 @@ var IORoom = class {
|
|
|
836
831
|
sessions
|
|
837
832
|
};
|
|
838
833
|
if (pluvWs.state.quit) {
|
|
834
|
+
yield this._closeWebSockets([pluvWs]).catch(() => null);
|
|
839
835
|
pluvWs.close(1011, "WebSocket broken.");
|
|
840
836
|
return;
|
|
841
837
|
}
|
|
@@ -1009,7 +1005,7 @@ var IORoom = class {
|
|
|
1009
1005
|
};
|
|
1010
1006
|
|
|
1011
1007
|
// src/version.generated.ts
|
|
1012
|
-
var version = "0.
|
|
1008
|
+
var version = "0.39.0";
|
|
1013
1009
|
|
|
1014
1010
|
// src/PluvServer.ts
|
|
1015
1011
|
var PluvServer = class {
|
|
@@ -1207,16 +1203,14 @@ var PluvServer = class {
|
|
|
1207
1203
|
});
|
|
1208
1204
|
}
|
|
1209
1205
|
_getIOAuthorize(options) {
|
|
1210
|
-
if (typeof this._authorize === "function")
|
|
1211
|
-
return this._authorize(options);
|
|
1212
|
-
}
|
|
1206
|
+
if (typeof this._authorize === "function") return this._authorize(options);
|
|
1213
1207
|
return this._authorize;
|
|
1214
1208
|
}
|
|
1215
1209
|
_getListeners() {
|
|
1216
1210
|
return this._listeners;
|
|
1217
1211
|
}
|
|
1218
1212
|
_logDebug(...data) {
|
|
1219
|
-
this._debug
|
|
1213
|
+
if (this._debug) console.log(...data);
|
|
1220
1214
|
}
|
|
1221
1215
|
};
|
|
1222
1216
|
|
package/dist/index.mjs
CHANGED
|
@@ -178,7 +178,7 @@ var AbstractPlatform = class {
|
|
|
178
178
|
this._initialized = false;
|
|
179
179
|
const { roomContext, persistence, pubSub } = config;
|
|
180
180
|
this._meta = config._meta;
|
|
181
|
-
roomContext
|
|
181
|
+
if (!!roomContext) this._roomContext = roomContext;
|
|
182
182
|
this.persistence = persistence != null ? persistence : new Persistence();
|
|
183
183
|
this.pubSub = pubSub != null ? pubSub : new PubSub();
|
|
184
184
|
}
|
|
@@ -552,19 +552,53 @@ var IORoom = class {
|
|
|
552
552
|
}, message));
|
|
553
553
|
});
|
|
554
554
|
}
|
|
555
|
+
_closeWebSockets(webSockets) {
|
|
556
|
+
return __async(this, null, function* () {
|
|
557
|
+
const closeWebSocket = (webSocket) => __async(this, null, function* () {
|
|
558
|
+
webSocket.state = __spreadProps(__spreadValues({}, webSocket.state), { quit: true });
|
|
559
|
+
const sessionId = webSocket.sessionId;
|
|
560
|
+
this._logDebug(`${colors.blue(`Unregistering connection for room ${this.id}:`)} ${sessionId}`);
|
|
561
|
+
this._sessions.delete(sessionId);
|
|
562
|
+
yield this._platform.persistence.deleteUser(this.id, sessionId).catch(() => null);
|
|
563
|
+
yield this._broadcast({
|
|
564
|
+
message: { type: "$exit", data: { sessionId } },
|
|
565
|
+
senderId: sessionId
|
|
566
|
+
});
|
|
567
|
+
try {
|
|
568
|
+
const [session, doc] = yield Promise.all([webSocket.getSession(), this._doc]);
|
|
569
|
+
const encodedState = doc.getEncodedState();
|
|
570
|
+
yield Promise.resolve(
|
|
571
|
+
this._listeners.onUserDisconnected({
|
|
572
|
+
context: this._context,
|
|
573
|
+
encodedState,
|
|
574
|
+
room: this.id,
|
|
575
|
+
user: session.user
|
|
576
|
+
})
|
|
577
|
+
);
|
|
578
|
+
} catch (error) {
|
|
579
|
+
console.error(error);
|
|
580
|
+
}
|
|
581
|
+
this._logDebug(`${colors.blue(`Unregistered connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
582
|
+
});
|
|
583
|
+
const promises = webSockets.map((webSocket) => __async(this, null, function* () {
|
|
584
|
+
yield closeWebSocket(webSocket).catch(() => null);
|
|
585
|
+
}));
|
|
586
|
+
yield Promise.all(promises).catch(() => null);
|
|
587
|
+
const size = this.getSize();
|
|
588
|
+
this._logDebug(`${colors.blue(`Room ${this.id} size:`)} ${size}`);
|
|
589
|
+
if (!!size) return;
|
|
590
|
+
if (!this._uninitialize) return;
|
|
591
|
+
const uninitialize = (yield this._uninitialize).bind(this);
|
|
592
|
+
yield uninitialize();
|
|
593
|
+
});
|
|
594
|
+
}
|
|
555
595
|
_emitQuitters() {
|
|
556
596
|
return __async(this, null, function* () {
|
|
557
597
|
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
558
598
|
const quitters = Array.from(this._sessions.values()).filter(
|
|
559
599
|
(pluvWs) => pluvWs.state.quit || currentTime - pluvWs.state.timers.ping > PING_TIMEOUT_MS
|
|
560
600
|
);
|
|
561
|
-
|
|
562
|
-
this._sessions.delete(pluvWs.sessionId);
|
|
563
|
-
});
|
|
564
|
-
const promises = quitters.map((quitter) => __async(this, null, function* () {
|
|
565
|
-
yield this._exitWebsocket(quitter);
|
|
566
|
-
}));
|
|
567
|
-
yield Promise.all(promises);
|
|
601
|
+
this._closeWebSockets(quitters);
|
|
568
602
|
});
|
|
569
603
|
}
|
|
570
604
|
_emitRegistered(pluvWs) {
|
|
@@ -594,32 +628,6 @@ var IORoom = class {
|
|
|
594
628
|
if (this._platform._config.registrationMode === "detached") return;
|
|
595
629
|
throw new Error("Platform must use detached mode");
|
|
596
630
|
}
|
|
597
|
-
_exitWebsocket(webSocket) {
|
|
598
|
-
return __async(this, null, function* () {
|
|
599
|
-
const session = yield webSocket.getSession();
|
|
600
|
-
yield this._broadcast({
|
|
601
|
-
message: {
|
|
602
|
-
type: "$exit",
|
|
603
|
-
data: { sessionId: session.id }
|
|
604
|
-
},
|
|
605
|
-
senderId: session.id
|
|
606
|
-
});
|
|
607
|
-
try {
|
|
608
|
-
const doc = yield this._doc;
|
|
609
|
-
const encodedState = doc.getEncodedState();
|
|
610
|
-
yield Promise.resolve(
|
|
611
|
-
this._listeners.onUserDisconnected({
|
|
612
|
-
context: this._context,
|
|
613
|
-
encodedState,
|
|
614
|
-
room: this.id,
|
|
615
|
-
user: session.user
|
|
616
|
-
})
|
|
617
|
-
);
|
|
618
|
-
} catch (err) {
|
|
619
|
-
console.error(err);
|
|
620
|
-
}
|
|
621
|
-
});
|
|
622
|
-
}
|
|
623
631
|
_getAbstractWs(webSocket) {
|
|
624
632
|
var _a, _b;
|
|
625
633
|
if (webSocket instanceof AbstractWebSocket) return webSocket;
|
|
@@ -754,25 +762,12 @@ var IORoom = class {
|
|
|
754
762
|
return { doc: this._doc, uninitialize: this._uninitialize };
|
|
755
763
|
}
|
|
756
764
|
_logDebug(...data) {
|
|
757
|
-
this._debug
|
|
765
|
+
if (this._debug) console.log(...data);
|
|
758
766
|
}
|
|
759
767
|
_onClose(webSocket) {
|
|
760
768
|
return () => __async(this, null, function* () {
|
|
761
769
|
if (!(yield this._initialized)) return;
|
|
762
|
-
|
|
763
|
-
this._logDebug(`${colors.blue(`Unregistering connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
764
|
-
this._sessions.delete(webSocket.sessionId);
|
|
765
|
-
this._platform.persistence.deleteUser(this.id, webSocket.sessionId).finally(() => __async(this, null, function* () {
|
|
766
|
-
yield this._exitWebsocket(webSocket);
|
|
767
|
-
const size = this.getSize();
|
|
768
|
-
this._logDebug(`${colors.blue(`Unregistered connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
769
|
-
this._logDebug(`${colors.blue(`Room ${this.id} size:`)} ${size}`);
|
|
770
|
-
if (size) return;
|
|
771
|
-
if (this._uninitialize) {
|
|
772
|
-
const uninitialize = (yield this._uninitialize).bind(this);
|
|
773
|
-
yield uninitialize();
|
|
774
|
-
}
|
|
775
|
-
}));
|
|
770
|
+
yield this._closeWebSockets([webSocket]);
|
|
776
771
|
});
|
|
777
772
|
}
|
|
778
773
|
_onMessage(webSocket) {
|
|
@@ -794,6 +789,7 @@ var IORoom = class {
|
|
|
794
789
|
sessions
|
|
795
790
|
};
|
|
796
791
|
if (pluvWs.state.quit) {
|
|
792
|
+
yield this._closeWebSockets([pluvWs]).catch(() => null);
|
|
797
793
|
pluvWs.close(1011, "WebSocket broken.");
|
|
798
794
|
return;
|
|
799
795
|
}
|
|
@@ -967,7 +963,7 @@ var IORoom = class {
|
|
|
967
963
|
};
|
|
968
964
|
|
|
969
965
|
// src/version.generated.ts
|
|
970
|
-
var version = "0.
|
|
966
|
+
var version = "0.39.0";
|
|
971
967
|
|
|
972
968
|
// src/PluvServer.ts
|
|
973
969
|
var PluvServer = class {
|
|
@@ -1165,16 +1161,14 @@ var PluvServer = class {
|
|
|
1165
1161
|
});
|
|
1166
1162
|
}
|
|
1167
1163
|
_getIOAuthorize(options) {
|
|
1168
|
-
if (typeof this._authorize === "function")
|
|
1169
|
-
return this._authorize(options);
|
|
1170
|
-
}
|
|
1164
|
+
if (typeof this._authorize === "function") return this._authorize(options);
|
|
1171
1165
|
return this._authorize;
|
|
1172
1166
|
}
|
|
1173
1167
|
_getListeners() {
|
|
1174
1168
|
return this._listeners;
|
|
1175
1169
|
}
|
|
1176
1170
|
_logDebug(...data) {
|
|
1177
|
-
this._debug
|
|
1171
|
+
if (this._debug) console.log(...data);
|
|
1178
1172
|
}
|
|
1179
1173
|
};
|
|
1180
1174
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluv/io",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.39.0",
|
|
4
4
|
"description": "@pluv/io server-side websocket manager",
|
|
5
5
|
"author": "leedavidcs",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,21 +21,21 @@
|
|
|
21
21
|
"jose": "^5.10.0",
|
|
22
22
|
"kleur": "^4.1.5",
|
|
23
23
|
"wonka": "^6.3.5",
|
|
24
|
-
"@pluv/crdt": "^0.
|
|
25
|
-
"@pluv/types": "^0.
|
|
24
|
+
"@pluv/crdt": "^0.39.0",
|
|
25
|
+
"@pluv/types": "^0.39.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"eslint": "^
|
|
28
|
+
"eslint": "^9.24.0",
|
|
29
29
|
"genversion": "^3.2.0",
|
|
30
30
|
"tsup": "^8.4.0",
|
|
31
31
|
"typescript": "^5.8.3",
|
|
32
|
-
"@pluv/tsconfig": "^0.
|
|
33
|
-
"eslint-config-pluv": "^0.
|
|
32
|
+
"@pluv/tsconfig": "^0.39.0",
|
|
33
|
+
"eslint-config-pluv": "^0.39.0"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"build": "pnpm run version && tsup src/index.ts --format esm,cjs --dts",
|
|
37
37
|
"dev": "tsup src/index.ts --format esm,cjs --watch --dts",
|
|
38
|
-
"lint": "eslint src/**/*.ts* --fix",
|
|
38
|
+
"lint": "eslint src/**/*.ts* --fix --max-warnings 0",
|
|
39
39
|
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
|
|
40
40
|
"version": "genversion ./src/version.generated.ts --esm"
|
|
41
41
|
}
|
|
@@ -9,13 +9,13 @@ export abstract class AbstractPersistence {
|
|
|
9
9
|
|
|
10
10
|
public abstract deleteUsers(room: string): Promise<void>;
|
|
11
11
|
|
|
12
|
-
public abstract getSize(room: string): Promise<number>;
|
|
13
|
-
|
|
14
12
|
public abstract getStorageState(room: string): Promise<string | null>;
|
|
15
13
|
|
|
16
14
|
public abstract getUser(room: string, connectionId: string): Promise<JsonObject | null>;
|
|
17
15
|
|
|
18
16
|
public abstract getUsers(room: string): Promise<readonly (JsonObject | null)[]>;
|
|
19
17
|
|
|
18
|
+
public abstract getUsersSize(room: string): Promise<number>;
|
|
19
|
+
|
|
20
20
|
public abstract setStorageState(room: string, state: string): Promise<void>;
|
|
21
21
|
}
|
package/src/AbstractPlatform.ts
CHANGED
|
@@ -51,7 +51,7 @@ export abstract class AbstractPlatform<
|
|
|
51
51
|
const { roomContext, persistence, pubSub } = config;
|
|
52
52
|
|
|
53
53
|
(this as any)._meta = (config as any)._meta;
|
|
54
|
-
roomContext
|
|
54
|
+
if (!!roomContext) this._roomContext = roomContext;
|
|
55
55
|
|
|
56
56
|
this.persistence = persistence ?? new Persistence();
|
|
57
57
|
this.pubSub = pubSub ?? new PubSub();
|
package/src/AbstractWebSocket.ts
CHANGED
|
@@ -94,7 +94,6 @@ export abstract class AbstractWebSocket<TWebSocket = any> {
|
|
|
94
94
|
* method, because the implementing class might have to transform the
|
|
95
95
|
* listener, and removing the same listener might be complicated as a
|
|
96
96
|
* result.
|
|
97
|
-
* @author leedavidcs
|
|
98
97
|
* @date August 28, 2022
|
|
99
98
|
*/
|
|
100
99
|
public abstract addEventListener<TType extends EventType>(type: TType, handler: AbstractListener<TType>): void;
|
package/src/IORoom.ts
CHANGED
|
@@ -87,7 +87,7 @@ interface SendMessageSender {
|
|
|
87
87
|
user: JsonObject | null;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
export type
|
|
90
|
+
export type WebSocketRegisterConfig<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>> = {
|
|
91
91
|
token?: string | null;
|
|
92
92
|
} & InferInitContextType<TPlatform>;
|
|
93
93
|
|
|
@@ -237,7 +237,6 @@ export class IORoom<
|
|
|
237
237
|
/**
|
|
238
238
|
* @description Doing this instead of .size because some sessions
|
|
239
239
|
* in the map can be considered as "omitted".
|
|
240
|
-
* @author leedavidcs
|
|
241
240
|
* @date December 21, 2022
|
|
242
241
|
*/
|
|
243
242
|
return Array.from(this._sessions.values()).reduce((count, pluvWs) => {
|
|
@@ -283,11 +282,10 @@ export class IORoom<
|
|
|
283
282
|
webSocket: InferPlatformWebSocketSource<TPlatform>,
|
|
284
283
|
...options: keyof InferInitContextType<TPlatform> extends never
|
|
285
284
|
? [{ token?: string }?]
|
|
286
|
-
: [
|
|
285
|
+
: [WebSocketRegisterConfig<TPlatform>]
|
|
287
286
|
): Promise<void> {
|
|
288
|
-
const _options = (options[0] ?? {}) as
|
|
287
|
+
const _options = (options[0] ?? {}) as WebSocketRegisterConfig<TPlatform>;
|
|
289
288
|
const token = _options.token ?? null;
|
|
290
|
-
|
|
291
289
|
const sessionId = this._platform.getSessionId(webSocket);
|
|
292
290
|
const sessionExists = typeof sessionId === "string" && this._sessions.has(sessionId);
|
|
293
291
|
|
|
@@ -361,21 +359,64 @@ export class IORoom<
|
|
|
361
359
|
});
|
|
362
360
|
}
|
|
363
361
|
|
|
362
|
+
private async _closeWebSockets(webSockets: readonly AbstractWebSocket[]): Promise<void> {
|
|
363
|
+
const closeWebSocket = async (webSocket: AbstractWebSocket): Promise<void> => {
|
|
364
|
+
webSocket.state = { ...webSocket.state, quit: true };
|
|
365
|
+
|
|
366
|
+
const sessionId = webSocket.sessionId;
|
|
367
|
+
|
|
368
|
+
this._logDebug(`${colors.blue(`Unregistering connection for room ${this.id}:`)} ${sessionId}`);
|
|
369
|
+
this._sessions.delete(sessionId);
|
|
370
|
+
|
|
371
|
+
await this._platform.persistence.deleteUser(this.id, sessionId).catch(() => null);
|
|
372
|
+
await this._broadcast({
|
|
373
|
+
message: { type: "$exit", data: { sessionId } },
|
|
374
|
+
senderId: sessionId,
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
try {
|
|
378
|
+
const [session, doc] = await Promise.all([webSocket.getSession(), this._doc]);
|
|
379
|
+
const encodedState = doc.getEncodedState();
|
|
380
|
+
|
|
381
|
+
await Promise.resolve(
|
|
382
|
+
this._listeners.onUserDisconnected({
|
|
383
|
+
context: this._context,
|
|
384
|
+
encodedState,
|
|
385
|
+
room: this.id,
|
|
386
|
+
user: session.user,
|
|
387
|
+
}),
|
|
388
|
+
);
|
|
389
|
+
} catch (error) {
|
|
390
|
+
console.error(error);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
this._logDebug(`${colors.blue(`Unregistered connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
const promises = webSockets.map(async (webSocket) => {
|
|
397
|
+
await closeWebSocket(webSocket).catch(() => null);
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
await Promise.all(promises).catch(() => null);
|
|
401
|
+
|
|
402
|
+
const size = this.getSize();
|
|
403
|
+
|
|
404
|
+
this._logDebug(`${colors.blue(`Room ${this.id} size:`)} ${size}`);
|
|
405
|
+
|
|
406
|
+
if (!!size) return;
|
|
407
|
+
if (!this._uninitialize) return;
|
|
408
|
+
|
|
409
|
+
const uninitialize = (await this._uninitialize).bind(this);
|
|
410
|
+
await uninitialize();
|
|
411
|
+
}
|
|
412
|
+
|
|
364
413
|
private async _emitQuitters(): Promise<void> {
|
|
365
414
|
const currentTime = new Date().getTime();
|
|
366
415
|
const quitters = Array.from(this._sessions.values()).filter(
|
|
367
416
|
(pluvWs) => pluvWs.state.quit || currentTime - pluvWs.state.timers.ping > PING_TIMEOUT_MS,
|
|
368
417
|
);
|
|
369
418
|
|
|
370
|
-
|
|
371
|
-
this._sessions.delete(pluvWs.sessionId);
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
const promises = quitters.map(async (quitter) => {
|
|
375
|
-
await this._exitWebsocket(quitter);
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
await Promise.all(promises);
|
|
419
|
+
this._closeWebSockets(quitters);
|
|
379
420
|
}
|
|
380
421
|
|
|
381
422
|
private async _emitRegistered(pluvWs: AbstractWebSocket): Promise<void> {
|
|
@@ -409,34 +450,6 @@ export class IORoom<
|
|
|
409
450
|
throw new Error("Platform must use detached mode");
|
|
410
451
|
}
|
|
411
452
|
|
|
412
|
-
private async _exitWebsocket(webSocket: AbstractWebSocket<any>): Promise<void> {
|
|
413
|
-
const session = await webSocket.getSession();
|
|
414
|
-
|
|
415
|
-
await this._broadcast({
|
|
416
|
-
message: {
|
|
417
|
-
type: "$exit",
|
|
418
|
-
data: { sessionId: session.id },
|
|
419
|
-
},
|
|
420
|
-
senderId: session.id,
|
|
421
|
-
});
|
|
422
|
-
|
|
423
|
-
try {
|
|
424
|
-
const doc = await this._doc;
|
|
425
|
-
const encodedState = doc.getEncodedState();
|
|
426
|
-
|
|
427
|
-
await Promise.resolve(
|
|
428
|
-
this._listeners.onUserDisconnected({
|
|
429
|
-
context: this._context,
|
|
430
|
-
encodedState,
|
|
431
|
-
room: this.id,
|
|
432
|
-
user: session.user,
|
|
433
|
-
}),
|
|
434
|
-
);
|
|
435
|
-
} catch (err) {
|
|
436
|
-
console.error(err);
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
|
|
440
453
|
private _getAbstractWs(webSocket: WebSocketType<TPlatform>): AbstractWebSocket | null {
|
|
441
454
|
if ((webSocket as unknown as any) instanceof AbstractWebSocket) return webSocket;
|
|
442
455
|
|
|
@@ -455,7 +468,7 @@ export class IORoom<
|
|
|
455
468
|
|
|
456
469
|
private async _getAuthorizedUser(
|
|
457
470
|
token: Maybe<string>,
|
|
458
|
-
options:
|
|
471
|
+
options: WebSocketRegisterConfig<TPlatform>,
|
|
459
472
|
): Promise<InferIOAuthorizeUser<InferIOAuthorize<this>>> {
|
|
460
473
|
const ioAuthorize = this._getIOAuthorize(options);
|
|
461
474
|
|
|
@@ -502,7 +515,7 @@ export class IORoom<
|
|
|
502
515
|
return doc;
|
|
503
516
|
}
|
|
504
517
|
|
|
505
|
-
private _getIOAuthorize(options:
|
|
518
|
+
private _getIOAuthorize(options: WebSocketRegisterConfig<TPlatform>): ResolvedPluvIOAuthorize<any, any> | null {
|
|
506
519
|
if (typeof this._authorize === "function") return this._authorize(options);
|
|
507
520
|
|
|
508
521
|
return this._authorize as ResolvedPluvIOAuthorize<any, any> | null;
|
|
@@ -560,12 +573,10 @@ export class IORoom<
|
|
|
560
573
|
switch (options.type) {
|
|
561
574
|
case "self": {
|
|
562
575
|
await this._sendSelfMessage(message, sender);
|
|
563
|
-
|
|
564
576
|
return;
|
|
565
577
|
}
|
|
566
578
|
case "sync": {
|
|
567
579
|
await this._sendSyncMessage(message, sender);
|
|
568
|
-
|
|
569
580
|
return;
|
|
570
581
|
}
|
|
571
582
|
case "broadcast":
|
|
@@ -610,33 +621,13 @@ export class IORoom<
|
|
|
610
621
|
}
|
|
611
622
|
|
|
612
623
|
private _logDebug(...data: any[]): void {
|
|
613
|
-
this._debug
|
|
624
|
+
if (this._debug) console.log(...data);
|
|
614
625
|
}
|
|
615
626
|
|
|
616
627
|
private _onClose(webSocket: AbstractWebSocket): () => Promise<void> {
|
|
617
628
|
return async (): Promise<void> => {
|
|
618
629
|
if (!(await this._initialized)) return;
|
|
619
|
-
|
|
620
|
-
webSocket.state = { ...webSocket.state, quit: true };
|
|
621
|
-
|
|
622
|
-
this._logDebug(`${colors.blue(`Unregistering connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
623
|
-
this._sessions.delete(webSocket.sessionId);
|
|
624
|
-
|
|
625
|
-
this._platform.persistence.deleteUser(this.id, webSocket.sessionId).finally(async () => {
|
|
626
|
-
await this._exitWebsocket(webSocket);
|
|
627
|
-
|
|
628
|
-
const size = this.getSize();
|
|
629
|
-
|
|
630
|
-
this._logDebug(`${colors.blue(`Unregistered connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
631
|
-
this._logDebug(`${colors.blue(`Room ${this.id} size:`)} ${size}`);
|
|
632
|
-
|
|
633
|
-
if (size) return;
|
|
634
|
-
|
|
635
|
-
if (this._uninitialize) {
|
|
636
|
-
const uninitialize = (await this._uninitialize).bind(this);
|
|
637
|
-
await uninitialize();
|
|
638
|
-
}
|
|
639
|
-
});
|
|
630
|
+
await this._closeWebSockets([webSocket]);
|
|
640
631
|
};
|
|
641
632
|
}
|
|
642
633
|
|
|
@@ -663,6 +654,7 @@ export class IORoom<
|
|
|
663
654
|
};
|
|
664
655
|
|
|
665
656
|
if (pluvWs.state.quit) {
|
|
657
|
+
await this._closeWebSockets([pluvWs]).catch(() => null);
|
|
666
658
|
pluvWs.close(1011, "WebSocket broken.");
|
|
667
659
|
|
|
668
660
|
return;
|
package/src/PluvIO.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { AbstractCrdtDocFactory } from "@pluv/crdt";
|
|
|
2
2
|
import { noop } from "@pluv/crdt";
|
|
3
3
|
import type { IOAuthorize, InferIOAuthorizeUser } from "@pluv/types";
|
|
4
4
|
import type { AbstractPlatform, InferInitContextType } from "./AbstractPlatform";
|
|
5
|
-
import {
|
|
5
|
+
import type { WebSocketRegisterConfig } from "./IORoom";
|
|
6
6
|
import { PluvProcedure } from "./PluvProcedure";
|
|
7
7
|
import type { MergedRouter, PluvRouterEventConfig } from "./PluvRouter";
|
|
8
8
|
import { PluvRouter } from "./PluvRouter";
|
|
@@ -133,7 +133,7 @@ export class PluvIO<
|
|
|
133
133
|
} as PluvServerConfig<TPlatform, TAuthorize, TContext, TEvents>);
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
private _getIOAuthorize(options:
|
|
136
|
+
private _getIOAuthorize(options: WebSocketRegisterConfig<TPlatform>): ResolvedPluvIOAuthorize<any, any> | null {
|
|
137
137
|
if (typeof this._authorize === "function") {
|
|
138
138
|
return this._authorize(options);
|
|
139
139
|
}
|
package/src/PluvServer.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { noop } from "@pluv/crdt";
|
|
|
3
3
|
import type { IOLike, Id, InferIOAuthorize, InferIOAuthorizeUser, JsonObject, Maybe } from "@pluv/types";
|
|
4
4
|
import colors from "kleur";
|
|
5
5
|
import type { AbstractPlatform, InferInitContextType, InferRoomContextType } from "./AbstractPlatform";
|
|
6
|
-
import type { IORoomListeners,
|
|
6
|
+
import type { IORoomListeners, WebSocketRegisterConfig } from "./IORoom";
|
|
7
7
|
import { IORoom } from "./IORoom";
|
|
8
8
|
import { PluvProcedure } from "./PluvProcedure";
|
|
9
9
|
import type { PluvRouterEventConfig } from "./PluvRouter";
|
|
@@ -347,10 +347,8 @@ export class PluvServer<
|
|
|
347
347
|
return await authorize({ platform: this._platform, secret }).encode(params as JWTEncodeParams<any, TPlatform>);
|
|
348
348
|
}
|
|
349
349
|
|
|
350
|
-
private _getIOAuthorize(options:
|
|
351
|
-
if (typeof this._authorize === "function")
|
|
352
|
-
return this._authorize(options);
|
|
353
|
-
}
|
|
350
|
+
private _getIOAuthorize(options: WebSocketRegisterConfig<TPlatform>): ResolvedPluvIOAuthorize<any, any> | null {
|
|
351
|
+
if (typeof this._authorize === "function") return this._authorize(options);
|
|
354
352
|
|
|
355
353
|
return this._authorize as ResolvedPluvIOAuthorize<any, any> | null;
|
|
356
354
|
}
|
|
@@ -360,6 +358,6 @@ export class PluvServer<
|
|
|
360
358
|
}
|
|
361
359
|
|
|
362
360
|
private _logDebug(...data: any[]): void {
|
|
363
|
-
this._debug
|
|
361
|
+
if (this._debug) console.log(...data);
|
|
364
362
|
}
|
|
365
363
|
}
|
package/src/types.ts
CHANGED
|
@@ -24,6 +24,7 @@ import type { AbstractWebSocket } from "./AbstractWebSocket";
|
|
|
24
24
|
import type { PluvRouter, PluvRouterEventConfig } from "./PluvRouter";
|
|
25
25
|
|
|
26
26
|
declare global {
|
|
27
|
+
// eslint-disable-next-line no-var
|
|
27
28
|
var console: {
|
|
28
29
|
error: (...data: any[]) => void;
|
|
29
30
|
log: (...data: any[]) => void;
|
package/src/version.generated.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by genversion.
|
|
2
|
-
export const version = '0.
|
|
2
|
+
export const version = '0.39.0'
|
package/src/version.ts
CHANGED
package/.eslintrc.js
DELETED