Skip to content

Commit

Permalink
feat(socket): Add Socket.IO package
Browse files Browse the repository at this point in the history
- Add package,
- Add documentation

Closes: #161
  • Loading branch information
Romakita committed Dec 12, 2017
1 parent 5942e36 commit be14025
Show file tree
Hide file tree
Showing 52 changed files with 1,715 additions and 93 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ index.js.map
!multipartfiles/index.js
!servestatic/index.js
!ajv/index.js
!socketio/index.js
src/**/*.js
src/**/*.js.map
test/**/*.js
Expand Down
45 changes: 23 additions & 22 deletions docs/_build/info.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
const {homepage, version} = require("../../package.json");
const github = homepage.replace("#readme", "");
const path = require("path");
const root = path.resolve(path.join(__dirname, "../../"));
const { homepage, version } = require('../../package.json')
const github = homepage.replace('#readme', '')
const path = require('path')
const root = path.resolve(path.join(__dirname, '../../'))

module.exports = {
root,
github,
host: `${github}/blob/v${version}/src/`,
modules: {
"core": "common/core",
"converters": "common/converters",
"di": "common/di",
"filters": "common/filters",
"mvc": "common/mvc",
"server": "common/server",
"ajv": "ajv",
"multipartfiles": "multipartfiles",
"servestatic": "servestatic",
"swagger": "swagger",
"testing": "testing"
'core': 'common/core',
'converters': 'common/converters',
'di': 'common/di',
'filters': 'common/filters',
'mvc': 'common/mvc',
'server': 'common/server',
'ajv': 'ajv',
'multipartfiles': 'multipartfiles',
'servestatic': 'servestatic',
'socketio': 'socketio',
'swagger': 'swagger',
'testing': 'testing'
},
symbolTypes: require("./types"),
symbolTypes: require('./types'),
symbols: new Map(),
status: {
"S": {value: "stable", label: "Stable"},
"D": {value: "deprecated", label: "Deprecated"},
"E": {value: "experimental", label: "Experimental"},
"P": {value: "private", label: "Private"},
"O": {value: "public", label: "Public"}
'S': { value: 'stable', label: 'Stable' },
'D': { value: 'deprecated', label: 'Deprecated' },
'E': { value: 'experimental', label: 'Experimental' },
'P': { value: 'private', label: 'Private' },
'O': { value: 'public', label: 'Public' }
}
};
}
Binary file added docs/_media/socketio.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions docs/api/common/di/service.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

### Description

The decorators `@Service()` a new service can be injected in other service or controller on there `constructor()`.
The decorators `@Service()` a new service can be injected in other service or controller on there `constructor`.
All services annotated with `@Service()` are constructed one time.
`@Service()` use the `reflect-metadata` to collect and inject service on controllers or other services.

> `@Service()` use the `reflect-metadata` to collect and inject service on controllers or other services.
25 changes: 25 additions & 0 deletions docs/api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,31 @@

<ul class="api-list"><li class="api-item" data-symbol="servestatic;ServeStaticService;service;S;false;false;false;false"><a href="#/api/servestatic/servestaticservice" class="symbol-container deprecated symbol-type-service symbol-name-servestatic-ServeStaticService" title="ServeStaticService"> <span class="symbol service"></span> ServeStaticService </a></li></ul>

#### socketio


<ul class="api-list"><li class="api-item" data-symbol="socketio;Args;decorator;@;false;false;true;false"><a href="#/api/socketio/args" class="symbol-container deprecated symbol-type-decorator symbol-name-socketio-Args" title="Args"> <span class="symbol decorator"></span> Args </a></li>
<li class="api-item" data-symbol="socketio;Broadcast;decorator;@;false;false;true;false"><a href="#/api/socketio/broadcast" class="symbol-container deprecated symbol-type-decorator symbol-name-socketio-Broadcast" title="Broadcast"> <span class="symbol decorator"></span> Broadcast </a></li>
<li class="api-item" data-symbol="socketio;BroadcastOthers;decorator;@;false;false;true;false"><a href="#/api/socketio/broadcastothers" class="symbol-container deprecated symbol-type-decorator symbol-name-socketio-BroadcastOthers" title="BroadcastOthers"> <span class="symbol decorator"></span> BroadcastOthers </a></li>
<li class="api-item" data-symbol="socketio;Emit;decorator;@;false;false;true;false"><a href="#/api/socketio/emit" class="symbol-container deprecated symbol-type-decorator symbol-name-socketio-Emit" title="Emit"> <span class="symbol decorator"></span> Emit </a></li>
<li class="api-item" data-symbol="socketio;IO;decorator;@;false;false;true;false"><a href="#/api/socketio/io" class="symbol-container deprecated symbol-type-decorator symbol-name-socketio-IO" title="IO"> <span class="symbol decorator"></span> IO </a></li>
<li class="api-item" data-symbol="socketio;ISocketHandlerMetadata;interface;I;false;false;true;false"><a href="#/api/socketio/isockethandlermetadata" class="symbol-container deprecated symbol-type-interface symbol-name-socketio-ISocketHandlerMetadata" title="ISocketHandlerMetadata"> <span class="symbol interface"></span> ISocketHandlerMetadata </a></li>
<li class="api-item" data-symbol="socketio;ISocketParamMetadata;interface;I;false;false;true;false"><a href="#/api/socketio/isocketparammetadata" class="symbol-container deprecated symbol-type-interface symbol-name-socketio-ISocketParamMetadata" title="ISocketParamMetadata"> <span class="symbol interface"></span> ISocketParamMetadata </a></li>
<li class="api-item" data-symbol="socketio;ISocketProviderMetadata;interface;I;false;false;true;false"><a href="#/api/socketio/isocketprovidermetadata" class="symbol-container deprecated symbol-type-interface symbol-name-socketio-ISocketProviderMetadata" title="ISocketProviderMetadata"> <span class="symbol interface"></span> ISocketProviderMetadata </a></li>
<li class="api-item" data-symbol="socketio;Input;decorator;@;false;false;true;false"><a href="#/api/socketio/input" class="symbol-container deprecated symbol-type-decorator symbol-name-socketio-Input" title="Input"> <span class="symbol decorator"></span> Input </a></li>
<li class="api-item" data-symbol="socketio;Nsp;decorator;@;false;false;true;false"><a href="#/api/socketio/nsp" class="symbol-container deprecated symbol-type-decorator symbol-name-socketio-Nsp" title="Nsp"> <span class="symbol decorator"></span> Nsp </a></li>
<li class="api-item" data-symbol="socketio;OnConnection;interface;I;false;false;true;false"><a href="#/api/socketio/onconnection" class="symbol-container deprecated symbol-type-interface symbol-name-socketio-OnConnection" title="OnConnection"> <span class="symbol interface"></span> OnConnection </a></li>
<li class="api-item" data-symbol="socketio;OnDisconnect;interface;I;false;false;true;false"><a href="#/api/socketio/ondisconnect" class="symbol-container deprecated symbol-type-interface symbol-name-socketio-OnDisconnect" title="OnDisconnect"> <span class="symbol interface"></span> OnDisconnect </a></li>
<li class="api-item" data-symbol="socketio;Socket;decorator;@;false;false;true;false"><a href="#/api/socketio/socket" class="symbol-container deprecated symbol-type-decorator symbol-name-socketio-Socket" title="Socket"> <span class="symbol decorator"></span> Socket </a></li>
<li class="api-item" data-symbol="socketio;SocketFilter;decorator;@;false;false;false;true"><a href="#/api/socketio/socketfilter" class="symbol-container deprecated symbol-type-decorator symbol-name-socketio-SocketFilter" title="SocketFilter"> <span class="symbol decorator"></span> SocketFilter </a></li>
<li class="api-item" data-symbol="socketio;SocketFilters;enum;E;false;false;false;true"><a href="#/api/socketio/socketfilters" class="symbol-container deprecated symbol-type-enum symbol-name-socketio-SocketFilters" title="SocketFilters"> <span class="symbol enum"></span> SocketFilters </a></li>
<li class="api-item" data-symbol="socketio;SocketHandlersBuilder;class;C;false;false;true;true"><a href="#/api/socketio/sockethandlersbuilder" class="symbol-container deprecated symbol-type-class symbol-name-socketio-SocketHandlersBuilder" title="SocketHandlersBuilder"> <span class="symbol class"></span> SocketHandlersBuilder </a></li>
<li class="api-item" data-symbol="socketio;SocketIOServer;service;S;false;false;true;false"><a href="#/api/socketio/socketioserver" class="symbol-container deprecated symbol-type-service symbol-name-socketio-SocketIOServer" title="SocketIOServer"> <span class="symbol service"></span> SocketIOServer </a></li>
<li class="api-item" data-symbol="socketio;SocketIOService;service;S;false;false;true;false"><a href="#/api/socketio/socketioservice" class="symbol-container deprecated symbol-type-service symbol-name-socketio-SocketIOService" title="SocketIOService"> <span class="symbol service"></span> SocketIOService </a></li>
<li class="api-item" data-symbol="socketio;SocketReturns;decorator;@;false;false;false;true"><a href="#/api/socketio/socketreturns" class="symbol-container deprecated symbol-type-decorator symbol-name-socketio-SocketReturns" title="SocketReturns"> <span class="symbol decorator"></span> SocketReturns </a></li>
<li class="api-item" data-symbol="socketio;SocketReturnsTypes;enum;E;false;false;false;true"><a href="#/api/socketio/socketreturnstypes" class="symbol-container deprecated symbol-type-enum symbol-name-socketio-SocketReturnsTypes" title="SocketReturnsTypes"> <span class="symbol enum"></span> SocketReturnsTypes </a></li>
<li class="api-item" data-symbol="socketio;SocketService;decorator;@;false;false;true;false"><a href="#/api/socketio/socketservice" class="symbol-container deprecated symbol-type-decorator symbol-name-socketio-SocketService" title="SocketService"> <span class="symbol decorator"></span> SocketService </a></li></ul>

#### swagger


Expand Down
135 changes: 78 additions & 57 deletions docs/tutorials/socket-io.md
Original file line number Diff line number Diff line change
@@ -1,95 +1,116 @@
# How to integrate Socket.io
> Socket.io enable real-time bidirectional event-based communication. It works on every platform, browser or device, focusing equally on reliability and speed.
# Socket.io
> Experimental feature. You can contribute to improve this feature !
Socket.io enable real-time bidirectional event-based communication. It works on every platform, browser or device, focusing equally on reliability and speed.

## Installation

Run this command:
```typescript
npm install --save socket.io
Before using the Socket.io, we need to install the [Socket.io](https://www.npmjs.com/package/socket.io) module.

```
If you want type checking for Socket.io, run this command:
```typescript
npm install --save-dev @types/socket.io
npm install --save socket.io @types/socket.io
```

## Example
Then add the following configuration in your [ServerLoader](api/common/server/serverloader.md):

Use the `$onReady` hook to create your Socket server:
```typescript
import {ServerLoader, ServerSettings, Inject} from "ts-express-decorators";
import Path = require("path");
import {ServerLoader, ServerSettings} from "ts-express-decorators";
import "ts-express-decorators/socketio"; // import socketio Ts.ED module

@ServerSettings({
rootDir: Path.resolve(__dirname),
componentsScan: [
"${rootDir}/services/**/*.js"
]
rootDir: __dirname,
socketIO: {
// ... see configuration
}
})
class Server extends ServerLoader {}
export class Server extends ServerLoader {

}
```

Wrap socket.io into a service:
## Configuration

```typescript
import * as SocketIO from "socket.io";
import {HttpServer, Inject, OnServerReady, Service} from "ts-express-decorators";
- `path` &lt;string&gt;: name of the path to capture (/socket.io).
- `serveClient` &lt;boolean&gt;: whether to serve the client files (true).
- `adapter` &lt;Adapter&gt;: the adapter to use. Defaults to an instance of the Adapter that ships with socket.io which is memory based. See [socket.io-adapter](https://github.com/socketio/socket.io-adapter).
- `origins` &lt;string&gt;: the allowed origins (*).
- `parser` &lt;Parser&gt;: the parser to use. Defaults to an instance of the Parser that ships with socket.io. See [socket.io-parser](https://github.com/socketio/socket.io-parser).

@Service()
export class SocketService implements OnServerReady {
For more information see [Socket.io documentation](https://socket.io/docs/server-api/#)

private _io: SocketIO.Server;
private stacks = [];
## Socket Service

constructor(@Inject(HttpServer) private httpServer: HttpServer) {
> Socket.IO allows you to “namespace” your sockets, which essentially means assigning different endpoints or paths.
This is a useful feature to minimize the number of resources (TCP connections) and at the same time separate concerns within your application
by introducing separation between communication channels. See [namespace documentation](https://socket.io/docs/rooms-and-namespaces/#).

}
All Socket service work under a namespace and you can create one Socket service per namespace.

$onServerReady() {
this.createServer();
}
Example:

```typescript
import * as SocketIO from "socket.io";
import {SocketService, IO} from "ts-express-decorators/socketio";

@SocketService("/my-namespace")
export class MySocketService {
constructor(@IO private io: SocketIO.Server) {}
/**
* Store all callbacks that will be adding to socket.io instance when
* it'll be created. See SocketService.createServer().
* Triggered when a new client connects to the Namespace.
*/
public onConnection(callback: Function): SocketService {
this.stacks.push(callback);
return this;
$onConnection(socket: SocketIO.Socket, nsp: SocketIO.Namespace) {

}
/**
* Triggered when a client disconnects from the Namespace.
*/
$onDisconnect(socket: SocketIO.Socket, nsp: SocketIO.Namespace) {

}
}
```

public emit = (eventName: string, ...args: any[]) => this._io.emit(eventName, ...args);
> @SocketService inherit from @Service decorator. That means, a SocketService can be injected to another Service, Controller or Middleware.
createServer() {
this._io = SocketIO(this.httpServer.get());
### Declaring an Input Event

// Map all callbacks to this connection events.
this.stacks.forEach(cb => this._io.on("connection", cb));
}
[@Input](api/socketio/input.md) decorator declare a method as a new handler for a specific `event`.

get io(): SocketIO.Server {
return this._io;
```typescript
@SocketService("/my-namespace")
export class MySocketService {
@Input("eventName")
myMethod(@Args(0) userName: string, @Socket socket: SocketIO.Socket, @Nsp nsp: SocketIO.Namespace) {
console.log(userName);
}
}
```

Finally, inject your service to another service or controller :
- [@Args](api/socketio/args.md) &lt;any|any[]&gt;: List of the parameters sent by the input event.
- [@Socket](api/socketio/socket.md) &lt;SocketIO.Socket&gt;: Socket instance.
- [@Nsp](api/socketio/nsp.md) &lt;[SocketIO.Namespace](https://socket.io/docs/rooms-and-namespaces/#)&gt;: Namespace instance.

```typescript
import {Controller} from "ts-express-decorators";
import SocketService from "../services/SocketService";
### Send a response

@Controller('/')
export class MySocketCtrl {

constructor(private socketService: SocketService) {
socketService.onConnection(this.onConnection);
}

private onConnection = (socket) => {
// write your code :)
}
You have a many choice to send a response to your client. Ts.ED offer some decorators to send a response:

![socketio](_media/socketio.png)

Example:

```typescript
@SocketService("/my-namespace")
export class MySocketService {
@Input("eventName")
@Emit("responseEventName") // or Broadcast or BroadcastOthers
async myMethod(@Args(0) userName: string, @Socket socket: SocketIO.Socket) {
return "Message " + userName;
}
}
```
> The method accept a promise as returned value.
!> Return value is only possible when the method is decorated by [@Emit](), [@Broadcast]() and [@BroadcastOthers]().

<div class="guide-links">
<a href="#/tutorials/passport">Passport</a>
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/swagger.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Then add the following configuration in your [ServerLoader](api/common/server/se

```typescript
import {ServerLoader, ServerSettings} from "ts-express-decorators";
import "ts-express-decorators/swagger"; // import swagger ts.ed module
import "ts-express-decorators/swagger"; // import swagger Ts.ED module

@ServerSettings({
rootDir: __dirname,
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
"@types/proxyquire": "^1.3.27",
"@types/sinon": "^2.2.1",
"@types/sinon-chai": "^2.7.27",
"@types/socket.io": "^1.4.31",
"@types/superagent": "^3.5.3",
"@types/supertest": "^2.0.0",
"ajv": "^5.2.4",
Expand All @@ -95,6 +96,7 @@
"semantic-release": "^7.0.2",
"sinon": "^4.0.1",
"sinon-chai": "^2.10.0",
"socket.io": "^2.0.4",
"supertest": "^3.0.0",
"swagger-ui-express": "^2.0.0",
"ts-node": "^3.0.2",
Expand All @@ -114,4 +116,4 @@
"master": "master",
"production": "production"
}
}
}
1 change: 1 addition & 0 deletions socketio/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "../lib/socketio";
6 changes: 6 additions & 0 deletions socketio/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// DO NOT REMOVE
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
__export(require("../lib/socketio"));
2 changes: 1 addition & 1 deletion src/core/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ export function deepExtends(out: any, obj: any, reducers: { [key: string]: (coll
return obj;
}

if (isPrimitiveOrPrimitiveClass(obj) || typeof obj === "function") {
if (isPrimitiveOrPrimitiveClass(obj) || typeof obj === "symbol" || typeof obj === "function") {
return obj;
}

Expand Down
6 changes: 4 additions & 2 deletions src/di/decorators/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
*/
/** */
import {InjectorService} from "../services/InjectorService";

/**
* The decorators `@Service()` declare a new service can be injected in other service or controller on there `constructor()`.
* The decorators `@Service()` declare a new service can be injected in other service or controller on there `constructor`.
* All services annotated with `@Service()` are constructed one time.
* `@Service()` use the `reflect-metadata` to collect and inject service on controllers or other services.
*
* > `@Service()` use the `reflect-metadata` to collect and inject service on controllers or other services.
*
* @returns {Function}
* @constructor
Expand Down
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
* @preferred
*/
/** */
require("source-map-support").install();
if (!require.extensions[".ts"]) {
require("source-map-support").install();
}
import "reflect-metadata";

export * from "./core";
Expand Down
3 changes: 2 additions & 1 deletion src/mvc/services/RouteService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ export class RouteService {
const method = route.method.toUpperCase();

route.method = <any>{
length: method.length, toString: () => {
length: method.length,
toString: () => {
return colorize(method, mapColor[method]);
}
};
Expand Down

0 comments on commit be14025

Please sign in to comment.