Nest.js equivalent program for below Node snippet - node.js

Can someone please help and tell me how I can write the following code snippet which is written as a node application to write as a nest application with just WebSockets and gateway class?
var webSocketsServerPort = 8080;
var webSocketServer = require('websocket').server;
var http = require('http');
var server = http.createServer(function(request, response) {
});
server.listen(webSocketsServerPort, function() {
console.log(
new Date() + ' Server is listening on port ' + webSocketsServerPort
);
);
});
var wsServer = new webSocketServer({
httpServer: server
});
wsServer.on('request', function(request) {
var connection = request.accept(null, request.origin);
connection.on('message', function(data) {
var message = JSON.parse(data.utf8Data);
});
connection.on('close', function(connection) {});
EDIT:
In main.ts I wrote this :
app.useWebSocketAdapter(new WsAdapter(app));
This is how my gateway class looks like:
import { WebSocketGateway, WebSocketServer, OnGatewayInit, OnGatewayDisconnect, OnGatewayConnection, SubscribeMessage } from "#nestjs/websockets";
import { Server } from "websocket";
import { Logger } from "#nestjs/common";
#WebSocketGateway(8080)
export class ChatterGateway implements OnGatewayInit, OnGatewayDisconnect, OnGatewayConnection {
#WebSocketServer() private server: server;
private logger: Logger = new Logger('ChatterGateway');
afterInit(server: server) {
this.logger.log('ChatGetway init');
}
handleConnection(client: any, data) {
this.logger.log('Client connected');
}
handleDisconnect(client: any) {
this.logger.log('Client disconnected');
}
#SubscribeMessage('request')
handleRequest(client: any, data) {
this.logger.log(data);
}
#SubscribeMessage('message')
handleMessage(client: any, data) {
this.logger.log(data);
}
}

Related

Web socket wss connection failed having secure web server in Node and Angular

I am trying to connect a secure websocket connection from client (angular app) with my server (nodejs). I used mkcert to generate my key and cert and server is running in https showing connection is secure. when I am trying to connect with WS, the webscoet connects with server but when I use WSS I am getting an error of WebSocket connection to 'wss://localhost:port/' failed. Can anyone let me know where am I getting wrong to connect wss or how to connect wss websocket connection here?
My client side code is
app.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
constructor(){
connectToServer();
}
title = 'SSL-WEB-SOCKET-CLIENT';
}
function connectToServer() {
let ws= new WebSocket("wss://localhost:8082/");
ws.addEventListener("open", ()=>{
console.log("We are connected");
ws.send("hey, I am Client. Nice to meet you!");
});
ws.addEventListener("error", (event)=> {
console.log('WebSocket error: ', event);
});
ws.addEventListener("message", ({data})=>{
console.log("Server sent us: "+data);
});
}
Server side code
main.ts
import { NestFactory } from '#nestjs/core';
import { AppModule } from './app.module';
import * as fs from 'fs';
async function bootstrap() {
const httpsOptions = {
key: fs.readFileSync('./localhost-key.pem'),
cert: fs.readFileSync('./localhost.pem'),
rejectUnauthorized: false,
};
const app = await NestFactory.create(AppModule, {
httpsOptions,
});
await app.listen(8090);
console.log('Server started at 8090');
}
bootstrap();
app.controller.ts
import { Controller, Get } from '#nestjs/common';
import { AppService } from './app.service';
#Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
#Get()
getSecureWssConn(): string {
return this.appService.getSecureWssConn();
}
}
app.service.ts
import { Injectable } from '#nestjs/common';
#Injectable()
export class AppService {
getSecureWssConn(): string {
// eslint-disable-next-line #typescript-eslint/no-var-requires
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8082 });
wss.on('connection', (ws) => {
console.log('New Client connected');
ws.on('message', (data) => {
console.log(`Client has sent us: ${data}`);
ws.send('Hello! I am Server. Nice to meet you.');
});
ws.on('close', () => {
console.log('Client Disconnected');
});
});
return 'Hello, I am your SERVER';
}
}
Server running in browser!

NodeJS Angular 8 chat application not receiving messages in client

I made a NodeJS server and an Angular 8 client to send and receive messages with socket.io. The server does receive the message but does not send/angular does not receive the message. Does this happen because I use localhost or did I do something wrong codewise?
NodeJS server:
let express = require('express');
let app = express();
let http = require('http');
let server = http.Server(app);
let socketIO = require('socket.io');
let io = socketIO(server);
const port = process.env.PORT || 3000;
io.on('connection', (socket) => {
console.log('user connected');
socket.on('new-message', (message) => {
console.log(message);
io.emit(message);
});
});
server.listen(port, () => {
console.log(`started on port: ${port}`);
});
Angular service:
import * as io from 'socket.io-client';
import { Observable } from 'rxjs/Observable';
import {Observer} from 'rxjs';
export class ChatService {
private url = 'http://localhost:3000';
private socket;
constructor() {
this.socket = io(this.url);
}
public sendMessage(message) {
this.socket.emit('new-message', message);
}
public getMessages = () => {
// return Observable.create((observer) => {
// console.log(observer);
// this.socket.on('new-message', (message) => {
// observer.next(message);
// });
// });
return new Observable((observer) => {
this.socket.on('new-message', (message) => {
observer.next(message);
observer.complete();
});
});
}
}
Angular component:
export class HomeComponent implements OnInit {
private message: string;
constructor(private chatService: ChatService) {
this.message = 'hello';
this.sendMessage();
}
ngOnInit(): void {
this.chatService.getMessages().subscribe((message: string) => {
console.log(message);
}, err => {
console.log(err);
});
}
sendMessage() {
this.chatService.sendMessage(this.message);
}
}
App.module.ts:
#NgModule({
declarations: [
AppComponent,
HomeComponent
], imports: [
], providers: [
ChatService
], entryComponents: []
})
export class AppModule {
}
In your server code you wrote io.emit(message); but emit function is called with two parameters - event name, and message to send.
Change it into io.emit('new-message', message); and it should work.
you need to change io.emit(message) to io.emit("message", { message: message }).
this code worked for me.

How to receive data from client using socket.io events inside express controller?

I am using Express framework with TypeScript:
I want to get client location at login using Socket IO, so on the client side, i made an emit event on login page. On the server side i tried to integrate a socket event into the login controller, which is placed before the response is sent back to the client, but the event from the server fires up just after i'm already signed in and clicked on sign out button which leads me to login page again (this is the moment when i receive the location message on server side from console.log(data)).
This is how the authentication controller file (auth.controller.ts) looks like:
import { io } from '../server/https';
....
..
public authenticate(req: Request, res: Response) {
if(req.body.email && req.body.password) {
....
..
io.on('connection', (socket: SocketIO.Socket) => {
console.log('New Socket Connected!');
socket.on('client-location', (data) => {
console.log(data);
});
socket.on('disconnect', (reason) => {
console.log(reason);
});
});
res.status(200).json({
resType: 'success',
token: 'Bearer ' + token,
userId: user.id,
message: 'Authenticated.',
loginNumber: result.session.length
});
};
....
..
}
The { io } import in the auth.controller.ts is the exported io constant from https.ts file.
Below is the https.ts file:
import socketIO from 'socket.io';
import HTTPS from 'https';
import app from '../app/index';
....
..
const options = {
cert: fs.readFileSync(path.resolve('../../../certificates/ca.crt')),
key: fs.readFileSync(path.resolve('../../../certificates/ca.key'))
}
export const server = HTTPS.createServer(options, app)
.listen(process.env.HTTP_SERVER_PORT, () => {
console.log(`Platform Server is running from
${process.env.HTTP_SERVER_HOST}, port: ${process.env.HTTP_SERVER_PORT}`);
});
export const io = socketIO.listen(server);
Something is not synchronized and i don't get it.
The client side is wrote in Angular 6 and the component from where the event is emited is below:
import { Component, OnInit } from '#angular/core';
import { LoginService } from '../../services/login.service';
import { Router } from '#angular/router';
import * as io from 'socket.io-client';
import { env } from '../../../../../environments/environment';
#Component({
selector: 'login-form',
templateUrl: './login-form.component.html',
styleUrls: ['./login-form.component.css']
})
export class LoginFormComponent implements OnInit {
public positionOptions = {
enableHighAccuracy: true,
maximumAge: 0
};
public LoginFormModel: any = {};
private URL = `${env.WS_SERVER_URL}:${env.HTTP_SERVER_PORT}`;
private socket;
constructor(private loginController: LoginService,
private router: Router) {
this.socket = io(this.URL);
}
ngOnInit() {}
public emitLocation() {
navigator.geolocation.getCurrentPosition(position => {
const { latitude: lat, longitude: lng } = position.coords;
console.log({ lat, lng });
this.socket.emit('client-location', { lat, lng });
},
err => {
console.log(err);
}, this.positionOptions);
}
loginEvent() {
this.loginController.login(this.LoginFormModel.email.value,
this.LoginFormModel.password.value)
.subscribe(
result => {
this.loginController.createSession('token', result.token);
this.emitLocation();
this.router.navigate(['user/profile']);
},
err => {
console.log(err);
});
}
}

typescript express typeorm createconnection

I am creating an app with typescript express node typeorm. I am having this issue where when I make a call through a service class to the database using typeorm, I get connection default was not found. Here are my code snippets:
//dataservice class
import { Connection, getConnection, EntityManager, Repository,
getManager } from "typeorm";
export class LeaveDataService {
private _db: Repository<Leave>;
constructor() {
this._db = getManager().getRepository(Leave);
}
/**
* applyForLeave
*/
public applyForLeave(leave: Leave): void {
if(leave !== null) {
let entity: Leave = this._db.create(leave);
this._db.save(entity);
}
}
/**
* getAllLeaves
*/
public async getAllLeaves(): Promise<Array<Leave>> {
let leaves: Promise<Array<Leave>> = this._db.find({
select: ["leaveDays","casualLeaveDays","id","staff","leaveType","endorsedBy","approvedBy"],
relations: ["staff", "leaveType"],
skip: 5,
take: 15
});
return leaves;
}
this is my ormconfig.json
{
"type":"sqlite",
"entities": ["./models/*.js"],
"database": "./leaveappdb.sql"
}
and this is the "controller" that responds to requests by calling the service class which is the first snippet:
import { Request, Response } from "express";
import { LeaveDataService } from "../services/leaveDataService";
import { LeaveIndexApiModel } from '../ApiModels/leaveIndexApiModel';
const dataService: LeaveDataService = new LeaveDataService();
export let index = async (req: Request, res: Response) => {
let result = await dataService.getAllLeaves();
let viewresult = new Array<LeaveIndexApiModel>();
result.forEach(leave => {
let apmodel =
new LeaveIndexApiModel(leave.leaveType.name,
`${leave.staff.firstname} ${leave.staff.lastname}`, leave.id);
viewresult.push(apmodel);
});
return res.status(200).send(viewresult);
}
then this is where I bootstrap my app.
import express = require('express');
import bodyParser = require('body-parser');
import path = require('path');
import * as home from './controllers/home';
import { createConnection } from 'typeorm';
import * as leavectrl from "./controllers/leaveController";
//create express server
//create app db connection.
createConnection().then(async connection => {
const app = express();
console.log("DB online!");
const approot = './';
const appport = process.env.Port || 8001;
//setup express for json parsing even with urlencoding
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(approot,'dist')));
//serve and respond to routes by api
app.get('/home', home.home);
app.get('/login',home.login);
//routes for leave
app.get('/api/leaves', leavectrl.index);
//default fall through
// app.get('*', (req: Request, res: Response)=>{
// res.sendFile(approot,'dist/index.html');
// });
app.listen(appport, ()=> console.log(`api is alive on port
${appport}`));
}).catch(error => console.log("Data Access Error : ", error));
Your configuration is seems to be good but you didn't called or used your ormconfig.json file to createConnection.
for Eg:
createConnection(./ormconfig.json).then(async connection => {
}).catch(error => console.log("Data Access Error : ", error));
Try with or i will give you a way to configure with class object to establish a DB connection
In config file:
import "reflect-metadata";
import { ConnectionOptions } from "typeorm";
import { abc } from "../DatabaseEntities/abc";
import { def } from '../DatabaseEntities/def';
export let dbOptions: ConnectionOptions = {
type: "sqlite",
name: app,
database: "./leaveappdb.sqlite3",
entities: [abc, def],
synchronize: true,
}
In server.ts
import { createConnection, createConnections } from 'typeorm';
import * as appConfig from './Config/config';
createConnection(appConfig.dbOptions).then(async connection => {
console.log("Connected to DB");
}).catch(error => console.log("TypeORM connection error: ", error));
I think this may help you..
Also, i have found that for connecting sqlite DB you are trying to connect a sql file. Kindly confirm that once too.
Thank you

Angular2 CLI Socket.io Cannot read property 'on' undefined

I want to use socket.io module for sending message and I am newbie in using it. I am trying to run socket.io within my Angular2 CLI + Node.js application and I am getting following error:
TypeError: Cannot read property 'on' of undefined
at MessagesComponent.webpackJsonp.363.MessagesComponent.sendMessage
(messages.component.ts:34)
What is wrong with my code and how can I connect and send message to the socket.io server?
messages.component.html
<div class="stick" style="background-color:#F5F5F5;">
<h5>Messages:</h5>
<ul>
<li *ngFor="let msg of msgs">
{{msg}}
</li>
</ul>
<input #mm/>
<button (click)="sendMessage(mm.value); mm.value=''">Send</button>
</div>
messages.component.ts
import { Component,Input,OnInit,Output,EventEmitter,HostListener,ElementRef, NgZone} from "#angular/core";
import * as sio from 'socket.io-client';
import { Observable } from 'rxjs/Observable';
#Component({
selector: "messages",
templateUrl: './messages.component.html'
})
export class MessagesComponent implements OnInit{
socket: SocketIOClient.Socket;
private url = 'http://localhost:4200';
constructor(private _zone: NgZone, public http: Http) {}
ngOnInit() {
}
sendMessage(message){
this.socket.on('connect', function(data) {
this.socket.emit('add-message', message);
});
}
getMessages() {
let observable = new Observable(observer => {
this.socket = io(this.url);
this.socket.on('message', (data) => {
observer.next(data);
});
return () => {
this.socket.disconnect();
};
})
return observable;
}
}
www.ts
import { app } from '../app';
import * as http from 'http';
/**
* Get port from environment and store in Express.
*/
const port = normalizePort(process.env.PORT || 3000);
app.set('port', port);
/**
* Create HTTP server.
*/
const server = http.createServer(app);
let io = require('socket.io').listen(server);
io.on('connection', (socket) => {
socket.on('disconnect', function(){
console.log('user disconnected');
});
socket.on('add-message', (message) => {
io.emit('message', {type:'new-message', text: message});
});
});
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
Solution:
constructor(private _zone: NgZone, public http: Http) {
this.socket = sio(this.url);
}
in your on callback use arrow function to preserve this keyword :
sendMessage(message){
this.socket.on('connect', (data) => {
this.socket.emit('add-message', message);
});
}
you have to instantiate your socket :
constructor(private _zone: NgZone, public http: Http) {
this.socket = sio(this.url);
}
in your on callback use arrow function to preserve this keyword :
sendMessage(message){
this.socket.on('connect', (data) => {
this.socket.emit('add-message', message);
});
}

Resources