@pluv/io 0.33.0 → 0.34.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 +12 -0
- package/dist/index.d.mts +89 -47
- package/dist/index.d.ts +89 -47
- package/dist/index.js +43 -37
- package/dist/index.mjs +40 -34
- package/package.json +5 -5
- package/src/AbstractPlatform.ts +9 -4
- package/src/IORoom.ts +15 -25
- package/src/PluvIO.ts +30 -13
- package/src/PluvRouter.ts +5 -4
- package/src/PluvServer.ts +54 -30
- package/src/createIO.ts +15 -6
- package/src/index.ts +3 -1
- package/src/types.ts +73 -6
- package/src/version.generated.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -77,8 +77,8 @@ var __async = (__this, __arguments, generator) => {
|
|
|
77
77
|
};
|
|
78
78
|
|
|
79
79
|
// src/index.ts
|
|
80
|
-
var
|
|
81
|
-
__export(
|
|
80
|
+
var index_exports = {};
|
|
81
|
+
__export(index_exports, {
|
|
82
82
|
AbstractPersistence: () => AbstractPersistence,
|
|
83
83
|
AbstractPlatform: () => AbstractPlatform,
|
|
84
84
|
AbstractPubSub: () => AbstractPubSub,
|
|
@@ -90,7 +90,7 @@ __export(src_exports, {
|
|
|
90
90
|
authorize: () => authorize,
|
|
91
91
|
createIO: () => createIO
|
|
92
92
|
});
|
|
93
|
-
module.exports = __toCommonJS(
|
|
93
|
+
module.exports = __toCommonJS(index_exports);
|
|
94
94
|
|
|
95
95
|
// src/AbstractPersistence.ts
|
|
96
96
|
var AbstractPersistence = class {
|
|
@@ -224,6 +224,8 @@ var AbstractPlatform = class {
|
|
|
224
224
|
this.persistence = persistence != null ? persistence : new Persistence();
|
|
225
225
|
this.pubSub = pubSub != null ? pubSub : new PubSub();
|
|
226
226
|
}
|
|
227
|
+
validateConfig(config) {
|
|
228
|
+
}
|
|
227
229
|
_initialize() {
|
|
228
230
|
if (this._initialized) throw new Error("Platform is already initialized");
|
|
229
231
|
this._initialized = true;
|
|
@@ -553,7 +555,7 @@ var IORoom = class {
|
|
|
553
555
|
}
|
|
554
556
|
this._sessions.set(pluvWs.sessionId, pluvWs);
|
|
555
557
|
yield this._platform.persistence.addUser(this.id, pluvWs.sessionId, user != null ? user : {});
|
|
556
|
-
if (this._platform.
|
|
558
|
+
if (this._platform._config.registrationMode === "attached") {
|
|
557
559
|
const onClose = this._onClose(pluvWs).bind(this);
|
|
558
560
|
const onMessage = this._onMessage(pluvWs).bind(this);
|
|
559
561
|
pluvWs.addEventListener("close", onClose);
|
|
@@ -590,13 +592,7 @@ var IORoom = class {
|
|
|
590
592
|
this._sessions.delete(pluvWs.sessionId);
|
|
591
593
|
});
|
|
592
594
|
const promises = quitters.map((quitter) => __async(this, null, function* () {
|
|
593
|
-
yield this.
|
|
594
|
-
message: {
|
|
595
|
-
type: "$EXIT",
|
|
596
|
-
data: { sessionId: quitter.sessionId }
|
|
597
|
-
},
|
|
598
|
-
senderId: quitter.sessionId
|
|
599
|
-
});
|
|
595
|
+
yield this._exitWebsocket(quitter);
|
|
600
596
|
}));
|
|
601
597
|
yield Promise.all(promises);
|
|
602
598
|
});
|
|
@@ -624,7 +620,7 @@ var IORoom = class {
|
|
|
624
620
|
});
|
|
625
621
|
}
|
|
626
622
|
_ensureDetached() {
|
|
627
|
-
if (this._platform.
|
|
623
|
+
if (this._platform._config.registrationMode === "detached") return;
|
|
628
624
|
throw new Error("Platform must use detached mode");
|
|
629
625
|
}
|
|
630
626
|
_exitWebsocket(webSocket) {
|
|
@@ -669,6 +665,7 @@ var IORoom = class {
|
|
|
669
665
|
const ioAuthorize = this._getIOAuthorize(options);
|
|
670
666
|
if (!ioAuthorize) return null;
|
|
671
667
|
if (!token) return null;
|
|
668
|
+
if (!ioAuthorize.secret) throw new Error("`authorize` was specified without a valid secret");
|
|
672
669
|
const payload = yield authorize({
|
|
673
670
|
platform: this._platform,
|
|
674
671
|
secret: ioAuthorize.secret
|
|
@@ -795,13 +792,7 @@ var IORoom = class {
|
|
|
795
792
|
this._logDebug(`${import_kleur.default.blue(`Unregistering connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
796
793
|
this._sessions.delete(webSocket.sessionId);
|
|
797
794
|
this._platform.persistence.deleteUser(this.id, webSocket.sessionId).finally(() => __async(this, null, function* () {
|
|
798
|
-
yield this.
|
|
799
|
-
message: {
|
|
800
|
-
type: "$EXIT",
|
|
801
|
-
data: { sessionId: webSocket.sessionId }
|
|
802
|
-
},
|
|
803
|
-
senderId: webSocket.sessionId
|
|
804
|
-
});
|
|
795
|
+
yield this._exitWebsocket(webSocket);
|
|
805
796
|
const size = this.getSize();
|
|
806
797
|
this._logDebug(`${import_kleur.default.blue(`Unregistered connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
807
798
|
this._logDebug(`${import_kleur.default.blue(`Room ${this.id} size:`)} ${size}`);
|
|
@@ -1002,7 +993,7 @@ var IORoom = class {
|
|
|
1002
993
|
};
|
|
1003
994
|
|
|
1004
995
|
// src/version.generated.ts
|
|
1005
|
-
var version = "0.
|
|
996
|
+
var version = "0.34.0";
|
|
1006
997
|
|
|
1007
998
|
// src/PluvServer.ts
|
|
1008
999
|
var PluvServer = class {
|
|
@@ -1106,14 +1097,11 @@ var PluvServer = class {
|
|
|
1106
1097
|
crdt = import_crdt2.noop,
|
|
1107
1098
|
debug = false,
|
|
1108
1099
|
getInitialStorage,
|
|
1109
|
-
onRoomDeleted,
|
|
1110
|
-
onRoomMessage,
|
|
1111
|
-
onStorageUpdated,
|
|
1112
|
-
onUserConnected,
|
|
1113
|
-
onUserDisconnected,
|
|
1114
1100
|
platform,
|
|
1115
1101
|
router = new PluvRouter({})
|
|
1116
1102
|
} = options;
|
|
1103
|
+
const { onRoomDeleted, onRoomMessage, onStorageUpdated, onUserConnected, onUserDisconnected } = options;
|
|
1104
|
+
platform.validateConfig(options);
|
|
1117
1105
|
this._crdt = crdt;
|
|
1118
1106
|
this._debug = debug;
|
|
1119
1107
|
this._platform = platform;
|
|
@@ -1129,6 +1117,10 @@ var PluvServer = class {
|
|
|
1129
1117
|
onUserDisconnected: (event) => onUserDisconnected == null ? void 0 : onUserDisconnected(event)
|
|
1130
1118
|
};
|
|
1131
1119
|
}
|
|
1120
|
+
get fetch() {
|
|
1121
|
+
if (!this._platform._fetch) throw new Error(`\`${this._platform._name}\` does not support \`fetch\``);
|
|
1122
|
+
return this._platform._fetch;
|
|
1123
|
+
}
|
|
1132
1124
|
/**
|
|
1133
1125
|
* @ignore
|
|
1134
1126
|
* @readonly
|
|
@@ -1148,6 +1140,9 @@ var PluvServer = class {
|
|
|
1148
1140
|
createRoom(room, ...options) {
|
|
1149
1141
|
var _a, _c;
|
|
1150
1142
|
const _b = (_a = options[0]) != null ? _a : {}, { _meta, debug, onDestroy, onMessage } = _b, platformRoomContext = __objRest(_b, ["_meta", "debug", "onDestroy", "onMessage"]);
|
|
1143
|
+
if (this._platform._config.handleMode !== "io") {
|
|
1144
|
+
throw new Error(`\`createRoom' is unsupported for \`${this._platform._name}\``);
|
|
1145
|
+
}
|
|
1151
1146
|
if (!/^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$/i.test(room)) throw new Error("Unsupported room name");
|
|
1152
1147
|
const roomContext = platformRoomContext;
|
|
1153
1148
|
const context = typeof this._context === "function" ? this._context(roomContext) : this._context;
|
|
@@ -1182,17 +1177,23 @@ var PluvServer = class {
|
|
|
1182
1177
|
}
|
|
1183
1178
|
createToken(params) {
|
|
1184
1179
|
return __async(this, null, function* () {
|
|
1180
|
+
var _a;
|
|
1185
1181
|
if (!this._authorize) {
|
|
1186
1182
|
throw new Error("IO does not specify authorize during initialization.");
|
|
1187
1183
|
}
|
|
1188
|
-
|
|
1189
|
-
const
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
}).encode(params);
|
|
1184
|
+
if (this._platform._createToken) return yield this._platform._createToken(params);
|
|
1185
|
+
const ioAuthorize = this._getIOAuthorize(params);
|
|
1186
|
+
const secret = (_a = ioAuthorize == null ? void 0 : ioAuthorize.secret) != null ? _a : null;
|
|
1187
|
+
if (!secret) throw new Error("`authorize` was specified without a valid secret");
|
|
1188
|
+
return yield authorize({ platform: this._platform, secret }).encode(params);
|
|
1194
1189
|
});
|
|
1195
1190
|
}
|
|
1191
|
+
_getIOAuthorize(options) {
|
|
1192
|
+
if (typeof this._authorize === "function") {
|
|
1193
|
+
return this._authorize(options);
|
|
1194
|
+
}
|
|
1195
|
+
return this._authorize;
|
|
1196
|
+
}
|
|
1196
1197
|
_getListeners() {
|
|
1197
1198
|
return this._listeners;
|
|
1198
1199
|
}
|
|
@@ -1219,13 +1220,12 @@ var PluvIO = class {
|
|
|
1219
1220
|
}
|
|
1220
1221
|
createToken(params) {
|
|
1221
1222
|
return __async(this, null, function* () {
|
|
1223
|
+
var _a;
|
|
1222
1224
|
if (!this._authorize) throw new Error("IO does not specify authorize during initialization.");
|
|
1223
|
-
const ioAuthorize =
|
|
1224
|
-
const secret = ioAuthorize.secret;
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
secret
|
|
1228
|
-
}).encode(params);
|
|
1225
|
+
const ioAuthorize = this._getIOAuthorize(params);
|
|
1226
|
+
const secret = (_a = ioAuthorize == null ? void 0 : ioAuthorize.secret) != null ? _a : null;
|
|
1227
|
+
if (!secret) throw new Error("`authorize` was specified without a valid secret");
|
|
1228
|
+
return yield authorize({ platform: this._platform, secret }).encode(params);
|
|
1229
1229
|
});
|
|
1230
1230
|
}
|
|
1231
1231
|
mergeRouters(...routers) {
|
|
@@ -1244,6 +1244,12 @@ var PluvIO = class {
|
|
|
1244
1244
|
platform: this._platform
|
|
1245
1245
|
}));
|
|
1246
1246
|
}
|
|
1247
|
+
_getIOAuthorize(options) {
|
|
1248
|
+
if (typeof this._authorize === "function") {
|
|
1249
|
+
return this._authorize(options);
|
|
1250
|
+
}
|
|
1251
|
+
return this._authorize;
|
|
1252
|
+
}
|
|
1247
1253
|
};
|
|
1248
1254
|
|
|
1249
1255
|
// src/createIO.ts
|
package/dist/index.mjs
CHANGED
|
@@ -182,6 +182,8 @@ var AbstractPlatform = class {
|
|
|
182
182
|
this.persistence = persistence != null ? persistence : new Persistence();
|
|
183
183
|
this.pubSub = pubSub != null ? pubSub : new PubSub();
|
|
184
184
|
}
|
|
185
|
+
validateConfig(config) {
|
|
186
|
+
}
|
|
185
187
|
_initialize() {
|
|
186
188
|
if (this._initialized) throw new Error("Platform is already initialized");
|
|
187
189
|
this._initialized = true;
|
|
@@ -511,7 +513,7 @@ var IORoom = class {
|
|
|
511
513
|
}
|
|
512
514
|
this._sessions.set(pluvWs.sessionId, pluvWs);
|
|
513
515
|
yield this._platform.persistence.addUser(this.id, pluvWs.sessionId, user != null ? user : {});
|
|
514
|
-
if (this._platform.
|
|
516
|
+
if (this._platform._config.registrationMode === "attached") {
|
|
515
517
|
const onClose = this._onClose(pluvWs).bind(this);
|
|
516
518
|
const onMessage = this._onMessage(pluvWs).bind(this);
|
|
517
519
|
pluvWs.addEventListener("close", onClose);
|
|
@@ -548,13 +550,7 @@ var IORoom = class {
|
|
|
548
550
|
this._sessions.delete(pluvWs.sessionId);
|
|
549
551
|
});
|
|
550
552
|
const promises = quitters.map((quitter) => __async(this, null, function* () {
|
|
551
|
-
yield this.
|
|
552
|
-
message: {
|
|
553
|
-
type: "$EXIT",
|
|
554
|
-
data: { sessionId: quitter.sessionId }
|
|
555
|
-
},
|
|
556
|
-
senderId: quitter.sessionId
|
|
557
|
-
});
|
|
553
|
+
yield this._exitWebsocket(quitter);
|
|
558
554
|
}));
|
|
559
555
|
yield Promise.all(promises);
|
|
560
556
|
});
|
|
@@ -582,7 +578,7 @@ var IORoom = class {
|
|
|
582
578
|
});
|
|
583
579
|
}
|
|
584
580
|
_ensureDetached() {
|
|
585
|
-
if (this._platform.
|
|
581
|
+
if (this._platform._config.registrationMode === "detached") return;
|
|
586
582
|
throw new Error("Platform must use detached mode");
|
|
587
583
|
}
|
|
588
584
|
_exitWebsocket(webSocket) {
|
|
@@ -627,6 +623,7 @@ var IORoom = class {
|
|
|
627
623
|
const ioAuthorize = this._getIOAuthorize(options);
|
|
628
624
|
if (!ioAuthorize) return null;
|
|
629
625
|
if (!token) return null;
|
|
626
|
+
if (!ioAuthorize.secret) throw new Error("`authorize` was specified without a valid secret");
|
|
630
627
|
const payload = yield authorize({
|
|
631
628
|
platform: this._platform,
|
|
632
629
|
secret: ioAuthorize.secret
|
|
@@ -753,13 +750,7 @@ var IORoom = class {
|
|
|
753
750
|
this._logDebug(`${colors.blue(`Unregistering connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
754
751
|
this._sessions.delete(webSocket.sessionId);
|
|
755
752
|
this._platform.persistence.deleteUser(this.id, webSocket.sessionId).finally(() => __async(this, null, function* () {
|
|
756
|
-
yield this.
|
|
757
|
-
message: {
|
|
758
|
-
type: "$EXIT",
|
|
759
|
-
data: { sessionId: webSocket.sessionId }
|
|
760
|
-
},
|
|
761
|
-
senderId: webSocket.sessionId
|
|
762
|
-
});
|
|
753
|
+
yield this._exitWebsocket(webSocket);
|
|
763
754
|
const size = this.getSize();
|
|
764
755
|
this._logDebug(`${colors.blue(`Unregistered connection for room ${this.id}:`)} ${webSocket.sessionId}`);
|
|
765
756
|
this._logDebug(`${colors.blue(`Room ${this.id} size:`)} ${size}`);
|
|
@@ -960,7 +951,7 @@ var IORoom = class {
|
|
|
960
951
|
};
|
|
961
952
|
|
|
962
953
|
// src/version.generated.ts
|
|
963
|
-
var version = "0.
|
|
954
|
+
var version = "0.34.0";
|
|
964
955
|
|
|
965
956
|
// src/PluvServer.ts
|
|
966
957
|
var PluvServer = class {
|
|
@@ -1064,14 +1055,11 @@ var PluvServer = class {
|
|
|
1064
1055
|
crdt = noop2,
|
|
1065
1056
|
debug = false,
|
|
1066
1057
|
getInitialStorage,
|
|
1067
|
-
onRoomDeleted,
|
|
1068
|
-
onRoomMessage,
|
|
1069
|
-
onStorageUpdated,
|
|
1070
|
-
onUserConnected,
|
|
1071
|
-
onUserDisconnected,
|
|
1072
1058
|
platform,
|
|
1073
1059
|
router = new PluvRouter({})
|
|
1074
1060
|
} = options;
|
|
1061
|
+
const { onRoomDeleted, onRoomMessage, onStorageUpdated, onUserConnected, onUserDisconnected } = options;
|
|
1062
|
+
platform.validateConfig(options);
|
|
1075
1063
|
this._crdt = crdt;
|
|
1076
1064
|
this._debug = debug;
|
|
1077
1065
|
this._platform = platform;
|
|
@@ -1087,6 +1075,10 @@ var PluvServer = class {
|
|
|
1087
1075
|
onUserDisconnected: (event) => onUserDisconnected == null ? void 0 : onUserDisconnected(event)
|
|
1088
1076
|
};
|
|
1089
1077
|
}
|
|
1078
|
+
get fetch() {
|
|
1079
|
+
if (!this._platform._fetch) throw new Error(`\`${this._platform._name}\` does not support \`fetch\``);
|
|
1080
|
+
return this._platform._fetch;
|
|
1081
|
+
}
|
|
1090
1082
|
/**
|
|
1091
1083
|
* @ignore
|
|
1092
1084
|
* @readonly
|
|
@@ -1106,6 +1098,9 @@ var PluvServer = class {
|
|
|
1106
1098
|
createRoom(room, ...options) {
|
|
1107
1099
|
var _a, _c;
|
|
1108
1100
|
const _b = (_a = options[0]) != null ? _a : {}, { _meta, debug, onDestroy, onMessage } = _b, platformRoomContext = __objRest(_b, ["_meta", "debug", "onDestroy", "onMessage"]);
|
|
1101
|
+
if (this._platform._config.handleMode !== "io") {
|
|
1102
|
+
throw new Error(`\`createRoom' is unsupported for \`${this._platform._name}\``);
|
|
1103
|
+
}
|
|
1109
1104
|
if (!/^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$/i.test(room)) throw new Error("Unsupported room name");
|
|
1110
1105
|
const roomContext = platformRoomContext;
|
|
1111
1106
|
const context = typeof this._context === "function" ? this._context(roomContext) : this._context;
|
|
@@ -1140,17 +1135,23 @@ var PluvServer = class {
|
|
|
1140
1135
|
}
|
|
1141
1136
|
createToken(params) {
|
|
1142
1137
|
return __async(this, null, function* () {
|
|
1138
|
+
var _a;
|
|
1143
1139
|
if (!this._authorize) {
|
|
1144
1140
|
throw new Error("IO does not specify authorize during initialization.");
|
|
1145
1141
|
}
|
|
1146
|
-
|
|
1147
|
-
const
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
}).encode(params);
|
|
1142
|
+
if (this._platform._createToken) return yield this._platform._createToken(params);
|
|
1143
|
+
const ioAuthorize = this._getIOAuthorize(params);
|
|
1144
|
+
const secret = (_a = ioAuthorize == null ? void 0 : ioAuthorize.secret) != null ? _a : null;
|
|
1145
|
+
if (!secret) throw new Error("`authorize` was specified without a valid secret");
|
|
1146
|
+
return yield authorize({ platform: this._platform, secret }).encode(params);
|
|
1152
1147
|
});
|
|
1153
1148
|
}
|
|
1149
|
+
_getIOAuthorize(options) {
|
|
1150
|
+
if (typeof this._authorize === "function") {
|
|
1151
|
+
return this._authorize(options);
|
|
1152
|
+
}
|
|
1153
|
+
return this._authorize;
|
|
1154
|
+
}
|
|
1154
1155
|
_getListeners() {
|
|
1155
1156
|
return this._listeners;
|
|
1156
1157
|
}
|
|
@@ -1177,13 +1178,12 @@ var PluvIO = class {
|
|
|
1177
1178
|
}
|
|
1178
1179
|
createToken(params) {
|
|
1179
1180
|
return __async(this, null, function* () {
|
|
1181
|
+
var _a;
|
|
1180
1182
|
if (!this._authorize) throw new Error("IO does not specify authorize during initialization.");
|
|
1181
|
-
const ioAuthorize =
|
|
1182
|
-
const secret = ioAuthorize.secret;
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
secret
|
|
1186
|
-
}).encode(params);
|
|
1183
|
+
const ioAuthorize = this._getIOAuthorize(params);
|
|
1184
|
+
const secret = (_a = ioAuthorize == null ? void 0 : ioAuthorize.secret) != null ? _a : null;
|
|
1185
|
+
if (!secret) throw new Error("`authorize` was specified without a valid secret");
|
|
1186
|
+
return yield authorize({ platform: this._platform, secret }).encode(params);
|
|
1187
1187
|
});
|
|
1188
1188
|
}
|
|
1189
1189
|
mergeRouters(...routers) {
|
|
@@ -1202,6 +1202,12 @@ var PluvIO = class {
|
|
|
1202
1202
|
platform: this._platform
|
|
1203
1203
|
}));
|
|
1204
1204
|
}
|
|
1205
|
+
_getIOAuthorize(options) {
|
|
1206
|
+
if (typeof this._authorize === "function") {
|
|
1207
|
+
return this._authorize(options);
|
|
1208
|
+
}
|
|
1209
|
+
return this._authorize;
|
|
1210
|
+
}
|
|
1205
1211
|
};
|
|
1206
1212
|
|
|
1207
1213
|
// src/createIO.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluv/io",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"description": "@pluv/io server-side websocket manager",
|
|
5
5
|
"author": "leedavidcs",
|
|
6
6
|
"license": "MIT",
|
|
@@ -21,16 +21,16 @@
|
|
|
21
21
|
"jose": "^5.9.6",
|
|
22
22
|
"kleur": "^4.1.5",
|
|
23
23
|
"wonka": "^6.3.4",
|
|
24
|
-
"@pluv/crdt": "^0.
|
|
25
|
-
"@pluv/types": "^0.
|
|
24
|
+
"@pluv/crdt": "^0.34.0",
|
|
25
|
+
"@pluv/types": "^0.34.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"eslint": "^8.57.1",
|
|
29
29
|
"genversion": "^3.2.0",
|
|
30
30
|
"tsup": "^8.3.5",
|
|
31
31
|
"typescript": "^5.7.2",
|
|
32
|
-
"@pluv/tsconfig": "^0.
|
|
33
|
-
"eslint-config-pluv": "^0.
|
|
32
|
+
"@pluv/tsconfig": "^0.34.0",
|
|
33
|
+
"eslint-config-pluv": "^0.34.0"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"build": "pnpm run version && tsup src/index.ts --format esm,cjs --dts",
|
package/src/AbstractPlatform.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type { AbstractPersistence } from "./AbstractPersistence";
|
|
2
2
|
import type { AbstractPubSub } from "./AbstractPubSub";
|
|
3
3
|
import type { AbstractWebSocket, InferWebSocketSource } from "./AbstractWebSocket";
|
|
4
|
+
import type { JWTEncodeParams } from "./authorize";
|
|
4
5
|
import { Persistence } from "./Persistence";
|
|
5
6
|
import { PubSub } from "./PubSub";
|
|
6
|
-
import type { WebSocketSerializedState } from "./types";
|
|
7
|
-
|
|
8
|
-
export type WebSocketRegistrationMode = "attached" | "detached";
|
|
7
|
+
import type { PlatformConfig, WebSocketSerializedState } from "./types";
|
|
9
8
|
|
|
10
9
|
export type InferPlatformWebSocketType<TPlatform extends AbstractPlatform> =
|
|
11
10
|
TPlatform extends AbstractPlatform<infer IAbstractWebSocket> ? IAbstractWebSocket : never;
|
|
@@ -33,6 +32,7 @@ export abstract class AbstractPlatform<
|
|
|
33
32
|
TWebSocket extends AbstractWebSocket = AbstractWebSocket,
|
|
34
33
|
TInitContext extends Record<string, any> = {},
|
|
35
34
|
TRoomContext extends Record<string, any> = {},
|
|
35
|
+
TConfig extends PlatformConfig = PlatformConfig,
|
|
36
36
|
> {
|
|
37
37
|
protected readonly _initContext: TInitContext | undefined;
|
|
38
38
|
protected readonly _roomContext: TRoomContext | undefined;
|
|
@@ -42,7 +42,10 @@ export abstract class AbstractPlatform<
|
|
|
42
42
|
public persistence: AbstractPersistence;
|
|
43
43
|
public pubSub: AbstractPubSub;
|
|
44
44
|
|
|
45
|
-
public
|
|
45
|
+
public readonly _createToken?: (params: JWTEncodeParams<any, any>) => Promise<string>;
|
|
46
|
+
public _fetch?: (req: any) => Promise<any>;
|
|
47
|
+
public abstract readonly _config: TConfig;
|
|
48
|
+
public abstract readonly _name: string;
|
|
46
49
|
|
|
47
50
|
constructor(config: AbstractPlatformConfig<TRoomContext> = {}) {
|
|
48
51
|
const { context, persistence, pubSub } = config;
|
|
@@ -77,6 +80,8 @@ export abstract class AbstractPlatform<
|
|
|
77
80
|
|
|
78
81
|
public abstract setSerializedState(webSocket: AbstractWebSocket, state: WebSocketSerializedState): void;
|
|
79
82
|
|
|
83
|
+
public validateConfig(config: any): void {}
|
|
84
|
+
|
|
80
85
|
protected _initialize(): this {
|
|
81
86
|
if (this._initialized) throw new Error("Platform is already initialized");
|
|
82
87
|
|
package/src/IORoom.ts
CHANGED
|
@@ -34,6 +34,8 @@ import type {
|
|
|
34
34
|
IORoomMessageEvent,
|
|
35
35
|
IOUserConnectedEvent,
|
|
36
36
|
IOUserDisconnectedEvent,
|
|
37
|
+
PluvIOAuthorize,
|
|
38
|
+
ResolvedPluvIOAuthorize,
|
|
37
39
|
WebSocketSession,
|
|
38
40
|
WebSocketType,
|
|
39
41
|
} from "./types";
|
|
@@ -49,7 +51,7 @@ interface BroadcastParams<TIO extends IORoom<any, any, any, any>> {
|
|
|
49
51
|
|
|
50
52
|
export interface IORoomListeners<
|
|
51
53
|
TPlatform extends AbstractPlatform<any>,
|
|
52
|
-
TAuthorize extends
|
|
54
|
+
TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>>,
|
|
53
55
|
TContext extends Record<string, any>,
|
|
54
56
|
TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>,
|
|
55
57
|
> {
|
|
@@ -68,7 +70,7 @@ export type BroadcastProxy<TIO extends IORoom<any, any, any, any>> = (<TEvent ex
|
|
|
68
70
|
|
|
69
71
|
export type IORoomConfig<
|
|
70
72
|
TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>,
|
|
71
|
-
TAuthorize extends
|
|
73
|
+
TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>> = any,
|
|
72
74
|
TContext extends Record<string, any> = {},
|
|
73
75
|
TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {},
|
|
74
76
|
> = Partial<IORoomListeners<TPlatform, TAuthorize, TContext, TEvents>> & {
|
|
@@ -92,7 +94,7 @@ export type WebsocketRegisterConfig<TPlatform extends AbstractPlatform<any> = Ab
|
|
|
92
94
|
|
|
93
95
|
export class IORoom<
|
|
94
96
|
TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>,
|
|
95
|
-
TAuthorize extends
|
|
97
|
+
TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>> = any,
|
|
96
98
|
TContext extends Record<string, any> = {},
|
|
97
99
|
TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {},
|
|
98
100
|
> implements IOLike<TAuthorize, TEvents>
|
|
@@ -320,7 +322,7 @@ export class IORoom<
|
|
|
320
322
|
|
|
321
323
|
await this._platform.persistence.addUser(this.id, pluvWs.sessionId, user ?? {});
|
|
322
324
|
|
|
323
|
-
if (this._platform.
|
|
325
|
+
if (this._platform._config.registrationMode === "attached") {
|
|
324
326
|
const onClose = this._onClose(pluvWs).bind(this);
|
|
325
327
|
const onMessage = this._onMessage(pluvWs).bind(this);
|
|
326
328
|
|
|
@@ -364,13 +366,7 @@ export class IORoom<
|
|
|
364
366
|
});
|
|
365
367
|
|
|
366
368
|
const promises = quitters.map(async (quitter) => {
|
|
367
|
-
await this.
|
|
368
|
-
message: {
|
|
369
|
-
type: "$EXIT",
|
|
370
|
-
data: { sessionId: quitter.sessionId },
|
|
371
|
-
},
|
|
372
|
-
senderId: quitter.sessionId,
|
|
373
|
-
});
|
|
369
|
+
await this._exitWebsocket(quitter);
|
|
374
370
|
});
|
|
375
371
|
|
|
376
372
|
await Promise.all(promises);
|
|
@@ -400,7 +396,7 @@ export class IORoom<
|
|
|
400
396
|
}
|
|
401
397
|
|
|
402
398
|
private _ensureDetached(): void {
|
|
403
|
-
if (this._platform.
|
|
399
|
+
if (this._platform._config.registrationMode === "detached") return;
|
|
404
400
|
|
|
405
401
|
throw new Error("Platform must use detached mode");
|
|
406
402
|
}
|
|
@@ -456,6 +452,8 @@ export class IORoom<
|
|
|
456
452
|
if (!ioAuthorize) return null as InferIOAuthorizeUser<InferIOAuthorize<this>>;
|
|
457
453
|
if (!token) return null as InferIOAuthorizeUser<InferIOAuthorize<this>>;
|
|
458
454
|
|
|
455
|
+
if (!ioAuthorize.secret) throw new Error("`authorize` was specified without a valid secret");
|
|
456
|
+
|
|
459
457
|
const payload = await authorize({
|
|
460
458
|
platform: this._platform,
|
|
461
459
|
secret: ioAuthorize.secret,
|
|
@@ -494,16 +492,14 @@ export class IORoom<
|
|
|
494
492
|
return doc;
|
|
495
493
|
}
|
|
496
494
|
|
|
497
|
-
private _getIOAuthorize(
|
|
495
|
+
private _getIOAuthorize(
|
|
496
|
+
options: WebsocketRegisterConfig<TPlatform>,
|
|
497
|
+
): ResolvedPluvIOAuthorize<any, any, any> | null {
|
|
498
498
|
if (typeof this._authorize === "function") {
|
|
499
499
|
return this._authorize(options);
|
|
500
500
|
}
|
|
501
501
|
|
|
502
|
-
return this._authorize as
|
|
503
|
-
required: any;
|
|
504
|
-
secret: string;
|
|
505
|
-
user: InputZodLike<any>;
|
|
506
|
-
} | null;
|
|
502
|
+
return this._authorize as ResolvedPluvIOAuthorize<any, any, any> | null;
|
|
507
503
|
}
|
|
508
504
|
|
|
509
505
|
private _getProcedure(
|
|
@@ -619,13 +615,7 @@ export class IORoom<
|
|
|
619
615
|
this._sessions.delete(webSocket.sessionId);
|
|
620
616
|
|
|
621
617
|
this._platform.persistence.deleteUser(this.id, webSocket.sessionId).finally(async () => {
|
|
622
|
-
await this.
|
|
623
|
-
message: {
|
|
624
|
-
type: "$EXIT",
|
|
625
|
-
data: { sessionId: webSocket.sessionId },
|
|
626
|
-
},
|
|
627
|
-
senderId: webSocket.sessionId,
|
|
628
|
-
});
|
|
618
|
+
await this._exitWebsocket(webSocket);
|
|
629
619
|
|
|
630
620
|
const size = this.getSize();
|
|
631
621
|
|
package/src/PluvIO.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AbstractCrdtDocFactory } from "@pluv/crdt";
|
|
2
2
|
import { noop } from "@pluv/crdt";
|
|
3
|
-
import type {
|
|
3
|
+
import type { IOAuthorize, InferIOAuthorizeUser, InputZodLike } from "@pluv/types";
|
|
4
4
|
import type { AbstractPlatform, InferInitContextType } from "./AbstractPlatform";
|
|
5
5
|
import { PluvProcedure } from "./PluvProcedure";
|
|
6
6
|
import type { MergedRouter, PluvRouterEventConfig } from "./PluvRouter";
|
|
@@ -8,24 +8,34 @@ import { PluvRouter } from "./PluvRouter";
|
|
|
8
8
|
import { PluvServer } from "./PluvServer";
|
|
9
9
|
import type { JWTEncodeParams } from "./authorize";
|
|
10
10
|
import { authorize } from "./authorize";
|
|
11
|
-
import type {
|
|
11
|
+
import type {
|
|
12
|
+
CrdtLibraryType,
|
|
13
|
+
GetInitialStorageFn,
|
|
14
|
+
InferPlatformConfig,
|
|
15
|
+
PluvContext,
|
|
16
|
+
PluvIOAuthorize,
|
|
17
|
+
PluvIOListeners,
|
|
18
|
+
ResolvedPluvIOAuthorize,
|
|
19
|
+
} from "./types";
|
|
12
20
|
import { __PLUV_VERSION } from "./version";
|
|
21
|
+
import { WebsocketRegisterConfig } from "./IORoom";
|
|
13
22
|
|
|
14
23
|
export type PluvIOConfig<
|
|
15
24
|
TPlatform extends AbstractPlatform<any>,
|
|
16
25
|
TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>>,
|
|
17
26
|
TContext extends Record<string, any>,
|
|
18
27
|
> = {
|
|
19
|
-
authorize?: TAuthorize;
|
|
20
28
|
context?: PluvContext<TPlatform, TContext>;
|
|
21
29
|
crdt?: CrdtLibraryType;
|
|
22
30
|
debug?: boolean;
|
|
23
31
|
platform: TPlatform;
|
|
24
|
-
}
|
|
32
|
+
} & (InferPlatformConfig<TPlatform>["requireAuth"] extends true
|
|
33
|
+
? { authorize: TAuthorize }
|
|
34
|
+
: { authorize?: TAuthorize });
|
|
25
35
|
|
|
26
36
|
export type ServerConfig<
|
|
27
37
|
TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>,
|
|
28
|
-
TAuthorize extends
|
|
38
|
+
TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>> = any,
|
|
29
39
|
TContext extends Record<string, any> = {},
|
|
30
40
|
TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {},
|
|
31
41
|
> = Partial<PluvIOListeners<TPlatform, TAuthorize, TContext, TEvents>> & {
|
|
@@ -35,7 +45,7 @@ export type ServerConfig<
|
|
|
35
45
|
|
|
36
46
|
export class PluvIO<
|
|
37
47
|
TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>,
|
|
38
|
-
TAuthorize extends
|
|
48
|
+
TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>> = any,
|
|
39
49
|
TContext extends Record<string, any> = {},
|
|
40
50
|
> {
|
|
41
51
|
public readonly version: string = __PLUV_VERSION as any;
|
|
@@ -64,15 +74,12 @@ export class PluvIO<
|
|
|
64
74
|
public async createToken(params: JWTEncodeParams<InferIOAuthorizeUser<TAuthorize>, TPlatform>): Promise<string> {
|
|
65
75
|
if (!this._authorize) throw new Error("IO does not specify authorize during initialization.");
|
|
66
76
|
|
|
67
|
-
const ioAuthorize =
|
|
68
|
-
|
|
77
|
+
const ioAuthorize = this._getIOAuthorize(params);
|
|
78
|
+
const secret = ioAuthorize?.secret ?? null;
|
|
69
79
|
|
|
70
|
-
|
|
80
|
+
if (!secret) throw new Error("`authorize` was specified without a valid secret");
|
|
71
81
|
|
|
72
|
-
return await authorize({
|
|
73
|
-
platform: this._platform,
|
|
74
|
-
secret,
|
|
75
|
-
}).encode(params);
|
|
82
|
+
return await authorize({ platform: this._platform, secret }).encode(params);
|
|
76
83
|
}
|
|
77
84
|
|
|
78
85
|
public mergeRouters<TRouters extends PluvRouter<TPlatform, TAuthorize, TContext, any>[]>(
|
|
@@ -99,4 +106,14 @@ export class PluvIO<
|
|
|
99
106
|
platform: this._platform,
|
|
100
107
|
});
|
|
101
108
|
}
|
|
109
|
+
|
|
110
|
+
private _getIOAuthorize(
|
|
111
|
+
options: WebsocketRegisterConfig<TPlatform>,
|
|
112
|
+
): ResolvedPluvIOAuthorize<any, any, any> | null {
|
|
113
|
+
if (typeof this._authorize === "function") {
|
|
114
|
+
return this._authorize(options);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return this._authorize as ResolvedPluvIOAuthorize<any, any, any> | null;
|
|
118
|
+
}
|
|
102
119
|
}
|
package/src/PluvRouter.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { IORouterLike } from "@pluv/types";
|
|
2
2
|
import type { AbstractPlatform, InferInitContextType } from "./AbstractPlatform";
|
|
3
3
|
import type { PluvProcedure } from "./PluvProcedure";
|
|
4
|
+
import type { PluvIOAuthorize } from "./types";
|
|
4
5
|
|
|
5
6
|
export type PluvRouterEventConfig<
|
|
6
7
|
TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>,
|
|
7
|
-
TAuthorize extends
|
|
8
|
+
TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>> = any,
|
|
8
9
|
TContext extends Record<string, any> = {},
|
|
9
10
|
> = { [P: string]: Pick<PluvProcedure<TPlatform, TAuthorize, TContext, any, any>, "config"> };
|
|
10
11
|
|
|
11
12
|
export type MergedRouter<
|
|
12
13
|
TRouters extends PluvRouter<TPlatform, TAuthorize, TContext, any>[] = [],
|
|
13
14
|
TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>,
|
|
14
|
-
TAuthorize extends
|
|
15
|
+
TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>> = any,
|
|
15
16
|
TContext extends Record<string, any> = {},
|
|
16
17
|
TRoot extends TRouters[0]["_defs"]["events"] = {},
|
|
17
18
|
> = TRouters extends [
|
|
@@ -23,7 +24,7 @@ export type MergedRouter<
|
|
|
23
24
|
|
|
24
25
|
export class PluvRouter<
|
|
25
26
|
TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>,
|
|
26
|
-
TAuthorize extends
|
|
27
|
+
TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>> = any,
|
|
27
28
|
TContext extends Record<string, any> = {},
|
|
28
29
|
TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {},
|
|
29
30
|
> implements IORouterLike<TEvents>
|