@eleven-am/pondsocket-nest 0.0.136 → 0.0.138
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/README.md +141 -541
- package/dist/context/context.d.ts +41 -0
- package/dist/context/context.js +238 -0
- package/{decorators → dist/decorators}/onConnectionRequest.js +2 -2
- package/{decorators → dist/decorators}/onEvent.js +2 -2
- package/{decorators → dist/decorators}/onJoinRequest.js +2 -2
- package/{decorators → dist/decorators}/onLeave.js +3 -4
- package/{decorators → dist/decorators}/onOutgoingEvent.js +10 -2
- package/{helpers → dist/helpers}/createParamDecorator.js +4 -3
- package/{helpers → dist/helpers}/misc.d.ts +1 -1
- package/dist/helpers/misc.js +27 -0
- package/dist/index.d.ts +6 -0
- package/{index.js → dist/index.js} +1 -0
- package/dist/managers/outgoingEvent.d.ts +5 -0
- package/{modules → dist/modules}/pondSocket.js +4 -5
- package/dist/performers/action.d.ts +8 -0
- package/dist/performers/action.js +121 -0
- package/dist/performers/errors.d.ts +4 -0
- package/dist/performers/errors.js +43 -0
- package/dist/performers/response.d.ts +5 -0
- package/dist/performers/response.js +65 -0
- package/{services → dist/services}/pondSocket.d.ts +12 -4
- package/dist/services/pondSocket.js +288 -0
- package/dist/types.d.ts +113 -0
- package/package.json +57 -46
- package/context/context.d.ts +0 -27
- package/context/context.js +0 -103
- package/helpers/misc.js +0 -13
- package/index.d.ts +0 -5
- package/managers/outgoingEvent.d.ts +0 -5
- package/performers/action.d.ts +0 -5
- package/performers/action.js +0 -89
- package/performers/errors.d.ts +0 -2
- package/performers/errors.js +0 -37
- package/performers/narrow.d.ts +0 -7
- package/performers/narrow.js +0 -21
- package/performers/response.d.ts +0 -3
- package/performers/response.js +0 -62
- package/services/pondSocket.js +0 -190
- package/types.d.ts +0 -64
- /package/{constants.d.ts → dist/constants.d.ts} +0 -0
- /package/{constants.js → dist/constants.js} +0 -0
- /package/{decorators → dist/decorators}/channel.d.ts +0 -0
- /package/{decorators → dist/decorators}/channel.js +0 -0
- /package/{decorators → dist/decorators}/channelInstance.d.ts +0 -0
- /package/{decorators → dist/decorators}/channelInstance.js +0 -0
- /package/{decorators → dist/decorators}/endpoint.d.ts +0 -0
- /package/{decorators → dist/decorators}/endpoint.js +0 -0
- /package/{decorators → dist/decorators}/endpointInstance.d.ts +0 -0
- /package/{decorators → dist/decorators}/endpointInstance.js +0 -0
- /package/{decorators → dist/decorators}/getChannel.d.ts +0 -0
- /package/{decorators → dist/decorators}/getChannel.js +0 -0
- /package/{decorators → dist/decorators}/getConnectionContext.d.ts +0 -0
- /package/{decorators → dist/decorators}/getConnectionContext.js +0 -0
- /package/{decorators → dist/decorators}/getConnectionHeaders.d.ts +0 -0
- /package/{decorators → dist/decorators}/getConnectionHeaders.js +0 -0
- /package/{decorators → dist/decorators}/getContext.d.ts +0 -0
- /package/{decorators → dist/decorators}/getContext.js +0 -0
- /package/{decorators → dist/decorators}/getEventContext.d.ts +0 -0
- /package/{decorators → dist/decorators}/getEventContext.js +0 -0
- /package/{decorators → dist/decorators}/getEventParams.d.ts +0 -0
- /package/{decorators → dist/decorators}/getEventParams.js +0 -0
- /package/{decorators → dist/decorators}/getEventPayload.d.ts +0 -0
- /package/{decorators → dist/decorators}/getEventPayload.js +0 -0
- /package/{decorators → dist/decorators}/getEventQuery.d.ts +0 -0
- /package/{decorators → dist/decorators}/getEventQuery.js +0 -0
- /package/{decorators → dist/decorators}/getJoinContext.d.ts +0 -0
- /package/{decorators → dist/decorators}/getJoinContext.js +0 -0
- /package/{decorators → dist/decorators}/getJoinParams.d.ts +0 -0
- /package/{decorators → dist/decorators}/getJoinParams.js +0 -0
- /package/{decorators → dist/decorators}/getLeaveEvent.d.ts +0 -0
- /package/{decorators → dist/decorators}/getLeaveEvent.js +0 -0
- /package/{decorators → dist/decorators}/getUserAssigns.d.ts +0 -0
- /package/{decorators → dist/decorators}/getUserAssigns.js +0 -0
- /package/{decorators → dist/decorators}/getUserData.d.ts +0 -0
- /package/{decorators → dist/decorators}/getUserData.js +0 -0
- /package/{decorators → dist/decorators}/getUserPresence.d.ts +0 -0
- /package/{decorators → dist/decorators}/getUserPresence.js +0 -0
- /package/{decorators → dist/decorators}/index.d.ts +0 -0
- /package/{decorators → dist/decorators}/index.js +0 -0
- /package/{decorators → dist/decorators}/onConnectionRequest.d.ts +0 -0
- /package/{decorators → dist/decorators}/onEvent.d.ts +0 -0
- /package/{decorators → dist/decorators}/onJoinRequest.d.ts +0 -0
- /package/{decorators → dist/decorators}/onLeave.d.ts +0 -0
- /package/{decorators → dist/decorators}/onOutgoingEvent.d.ts +0 -0
- /package/{decorators → dist/decorators}/useGuards.d.ts +0 -0
- /package/{decorators → dist/decorators}/useGuards.js +0 -0
- /package/{decorators → dist/decorators}/usePipes.d.ts +0 -0
- /package/{decorators → dist/decorators}/usePipes.js +0 -0
- /package/{helpers → dist/helpers}/createContextParamDecorator.d.ts +0 -0
- /package/{helpers → dist/helpers}/createContextParamDecorator.js +0 -0
- /package/{helpers → dist/helpers}/createParamDecorator.d.ts +0 -0
- /package/{managers → dist/managers}/channel.d.ts +0 -0
- /package/{managers → dist/managers}/channel.js +0 -0
- /package/{managers → dist/managers}/channelInstance.d.ts +0 -0
- /package/{managers → dist/managers}/channelInstance.js +0 -0
- /package/{managers → dist/managers}/class.d.ts +0 -0
- /package/{managers → dist/managers}/class.js +0 -0
- /package/{managers → dist/managers}/connection.d.ts +0 -0
- /package/{managers → dist/managers}/connection.js +0 -0
- /package/{managers → dist/managers}/createMetadataManager.d.ts +0 -0
- /package/{managers → dist/managers}/createMetadataManager.js +0 -0
- /package/{managers → dist/managers}/endpoint.d.ts +0 -0
- /package/{managers → dist/managers}/endpoint.js +0 -0
- /package/{managers → dist/managers}/endpointInstance.d.ts +0 -0
- /package/{managers → dist/managers}/endpointInstance.js +0 -0
- /package/{managers → dist/managers}/event.d.ts +0 -0
- /package/{managers → dist/managers}/event.js +0 -0
- /package/{managers → dist/managers}/guards.d.ts +0 -0
- /package/{managers → dist/managers}/guards.js +0 -0
- /package/{managers → dist/managers}/handlers.d.ts +0 -0
- /package/{managers → dist/managers}/handlers.js +0 -0
- /package/{managers → dist/managers}/join.d.ts +0 -0
- /package/{managers → dist/managers}/join.js +0 -0
- /package/{managers → dist/managers}/leave.d.ts +0 -0
- /package/{managers → dist/managers}/leave.js +0 -0
- /package/{managers → dist/managers}/method.d.ts +0 -0
- /package/{managers → dist/managers}/method.js +0 -0
- /package/{managers → dist/managers}/outgoingEvent.js +0 -0
- /package/{managers → dist/managers}/parametres.d.ts +0 -0
- /package/{managers → dist/managers}/parametres.js +0 -0
- /package/{managers → dist/managers}/pipes.d.ts +0 -0
- /package/{managers → dist/managers}/pipes.js +0 -0
- /package/{managers → dist/managers}/property.d.ts +0 -0
- /package/{managers → dist/managers}/property.js +0 -0
- /package/{modules → dist/modules}/pondSocket.d.ts +0 -0
- /package/{types.js → dist/types.js} +0 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.performErrors = performErrors;
|
|
4
|
+
exports.logHandlerError = logHandlerError;
|
|
5
|
+
const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
|
|
6
|
+
const common_1 = require("@nestjs/common");
|
|
7
|
+
const logger = new common_1.Logger('PondSocketHandler');
|
|
8
|
+
function performErrors(error, response, lifecycle) {
|
|
9
|
+
var _a;
|
|
10
|
+
let message;
|
|
11
|
+
let data;
|
|
12
|
+
let status;
|
|
13
|
+
if (error instanceof common_1.HttpException) {
|
|
14
|
+
message = error.message;
|
|
15
|
+
status = error.getStatus();
|
|
16
|
+
data = (_a = error.getResponse()) === null || _a === void 0 ? void 0 : _a.message;
|
|
17
|
+
}
|
|
18
|
+
else if (error instanceof Error) {
|
|
19
|
+
message = error.message;
|
|
20
|
+
status = 500;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
message = 'An unknown error occurred';
|
|
24
|
+
status = 500;
|
|
25
|
+
}
|
|
26
|
+
logger.error(message, error instanceof Error ? error.stack : undefined);
|
|
27
|
+
if (lifecycle === 'event') {
|
|
28
|
+
return response.reply(pondsocket_common_1.ErrorTypes.INTERNAL_SERVER_ERROR, {
|
|
29
|
+
code: pondsocket_common_1.ErrorTypes.INTERNAL_SERVER_ERROR,
|
|
30
|
+
message,
|
|
31
|
+
data,
|
|
32
|
+
status,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
const pendingResponse = response;
|
|
36
|
+
if (!pendingResponse.hasResponded) {
|
|
37
|
+
return pendingResponse.decline(message, status);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function logHandlerError(error, lifecycle, propertyKey) {
|
|
41
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
42
|
+
logger.error(`Error in ${lifecycle} handler "${String(propertyKey)}": ${message}`, error instanceof Error ? error.stack : undefined);
|
|
43
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Channel, ConnectionContext, EventContext, JoinContext, LeaveEvent } from '@eleven-am/pondsocket/types';
|
|
2
|
+
import { PondLifecycle, PondResponse } from '../types';
|
|
3
|
+
type ResponseContext = JoinContext<string> | EventContext<string> | ConnectionContext<string> | LeaveEvent;
|
|
4
|
+
export declare function performResponse(socketId: string, channel: Channel | null, data: PondResponse | null | undefined, context: ResponseContext, lifecycle: Exclude<PondLifecycle, 'outgoing'>): void;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.performResponse = performResponse;
|
|
15
|
+
const pondsocket_common_1 = require("@eleven-am/pondsocket-common");
|
|
16
|
+
function isNotEmpty(value) {
|
|
17
|
+
if (value === null || value === undefined) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
if (typeof value === 'object') {
|
|
21
|
+
return Object.keys(value).length !== 0;
|
|
22
|
+
}
|
|
23
|
+
return value !== '';
|
|
24
|
+
}
|
|
25
|
+
function performResponse(socketId, channel, data, context, lifecycle) {
|
|
26
|
+
if (lifecycle === 'leave' || !isNotEmpty(data)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if ((lifecycle === 'join' || lifecycle === 'connection') && context.hasResponded) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const { event, eventParams, presence, assigns, broadcast, broadcastFrom, broadcastTo, decline, payload: explicitPayload } = data, legacyPayload = __rest(data, ["event", "eventParams", "presence", "assigns", "broadcast", "broadcastFrom", "broadcastTo", "decline", "payload"]);
|
|
33
|
+
const responseContext = context;
|
|
34
|
+
if (decline && (lifecycle === 'join' || lifecycle === 'connection')) {
|
|
35
|
+
const options = typeof decline === 'string' ? { message: decline } : decline;
|
|
36
|
+
responseContext.decline(options.message, options.status);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (assigns !== undefined) {
|
|
40
|
+
responseContext.assign(assigns);
|
|
41
|
+
}
|
|
42
|
+
if (lifecycle === 'connection' || lifecycle === 'join') {
|
|
43
|
+
responseContext.accept();
|
|
44
|
+
}
|
|
45
|
+
const payload = explicitPayload !== null && explicitPayload !== void 0 ? explicitPayload : (isNotEmpty(legacyPayload) ? legacyPayload : {});
|
|
46
|
+
if (event) {
|
|
47
|
+
responseContext.reply(eventParams ? (0, pondsocket_common_1.buildPondRoute)(event, eventParams) : event, payload);
|
|
48
|
+
}
|
|
49
|
+
if (lifecycle === 'join' || lifecycle === 'event') {
|
|
50
|
+
const channelContext = responseContext;
|
|
51
|
+
if (broadcast) {
|
|
52
|
+
channelContext.broadcast(eventParams ? (0, pondsocket_common_1.buildPondRoute)(broadcast, eventParams) : broadcast, payload);
|
|
53
|
+
}
|
|
54
|
+
if (broadcastFrom) {
|
|
55
|
+
channelContext.broadcastFrom(eventParams ? (0, pondsocket_common_1.buildPondRoute)(broadcastFrom, eventParams) : broadcastFrom, payload);
|
|
56
|
+
}
|
|
57
|
+
if (broadcastTo) {
|
|
58
|
+
const broadcastEvent = eventParams ? (0, pondsocket_common_1.buildPondRoute)(broadcastTo.event, eventParams) : broadcastTo.event;
|
|
59
|
+
channelContext.broadcastTo(broadcastEvent, payload, broadcastTo.users);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (channel && presence !== undefined) {
|
|
63
|
+
channel.upsertPresence(socketId, presence);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { PondSocket } from '@eleven-am/pondsocket';
|
|
1
2
|
import type { IDistributedBackend } from '@eleven-am/pondsocket/types';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { HttpAdapterHost, ModuleRef } from '@nestjs/core';
|
|
3
|
+
import { OnModuleDestroy, OnModuleInit, PipeTransform } from '@nestjs/common';
|
|
4
|
+
import { DiscoveryService, HttpAdapterHost, ModuleRef } from '@nestjs/core';
|
|
5
5
|
import { CanActivate, Constructor } from '../types';
|
|
6
6
|
export declare class PondSocketService implements OnModuleInit, OnModuleDestroy {
|
|
7
7
|
private readonly moduleRef;
|
|
@@ -16,9 +16,17 @@ export declare class PondSocketService implements OnModuleInit, OnModuleDestroy
|
|
|
16
16
|
private readonly logger;
|
|
17
17
|
private socket;
|
|
18
18
|
constructor(moduleRef: ModuleRef, discovery: DiscoveryService, adapterHost: HttpAdapterHost, globalGuards: Constructor<CanActivate>[], globalPipes: Constructor<PipeTransform>[], isExclusiveSocketServer: boolean, distributedBackend?: IDistributedBackend | undefined, maxMessageSize?: number | undefined, heartbeatInterval?: number | undefined);
|
|
19
|
+
get pondSocket(): PondSocket | null;
|
|
20
|
+
isHealthy(): boolean;
|
|
19
21
|
onModuleInit(): Promise<void>;
|
|
20
|
-
onModuleDestroy(): void
|
|
22
|
+
onModuleDestroy(): Promise<void>;
|
|
21
23
|
private manageEndpoint;
|
|
22
24
|
private manageChannel;
|
|
25
|
+
private getDefinitionHandlers;
|
|
26
|
+
private getSingleHandler;
|
|
27
|
+
private assertUniquePaths;
|
|
28
|
+
private getEndpointRegistration;
|
|
29
|
+
private getChannelRegistration;
|
|
30
|
+
private getProviders;
|
|
23
31
|
private getGroupedInstances;
|
|
24
32
|
}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.PondSocketService = void 0;
|
|
13
|
+
const pondsocket_1 = require("@eleven-am/pondsocket");
|
|
14
|
+
const common_1 = require("@nestjs/common");
|
|
15
|
+
const channel_1 = require("../managers/channel");
|
|
16
|
+
const channelInstance_1 = require("../managers/channelInstance");
|
|
17
|
+
const connection_1 = require("../managers/connection");
|
|
18
|
+
const endpoint_1 = require("../managers/endpoint");
|
|
19
|
+
const endpointInstance_1 = require("../managers/endpointInstance");
|
|
20
|
+
const event_1 = require("../managers/event");
|
|
21
|
+
const join_1 = require("../managers/join");
|
|
22
|
+
const leave_1 = require("../managers/leave");
|
|
23
|
+
const outgoingEvent_1 = require("../managers/outgoingEvent");
|
|
24
|
+
const action_1 = require("../performers/action");
|
|
25
|
+
const errors_1 = require("../performers/errors");
|
|
26
|
+
class PondSocketService {
|
|
27
|
+
constructor(moduleRef, discovery, adapterHost, globalGuards, globalPipes, isExclusiveSocketServer, distributedBackend, maxMessageSize, heartbeatInterval) {
|
|
28
|
+
this.moduleRef = moduleRef;
|
|
29
|
+
this.discovery = discovery;
|
|
30
|
+
this.adapterHost = adapterHost;
|
|
31
|
+
this.globalGuards = globalGuards;
|
|
32
|
+
this.globalPipes = globalPipes;
|
|
33
|
+
this.isExclusiveSocketServer = isExclusiveSocketServer;
|
|
34
|
+
this.distributedBackend = distributedBackend;
|
|
35
|
+
this.maxMessageSize = maxMessageSize;
|
|
36
|
+
this.heartbeatInterval = heartbeatInterval;
|
|
37
|
+
this.logger = new common_1.Logger(PondSocketService.name);
|
|
38
|
+
this.socket = null;
|
|
39
|
+
}
|
|
40
|
+
get pondSocket() {
|
|
41
|
+
return this.socket;
|
|
42
|
+
}
|
|
43
|
+
isHealthy() {
|
|
44
|
+
var _a, _b;
|
|
45
|
+
return (_b = (_a = this.socket) === null || _a === void 0 ? void 0 : _a.isHealthy()) !== null && _b !== void 0 ? _b : false;
|
|
46
|
+
}
|
|
47
|
+
onModuleInit() {
|
|
48
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
+
const instances = this.getGroupedInstances();
|
|
50
|
+
this.socket = new pondsocket_1.PondSocket({
|
|
51
|
+
server: this.adapterHost.httpAdapter.getHttpServer(),
|
|
52
|
+
closeHttpServerOnShutdown: false,
|
|
53
|
+
exclusiveServer: this.isExclusiveSocketServer,
|
|
54
|
+
distributedBackend: this.distributedBackend,
|
|
55
|
+
maxMessageSize: this.maxMessageSize,
|
|
56
|
+
heartbeatInterval: this.heartbeatInterval,
|
|
57
|
+
});
|
|
58
|
+
yield this.socket.ready();
|
|
59
|
+
instances.forEach((instance) => this.manageEndpoint(this.socket, instance));
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
onModuleDestroy() {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
const socket = this.socket;
|
|
65
|
+
this.socket = null;
|
|
66
|
+
yield (socket === null || socket === void 0 ? void 0 : socket.closeAsync());
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
manageEndpoint(socket, groupedInstance) {
|
|
70
|
+
const instance = groupedInstance.endpoint.instance;
|
|
71
|
+
const registration = this.getEndpointRegistration(groupedInstance.endpoint);
|
|
72
|
+
const { set: setEndpoint } = (0, endpointInstance_1.manageEndpointInstance)(instance);
|
|
73
|
+
if (!registration) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const handlers = [
|
|
77
|
+
...(0, connection_1.manageConnection)(instance).get(),
|
|
78
|
+
...this.getDefinitionHandlers(instance, registration, 'connection'),
|
|
79
|
+
];
|
|
80
|
+
const handler = this.getSingleHandler(handlers, 'connection', groupedInstance.endpoint.name);
|
|
81
|
+
const endpoint = socket.createEndpoint(registration, (context) => __awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
if (handler) {
|
|
83
|
+
yield handler.value(instance, this.moduleRef, this.globalGuards, this.globalPipes, context);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
context.accept();
|
|
87
|
+
}
|
|
88
|
+
}));
|
|
89
|
+
const endpointPath = typeof registration === 'string' ? registration : registration.path;
|
|
90
|
+
this.logger.log(`${groupedInstance.endpoint.name} {${endpointPath}}`);
|
|
91
|
+
if (handler) {
|
|
92
|
+
this.logger.log(`Mapped {${endpointPath}, CONNECTION}`);
|
|
93
|
+
}
|
|
94
|
+
setEndpoint(endpoint);
|
|
95
|
+
groupedInstance.channels.forEach((channel) => this.manageChannel(channel, endpoint, endpointPath));
|
|
96
|
+
}
|
|
97
|
+
manageChannel(provider, endpoint, endpointPath) {
|
|
98
|
+
const instance = provider.instance;
|
|
99
|
+
const registration = this.getChannelRegistration(provider);
|
|
100
|
+
if (!registration) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const { set: setChannel } = (0, channelInstance_1.manageChannelInstance)(instance);
|
|
104
|
+
const joinHandlers = [
|
|
105
|
+
...(0, join_1.manageJoin)(instance).get(),
|
|
106
|
+
...this.getDefinitionHandlers(instance, registration, 'join'),
|
|
107
|
+
];
|
|
108
|
+
const joinHandler = this.getSingleHandler(joinHandlers, 'join', provider.name);
|
|
109
|
+
const channelInstance = endpoint.createChannel(registration, (context) => __awaiter(this, void 0, void 0, function* () {
|
|
110
|
+
if (joinHandler) {
|
|
111
|
+
yield joinHandler.value(instance, this.moduleRef, this.globalGuards, this.globalPipes, context);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
context.accept();
|
|
115
|
+
}
|
|
116
|
+
}));
|
|
117
|
+
const path = typeof registration === 'string' ? registration : registration.path;
|
|
118
|
+
const fullPath = `${endpointPath}/${path}`.replace(/\/+/g, '/');
|
|
119
|
+
this.logger.log(`${provider.name} {${fullPath}}`);
|
|
120
|
+
if (joinHandler) {
|
|
121
|
+
this.logger.log(`Mapped {${fullPath}, JOIN}`);
|
|
122
|
+
}
|
|
123
|
+
setChannel(channelInstance);
|
|
124
|
+
const eventHandlers = [
|
|
125
|
+
...(0, event_1.manageEvent)(instance).get(),
|
|
126
|
+
...this.getDefinitionHandlers(instance, registration, 'event'),
|
|
127
|
+
];
|
|
128
|
+
this.assertUniquePaths(eventHandlers, 'event', provider.name);
|
|
129
|
+
eventHandlers.forEach((handler) => {
|
|
130
|
+
channelInstance.onEvent(handler.path, (context) => __awaiter(this, void 0, void 0, function* () {
|
|
131
|
+
yield handler.value(instance, this.moduleRef, this.globalGuards, this.globalPipes, context);
|
|
132
|
+
}));
|
|
133
|
+
this.logger.log(`Mapped {${fullPath}/${handler.path}, EVENT}`);
|
|
134
|
+
});
|
|
135
|
+
const outgoingHandlers = [
|
|
136
|
+
...(0, outgoingEvent_1.manageOutgoingEvent)(instance).get(),
|
|
137
|
+
...this.getDefinitionHandlers(instance, registration, 'outgoing'),
|
|
138
|
+
];
|
|
139
|
+
this.assertUniquePaths(outgoingHandlers, 'outgoing event', provider.name);
|
|
140
|
+
outgoingHandlers.forEach((handler) => {
|
|
141
|
+
channelInstance.handleOutgoingEvent(handler.path, (context) => __awaiter(this, void 0, void 0, function* () {
|
|
142
|
+
yield handler.value(instance, this.moduleRef, this.globalGuards, this.globalPipes, context);
|
|
143
|
+
}));
|
|
144
|
+
this.logger.log(`Mapped {${fullPath}/${handler.path}, OUTGOING}`);
|
|
145
|
+
});
|
|
146
|
+
const leaveHandlers = [
|
|
147
|
+
...(0, leave_1.manageLeave)(instance).get(),
|
|
148
|
+
...this.getDefinitionHandlers(instance, registration, 'leave'),
|
|
149
|
+
];
|
|
150
|
+
const leaveHandler = this.getSingleHandler(leaveHandlers, 'leave', provider.name);
|
|
151
|
+
if (leaveHandler) {
|
|
152
|
+
channelInstance.onLeave((event) => leaveHandler.value(instance, this.moduleRef, this.globalGuards, this.globalPipes, event));
|
|
153
|
+
this.logger.log(`Mapped {${fullPath}, LEAVE}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
getDefinitionHandlers(instance, registration, lifecycle) {
|
|
157
|
+
var _a;
|
|
158
|
+
if (typeof registration === 'string') {
|
|
159
|
+
return [];
|
|
160
|
+
}
|
|
161
|
+
const definitions = (_a = (0, pondsocket_1.getPondMetadata)(instance, pondsocket_1.pondHandlerMetadataKey)) !== null && _a !== void 0 ? _a : [];
|
|
162
|
+
return definitions
|
|
163
|
+
.filter((definition) => definition.definition === registration && definition.lifecycle === lifecycle)
|
|
164
|
+
.map((definition) => {
|
|
165
|
+
var _a;
|
|
166
|
+
return ({
|
|
167
|
+
path: (_a = definition.event) !== null && _a !== void 0 ? _a : '',
|
|
168
|
+
value: (target, moduleRef, guards, pipes, input) => __awaiter(this, void 0, void 0, function* () {
|
|
169
|
+
const typedTarget = target;
|
|
170
|
+
const method = typedTarget[definition.propertyKey];
|
|
171
|
+
if (typeof method !== 'function') {
|
|
172
|
+
throw new Error(`${typedTarget.constructor.name}.${String(definition.propertyKey)} is not a method`);
|
|
173
|
+
}
|
|
174
|
+
try {
|
|
175
|
+
return yield (0, action_1.performAction)(typedTarget, moduleRef, guards, pipes, method, String(definition.propertyKey), input, lifecycle, definition.definition);
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
if (lifecycle === 'connection' || lifecycle === 'join' || lifecycle === 'event') {
|
|
179
|
+
return (0, errors_1.performErrors)(error, input, lifecycle);
|
|
180
|
+
}
|
|
181
|
+
(0, errors_1.logHandlerError)(error, lifecycle, definition.propertyKey);
|
|
182
|
+
if (lifecycle === 'outgoing') {
|
|
183
|
+
input.block();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}),
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
getSingleHandler(handlers, lifecycle, providerName) {
|
|
191
|
+
if (handlers.length > 1) {
|
|
192
|
+
throw new Error(`${providerName} declares multiple ${lifecycle} handlers; exactly one is allowed`);
|
|
193
|
+
}
|
|
194
|
+
return handlers[0];
|
|
195
|
+
}
|
|
196
|
+
assertUniquePaths(handlers, lifecycle, providerName) {
|
|
197
|
+
const paths = new Set();
|
|
198
|
+
handlers.forEach(({ path }) => {
|
|
199
|
+
if (paths.has(path)) {
|
|
200
|
+
throw new Error(`${providerName} declares duplicate ${lifecycle} handler "${path}"`);
|
|
201
|
+
}
|
|
202
|
+
paths.add(path);
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
getEndpointRegistration(provider) {
|
|
206
|
+
var _a;
|
|
207
|
+
const metadata = (0, pondsocket_1.getPondMetadata)(provider.metatype, pondsocket_1.pondEndpointMetadataKey);
|
|
208
|
+
return (_a = metadata === null || metadata === void 0 ? void 0 : metadata.definition) !== null && _a !== void 0 ? _a : (0, endpoint_1.manageEndpoint)(provider.metatype).get();
|
|
209
|
+
}
|
|
210
|
+
getChannelRegistration(provider) {
|
|
211
|
+
var _a;
|
|
212
|
+
const metadata = (0, pondsocket_1.getPondMetadata)(provider.metatype, pondsocket_1.pondChannelMetadataKey);
|
|
213
|
+
return (_a = metadata === null || metadata === void 0 ? void 0 : metadata.definition) !== null && _a !== void 0 ? _a : (0, channel_1.manageChannel)(provider.metatype).get();
|
|
214
|
+
}
|
|
215
|
+
getProviders() {
|
|
216
|
+
const wrappers = [...this.discovery.getProviders(), ...this.discovery.getControllers()];
|
|
217
|
+
const providers = new Map();
|
|
218
|
+
wrappers.forEach((wrapper) => {
|
|
219
|
+
var _a;
|
|
220
|
+
if (wrapper.instance && typeof wrapper.metatype === 'function') {
|
|
221
|
+
providers.set(wrapper.metatype, {
|
|
222
|
+
host: wrapper.host,
|
|
223
|
+
instance: wrapper.instance,
|
|
224
|
+
metatype: wrapper.metatype,
|
|
225
|
+
name: String((_a = wrapper.name) !== null && _a !== void 0 ? _a : wrapper.metatype.name),
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
return [...providers.values()];
|
|
230
|
+
}
|
|
231
|
+
getGroupedInstances() {
|
|
232
|
+
const providers = this.getProviders();
|
|
233
|
+
const endpoints = providers.filter((provider) => this.getEndpointRegistration(provider));
|
|
234
|
+
const channels = providers.filter((provider) => this.getChannelRegistration(provider));
|
|
235
|
+
if (channels.length > 0 && endpoints.length === 0) {
|
|
236
|
+
throw new Error('PondSocket channels were discovered, but no endpoint is registered');
|
|
237
|
+
}
|
|
238
|
+
const endpointByType = new Map(endpoints.map((endpoint) => [endpoint.metatype, endpoint]));
|
|
239
|
+
const grouped = new Map(endpoints.map((endpoint) => [endpoint, []]));
|
|
240
|
+
const endpointPaths = new Set();
|
|
241
|
+
endpoints.forEach((endpoint) => {
|
|
242
|
+
const registration = this.getEndpointRegistration(endpoint);
|
|
243
|
+
const path = typeof registration === 'string' ? registration : registration.path;
|
|
244
|
+
if (endpointPaths.has(path)) {
|
|
245
|
+
throw new Error(`Multiple PondSocket endpoints declare the path "${path}"`);
|
|
246
|
+
}
|
|
247
|
+
endpointPaths.add(path);
|
|
248
|
+
});
|
|
249
|
+
channels.forEach((channel) => {
|
|
250
|
+
const metadata = (0, pondsocket_1.getPondMetadata)(channel.metatype, pondsocket_1.pondChannelMetadataKey);
|
|
251
|
+
const reference = metadata === null || metadata === void 0 ? void 0 : metadata.options.endpoint;
|
|
252
|
+
let endpoint;
|
|
253
|
+
if (reference) {
|
|
254
|
+
let endpointType = reference;
|
|
255
|
+
if (!endpointByType.has(endpointType)) {
|
|
256
|
+
try {
|
|
257
|
+
endpointType = reference();
|
|
258
|
+
}
|
|
259
|
+
catch (_a) {
|
|
260
|
+
throw new Error(`${channel.name} references an invalid PondSocket endpoint`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
endpoint = endpointByType.get(endpointType);
|
|
264
|
+
if (!endpoint) {
|
|
265
|
+
throw new Error(`${channel.name} references endpoint ${endpointType.name}, but it is not registered as a Nest provider`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
else if (endpoints.length === 1) {
|
|
269
|
+
endpoint = endpoints[0];
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
const localEndpoints = endpoints.filter((candidate) => candidate.host === channel.host);
|
|
273
|
+
if (localEndpoints.length === 1) {
|
|
274
|
+
endpoint = localEndpoints[0];
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (!endpoint) {
|
|
278
|
+
throw new Error(`${channel.name} cannot be associated with an endpoint. Pass { endpoint: EndpointClass } to Channel().`);
|
|
279
|
+
}
|
|
280
|
+
grouped.get(endpoint).push(channel);
|
|
281
|
+
});
|
|
282
|
+
return [...grouped].map(([endpoint, groupedChannels]) => ({
|
|
283
|
+
endpoint,
|
|
284
|
+
channels: groupedChannels,
|
|
285
|
+
}));
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
exports.PondSocketService = PondSocketService;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { AnyPondChannelDefinition, AnyPondSchema, AssignsOf, ConnectionContext, EventContext as CoreEventContext, EventPayload, EventReplyPayload, EventsOf, IDistributedBackend, JoinContext as CoreJoinContext, LeaveEvent, OutgoingContext as CoreOutgoingContext, OutgoingPayload, PathOf, Params, PondAssigns, PondHandlerLifecycle, PondEndpointDefinition, PondMessage, PondPresence, PresenceOf, SchemaOf, ServerActions } from '@eleven-am/pondsocket/types';
|
|
2
|
+
import type { ModuleMetadata, PipeTransform, Type } from '@nestjs/common';
|
|
3
|
+
import type { ModuleRef } from '@nestjs/core';
|
|
4
|
+
import type { Context } from './context/context';
|
|
5
|
+
export interface NestContext<Schema extends AnyPondSchema = AnyPondSchema, Path extends string = string, EventName extends Extract<keyof EventsOf<Schema>, string> = Extract<keyof EventsOf<Schema>, string>> {
|
|
6
|
+
connection?: ConnectionContext<Path>;
|
|
7
|
+
join?: CoreJoinContext<Path, Schema>;
|
|
8
|
+
event?: CoreEventContext<Path, Schema, EventName>;
|
|
9
|
+
outgoing?: CoreOutgoingContext<Path, Schema, EventName>;
|
|
10
|
+
leave?: LeaveEvent;
|
|
11
|
+
}
|
|
12
|
+
export type ParamDecoratorCallback<Input> = (data: Input, context: Context, type: unknown) => unknown | Promise<unknown>;
|
|
13
|
+
export interface ParamDecoratorMetadata {
|
|
14
|
+
index: number;
|
|
15
|
+
callback: (context: Context, globalPipes: Constructor<PipeTransform>[], moduleRef: ModuleRef) => Promise<unknown>;
|
|
16
|
+
}
|
|
17
|
+
export type HandlerFunction<Context> = (instance: unknown, moduleRef: ModuleRef, globalGuards: Constructor<CanActivate>[], globalPipes: Constructor<PipeTransform>[], ctx: Context) => Promise<unknown>;
|
|
18
|
+
export type HandlerData<Context> = {
|
|
19
|
+
path: string;
|
|
20
|
+
value: HandlerFunction<Context>;
|
|
21
|
+
};
|
|
22
|
+
export type Constructor<T, Parameters extends any[] = any[]> = new (...args: Parameters) => T;
|
|
23
|
+
export interface CanActivate {
|
|
24
|
+
/**
|
|
25
|
+
* @desc Whether the client can continue with the request
|
|
26
|
+
* @param context - The context of the request
|
|
27
|
+
*/
|
|
28
|
+
canActivate(context: Context): boolean | Promise<boolean>;
|
|
29
|
+
}
|
|
30
|
+
export type GroupedInstances = {
|
|
31
|
+
endpoint: PondProvider;
|
|
32
|
+
channels: PondProvider[];
|
|
33
|
+
};
|
|
34
|
+
export interface PondProvider {
|
|
35
|
+
host?: {
|
|
36
|
+
metatype?: Type;
|
|
37
|
+
};
|
|
38
|
+
instance: any;
|
|
39
|
+
metatype: Type;
|
|
40
|
+
name: string;
|
|
41
|
+
}
|
|
42
|
+
export interface Metadata extends Omit<ModuleMetadata, 'controllers'> {
|
|
43
|
+
guards?: Constructor<CanActivate>[];
|
|
44
|
+
pipes?: Constructor<PipeTransform>[];
|
|
45
|
+
isExclusiveSocketServer?: boolean;
|
|
46
|
+
backend?: IDistributedBackend;
|
|
47
|
+
maxMessageSize?: number;
|
|
48
|
+
heartbeatInterval?: number;
|
|
49
|
+
isGlobal?: boolean;
|
|
50
|
+
}
|
|
51
|
+
export interface AsyncFactoryResult {
|
|
52
|
+
backend?: IDistributedBackend;
|
|
53
|
+
maxMessageSize?: number;
|
|
54
|
+
heartbeatInterval?: number;
|
|
55
|
+
}
|
|
56
|
+
export interface AsyncMetadata extends Omit<Metadata, 'backend' | 'maxMessageSize' | 'heartbeatInterval'> {
|
|
57
|
+
isGlobal?: boolean;
|
|
58
|
+
inject?: any[];
|
|
59
|
+
imports?: any[];
|
|
60
|
+
useFactory: (...args: any[]) => Promise<AsyncFactoryResult> | AsyncFactoryResult;
|
|
61
|
+
}
|
|
62
|
+
export type PondResponse<Event extends string = string, Payload extends PondMessage = PondMessage, Presence extends PondPresence = PondPresence, Assigns extends PondAssigns = PondAssigns> = {
|
|
63
|
+
event?: Event;
|
|
64
|
+
eventParams?: Params<Event>;
|
|
65
|
+
broadcast?: Event;
|
|
66
|
+
broadcastFrom?: Event;
|
|
67
|
+
assigns?: Partial<Assigns>;
|
|
68
|
+
presence?: Partial<Presence>;
|
|
69
|
+
broadcastTo?: {
|
|
70
|
+
event: Event;
|
|
71
|
+
users: string[];
|
|
72
|
+
};
|
|
73
|
+
decline?: string | {
|
|
74
|
+
message?: string;
|
|
75
|
+
status?: number;
|
|
76
|
+
};
|
|
77
|
+
payload?: Payload;
|
|
78
|
+
} & Partial<Payload>;
|
|
79
|
+
export type PondLifecycle = PondHandlerLifecycle;
|
|
80
|
+
type EndpointPathOf<Definition extends PondEndpointDefinition> = Definition extends PondEndpointDefinition<infer Path> ? Path : never;
|
|
81
|
+
export type PondConnectionContext<Definition extends PondEndpointDefinition> = Omit<Context<AnyPondSchema, EndpointPathOf<Definition>>, 'block' | 'broadcast' | 'broadcastFrom' | 'broadcastTo' | 'channel' | 'eventContext' | 'evictUser' | 'joinContext' | 'joinParams' | 'leaveEvent' | 'outgoingContext' | 'payload' | 'presence' | 'removePresence' | 'trackPresence' | 'transform' | 'updatePresence'> & {
|
|
82
|
+
readonly connectionContext: ConnectionContext<EndpointPathOf<Definition>>;
|
|
83
|
+
readonly params: Params<EndpointPathOf<Definition>>;
|
|
84
|
+
};
|
|
85
|
+
export type PondJoinContext<Definition extends AnyPondChannelDefinition> = Omit<Context<SchemaOf<Definition>, PathOf<Definition>>, 'block' | 'connectionContext' | 'eventContext' | 'evictUser' | 'leaveEvent' | 'outgoingContext' | 'payload' | 'removePresence' | 'transform' | 'updatePresence'> & {
|
|
86
|
+
readonly joinContext: CoreJoinContext<PathOf<Definition>, SchemaOf<Definition>>;
|
|
87
|
+
readonly joinParams: SchemaOf<Definition>['joinParams'];
|
|
88
|
+
};
|
|
89
|
+
export type PondEventContext<Definition extends AnyPondChannelDefinition, Event extends Extract<keyof EventsOf<SchemaOf<Definition>>, string>> = Omit<Context<SchemaOf<Definition>, Event, Event>, 'accept' | 'block' | 'connectionContext' | 'decline' | 'joinContext' | 'joinParams' | 'leaveEvent' | 'outgoingContext' | 'reply' | 'transform'> & {
|
|
90
|
+
readonly eventContext: CoreEventContext<Event, SchemaOf<Definition>, Event>;
|
|
91
|
+
readonly event: CoreEventContext<Event, SchemaOf<Definition>, Event>['event'];
|
|
92
|
+
readonly payload: EventPayload<EventsOf<SchemaOf<Definition>>, Event>;
|
|
93
|
+
reply(payload: EventReplyPayload<EventsOf<SchemaOf<Definition>>, Event>): PondEventContext<Definition, Event>;
|
|
94
|
+
};
|
|
95
|
+
type PondOutgoingContextForAction<Definition extends AnyPondChannelDefinition, Event extends Extract<keyof EventsOf<SchemaOf<Definition>>, string>, Action extends ServerActions.BROADCAST | ServerActions.SYSTEM> = Omit<Context<SchemaOf<Definition>, Event, Event>, 'accept' | 'action' | 'assign' | 'broadcast' | 'broadcastFrom' | 'broadcastTo' | 'connectionContext' | 'decline' | 'eventContext' | 'evictUser' | 'joinContext' | 'joinParams' | 'leaveEvent' | 'removePresence' | 'reply' | 'event' | 'outgoingContext' | 'payload' | 'trackPresence' | 'transform' | 'updatePresence'> & {
|
|
96
|
+
readonly action: Action;
|
|
97
|
+
readonly outgoingContext: CoreOutgoingContext<Event, SchemaOf<Definition>, Event, Action>;
|
|
98
|
+
readonly event: CoreOutgoingContext<Event, SchemaOf<Definition>, Event, Action>['event'];
|
|
99
|
+
readonly payload: OutgoingPayload<SchemaOf<Definition>, Event, Action>;
|
|
100
|
+
transform(payload: OutgoingPayload<SchemaOf<Definition>, Event, Action>): PondOutgoingContextForAction<Definition, Event, Action>;
|
|
101
|
+
};
|
|
102
|
+
export type PondOutgoingContext<Definition extends AnyPondChannelDefinition, Event extends Extract<keyof EventsOf<SchemaOf<Definition>>, string>> = PondOutgoingContextForAction<Definition, Event, ServerActions.BROADCAST> | PondOutgoingContextForAction<Definition, Event, ServerActions.SYSTEM>;
|
|
103
|
+
export type PondCoreJoinContext<Definition extends AnyPondChannelDefinition> = CoreJoinContext<PathOf<Definition>, SchemaOf<Definition>>;
|
|
104
|
+
export type PondCoreEventContext<Definition extends AnyPondChannelDefinition, Event extends Extract<keyof EventsOf<SchemaOf<Definition>>, string>> = CoreEventContext<Event, SchemaOf<Definition>, Event>;
|
|
105
|
+
export type PondCoreOutgoingContext<Definition extends AnyPondChannelDefinition, Event extends Extract<keyof EventsOf<SchemaOf<Definition>>, string>> = CoreOutgoingContext<Event, SchemaOf<Definition>, Event, ServerActions.BROADCAST> | CoreOutgoingContext<Event, SchemaOf<Definition>, Event, ServerActions.SYSTEM>;
|
|
106
|
+
export type PondEventPayload<Definition extends AnyPondChannelDefinition, Event extends Extract<keyof EventsOf<SchemaOf<Definition>>, string>> = EventPayload<EventsOf<SchemaOf<Definition>>, Event>;
|
|
107
|
+
export type PondSchemaPresence<Definition extends AnyPondChannelDefinition> = PresenceOf<SchemaOf<Definition>>;
|
|
108
|
+
export type PondSchemaAssigns<Definition extends AnyPondChannelDefinition> = AssignsOf<SchemaOf<Definition>>;
|
|
109
|
+
export type PondResponseFor<Definition extends AnyPondChannelDefinition, Event extends Extract<keyof EventsOf<SchemaOf<Definition>>, string>> = Omit<PondResponse<Event, EventReplyPayload<EventsOf<SchemaOf<Definition>>, Event>, PresenceOf<SchemaOf<Definition>>, AssignsOf<SchemaOf<Definition>>>, 'eventParams'> & {
|
|
110
|
+
eventParams?: Params<Event>;
|
|
111
|
+
};
|
|
112
|
+
export type PondEventHandler<Definition extends AnyPondChannelDefinition, Event extends Extract<keyof EventsOf<SchemaOf<Definition>>, string>> = (context: PondEventContext<Definition, Event>) => PondResponseFor<Definition, Event> | null | undefined | Promise<PondResponseFor<Definition, Event> | null | undefined>;
|
|
113
|
+
export {};
|