Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions src/SocketControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,18 +163,18 @@ export class SocketControllers {
);

if (connectedAction) {
this.executeAction(socket, controller, connectedAction);
void this.executeAction(socket, controller, connectedAction);
}

if (disconnectedAction) {
socket.on('disconnect', () => {
this.executeAction(socket, controller, disconnectedAction);
void this.executeAction(socket, controller, disconnectedAction);
});
}

if (disconnectingAction) {
socket.on('disconnecting', () => {
this.executeAction(socket, controller, disconnectingAction);
void this.executeAction(socket, controller, disconnectingAction);
});
}

Expand All @@ -187,39 +187,39 @@ export class SocketControllers {
messages.push(ack);
}

this.executeAction(socket, controller, messageAction, messageAction.options.name as string, messages);
void this.executeAction(socket, controller, messageAction, messageAction.options.name as string, messages);
});
}
}

private executeAction(
private async executeAction(
socket: Socket,
controller: HandlerMetadata<ControllerMetadata>,
action: ActionMetadata,
eventName?: string,
data?: any[]
) {
const parameters = this.resolveParameters(socket, controller.metadata, action.parameters || [], data);
try {
let container = this.container;
if (this.options.scopedContainerGetter) {
container = this.options.scopedContainerGetter(
this.collectScopedContainerParams(socket, action.type, eventName, data, controller.metadata.namespace)
);
}

let container = this.container;
if (this.options.scopedContainerGetter) {
container = this.options.scopedContainerGetter(
this.collectScopedContainerParams(socket, action.type, eventName, data, controller.metadata.namespace)
);
}

try {
const controllerInstance: any = container.get(controller.target);
const actionResult = controllerInstance[action.methodName](...parameters);
Promise.resolve(actionResult)
.then(result => {
this.handleActionResult(socket, action, result, ResultType.EMIT_ON_SUCCESS);
})
.catch(error => {
this.handleActionResult(socket, action, error, ResultType.EMIT_ON_FAIL);
});
const result = await Promise.resolve(actionResult);
this.handleActionResult(socket, action, result, ResultType.EMIT_ON_SUCCESS);
} catch (error: any) {
this.handleActionResult(socket, action, error, ResultType.EMIT_ON_FAIL);
}

if (this.options.scopedContainerDisposer) {
this.options.scopedContainerDisposer(container);
}
}

private handleActionResult(socket: Socket, action: ActionMetadata, result: any, resultType: ResultType) {
Expand Down
2 changes: 2 additions & 0 deletions src/types/SocketControllersOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export interface SocketControllersOptions {
get<T>(someClass: { new (...args: any[]): T } | Function): T;
};

scopedContainerDisposer?: (container: { get<T>(someClass: { new (...args: any[]): T } | Function): T }) => void;

io?: Server;

port?: number;
Expand Down
50 changes: 49 additions & 1 deletion test/functional/scoped-controllers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createServer, Server as HttpServer } from 'http';
import { Server } from 'socket.io';
import { io, Socket } from 'socket.io-client';
import { SocketControllers } from '../../src/SocketControllers';
import { Container, Inject, Service, Token } from 'typedi';
import { Container, ContainerInstance, Inject, Service, Token } from 'typedi';
import { SocketController } from '../../src/decorators/SocketController';
import { OnConnect } from '../../src/decorators/OnConnect';
import { ConnectedSocket } from '../../src/decorators/ConnectedSocket';
Expand Down Expand Up @@ -206,4 +206,52 @@ describe('Scoped controllers', () => {
expect(testResult[1].messageArgs).toEqual(['args1']);
expect(testResult[1].nspParams).toEqual({ test: 'string' });
});

it('container should be disposed', async () => {
const token = new Token('ADDITIONAL');

@Service({ global: true })
class TestService {}

@SocketController('/string')
@Service()
class TestController {
constructor(private testService: TestService, @Inject(token) public myAdditional: number) {}

@OnConnect()
connected(@ConnectedSocket() socket: Socket) {
socket.emit('connected');
}

@OnMessage('test')
@EmitOnSuccess('done')
test() {
testResult.push(this.myAdditional);
}
}

let container;
socketControllers = new SocketControllers({
io: wsApp,
container: Container,
controllers: [TestController],
scopedContainerGetter: () => {
container = Container.of('test');
container.set(token, 'test');
return container;
},
scopedContainerDisposer: (scopedContainer: ContainerInstance) => {
scopedContainer.reset({ strategy: 'resetServices' });
},
});
wsClient = io(PATH_FOR_CLIENT + '/string', { reconnection: false, timeout: 5000, forceNew: true });

await waitForEvent(wsClient, 'connected');
wsClient.emit('test');
await waitForEvent(wsClient, 'done');

expect(Container.has(TestService)).toBe(true);
expect(container.has(token)).toBe(false);
expect(container.has(TestController)).toBe(false);
});
});