feat: add lazy inject and websocket debug
Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
parent
d554b91358
commit
6780791747
@ -15,7 +15,7 @@ let handler = {
|
|||||||
let origin = argumentsList[param.index];
|
let origin = argumentsList[param.index];
|
||||||
let props = getVaildModelMetadata(param.type);
|
let props = getVaildModelMetadata(param.type);
|
||||||
for (const prop of props) {
|
for (const prop of props) {
|
||||||
if (!prop.handle(origin[prop.name])) {
|
if (!origin || !prop.handle(origin[prop.name])) {
|
||||||
throw new VaildError(prop.message);
|
throw new VaildError(prop.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
21
packages/core/cc-server.http
Normal file
21
packages/core/cc-server.http
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
@url=https://faas.n.yumc.pw
|
||||||
|
|
||||||
|
###
|
||||||
|
GET {{url}}/example
|
||||||
|
|
||||||
|
###
|
||||||
|
POST {{url}}/example
|
||||||
|
|
||||||
|
{
|
||||||
|
"username": 1
|
||||||
|
}
|
||||||
|
|
||||||
|
###
|
||||||
|
@websocket={{url}}/websocket
|
||||||
|
|
||||||
|
###
|
||||||
|
POST {{websocket}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"name":"Socket.IO"
|
||||||
|
}
|
@ -25,6 +25,7 @@
|
|||||||
"@cc-server/ioc": "^0.4.0",
|
"@cc-server/ioc": "^0.4.0",
|
||||||
"@cc-server/ws": "^0.4.0",
|
"@cc-server/ws": "^0.4.0",
|
||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
|
"globby": "^9.2.0",
|
||||||
"inversify": "^5.0.1",
|
"inversify": "^5.0.1",
|
||||||
"inversify-express-utils": "^6.3.2",
|
"inversify-express-utils": "^6.3.2",
|
||||||
"prettyjson": "^1.2.1",
|
"prettyjson": "^1.2.1",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
import { TYPE, io } from '@cc-server/ws'
|
||||||
|
import { DBClient } from '@cc-server/db'
|
||||||
import { inject, postConstruct } from '@cc-server/ioc';
|
import { inject, postConstruct } from '@cc-server/ioc';
|
||||||
import { Vaild, NotBlank, NotNull, controller, requestBody, httpGet, httpPost, requestParam } from '@cc-server/binding'
|
import { Vaild, NotBlank, NotNull, controller, requestBody, httpGet, httpPost, requestParam } from '@cc-server/binding'
|
||||||
import { DBClient } from '@cc-server/db'
|
|
||||||
import '@cc-server/db-mongo'
|
import '@cc-server/db-mongo'
|
||||||
|
|
||||||
//process.env.FAAS_MONGO_URL = 'mongodb://192.168.0.2:27017';
|
//process.env.FAAS_MONGO_URL = 'mongodb://192.168.0.2:27017';
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import { namespace, listener, interfaces, io } from '@cc-server/ws'
|
import { controller, httpPost, requestBody } from '@cc-server/binding';
|
||||||
|
import { namespace, listener, interfaces, io, TYPE } from '@cc-server/ws'
|
||||||
|
import { lazyInjectNamed } from '@cc-server/ioc'
|
||||||
|
|
||||||
@namespace('/', (socket: io.Socket, next: (err?: any) => void) => {
|
@namespace('/', (socket: io.Socket, next: (err?: any) => void) => {
|
||||||
console.log(socket.nsp.name, socket.id, 'before connection');
|
console.log(socket.nsp.name, socket.id, 'before connection');
|
||||||
@ -31,3 +33,17 @@ export class Namespace extends interfaces.Namespace {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@controller('/websocket')
|
||||||
|
export class WebSocketController {
|
||||||
|
@lazyInjectNamed(TYPE.Namespace, Namespace.name)
|
||||||
|
private root: Namespace;
|
||||||
|
|
||||||
|
@httpPost('/')
|
||||||
|
public async create(
|
||||||
|
@requestBody() model: Object
|
||||||
|
): Promise<Object> {
|
||||||
|
this.root.nsp.send(JSON.stringify(model));
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,38 +1,82 @@
|
|||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import * as http from 'http'
|
import * as fs from 'fs';
|
||||||
|
import * as http from 'http';
|
||||||
|
import * as globby from "globby";
|
||||||
import * as express from "express";
|
import * as express from "express";
|
||||||
import * as prettyjson from "prettyjson";
|
import * as prettyjson from "prettyjson";
|
||||||
import * as bodyParser from 'body-parser';
|
import * as bodyParser from 'body-parser';
|
||||||
import { buildWebSocket, io } from '@cc-server/ws'
|
import { buildWebSocket, io, getNamespaceInfo } from '@cc-server/ws'
|
||||||
import { buildProviderModule, Container } from '@cc-server/ioc';
|
import { buildProviderModule, Container, initContainer, getContainer } from '@cc-server/ioc';
|
||||||
import { InversifyExpressServer, interfaces, getRouteInfo, rebuildServer } from '@cc-server/binding'
|
import { InversifyExpressServer, getRouteInfo, rebuildServer, controller, httpGet } from '@cc-server/binding';
|
||||||
|
|
||||||
export { io, http, express }
|
export { http, express }
|
||||||
|
|
||||||
|
@controller('/actuator')
|
||||||
|
class Actuator {
|
||||||
|
@httpGet('/mappings')
|
||||||
|
private mappings() {
|
||||||
|
return {
|
||||||
|
http: getRouteInfo(getContainer()),
|
||||||
|
websocket: getNamespaceInfo()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class CcServerBoot {
|
export class CcServerBoot {
|
||||||
private _container: Container;
|
private _container: Container;
|
||||||
private _server: http.Server;
|
private _server: http.Server;
|
||||||
private _serverInstance: express.Application;
|
private _serverInstance: express.Application;
|
||||||
private _serverInversify: InversifyExpressServer;
|
private _serverInversify: InversifyExpressServer;
|
||||||
private _wsServer: io.Server;
|
private _serverWebsocket: io.Server;
|
||||||
|
private _beforeUse: express.RequestHandler[] = [];
|
||||||
|
private _afterUse: express.ErrorRequestHandler[] = [];
|
||||||
|
|
||||||
constructor(container?: Container) {
|
constructor(container?: Container) {
|
||||||
this._container = container || new Container();
|
this._container = container || this.$createContainer();
|
||||||
this._serverInstance = express();
|
this._serverInstance = this.$createExpressServer();
|
||||||
this._server = http.createServer(this._serverInstance);
|
this._server = this.$createServer();
|
||||||
// start the server
|
this._serverInversify = this.$createInversifyServer();
|
||||||
this._serverInversify = new InversifyExpressServer(this._container, null, null, this._serverInstance);
|
this._serverWebsocket = this.$createWebsocketServer();
|
||||||
this._serverInversify.setConfig((app) => {
|
initContainer(this._container);
|
||||||
app.use(bodyParser.urlencoded({
|
}
|
||||||
extended: true
|
|
||||||
}));
|
protected $createContainer(): Container {
|
||||||
app.use(bodyParser.json());
|
return new Container();
|
||||||
app.use(bodyParser.raw());
|
}
|
||||||
});
|
|
||||||
this._wsServer = io(this._server, {
|
protected $createServer(): http.Server {
|
||||||
|
return http.createServer(this._serverInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected $createExpressServer(): express.Application {
|
||||||
|
return express();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected $createInversifyServer(): InversifyExpressServer {
|
||||||
|
return new InversifyExpressServer(this._container, null, null, this._serverInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected $createWebsocketServer(): io.Server {
|
||||||
|
return io(this._server, {
|
||||||
path: '/ws',
|
path: '/ws',
|
||||||
serveClient: false,
|
serveClient: false,
|
||||||
})
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected use(middleware: express.RequestHandler) {
|
||||||
|
this._beforeUse.push(middleware)
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected error(middleware: express.ErrorRequestHandler) {
|
||||||
|
this._afterUse.push(middleware)
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected $onMountingMiddlewares() {
|
||||||
|
this.use(bodyParser.urlencoded({ extended: true }))
|
||||||
|
.use(bodyParser.json())
|
||||||
|
.use(bodyParser.raw());
|
||||||
}
|
}
|
||||||
|
|
||||||
get server() {
|
get server() {
|
||||||
@ -48,23 +92,34 @@ export class CcServerBoot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get websocket() {
|
get websocket() {
|
||||||
return this._wsServer;
|
return this._serverWebsocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setConfig(fn: interfaces.ConfigFunction) {
|
public static(root: string = 'public') {
|
||||||
this._serverInversify.setConfig(fn)
|
this.express.use(express.static(root));
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public setErrorConfig(fn: interfaces.ConfigFunction) {
|
public scan(path: fs.PathLike) {
|
||||||
this._serverInversify.setErrorConfig(fn)
|
let files = fs.readdirSync(path);
|
||||||
|
for (const file of files) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public build() {
|
public build() {
|
||||||
|
this.$onMountingMiddlewares();
|
||||||
|
this._serverInversify.setConfig((app) => {
|
||||||
|
this._beforeUse.every(m => app.use(m))
|
||||||
|
})
|
||||||
|
this._serverInversify.setErrorConfig((app) => {
|
||||||
|
this._afterUse.every(m => app.use(m))
|
||||||
|
})
|
||||||
this._container.load(buildProviderModule());
|
this._container.load(buildProviderModule());
|
||||||
this._serverInstance = this._serverInversify.build();
|
this._serverInstance = this._serverInversify.build();
|
||||||
rebuildServer(this._container);
|
rebuildServer(this._container);
|
||||||
buildWebSocket(this._container, this._wsServer);
|
buildWebSocket(this._container, this._serverWebsocket);
|
||||||
return this._serverInstance;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public start(port: number = 80) {
|
public start(port: number = 80) {
|
||||||
|
@ -3,9 +3,4 @@ import { CcServerBoot, express } from './index'
|
|||||||
import './function/http';
|
import './function/http';
|
||||||
import './function/websocket';
|
import './function/websocket';
|
||||||
|
|
||||||
let server = new CcServerBoot();
|
new CcServerBoot().static('public').build().start();
|
||||||
|
|
||||||
server.express.use(express.static('public'));
|
|
||||||
|
|
||||||
server.build();
|
|
||||||
server.start();
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
|
"registry": "https://repo.yumc.pw/repository/npm-hosted/"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"watch": "npx tsc --watch",
|
||||||
"build": "rimraf dist && npx tsc",
|
"build": "rimraf dist && npx tsc",
|
||||||
"test": "echo \"Error: run tests from root\" && exit 1"
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
||||||
},
|
},
|
||||||
|
104
packages/ioc/src/decorators.ts
Normal file
104
packages/ioc/src/decorators.ts
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import { interfaces, Container } from "inversify";
|
||||||
|
|
||||||
|
let _container: Container;
|
||||||
|
|
||||||
|
const CONTAINER = Symbol.for("@cc-server/ioc:Container");
|
||||||
|
const INJECTION = Symbol.for("INJECTION");
|
||||||
|
|
||||||
|
function _proxyGetter(
|
||||||
|
proto: any,
|
||||||
|
key: string,
|
||||||
|
resolve: () => any,
|
||||||
|
doCache: boolean
|
||||||
|
) {
|
||||||
|
function getter() {
|
||||||
|
if (doCache && !Reflect.hasMetadata(INJECTION, this, key)) {
|
||||||
|
Reflect.defineMetadata(INJECTION, resolve(), this, key);
|
||||||
|
}
|
||||||
|
if (Reflect.hasMetadata(INJECTION, this, key)) {
|
||||||
|
return Reflect.getMetadata(INJECTION, this, key);
|
||||||
|
} else {
|
||||||
|
return resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setter(newVal: any) {
|
||||||
|
Reflect.defineMetadata(INJECTION, newVal, this, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.defineProperty(proto, key, {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get: getter,
|
||||||
|
set: setter
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function initContainer(container: Container) {
|
||||||
|
Reflect.defineMetadata(CONTAINER, container, Reflect);
|
||||||
|
_container = container;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContainer(): Container {
|
||||||
|
return _container || Reflect.getMetadata(CONTAINER, Reflect)
|
||||||
|
}
|
||||||
|
|
||||||
|
function makePropertyInjectDecorator(doCache: boolean) {
|
||||||
|
return function(serviceIdentifier: interfaces.ServiceIdentifier<any>) {
|
||||||
|
return function(proto: any, key: string): void {
|
||||||
|
let resolve = () => {
|
||||||
|
return getContainer().get(serviceIdentifier);
|
||||||
|
};
|
||||||
|
_proxyGetter(proto, key, resolve, doCache);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function makePropertyInjectNamedDecorator(doCache: boolean) {
|
||||||
|
return function(serviceIdentifier: interfaces.ServiceIdentifier<any>, named: string) {
|
||||||
|
return function(proto: any, key: string): void {
|
||||||
|
let resolve = () => {
|
||||||
|
return getContainer().getNamed(serviceIdentifier, named);
|
||||||
|
};
|
||||||
|
_proxyGetter(proto, key, resolve, doCache);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function makePropertyInjectTaggedDecorator(doCache: boolean) {
|
||||||
|
return function(serviceIdentifier: interfaces.ServiceIdentifier<any>, key: string, value: any) {
|
||||||
|
return function(proto: any, propertyName: string): void {
|
||||||
|
let resolve = () => {
|
||||||
|
return getContainer().getTagged(serviceIdentifier, key, value);
|
||||||
|
};
|
||||||
|
_proxyGetter(proto, propertyName, resolve, doCache);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function makePropertyMultiInjectDecorator(doCache: boolean) {
|
||||||
|
return function(serviceIdentifier: interfaces.ServiceIdentifier<any>) {
|
||||||
|
return function(proto: any, key: string): void {
|
||||||
|
let resolve = () => {
|
||||||
|
return getContainer().getAll(serviceIdentifier);
|
||||||
|
};
|
||||||
|
_proxyGetter(proto, key, resolve, doCache);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let doCache = true;
|
||||||
|
|
||||||
|
let lazyInject = makePropertyInjectDecorator(doCache)
|
||||||
|
let lazyInjectNamed = makePropertyInjectNamedDecorator(doCache)
|
||||||
|
let lazyInjectTagged = makePropertyInjectTaggedDecorator(doCache)
|
||||||
|
let lazyMultiInject = makePropertyMultiInjectDecorator(doCache)
|
||||||
|
|
||||||
|
export {
|
||||||
|
initContainer,
|
||||||
|
getContainer,
|
||||||
|
lazyInject,
|
||||||
|
lazyInjectNamed,
|
||||||
|
lazyInjectTagged,
|
||||||
|
lazyMultiInject
|
||||||
|
};
|
@ -1,17 +1,20 @@
|
|||||||
import "reflect-metadata";
|
import "reflect-metadata";
|
||||||
import { Container, inject, interfaces, injectable, postConstruct } from 'inversify';
|
import { interfaces } from 'inversify';
|
||||||
import { autoProvide, provide, fluentProvide, buildProviderModule } from 'inversify-binding-decorators';
|
import { fluentProvide } from 'inversify-binding-decorators';
|
||||||
|
|
||||||
const provideNamed = (identifier: interfaces.ServiceIdentifier<any>, name: string) => {
|
const provideNamed = (identifier: interfaces.ServiceIdentifier<any>, name: string) => {
|
||||||
return fluentProvide(identifier)
|
return fluentProvide(identifier).whenTargetNamed(name).done();
|
||||||
.whenTargetNamed(name)
|
|
||||||
.done();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const provideSingleton = (identifier: interfaces.ServiceIdentifier<any>) => {
|
const provideSingleton = (identifier: interfaces.ServiceIdentifier<any>) => {
|
||||||
return fluentProvide(identifier)
|
return fluentProvide(identifier).inSingletonScope().done();
|
||||||
.inSingletonScope()
|
|
||||||
.done();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export { autoProvide, provide, provideNamed, provideSingleton, Container, inject, injectable, postConstruct, buildProviderModule };
|
export * from 'inversify'
|
||||||
|
export * from './decorators'
|
||||||
|
export * from 'inversify-binding-decorators'
|
||||||
|
export {
|
||||||
|
fluentProvide,
|
||||||
|
provideNamed,
|
||||||
|
provideSingleton
|
||||||
|
};
|
||||||
|
19
packages/ws/src/debug.ts
Normal file
19
packages/ws/src/debug.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { getNamespacesMetadata, getNamespaceMetadata, getNamespaceListenerMetadata } from './utils'
|
||||||
|
|
||||||
|
export function getNamespaceInfo() {
|
||||||
|
let namespaces = getNamespacesMetadata();
|
||||||
|
console.log(namespaces)
|
||||||
|
return namespaces.map(namespace => {
|
||||||
|
let listenerMetadata = getNamespaceListenerMetadata(namespace.target);
|
||||||
|
console.log(namespace, listenerMetadata)
|
||||||
|
return {
|
||||||
|
namespace: namespace.name,
|
||||||
|
listeners: listenerMetadata.map(listener => {
|
||||||
|
return {
|
||||||
|
event: listener.name,
|
||||||
|
method: listener.key,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -1,7 +1,8 @@
|
|||||||
import { inject, injectable, decorate } from "inversify";
|
import { inject, injectable, decorate } from "inversify";
|
||||||
import { interfaces } from './interfaces'
|
import { interfaces } from './interfaces'
|
||||||
import { METADATA_KEY } from './constants'
|
import { METADATA_KEY, TYPE } from './constants'
|
||||||
import { getNamespaceListenerMetadata, getNamespacesMetadata } from './utils'
|
import { getNamespaceListenerMetadata, getNamespacesMetadata } from './utils'
|
||||||
|
import { provideNamed, fluentProvide } from "@cc-server/ioc/src";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Socket.io Namespace
|
* Socket.io Namespace
|
||||||
@ -16,6 +17,10 @@ export function namespace(name?: string, ...middleware: interfaces.Middleware[])
|
|||||||
target: target
|
target: target
|
||||||
};
|
};
|
||||||
decorate(injectable(), target);
|
decorate(injectable(), target);
|
||||||
|
//decorate(fluentProvide(TYPE.Namespace)
|
||||||
|
// .inSingletonScope()
|
||||||
|
// .whenTargetNamed(target.constructor.name)
|
||||||
|
// .done(), target);
|
||||||
Reflect.defineMetadata(METADATA_KEY.namespace, currentMetadata, target);
|
Reflect.defineMetadata(METADATA_KEY.namespace, currentMetadata, target);
|
||||||
const previousMetadata: interfaces.NamespaceMetadata[] = getNamespacesMetadata();
|
const previousMetadata: interfaces.NamespaceMetadata[] = getNamespacesMetadata();
|
||||||
Reflect.defineMetadata(METADATA_KEY.namespace, [currentMetadata, ...previousMetadata], Reflect);
|
Reflect.defineMetadata(METADATA_KEY.namespace, [currentMetadata, ...previousMetadata], Reflect);
|
||||||
|
@ -3,5 +3,7 @@ import * as io from 'socket.io'
|
|||||||
export * from './builder'
|
export * from './builder'
|
||||||
export * from './decorators'
|
export * from './decorators'
|
||||||
export * from './interfaces'
|
export * from './interfaces'
|
||||||
|
export * from './debug'
|
||||||
|
export { TYPE } from './constants'
|
||||||
export { getSocketContext } from './utils'
|
export { getSocketContext } from './utils'
|
||||||
export { io }
|
export { io }
|
||||||
|
Loading…
Reference in New Issue
Block a user