@pluv/io 2.1.0 → 2.2.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.
- package/.turbo/turbo-build.log +9 -9
- package/CHANGELOG.md +15 -0
- package/dist/index.d.mts +22 -25
- package/dist/index.d.ts +22 -25
- package/dist/index.js +126 -105
- package/dist/index.mjs +126 -105
- package/package.json +5 -5
- package/src/AbstractPlatform.ts +7 -2
- package/src/IORoom.ts +11 -5
- package/src/PluvIO.ts +9 -5
- package/src/PluvServer.ts +261 -248
- package/src/createIO.ts +1 -1
- package/src/types.ts +13 -8
- package/src/version.generated.ts +1 -1
package/dist/index.mjs
CHANGED
|
@@ -613,6 +613,7 @@ var IORoom = class {
|
|
|
613
613
|
this._listeners.onUserDisconnected({
|
|
614
614
|
context: this._context,
|
|
615
615
|
encodedState,
|
|
616
|
+
platform: this._platform,
|
|
616
617
|
room: this.id,
|
|
617
618
|
user
|
|
618
619
|
})
|
|
@@ -670,6 +671,7 @@ var IORoom = class {
|
|
|
670
671
|
this._listeners.onUserConnected({
|
|
671
672
|
context: this._context,
|
|
672
673
|
encodedState,
|
|
674
|
+
platform: this._platform,
|
|
673
675
|
room: this.id,
|
|
674
676
|
user,
|
|
675
677
|
webSocket: pluvWs.webSocket
|
|
@@ -833,6 +835,7 @@ var IORoom = class {
|
|
|
833
835
|
this._listeners.onDestroy(__spreadProps(__spreadValues({}, "_meta" in this._platform && !!this._platform._meta ? { _meta: this._platform._meta } : {}), {
|
|
834
836
|
context: this._context,
|
|
835
837
|
encodedState,
|
|
838
|
+
platform: this._platform,
|
|
836
839
|
room: this.id
|
|
837
840
|
}))
|
|
838
841
|
);
|
|
@@ -871,6 +874,7 @@ var IORoom = class {
|
|
|
871
874
|
garbageCollect: () => __async(this, null, function* () {
|
|
872
875
|
yield this.garbageCollect();
|
|
873
876
|
}),
|
|
877
|
+
platform: this._platform,
|
|
874
878
|
get presence() {
|
|
875
879
|
return session.presence;
|
|
876
880
|
},
|
|
@@ -897,6 +901,7 @@ var IORoom = class {
|
|
|
897
901
|
context: this._context,
|
|
898
902
|
encodedState: doc.getEncodedState(),
|
|
899
903
|
message,
|
|
904
|
+
platform: this._platform,
|
|
900
905
|
room: this.id,
|
|
901
906
|
user: session.user,
|
|
902
907
|
webSocket: session.webSocket.webSocket
|
|
@@ -1063,6 +1068,7 @@ var IORoom = class {
|
|
|
1063
1068
|
garbageCollect: () => __async(this, null, function* () {
|
|
1064
1069
|
yield this.garbageCollect();
|
|
1065
1070
|
}),
|
|
1071
|
+
platform: this._platform,
|
|
1066
1072
|
get presence() {
|
|
1067
1073
|
return null;
|
|
1068
1074
|
},
|
|
@@ -1114,14 +1120,56 @@ var pickBy = (obj, by) => {
|
|
|
1114
1120
|
};
|
|
1115
1121
|
|
|
1116
1122
|
// src/version.generated.ts
|
|
1117
|
-
var version = "2.1
|
|
1123
|
+
var version = "2.2.1";
|
|
1118
1124
|
|
|
1119
1125
|
// src/PluvServer.ts
|
|
1120
1126
|
var PluvServer = class {
|
|
1121
1127
|
constructor(options) {
|
|
1122
1128
|
this.version = version;
|
|
1123
|
-
this.
|
|
1124
|
-
|
|
1129
|
+
this._config = __spreadValues({
|
|
1130
|
+
crdt: noop2,
|
|
1131
|
+
debug: false,
|
|
1132
|
+
router: new PluvRouter({})
|
|
1133
|
+
}, options);
|
|
1134
|
+
const {
|
|
1135
|
+
onRoomDeleted,
|
|
1136
|
+
onRoomMessage,
|
|
1137
|
+
onStorageUpdated,
|
|
1138
|
+
onUserConnected,
|
|
1139
|
+
onUserDisconnected
|
|
1140
|
+
} = options;
|
|
1141
|
+
this._listeners = {
|
|
1142
|
+
onRoomDeleted: (event) => onRoomDeleted == null ? void 0 : onRoomDeleted(event),
|
|
1143
|
+
onRoomMessage: (event) => onRoomMessage == null ? void 0 : onRoomMessage(event),
|
|
1144
|
+
onStorageUpdated: (event) => onStorageUpdated == null ? void 0 : onStorageUpdated(event),
|
|
1145
|
+
onUserConnected: (event) => onUserConnected == null ? void 0 : onUserConnected(event),
|
|
1146
|
+
onUserDisconnected: (event) => onUserDisconnected == null ? void 0 : onUserDisconnected(event)
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
1149
|
+
get fetch() {
|
|
1150
|
+
const platform = this._config.platform();
|
|
1151
|
+
return (...args) => {
|
|
1152
|
+
if (!platform._fetch)
|
|
1153
|
+
throw new Error(`\`${platform._name}\` does not support \`fetch\``);
|
|
1154
|
+
return platform._fetch(...args);
|
|
1155
|
+
};
|
|
1156
|
+
}
|
|
1157
|
+
/**
|
|
1158
|
+
* @ignore
|
|
1159
|
+
* @readonly
|
|
1160
|
+
* @deprecated Internal use only. Changes to this will never be marked as breaking.
|
|
1161
|
+
*/
|
|
1162
|
+
get _defs() {
|
|
1163
|
+
return {
|
|
1164
|
+
authorize: this._config.authorize,
|
|
1165
|
+
context: this._config.context,
|
|
1166
|
+
events: this._router._defs.events,
|
|
1167
|
+
platform: this._config.platform()
|
|
1168
|
+
};
|
|
1169
|
+
}
|
|
1170
|
+
get _baseRouter() {
|
|
1171
|
+
const listeners = this._getListeners();
|
|
1172
|
+
return new PluvRouter({
|
|
1125
1173
|
$getOthers: this._procedure.sync((data, { room, session, sessions }) => {
|
|
1126
1174
|
const currentTime = Date.now();
|
|
1127
1175
|
const others = sessions.filter((wsSession) => {
|
|
@@ -1156,46 +1204,54 @@ var PluvServer = class {
|
|
|
1156
1204
|
timers: { presence: timers.presence }
|
|
1157
1205
|
}
|
|
1158
1206
|
};
|
|
1159
|
-
}).self((_0, _1) => __async(this, [_0, _1], function* (data, { context, doc, room, session }) {
|
|
1160
|
-
var _a;
|
|
1161
|
-
const oldState = yield
|
|
1207
|
+
}).self((_0, _1) => __async(this, [_0, _1], function* (data, { context, doc, platform, room, session }) {
|
|
1208
|
+
var _a, _b;
|
|
1209
|
+
const oldState = yield platform.persistence.getStorageState(room);
|
|
1162
1210
|
const update = data == null ? void 0 : data.update;
|
|
1163
1211
|
if (!oldState) {
|
|
1164
|
-
const loadedState = yield (_a = this.
|
|
1212
|
+
const loadedState = yield (_b = (_a = this._config).getInitialStorage) == null ? void 0 : _b.call(_a, {
|
|
1213
|
+
context,
|
|
1214
|
+
room
|
|
1215
|
+
});
|
|
1165
1216
|
if (!!loadedState) {
|
|
1166
1217
|
doc.applyEncodedState({ update: loadedState }).getEncodedState();
|
|
1167
1218
|
}
|
|
1168
1219
|
}
|
|
1169
1220
|
if (!doc.isEmpty()) {
|
|
1170
1221
|
const encodedState2 = doc.getEncodedState();
|
|
1171
|
-
return {
|
|
1222
|
+
return {
|
|
1223
|
+
$storageReceived: { changeKind: "unchanged", state: encodedState2 }
|
|
1224
|
+
};
|
|
1172
1225
|
}
|
|
1173
1226
|
if (!!update) {
|
|
1174
1227
|
const encodedState2 = doc.applyEncodedState({ update }).getEncodedState();
|
|
1175
1228
|
const storageSize = new TextEncoder().encode(encodedState2).length;
|
|
1176
|
-
if (!!this.
|
|
1229
|
+
if (!!this._config.limits.storageMaxSize && storageSize > this._config.limits.storageMaxSize) {
|
|
1177
1230
|
throw new Error("Storage has exceeded the size limit");
|
|
1178
1231
|
}
|
|
1179
|
-
yield
|
|
1232
|
+
yield platform.persistence.setStorageState(room, encodedState2).catch((error) => {
|
|
1180
1233
|
this._logDebug(error);
|
|
1181
1234
|
});
|
|
1182
|
-
|
|
1235
|
+
listeners.onStorageUpdated({
|
|
1183
1236
|
context,
|
|
1184
1237
|
encodedState: encodedState2,
|
|
1238
|
+
platform,
|
|
1185
1239
|
room,
|
|
1186
1240
|
user: session == null ? void 0 : session.user,
|
|
1187
1241
|
webSocket: session == null ? void 0 : session.webSocket.webSocket
|
|
1188
1242
|
});
|
|
1189
|
-
return {
|
|
1243
|
+
return {
|
|
1244
|
+
$storageReceived: { changeKind: "initialized", state: encodedState2 }
|
|
1245
|
+
};
|
|
1190
1246
|
}
|
|
1191
1247
|
const encodedState = doc.getEncodedState();
|
|
1192
1248
|
return { $storageReceived: { changeKind: "empty", state: encodedState } };
|
|
1193
1249
|
})),
|
|
1194
|
-
$ping: this._procedure.self((data, { session }) => {
|
|
1250
|
+
$ping: this._procedure.self((data, { platform, session }) => {
|
|
1195
1251
|
if (!session) return {};
|
|
1196
1252
|
const currentTime = (/* @__PURE__ */ new Date()).getTime();
|
|
1197
1253
|
const prevState = session.webSocket.state;
|
|
1198
|
-
|
|
1254
|
+
platform.setSerializedState(session.webSocket, __spreadProps(__spreadValues({}, prevState), {
|
|
1199
1255
|
timers: __spreadProps(__spreadValues({}, prevState.timers), {
|
|
1200
1256
|
ping: currentTime
|
|
1201
1257
|
})
|
|
@@ -1206,10 +1262,13 @@ var PluvServer = class {
|
|
|
1206
1262
|
const presence = data == null ? void 0 : data.presence;
|
|
1207
1263
|
const { session } = context;
|
|
1208
1264
|
if (!session) return {};
|
|
1209
|
-
const cleanedPatch = pickBy(
|
|
1265
|
+
const cleanedPatch = pickBy(
|
|
1266
|
+
presence != null ? presence : {},
|
|
1267
|
+
(value) => typeof value !== "undefined"
|
|
1268
|
+
);
|
|
1210
1269
|
const updated = Object.assign(/* @__PURE__ */ Object.create(null), session.presence, cleanedPatch);
|
|
1211
1270
|
const bytes = new TextEncoder().encode(JSON.stringify(updated)).length;
|
|
1212
|
-
if (!!this.
|
|
1271
|
+
if (!!this._config.limits.presenceMaxSize && bytes > this._config.limits.presenceMaxSize) {
|
|
1213
1272
|
throw new Error(
|
|
1214
1273
|
`Large presence. Presence must be at most 512 bytes. Current size: ${bytes.toLocaleString()}`
|
|
1215
1274
|
);
|
|
@@ -1222,7 +1281,7 @@ var PluvServer = class {
|
|
|
1222
1281
|
}
|
|
1223
1282
|
};
|
|
1224
1283
|
}),
|
|
1225
|
-
$updateStorage: this._procedure.broadcast((data, { context, doc, room }) => {
|
|
1284
|
+
$updateStorage: this._procedure.broadcast((data, { context, doc, platform, room }) => {
|
|
1226
1285
|
var _a;
|
|
1227
1286
|
const origin = data == null ? void 0 : data.origin;
|
|
1228
1287
|
const update = (_a = data == null ? void 0 : data.update) != null ? _a : null;
|
|
@@ -1230,113 +1289,72 @@ var PluvServer = class {
|
|
|
1230
1289
|
const updated = update === null ? doc : doc.applyEncodedState({ update });
|
|
1231
1290
|
const encodedState = updated.getEncodedState();
|
|
1232
1291
|
const storageSize = new TextEncoder().encode(encodedState).length;
|
|
1233
|
-
if (!!this.
|
|
1292
|
+
if (!!this._config.limits.storageMaxSize && storageSize > this._config.limits.storageMaxSize) {
|
|
1234
1293
|
throw new Error("Storage has exceeded the size limit");
|
|
1235
1294
|
}
|
|
1236
|
-
|
|
1237
|
-
|
|
1295
|
+
platform.persistence.setStorageState(room, encodedState).then(() => {
|
|
1296
|
+
listeners.onStorageUpdated({
|
|
1238
1297
|
context,
|
|
1239
1298
|
encodedState,
|
|
1299
|
+
platform,
|
|
1240
1300
|
room
|
|
1241
1301
|
});
|
|
1242
1302
|
});
|
|
1243
1303
|
return { $storageUpdated: { state: encodedState } };
|
|
1244
1304
|
})
|
|
1245
1305
|
});
|
|
1246
|
-
this._context = {};
|
|
1247
|
-
this._getInitialStorage = null;
|
|
1248
|
-
const {
|
|
1249
|
-
authorize: authorize2,
|
|
1250
|
-
context,
|
|
1251
|
-
crdt = noop2,
|
|
1252
|
-
debug = false,
|
|
1253
|
-
getInitialStorage,
|
|
1254
|
-
io,
|
|
1255
|
-
limits,
|
|
1256
|
-
platform,
|
|
1257
|
-
router = new PluvRouter({})
|
|
1258
|
-
} = options;
|
|
1259
|
-
const {
|
|
1260
|
-
onRoomDeleted,
|
|
1261
|
-
onRoomMessage,
|
|
1262
|
-
onStorageUpdated,
|
|
1263
|
-
onUserConnected,
|
|
1264
|
-
onUserDisconnected
|
|
1265
|
-
} = options;
|
|
1266
|
-
platform.validateConfig(options);
|
|
1267
|
-
this._crdt = crdt;
|
|
1268
|
-
this._debug = debug;
|
|
1269
|
-
this._io = io;
|
|
1270
|
-
this._limits = limits;
|
|
1271
|
-
this._platform = platform;
|
|
1272
|
-
this._router = router ? PluvRouter.merge(this._baseRouter, router) : this._baseRouter;
|
|
1273
|
-
if (authorize2) this._authorize = authorize2;
|
|
1274
|
-
if (context) this._context = context;
|
|
1275
|
-
if (getInitialStorage) this._getInitialStorage = getInitialStorage;
|
|
1276
|
-
this._listeners = {
|
|
1277
|
-
onRoomDeleted: (event) => onRoomDeleted == null ? void 0 : onRoomDeleted(event),
|
|
1278
|
-
onRoomMessage: (event) => onRoomMessage == null ? void 0 : onRoomMessage(event),
|
|
1279
|
-
onStorageUpdated: (event) => onStorageUpdated == null ? void 0 : onStorageUpdated(event),
|
|
1280
|
-
onUserConnected: (event) => onUserConnected == null ? void 0 : onUserConnected(event),
|
|
1281
|
-
onUserDisconnected: (event) => onUserDisconnected == null ? void 0 : onUserDisconnected(event)
|
|
1282
|
-
};
|
|
1283
|
-
}
|
|
1284
|
-
get fetch() {
|
|
1285
|
-
return (...args) => {
|
|
1286
|
-
if (!this._platform._fetch)
|
|
1287
|
-
throw new Error(`\`${this._platform._name}\` does not support \`fetch\``);
|
|
1288
|
-
return this._platform._fetch(...args);
|
|
1289
|
-
};
|
|
1290
|
-
}
|
|
1291
|
-
/**
|
|
1292
|
-
* @ignore
|
|
1293
|
-
* @readonly
|
|
1294
|
-
* @deprecated Internal use only. Changes to this will never be marked as breaking.
|
|
1295
|
-
*/
|
|
1296
|
-
get _defs() {
|
|
1297
|
-
return {
|
|
1298
|
-
authorize: this._authorize,
|
|
1299
|
-
context: this._context,
|
|
1300
|
-
events: this._router._defs.events,
|
|
1301
|
-
platform: this._platform
|
|
1302
|
-
};
|
|
1303
1306
|
}
|
|
1304
1307
|
get _procedure() {
|
|
1305
1308
|
return new PluvProcedure();
|
|
1306
1309
|
}
|
|
1310
|
+
get _router() {
|
|
1311
|
+
return this._config.router ? PluvRouter.merge(this._baseRouter, this._config.router) : this._baseRouter;
|
|
1312
|
+
}
|
|
1307
1313
|
createRoom(room, ...options) {
|
|
1308
1314
|
var _a, _c;
|
|
1309
1315
|
const _b = (_a = options[0]) != null ? _a : {}, { _meta, debug, onDestroy, onMessage } = _b, platformRoomContext = __objRest(_b, ["_meta", "debug", "onDestroy", "onMessage"]);
|
|
1310
|
-
|
|
1311
|
-
|
|
1316
|
+
const platform = this._config.platform();
|
|
1317
|
+
platform.validateConfig(this._config);
|
|
1318
|
+
if (platform._config.handleMode !== "io") {
|
|
1319
|
+
throw new Error(`\`createRoom\` is unsupported for \`${platform._name}\``);
|
|
1312
1320
|
}
|
|
1313
1321
|
if (!/^[a-z0-9](?:[a-z0-9-_]*[a-z0-9])?$/i.test(room))
|
|
1314
1322
|
throw new Error("Unsupported room name");
|
|
1315
1323
|
const roomContext = platformRoomContext;
|
|
1316
|
-
const context = typeof this.
|
|
1324
|
+
const context = typeof this._config.context === "function" ? this._config.context(roomContext) : this._config.context;
|
|
1325
|
+
const listeners = this._getListeners();
|
|
1326
|
+
const logDebug = this._logDebug.bind(this);
|
|
1317
1327
|
const newRoom = new IORoom(room, __spreadProps(__spreadValues({}, !!_meta ? { _meta } : {}), {
|
|
1318
|
-
authorize: (_c = this.
|
|
1328
|
+
authorize: (_c = this._config.authorize) != null ? _c : void 0,
|
|
1319
1329
|
context,
|
|
1320
|
-
crdt: this.
|
|
1321
|
-
debug: debug != null ? debug : this.
|
|
1322
|
-
onDestroy
|
|
1323
|
-
this
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1330
|
+
crdt: this._config.crdt,
|
|
1331
|
+
debug: debug != null ? debug : this._config.debug,
|
|
1332
|
+
onDestroy(event) {
|
|
1333
|
+
return __async(this, null, function* () {
|
|
1334
|
+
logDebug(`${colors2.blue("Deleting empty room:")} ${room}`);
|
|
1335
|
+
yield Promise.resolve(onDestroy == null ? void 0 : onDestroy(event));
|
|
1336
|
+
yield Promise.resolve(listeners.onRoomDeleted(event));
|
|
1337
|
+
yield event.platform.persistence.deleteStorageState(room);
|
|
1338
|
+
logDebug(`${colors2.blue("Deleted room:")} ${room}`);
|
|
1339
|
+
});
|
|
1340
|
+
},
|
|
1341
|
+
onMessage(event) {
|
|
1342
|
+
return __async(this, null, function* () {
|
|
1343
|
+
yield Promise.resolve(onMessage == null ? void 0 : onMessage(event));
|
|
1344
|
+
yield Promise.resolve(listeners.onRoomMessage(event));
|
|
1345
|
+
});
|
|
1346
|
+
},
|
|
1347
|
+
onUserConnected(event) {
|
|
1348
|
+
return __async(this, null, function* () {
|
|
1349
|
+
yield Promise.resolve(listeners.onUserConnected(event));
|
|
1350
|
+
});
|
|
1351
|
+
},
|
|
1352
|
+
onUserDisconnected(event) {
|
|
1353
|
+
return __async(this, null, function* () {
|
|
1354
|
+
yield Promise.resolve(listeners.onUserDisconnected(event));
|
|
1355
|
+
});
|
|
1356
|
+
},
|
|
1357
|
+
platform,
|
|
1340
1358
|
roomContext,
|
|
1341
1359
|
router: this._router
|
|
1342
1360
|
}));
|
|
@@ -1345,14 +1363,14 @@ var PluvServer = class {
|
|
|
1345
1363
|
}
|
|
1346
1364
|
createToken(params) {
|
|
1347
1365
|
return __async(this, null, function* () {
|
|
1348
|
-
return yield this.
|
|
1366
|
+
return yield this._config.io.createToken(params);
|
|
1349
1367
|
});
|
|
1350
1368
|
}
|
|
1351
1369
|
_getListeners() {
|
|
1352
1370
|
return this._listeners;
|
|
1353
1371
|
}
|
|
1354
1372
|
_logDebug(...data) {
|
|
1355
|
-
if (this.
|
|
1373
|
+
if (this._config.debug) console.log(...data);
|
|
1356
1374
|
}
|
|
1357
1375
|
};
|
|
1358
1376
|
|
|
@@ -1397,10 +1415,13 @@ var PluvIO = class {
|
|
|
1397
1415
|
`createToken called with large payload. User must be at most 512 bytes. Current size: ${bytes.toLocaleString()}`
|
|
1398
1416
|
);
|
|
1399
1417
|
}
|
|
1400
|
-
|
|
1418
|
+
const platform = this._platform();
|
|
1419
|
+
if (platform._createToken) {
|
|
1420
|
+
return yield platform._createToken(__spreadProps(__spreadValues({}, params), { authorize: ioAuthorize }));
|
|
1421
|
+
}
|
|
1401
1422
|
const secret = (_a = ioAuthorize == null ? void 0 : ioAuthorize.secret) != null ? _a : null;
|
|
1402
1423
|
if (!secret) throw new Error("`authorize` was specified without a valid secret");
|
|
1403
|
-
return yield authorize({ platform
|
|
1424
|
+
return yield authorize({ platform, secret }).encode(
|
|
1404
1425
|
params
|
|
1405
1426
|
);
|
|
1406
1427
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluv/io",
|
|
3
|
-
"version": "2.1
|
|
3
|
+
"version": "2.2.1",
|
|
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.10.0",
|
|
22
22
|
"kleur": "^4.1.5",
|
|
23
23
|
"wonka": "^6.3.5",
|
|
24
|
-
"@pluv/crdt": "^2.1
|
|
25
|
-
"@pluv/types": "^2.1
|
|
24
|
+
"@pluv/crdt": "^2.2.1",
|
|
25
|
+
"@pluv/types": "^2.2.1"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"eslint": "^9.26.0",
|
|
29
29
|
"genversion": "^3.2.0",
|
|
30
30
|
"tsup": "^8.4.0",
|
|
31
31
|
"typescript": "^5.8.3",
|
|
32
|
-
"@pluv/tsconfig": "^2.1
|
|
33
|
-
"eslint-config-pluv": "^2.1
|
|
32
|
+
"@pluv/tsconfig": "^2.2.1",
|
|
33
|
+
"eslint-config-pluv": "^2.2.1"
|
|
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,10 +1,11 @@
|
|
|
1
|
+
import type { Maybe } from "@pluv/types";
|
|
1
2
|
import type { AbstractPersistence } from "./AbstractPersistence";
|
|
2
3
|
import type { AbstractPubSub } from "./AbstractPubSub";
|
|
3
4
|
import type { AbstractWebSocket, InferWebSocketSource } from "./AbstractWebSocket";
|
|
4
5
|
import type { JWTEncodeParams } from "./authorize";
|
|
5
6
|
import { Persistence } from "./Persistence";
|
|
6
7
|
import { PubSub } from "./PubSub";
|
|
7
|
-
import type { PlatformConfig, WebSocketSerializedState } from "./types";
|
|
8
|
+
import type { PlatformConfig, ResolvedPluvIOAuthorize, WebSocketSerializedState } from "./types";
|
|
8
9
|
|
|
9
10
|
export type InferPlatformWebSocketType<TPlatform extends AbstractPlatform> =
|
|
10
11
|
TPlatform extends AbstractPlatform<infer IAbstractWebSocket> ? IAbstractWebSocket : never;
|
|
@@ -44,7 +45,11 @@ export abstract class AbstractPlatform<
|
|
|
44
45
|
public persistence: AbstractPersistence;
|
|
45
46
|
public pubSub: AbstractPubSub;
|
|
46
47
|
|
|
47
|
-
public readonly _createToken?: (
|
|
48
|
+
public readonly _createToken?: (
|
|
49
|
+
params: JWTEncodeParams<any, any> & {
|
|
50
|
+
authorize: Maybe<ResolvedPluvIOAuthorize<any, any>>;
|
|
51
|
+
},
|
|
52
|
+
) => Promise<string>;
|
|
48
53
|
public _fetch?: (...args: any[]) => Promise<any>;
|
|
49
54
|
public abstract readonly _config: TConfig;
|
|
50
55
|
public abstract readonly _name: string;
|
package/src/IORoom.ts
CHANGED
|
@@ -60,7 +60,7 @@ export interface IORoomListeners<
|
|
|
60
60
|
TContext extends Record<string, any>,
|
|
61
61
|
TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>,
|
|
62
62
|
> {
|
|
63
|
-
onDestroy: (event: IORoomListenerEvent<TContext>) => void;
|
|
63
|
+
onDestroy: (event: IORoomListenerEvent<TPlatform, TContext>) => void;
|
|
64
64
|
onMessage: (event: IORoomMessageEvent<TPlatform, TAuthorize, TContext, TEvents>) => void;
|
|
65
65
|
onUserConnected: (event: IOUserConnectedEvent<TPlatform, TAuthorize, TContext>) => void;
|
|
66
66
|
onUserDisconnected: (event: IOUserDisconnectedEvent<TPlatform, TAuthorize, TContext>) => void;
|
|
@@ -87,7 +87,7 @@ export type IORoomConfig<
|
|
|
87
87
|
> = Partial<IORoomListeners<TPlatform, TAuthorize, TContext, TEvents>> & {
|
|
88
88
|
authorize?: TAuthorize;
|
|
89
89
|
context: TContext;
|
|
90
|
-
crdt?: { doc: (value: any) => AbstractCrdtDocFactory<any> };
|
|
90
|
+
crdt?: { doc: (value: any) => AbstractCrdtDocFactory<any, any> };
|
|
91
91
|
debug: boolean;
|
|
92
92
|
platform: TPlatform;
|
|
93
93
|
roomContext: InferRoomContextType<TPlatform>;
|
|
@@ -124,14 +124,14 @@ export class IORoom<
|
|
|
124
124
|
{
|
|
125
125
|
public readonly id: string;
|
|
126
126
|
|
|
127
|
-
private _doc: Promise<CrdtDocLike<any>>;
|
|
127
|
+
private _doc: Promise<CrdtDocLike<any, any>>;
|
|
128
128
|
private _lastGarbageCollectMs: number = -1 * (GARBAGE_COLLECT_INTERVAL_MS + 1);
|
|
129
129
|
private _uninitialize: Promise<() => Promise<void>> | null = null;
|
|
130
130
|
|
|
131
131
|
private readonly _authorize: TAuthorize = null as TAuthorize;
|
|
132
132
|
private readonly _context: TContext;
|
|
133
133
|
private readonly _debug: boolean;
|
|
134
|
-
private readonly _docFactory: AbstractCrdtDocFactory<any>;
|
|
134
|
+
private readonly _docFactory: AbstractCrdtDocFactory<any, any>;
|
|
135
135
|
private readonly _listeners: IORoomListeners<TPlatform, TAuthorize, TContext, TEvents>;
|
|
136
136
|
private readonly _platform: TPlatform;
|
|
137
137
|
private readonly _router: PluvRouter<TPlatform, TAuthorize, TContext, TEvents>;
|
|
@@ -472,6 +472,7 @@ export class IORoom<
|
|
|
472
472
|
this._listeners.onUserDisconnected({
|
|
473
473
|
context: this._context,
|
|
474
474
|
encodedState,
|
|
475
|
+
platform: this._platform,
|
|
475
476
|
room: this.id,
|
|
476
477
|
user,
|
|
477
478
|
}),
|
|
@@ -538,6 +539,7 @@ export class IORoom<
|
|
|
538
539
|
this._listeners.onUserConnected({
|
|
539
540
|
context: this._context,
|
|
540
541
|
encodedState,
|
|
542
|
+
platform: this._platform,
|
|
541
543
|
room: this.id,
|
|
542
544
|
user,
|
|
543
545
|
webSocket: pluvWs.webSocket,
|
|
@@ -626,7 +628,7 @@ export class IORoom<
|
|
|
626
628
|
}
|
|
627
629
|
}
|
|
628
630
|
|
|
629
|
-
private async _getInitialDoc(): Promise<CrdtDocLike<any>> {
|
|
631
|
+
private async _getInitialDoc(): Promise<CrdtDocLike<any, any>> {
|
|
630
632
|
const doc = this._docFactory.getEmpty();
|
|
631
633
|
const encodedState = await this._platform.persistence.getStorageState(this.id);
|
|
632
634
|
|
|
@@ -769,6 +771,7 @@ export class IORoom<
|
|
|
769
771
|
: {}),
|
|
770
772
|
context: this._context,
|
|
771
773
|
encodedState,
|
|
774
|
+
platform: this._platform,
|
|
772
775
|
room: this.id,
|
|
773
776
|
}),
|
|
774
777
|
);
|
|
@@ -825,6 +828,7 @@ export class IORoom<
|
|
|
825
828
|
garbageCollect: async () => {
|
|
826
829
|
await this.garbageCollect();
|
|
827
830
|
},
|
|
831
|
+
platform: this._platform,
|
|
828
832
|
get presence() {
|
|
829
833
|
return session.presence as JsonObject | null;
|
|
830
834
|
},
|
|
@@ -864,6 +868,7 @@ export class IORoom<
|
|
|
864
868
|
InferEventsOutput<TEvents>,
|
|
865
869
|
keyof InferEventsOutput<TEvents>
|
|
866
870
|
>,
|
|
871
|
+
platform: this._platform,
|
|
867
872
|
room: this.id,
|
|
868
873
|
user: session.user,
|
|
869
874
|
webSocket: session.webSocket.webSocket,
|
|
@@ -1105,6 +1110,7 @@ export class IORoom<
|
|
|
1105
1110
|
garbageCollect: async () => {
|
|
1106
1111
|
await this.garbageCollect();
|
|
1107
1112
|
},
|
|
1113
|
+
platform: this._platform,
|
|
1108
1114
|
get presence() {
|
|
1109
1115
|
return null;
|
|
1110
1116
|
},
|
package/src/PluvIO.ts
CHANGED
|
@@ -37,7 +37,7 @@ export type PluvIOConfig<
|
|
|
37
37
|
crdt?: CrdtLibraryType;
|
|
38
38
|
debug?: boolean;
|
|
39
39
|
limits?: PluvIOLimits;
|
|
40
|
-
platform: TPlatform;
|
|
40
|
+
platform: () => TPlatform;
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
type ResolvedServerConfig<
|
|
@@ -90,10 +90,10 @@ export class PluvIO<
|
|
|
90
90
|
TPlatform,
|
|
91
91
|
TContext
|
|
92
92
|
>;
|
|
93
|
-
private readonly _crdt: { doc: (value: any) => AbstractCrdtDocFactory<any> };
|
|
93
|
+
private readonly _crdt: { doc: (value: any) => AbstractCrdtDocFactory<any, any> };
|
|
94
94
|
private readonly _debug: boolean;
|
|
95
95
|
private readonly _limits: PluvIOLimits;
|
|
96
|
-
private readonly _platform: TPlatform;
|
|
96
|
+
private readonly _platform: () => TPlatform;
|
|
97
97
|
|
|
98
98
|
public get procedure(): PluvProcedure<TPlatform, TAuthorize, TContext, {}, {}> {
|
|
99
99
|
return new PluvProcedure();
|
|
@@ -141,19 +141,23 @@ export class PluvIO<
|
|
|
141
141
|
);
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
const platform = this._platform();
|
|
145
|
+
|
|
144
146
|
/**
|
|
145
147
|
* !HACK
|
|
146
148
|
* @description Allow the platform to overwrite this behavior as needed. This is introduced
|
|
147
149
|
* to support platformPluv
|
|
148
150
|
* @date December 15, 2024
|
|
149
151
|
*/
|
|
150
|
-
if (
|
|
152
|
+
if (platform._createToken) {
|
|
153
|
+
return await platform._createToken({ ...params, authorize: ioAuthorize });
|
|
154
|
+
}
|
|
151
155
|
|
|
152
156
|
const secret = ioAuthorize?.secret ?? null;
|
|
153
157
|
|
|
154
158
|
if (!secret) throw new Error("`authorize` was specified without a valid secret");
|
|
155
159
|
|
|
156
|
-
return await authorize({ platform
|
|
160
|
+
return await authorize({ platform, secret }).encode(
|
|
157
161
|
params as JWTEncodeParams<any, TPlatform>,
|
|
158
162
|
);
|
|
159
163
|
}
|