This commit is contained in:
sx1989827 2021-08-09 23:08:08 +08:00
parent 38341827a8
commit ffaecc5b86
77 changed files with 1004 additions and 314 deletions

View File

@ -4,14 +4,18 @@ export enum ECommon_HttpApi_Method {
DELETE="DELETE",
PUT="PUT"
}
export interface ICommon_Http_Route {
method:ECommon_HttpApi_Method,
path:string,
req:any,
res:any,
ignoreValidate?:boolean
}
export interface ICommon_HttpApi {
baseUrl:string,
routes:{
[param:string]:{
method:ECommon_HttpApi_Method,
path:string,
req:any,
res:any
}
[param:string]:ICommon_Http_Route
}
}

View File

@ -1,6 +1,6 @@
import { ICommon_Http_User_Test_Res } from "./userRes";
import {ECommon_HttpApi_Method, ICommon_HttpApi} from "./types"
const api:ICommon_HttpApi={
const api={
baseUrl:"/user",
routes:{
test:{
@ -10,7 +10,7 @@ const api:ICommon_HttpApi={
name:string,
age:number
}>{},
res:<ICommon_Http_User_Test_Res>{}
res:<ICommon_Http_User_Test_Res>{},
}
}
}

View File

@ -0,0 +1,6 @@
export default {
overUploadFileSize:{
code:1,
msg:"over up;oad file size"
}
}

3
code/common/status/ok.ts Normal file
View File

@ -0,0 +1,3 @@
export default {
ok:"operation successful"
}

View File

@ -1,4 +1,7 @@
import { Rpc } from './../rpc/rpc';
import { IServer_Common_Config_Base } from "../types/config";
import { init } from "../util/init";
import { getNacosInstance } from '../nacos/nacos';
export default abstract class Application{
Application(){
@ -6,6 +9,9 @@ export default abstract class Application{
}
async start() {
await init()
if(getNacosInstance().rpcServer) {
await Rpc.start(getNacosInstance().serverPort)
}
await this.config();
}
async config(){}

View File

@ -1,8 +1,8 @@
import IServer_Mysql_Model_Issue_Type, { Issue_Type_Table } from './../model/mysql/issue_type';
import IServer_DB_Model_Issue_Type, { Table_Issue_Type } from './../model/mysql/issue_type';
import { getMysqlInstance } from "../mysql";
export async function getIssueTypeListMapper() {
var mysql=getMysqlInstance()
var ret=await mysql.execute<IServer_Mysql_Model_Issue_Type[]>(`select * from ${Issue_Type_Table}`)
var ret=await mysql.execute<IServer_DB_Model_Issue_Type[]>(`select * from ${Table_Issue_Type}`)
return ret
}

View File

@ -0,0 +1,10 @@
export default interface IServer_DB_Model_Comment {
id:bigint,
type:number,
type_id:bigint,
user_id:bigint,
content:string,
created_time:number,
modified_time:number
}
export const Table_Comment="comment"

View File

@ -0,0 +1,12 @@
export default interface IServer_DB_Model_Field {
id:bigint,
type_id:bigint,
system:number,
description:string,
created_time:number,
modified_time:number,
created_by:bigint,
modified_by:bigint,
name:string
}
export const Table_Field="field"

View File

@ -0,0 +1,10 @@
export default interface IServer_DB_Model_Field_Component {
id:bigint,
description:string,
created_time:number,
modified_time:number,
created_by:bigint,
modified_by:bigint,
name:string
}
export const Table_Field_Component="field_component"

View File

@ -0,0 +1,12 @@
export default interface IServer_DB_Model_Field_Component_Field {
id:bigint,
type_id:bigint,
system:number,
description:string,
created_time:number,
modified_time:number,
created_by:bigint,
modified_by:bigint,
name:string
}
export const Table_Field_Component_Field="field_component_field"

View File

@ -0,0 +1,8 @@
export default interface IServer_DB_Model_Field_Config_Value {
id: bigint,
field_id :bigint,
value :string,
sort :number,
label :string,
}
export const Table_Field_Config_Value="field_config_value"

View File

@ -0,0 +1,11 @@
export default interface IServer_DB_Model_Field_Solution {
id :bigint,
created_time :number,
modified_time :number ,
created_by :bigint,
modified_by: bigint,
name :string,
description :string,
system :number,
}
export const Table_Field_Solution="field_solution"

View File

@ -0,0 +1,7 @@
export default interface IServer_DB_Model_Field_Solution_Config_Or_Field {
id :bigint,
type :number,
field_solution_id :bigint,
component_or_field_id :bigint,
}
export const Table_Field_Solution_Config_Or_Field="field_solution_config_or_field"

View File

@ -0,0 +1,6 @@
export default interface IServer_DB_Model_Field_Solution_Workflow {
id: bigint,
field_solution_id :bigint,
workflow_id :bigint,
}
export const Table_Field_Solution_Workflow="field_solution_workflow"

View File

@ -0,0 +1,11 @@
export default interface IServer_DB_Model_Field_Solution_Workflow_Action {
id :bigint,
field_solution :bigint ,
workflow_action_id :bigint ,
field :bigint,
optional :number,
default_value :string,
multi :number,
sort :number,
}
export const Table_Field_Solution_Workflow_Action="field_solution_workflow_action"

View File

@ -0,0 +1,8 @@
export default interface IServer_DB_Model_Field_Type {
id :bigint,
name :string,
icon :bigint,
description :string,
multi :number,
}
export const Table_Field_Type="field_type"

View File

@ -0,0 +1,11 @@
export default interface IServer_DB_Model_File {
id :bigint,
user_id :bigint,
project_id :bigint ,
size: bigint ,
filename :string,
type :string,
created_time :number,
path :string,
}
export const Table_File="file"

View File

@ -0,0 +1,8 @@
export default interface IServer_DB_Model_Group {
id :bigint ,
name :string,
created_time :number,
modified_time :number,
created_by :bigint ,
}
export const Table_Group="group"

View File

@ -1,8 +1,8 @@
export default interface IServer_Mysql_Model_Issue_Type {
export default interface IServer_DB_Model_Issue_Type {
id:bigint,
name:string,
icon:bigint,
description:string,
multi:number
}
export const Issue_Type_Table="issue_type"
export const Table_Issue_Type="issue_type"

View File

@ -0,0 +1,11 @@
export default interface IServer_DB_Model_Issue_Type_Solution {
id :bigint ,
name :string,
description :string,
system :number,
created_time :number,
modify_time :number,
created_by :bigint ,
modified_by :bigint ,
}
export const Table_Issue_Type_Solution="issue_type_solution"

View File

@ -0,0 +1,6 @@
export default interface IServer_DB_Model_Issue_Type {
id :bigint ,
issue_type_id :bigint,
issue_type_solution_id :bigint,
}
export const Table_Issue_Type="issue_type"

View File

@ -0,0 +1,9 @@
export default interface IServer_DB_Model_Permission {
id: bigint,
name :string,
created_time :number,
modified_time :number,
type :number,
value :number,
}
export const Table_Permission="permission"

View File

@ -0,0 +1,9 @@
export default interface IServer_DB_Model_Permission_Target {
id :bigint,
permission_id: bigint,
target_id :bigint,
target_type :number,
item_id :bigint,
item_type :number,
}
export const Table_Permission_Target="permission_target"

View File

@ -0,0 +1,11 @@
export default interface IServer_DB_Model_Project {
id :bigint,
key :string,
name :string,
created_time :number,
modified_time :number,
image :bigint,
created_by :bigint ,
description :string,
}
export const Table_Project="project"

View File

@ -0,0 +1,6 @@
export default interface IServer_DB_Model_Project_Field_Solution {
id: bigint,
project_id :bigint ,
field_solution_id :bigint ,
}
export const Table_Project_Field_Solution="project_field_solution"

View File

@ -0,0 +1,15 @@
export default interface IServer_DB_Model_Project_Issue {
unique_id :number,
id :bigint ,
created_time :number,
modified_time :number,
created_by :bigint ,
modified_by :bigint ,
project_id :bigint ,
issue_type_id :bigint ,
name :string,
priority :number,
assigner_id :bigint ,
reporter_id :bigint ,
}
export const Table_Project_Issue="project_issue"

View File

@ -0,0 +1,6 @@
export default interface IServer_DB_Model_Project_Issue_Description {
id :bigint,
project_issue_id :bigint,
content:string
}
export const Table_Project_Issue_Description="project_issue_description"

View File

@ -0,0 +1,8 @@
export default interface IServer_DB_Model_Project_Issue_Field_Value {
id :bigint,
project_issue_id :bigint,
field_id :bigint,
value :string,
sort :number,
}
export const Table_Project_Issue_Field_Value="project_issue_field_value"

View File

@ -0,0 +1,6 @@
export default interface IServer_DB_Model_Project_Issue_Parent {
id :bigint,
parent_id :bigint,
child_id:bigint
}
export const Table_Project_Issue_Parent="project_issue_parent"

View File

@ -0,0 +1,6 @@
export default interface IServer_DB_Model_Project_Issue_Related {
id :bigint,
project_issue_1_id :bigint,
project_issue_2_id:bigint
}
export const Table_Project_Issue_Related="project_issue_related"

View File

@ -0,0 +1,6 @@
export default interface IServer_DB_Model_Project_Issue_Solution {
id :bigint,
project_id :bigint,
issue_solution_id:bigint
}
export const Table_Project_Issue_Solution="project_issue_solution"

View File

@ -0,0 +1,5 @@
export default interface IServer_DB_Model_Project_Lable {
id :bigint,
name:string
}
export const Table_Project_Label="project_label"

View File

@ -0,0 +1,6 @@
export default interface IServer_DB_Model_Project_Lable_Issue {
id :bigint,
project_label_id:bigint,
project_issue_id:bigint
}
export const Table_Project_Label_Issue="project_label_issue"

View File

@ -0,0 +1,5 @@
export default interface IServer_DB_Model_Project_Module {
id :bigint,
name:string
}
export const Table_Project_Module="project_module"

View File

@ -0,0 +1,6 @@
export default interface IServer_DB_Model_Project_Module_Issue {
id :bigint,
project_module_id:bigint,
project_issue_id:bigint
}
export const Table_Project_Module_Issue="project_module_issue"

View File

@ -0,0 +1,6 @@
export default interface IServer_DB_Model_Project_Module_Parent {
id :bigint,
parent_id:bigint,
child_id:bigint
}
export const Table_Project_Module_Parent="project_module_parent"

View File

@ -0,0 +1,14 @@
export default interface IServer_DB_Model_Project_Release {
id :bigint ,
name :string,
start_time :number,
release_time :number,
description :string,
created_time :number,
modify_time :number,
created_by :bigint ,
modified_by :bigint,
status :number,
project_id :bigint,
}
export const Table_Project_Release="project_release"

View File

@ -0,0 +1,6 @@
export default interface IServer_DB_Model_Project_Release_Issue {
id :bigint ,
project_release_id :bigint,
project_issue_id:bigint
}
export const Table_Project_Release_Issue="project_release_issue"

View File

@ -0,0 +1,9 @@
export default interface IServer_DB_Model_Project_User {
id :bigint,
permission :bigint ,
created_time :number,
modified_time :number,
project_id :bigint ,
user_id :bigint ,
}
export const Table_Project_User="project_user"

View File

@ -0,0 +1,6 @@
export default interface IServer_DB_Model_Project_Workflow_Solution {
id :bigint,
project_id :bigint ,
workflow_solution_id :bigint ,
}
export const Table_Project_Workflow_Solution="project_workflow_solution"

View File

@ -0,0 +1,7 @@
export default interface IServer_DB_Model_Role {
id :bigint,
name :string,
created_time :number,
modified_time :number,
}
export const Table_Role="role"

View File

@ -0,0 +1,6 @@
export default interface IServer_DB_Model_Role_Permission {
role_id :bigint,
permission_id :bigint,
id :bigint ,
}
export const Table_Role_Permission="role_permission"

View File

@ -0,0 +1,13 @@
export default interface IServer_DB_Model_User {
id :bigint,
username :string,
email :string,
phone :string,
created_time :number,
modified_time :number,
password :string,
sign :string,
location :string,
title :string,
}
export const Table_User="user"

View File

@ -0,0 +1,6 @@
export default interface IServer_DB_Model_User_Has_Group {
user_id :bigint,
group_id :bigint,
id :bigint ,
}
export const Table_User_Has_Group="user_has_group"

View File

@ -0,0 +1,6 @@
export default interface IServer_DB_Model_User_Role {
user_id :bigint,
role_id :bigint,
id :bigint ,
}
export const Table_User_Role="user_role"

View File

@ -0,0 +1,10 @@
export default interface IServer_DB_Model_User_Setting {
id :bigint ,
key :string,
value :string,
type :number,
created_time :number,
modified_time :number,
user_id :bigint,
}
export const Table_User_Setting="user_setting"

View File

@ -0,0 +1,11 @@
export default interface IServer_DB_Model_Workflow {
id :bigint ,
name :string,
description :string,
system :number,
created_time :number,
modified_time :number,
created_by :bigint ,
modified_by :bigint ,
}
export const Table_Workflow="workflow"

View File

@ -0,0 +1,10 @@
export default interface IServer_DB_Model_Workflow_Action {
id :bigint ,
name :string,
system :number,
description :string,
source_node_id :bigint ,
dest_node_id :bigint ,
workflow_id :bigint,
}
export const Table_Workflow_Action="workflow_action"

View File

@ -0,0 +1,9 @@
export default interface IServer_DB_Model_Workflow_Node {
id :bigint ,
name :string,
description :string,
system :number,
status :number,
workflow_id :bigint ,
}
export const Table_Workflow_Node="workflow_node"

View File

@ -0,0 +1,11 @@
export default interface IServer_DB_Model_Workflow_Solution {
id :bigint ,
created_time :number,
modified_time :number,
created_by :bigint ,
modified_by :bigint,
system :number,
name :string,
description :string,
}
export const Table_Workflow_Solution="workflow_solution"

View File

@ -0,0 +1,7 @@
export default interface IServer_DB_Model_Workflow_Solution_Issue_Type {
id :bigint,
workflow_solution_id :bigint,
workflow_id :bigint ,
issue_type_id :bigint ,
}
export const Table_Workflow_Solution_Issue_Type="workflow_solution_issue_type"

View File

@ -0,0 +1,43 @@
import { IServer_Common_Http_Proxy } from './../types/http';
import Cookie, { IServer_Common_Cookie_Option } from "./cookie";
import HttpHeader from "./header";
import HttpStatus from "./status";
export default class HttpContext {
private cookie:Cookie;
private header:HttpHeader;
private status:HttpStatus
constructor(obj:IServer_Common_Http_Proxy){
this.cookie=new Cookie(obj.headers["cookie"])
this.header=new HttpHeader(obj.headers)
this.status=new HttpStatus()
}
setHeader(key:string,value:string){
this.header.set(key,value)
}
getHeader(key:string){
return this.header.get(key)
}
getCookie(key:string){
return this.cookie.get(key)
}
setCookie(key:string,value:string,option?:IServer_Common_Cookie_Option){
this.cookie.set(key,value,option)
}
setStatus(status:number){
this.status.set(status)
}
redirect(uri:string) {
this.setStatus(320);
this.setHeader("Location",uri);
}
get cookieValue() {
return this.cookie.values;
}
get headerValue(){
return this.header.values;
}
get statusValue() {
return this.status.value;
}
}

View File

@ -0,0 +1,77 @@
export interface IServer_Common_Cookie_Option {
expires:string,
maxAge:string,
secure:boolean,
httpOnly:boolean,
domain:string,
path:string,
sameSite:string
}
export default class Cookie {
private bChange=false;
private incomingCookies={}
private outcomingCookies:{
[param:string]:{
value:string,
option:IServer_Common_Cookie_Option
}
}={}
constructor(str:string){
if(!str)
{
return;
}
let key_values =str.split(";")
for(let obj of key_values) {
obj=obj.trim()
let key_value=obj.split("=")
this.incomingCookies[key_value[0]]=key_value[1]
}
}
get(key:string):string{
return this.incomingCookies[key];
}
set(key:string,value:string,option?:IServer_Common_Cookie_Option) {
this.bChange=true
this.outcomingCookies[key]={
value:value,
option:option
}
}
get isChange () {
return this.bChange;
}
get values():string[] {
let ret=[]
for(let key in this.outcomingCookies) {
let obj=this.outcomingCookies[key]
let arr=[]
arr.push(`${key}=${obj.value}`)
if(obj.option) {
if(obj.option.domain){
arr.push(`Domain=${obj.option.domain}`)
}
if(obj.option.path){
arr.push(`Path=${obj.option.path}`)
}
if(obj.option.expires){
arr.push(`Expires=${obj.option.expires}`)
}
if(obj.option.maxAge){
arr.push(`Max-Age=${obj.option.maxAge}`)
}
if(obj.option.secure){
arr.push(`Secure}`)
}
if(obj.option.httpOnly){
arr.push(`HttpOnly`)
}
if(obj.option.sameSite){
arr.push(`SameSite=${obj.option.sameSite}`)
}
}
ret.push(arr.join("; "))
}
return ret;
}
}

View File

@ -0,0 +1,24 @@
export default class HttpHeader {
private incomingHeaders:{
[param:string]:string
}={}
private outcomingHeaders:{
[param:string]:string
}={}
constructor(headers:{
[param:string]:string
}){
for(let key in headers){
this.incomingHeaders[key]=headers[key]
}
}
get(key:string){
return this.incomingHeaders[key]
}
set(key:string,value:string){
this.outcomingHeaders[key]=value
}
get values(){
return this.outcomingHeaders
}
}

View File

@ -1,72 +1,54 @@
import { EServer_Common_Http_Structure_HandleParam_Category, IServer_Common_Http_Structure, IServer_Common_Http_Structure_HandleParam } from "../types/http";
import { ICommon_Http_Route } from './../../../common/routes/types';
import { EServer_Common_Http_Structure_HandleParam_Category, IServer_Common_Http_Proxy, IServer_Common_Http_Req_File, IServer_Common_Http_Structure, IServer_Common_Http_Structure_HandleParam } from "../types/http";
import "reflect-metadata"
import { Context } from "koa";
import { ICommon_HttpApi } from "../../../common/routes/types";
import HttpContext from "./context"
var g_objRoute:{
[param:string]:IServer_Common_Http_Structure[]
[param:string]:IServer_Common_Http_Structure
}={}
var g_objParam:{
[param:string]:IServer_Common_Http_Structure_HandleParam[]
}={}
var g_objController=new WeakMap
export function HttpCookies(target: Object, propertyKey: string, parameterIndex: number){
let key=target.constructor.name+"::"+propertyKey
let obj:IServer_Common_Http_Structure_HandleParam={
name:null,
index:parameterIndex,
type:null,
category:EServer_Common_Http_Structure_HandleParam_Category.Cookie
}
if(!g_objParam[key]){
g_objParam[key]=[]
}
g_objParam[key].unshift(obj)
export function getHttpRoutes() {
return g_objRoute;
}
export function HttpController(obj:ICommon_HttpApi){
return function(target:Function) {
let name=target.name.toLocaleLowerCase()
let baseUrl=obj.baseUrl
let category=baseUrl.substr(1).toLocaleLowerCase()
if(!g_objRoute[name] || name===category)
{
if(name==category)
{
g_objController.set(target,category)
}
return
}
if(!g_objRoute[category])
{
g_objRoute[category]=[]
}
g_objRoute[category]=g_objRoute[category].concat(g_objRoute[name])
delete g_objRoute[name]
g_objController.set(target,category)
}
}
export function HttpApi(objParam) {
export function DHttpApi(objParam:ICommon_Http_Route) {
return function (target,propertyKey:string,desc:PropertyDescriptor) {
let name=target.constructor.name.toLocaleLowerCase()
let obj=g_objRoute[name]
if(!obj)
{
g_objRoute[name]=[]
obj=g_objRoute[name]
}
let name=objParam.method+" "+objParam.path
let key=target.constructor.name+"::"+propertyKey
let handle=desc.value
let handle=desc.value.bind(target)
let temp:IServer_Common_Http_Structure={
...<any>objParam,
method:objParam.method,
path:objParam.path,
ignoreValidate:objParam.ignoreValidate,
handle:handle,
handleParam:g_objParam[key]
}
obj.push(temp)
g_objRoute[name]=temp
}
}
export function HttpReqParam(name:string,defalutValue?:any){
export function DHttpReqParamFile(name:string){
return function(target: Object, propertyKey: string, parameterIndex: number){
let types=Reflect.getMetadata("design:paramtypes",target,propertyKey);
let type=types[parameterIndex].name
let key=target.constructor.name+"::"+propertyKey
let obj:IServer_Common_Http_Structure_HandleParam={
name:name,
index:parameterIndex,
type:type,
category:EServer_Common_Http_Structure_HandleParam_Category.File
}
if(!g_objParam[key]){
g_objParam[key]=[]
}
g_objParam[key].unshift(obj)
}
}
export function DHttpReqParam(name:string,defalutValue?:any){
return function(target: Object, propertyKey: string, parameterIndex: number){
let types=Reflect.getMetadata("design:paramtypes",target,propertyKey);
let type=types[parameterIndex].name
@ -88,7 +70,7 @@ export function HttpReqParam(name:string,defalutValue?:any){
}
}
export function HttpReqParamRequired(name:string){
export function DHttpReqParamRequired(name:string){
return function(target: Object, propertyKey: string, parameterIndex: number){
let types=Reflect.getMetadata("design:paramtypes",target,propertyKey);
let type=types[parameterIndex].name
@ -107,45 +89,50 @@ export function HttpReqParamRequired(name:string){
}
}
export function HttpReqHeader(name:string,defalutValue?:any){
return function(target: Object, propertyKey: string, parameterIndex: number){
let types=Reflect.getMetadata("design:paramtypes",target,propertyKey);
export function DHttpContext(target: Object, propertyKey: string, parameterIndex: number){
let types=Reflect.getMetadata("design:paramtypes",target,propertyKey);
let type=types[parameterIndex].name
let key=target.constructor.name+"::"+propertyKey
let obj:IServer_Common_Http_Structure_HandleParam={
name:name,
name:null,
index:parameterIndex,
type:type,
category:EServer_Common_Http_Structure_HandleParam_Category.Header
}
if(defalutValue!==undefined)
{
obj["defaultValue"]=defalutValue
category:EServer_Common_Http_Structure_HandleParam_Category.Content
}
if(!g_objParam[key]){
g_objParam[key]=[]
}
g_objParam[key].unshift(obj)
}
}
export function getRouteApi(instance:Object):[string,IServer_Common_Http_Structure[]] {
let category=g_objController.get(instance.constructor)
let arr=g_objRoute[category]
return [category,arr]
export function DHttpContent(target: Object, propertyKey: string, parameterIndex: number){
let types=Reflect.getMetadata("design:paramtypes",target,propertyKey);
let type=types[parameterIndex].name
let key=target.constructor.name+"::"+propertyKey
let obj:IServer_Common_Http_Structure_HandleParam={
name:null,
index:parameterIndex,
type:type,
category:EServer_Common_Http_Structure_HandleParam_Category.Content
}
if(!g_objParam[key]){
g_objParam[key]=[]
}
g_objParam[key].unshift(obj)
}
export async function handleHttpCall(obj:IServer_Common_Http_Structure,ctx:Context,instance:any):Promise<any> {
export async function handleHttpCall(obj:IServer_Common_Http_Structure,ctx:IServer_Common_Http_Proxy):Promise<IServer_Common_Http_Proxy> {
let handle=obj.handle
handle=handle.bind(instance)
let arrHandleParam=obj.handleParam
let arrHandleParam=obj.handleParam??[]
let arr=[]
let objContext=new HttpContext(ctx)
for(let obj of arrHandleParam)
{
let name=obj.name
if(obj.category==EServer_Common_Http_Structure_HandleParam_Category.Param)
{
let value=ctx.state.p[name]
let value=ctx.data[name]
if(value===undefined || value===null)
{
if(obj.required)
@ -180,55 +167,41 @@ export async function handleHttpCall(obj:IServer_Common_Http_Structure,ctx:Conte
}
arr.push(value)
}
else if (obj.category==EServer_Common_Http_Structure_HandleParam_Category.Header)
else if(obj.category==EServer_Common_Http_Structure_HandleParam_Category.Context)
{
let value:any=ctx.headers[name]
if(value===undefined || value===null)
{
value=obj.defaultValue
arr.push(value)
continue
}
if(obj.type=="Number")
{
value=Number(value)
}
else if(obj.type=="Boolean")
{
if(value=="true" || (!isNaN(Number(value)) && Number(value) !=0))
{
value=true
}
else
{
value=false
}
}
else if(obj.type=="Object")
{
value=JSON.parse(value)
}
arr.push(value)
arr.push(objContext)
}
else if(obj.category==EServer_Common_Http_Structure_HandleParam_Category.Cookie)
else if(obj.category==EServer_Common_Http_Structure_HandleParam_Category.File)
{
arr.push(ctx.cookies)
let objFile:IServer_Common_Http_Req_File=ctx.data[name]
arr.push(objFile)
}
else if(obj.category==EServer_Common_Http_Structure_HandleParam_Category.Content)
{
let obj={};
for (let name in ctx.data) {
let value = ctx.data[name]
if (value === undefined || value === null) {
continue
}
obj[name]=value
}
arr.push(obj)
}
}
let objRet:any
let objRet:IServer_Common_Http_Proxy=<IServer_Common_Http_Proxy>{}
try {
let ret=await handle(...arr);
objRet={
code:0,
data:ret
}
}
catch(err)
{
objRet={
code:err.code,
msg:err.msg
objRet.data=ret;
objRet.status=objContext.statusValue;
objRet.headers=objContext.headerValue;
let cookies=objContext.cookieValue;
if(cookies.length>0) {
objRet.headers["set-cookie"]=JSON.stringify(cookies)
}
} catch(err) {
objRet.status=500;
objRet.data=err
}
return objRet
}

View File

@ -0,0 +1,9 @@
export default class HttpStatus {
private status=200;
set(status:number){
this.status=status
}
get value(){
return this.status
}
}

View File

@ -1,8 +1,10 @@
import * as log from "log4js"
import * as path from "path"
import * as os from "os"
import * as fs from "fs"
export class Log {
constructor() {
let filePath=path.resolve(os.homedir(),`teamlinker-log/${process.env.nacosNamespace}`,`teamlinker-${process.env.nacosName}.log`)
var config={
appenders:{
console:{
@ -10,22 +12,27 @@ export class Log {
},
file:{
type: 'file',
filename:path.resolve(os.homedir(),`teamlinker-log/${process.env.nacosNamespace}`,`teamlinker.log`),
filename:filePath,
maxLogSize:200*1024*1024,
encoding : 'utf-8'
}
},
},
categories:{
default:{
appenders:["console","file"],
level:"all"
},
[process.env.nacosName]:{
appenders:["console","file"],
level:"all"
}
}
}
log.configure(config)
let logger=log.getLogger();
let logger=log.getLogger(process.env.nacosName);
console.info=console.log=logger.info.bind(logger)
console.warn=console.warn.bind(logger)
console.error=console.error.bind(logger)
console.warn=logger.warn.bind(logger)
console.error=logger.error.bind(logger)
}
}

View File

@ -19,6 +19,7 @@ export default class Nacos<T extends IServer_Common_Config_Base> {
private nacosUrl:string
private nacosPort:number
private nacosNamespace:string
private objConfigCurrentService:any
constructor(url:string,port:number,name:string,configName:string,namesapce:string="public",logger=console)
{
this.nacosUrl=url;
@ -41,13 +42,20 @@ export default class Nacos<T extends IServer_Common_Config_Base> {
const content= await this.config.getConfig(this.configName, 'DEFAULT_GROUP');
const obj=JSON.parse(content)
this.objConfig=obj
this.objConfigCurrent=this.objConfig.services[this.name]
this.objConfigCurrentService=this.objConfig.services[this.name]
this.objConfigCurrent=this.objConfig.services[this.name].config
await this.client.ready()
await this.client.registerInstance(this.name, {
ip: this.objConfigCurrent.ip || '127.0.0.1',
port: this.objConfigCurrent.port,
ip: this.objConfigCurrentService.ip || '127.0.0.1',
port: this.objConfigCurrentService.port,
});
}
get serverPort():number {
return this.objConfigCurrentService.port
}
get rpcServer():boolean {
return this.objConfigCurrentService.rpcServer
}
get configInfo():T {
return this.objConfigCurrent
}

View File

@ -1,3 +1,4 @@
import { IServer_Common_Http_Proxy } from './../types/http';
import { IServer_Common_Nacos_Instance } from './../types/nacos';
import { EServer_Common_Config_Services } from './../types/config';
import { Redis } from '../cache/redis';
@ -5,10 +6,16 @@ import * as sio from "socket.io"
import * as ioClient from "socket.io-client"
import { REDIS_GATEWAY } from '../cache/keys/gateway';
import * as http from 'http';
import { getHttpRoutes, handleHttpCall } from '../http/http';
interface ISocketStruct {
name:string,
args:any[]
}
interface ISocketRPCResponseStruct {
code:number,
msg?:string,
data?:any
}
var g_RevieveFunc={
}
@ -28,14 +35,38 @@ export class Rpc{
transports: ['websocket', 'polling']
})
Rpc.io.on("connection",(socket)=>{
socket.on("data",async (arg:ISocketStruct,callback)=>{
socket.on("rpc-call",async (arg:ISocketStruct,callback)=>{
let funcName=arg.name
if(g_RevieveFunc[funcName] && g_RevieveInstance[funcName])
{
let ret=await g_RevieveFunc[funcName].apply(g_RevieveInstance[funcName],arg.args)
callback(ret)
let objRes=<ISocketRPCResponseStruct>{}
try {
let ret=await g_RevieveFunc[funcName].apply(g_RevieveInstance[funcName],arg.args)
objRes.code=0
objRes.data=ret
callback(objRes)
} catch (err) {
objRes.code=err.code
objRes.msg=err.msg;
callback(objRes)
}
}
})
socket.on("http-call",async (arg:IServer_Common_Http_Proxy,callback)=>{
let key=arg.method+ " " +arg.path
let objRoute=getHttpRoutes()
for(let keyRoute in objRoute) {
if(key==keyRoute){
let ret=await handleHttpCall(objRoute[keyRoute],arg)
callback(ret)
return
}
}
let obj:IServer_Common_Http_Proxy=<IServer_Common_Http_Proxy>{}
obj.status=404
callback(obj)
})
})
}
static async validInstance(name:string):Promise<IServer_Common_Nacos_Instance>
@ -46,13 +77,46 @@ export class Rpc{
}
}
export function RPCSend(rpcName:EServer_Common_Config_Services){
export async function proxyRequest(objProxy:IServer_Common_Http_Proxy,targetServer:EServer_Common_Config_Services):Promise<IServer_Common_Http_Proxy> {
return new Promise(async function(resolve,reject){
if(!g_Socket[targetServer] || !g_Socket[targetServer].connected)
{
if(g_Socket[targetServer] && !g_Socket[targetServer].connected) {
g_Socket[targetServer].close()
}
let instance=await Rpc.validInstance(targetServer)
if(!instance)
{
resolve(null)
return
}
let socket=ioClient.io(`ws://${instance.ip}:${instance.port}`)
g_Socket[targetServer]=socket
socket.on("connect",()=>{
socket.emit("http-call",objProxy,(res:IServer_Common_Http_Proxy)=>{
resolve(res)
})
})
}
else
{
g_Socket[targetServer].emit("http-call",objProxy,(res:IServer_Common_Http_Proxy)=>{
resolve(res)
})
}
})
}
export function DRPCSend(rpcName:EServer_Common_Config_Services){
return function (target: Object, propertyName: string, descriptor: TypedPropertyDescriptor<Function>) {
descriptor.value = function () {
let args=Array.from(arguments)
return new Promise(async function(resolve){
return new Promise(async function(resolve,reject){
if(!g_Socket[rpcName] || !g_Socket[rpcName].connected)
{
if(g_Socket[rpcName] && !g_Socket[rpcName].connected) {
g_Socket[rpcName].close()
}
let instance=await Rpc.validInstance(rpcName)
if(!instance)
{
@ -62,21 +126,39 @@ export function RPCSend(rpcName:EServer_Common_Config_Services){
let socket=ioClient.io(`ws://${instance.ip}:${instance.port}`)
g_Socket[rpcName]=socket
socket.on("connect",()=>{
socket.emit("data",<ISocketStruct>{
socket.emit("rpc-call",<ISocketStruct>{
name:propertyName,
args:args
},(res)=>{
resolve(res)
},(res:ISocketRPCResponseStruct)=>{
if(res.code==0)
{
resolve(res.data)
} else {
reject({
code:res.code,
msg:res.msg
})
}
})
})
}
else
{
g_Socket[rpcName].emit("data",<ISocketStruct>{
g_Socket[rpcName].emit("rpc-call",<ISocketStruct>{
name:propertyName,
args:args
},(res)=>{
resolve(res)
},(res:ISocketRPCResponseStruct)=>{
if(res.code==0)
{
resolve(res.data)
} else {
reject({
code:res.code,
msg:res.msg
})
}
})
}
})
@ -84,7 +166,7 @@ export function RPCSend(rpcName:EServer_Common_Config_Services){
}
}
export function RPCRecieve(target: Object, propertyName: string, descriptor: TypedPropertyDescriptor<Function>) {
export function DRPCRecieve(target: Object, propertyName: string, descriptor: TypedPropertyDescriptor<Function>) {
if(!g_RevieveFunc[propertyName])
{
g_RevieveFunc[propertyName]=descriptor.value;

View File

@ -1,6 +1,5 @@
export interface IServer_Common_Config_Base {
port:number,
ip?:string
}
export interface IServer_Common_Config_Redis {

View File

@ -1,7 +1,10 @@
export enum EServer_Common_Http_Structure_HandleParam_Category {
Content,
File,
Param,
Header,
Cookie
Cookie,
Context
}
export interface IServer_Common_Http_Structure_HandleParam {
name:string,
@ -14,8 +17,31 @@ export interface IServer_Common_Http_Structure_HandleParam {
export interface IServer_Common_Http_Structure {
method:string,
path:string,
user?:boolean,
admin?:boolean,
ignoreValidate?:boolean,
handle:(...args: any[]) => any,
handleParam:IServer_Common_Http_Structure_HandleParam[]
}
export enum EServer_Common_Http_Body_Type {
NONE,
URIENCODED,
JSON,
FORMDATA,
BINARY
}
export interface IServer_Common_Http_Proxy {
status:number,
path:string,
method:string,
headers:{
[param:string]:string
},
data:any,
bodyType:EServer_Common_Http_Body_Type
}
export interface IServer_Common_Http_Req_File {
fileName:string,
data:string
}

View File

@ -0,0 +1,18 @@
export function generateHttpErrorResponse(obj:{
code:number,
msg:string
}) {
return {
code:obj.code,
msg:obj.msg
}
}
export function generateHttpOkResponse(msg:string,data) {
return {
code:0,
msg:msg,
data:data
}
}

View File

@ -1,37 +1,133 @@
import * as Koa from "koa"
import * as body from 'koa-bodyparser';
import * as session from 'koa-session2';
import * as http from "http"
import single from "../util/single";
import { init } from "../util/util";
import userApi from "../rpc/user"
import userCall from "../rpc/user"
import Application from "../../common/app/app"
import {getIssueTypeListMapper} from "../../common/db/command/gateway"
import { getNacosInstance } from "../../common/nacos/nacos";
import { CacheService } from './../cache/service';
import {generateHttpErrorResponse} from "../../common/util/http"
import ERROR from "../../../common/status/error"
import OK from "../../../common/status/ok"
import * as userApi from "../../../common/routes/user"
import { ICommon_HttpApi } from "../../../common/routes/types";
import { proxyRequest } from "../../common/rpc/rpc";
import { EServer_Common_Http_Body_Type, IServer_Common_Http_Proxy, IServer_Common_Http_Req_File } from "../../common/types/http";
import { parseFormData } from "../util/util";
import { PassThrough } from "stream";
var apis:ICommon_HttpApi[]=[userApi];
var app = new Koa();
var pipe=function (from,to) :Promise<string>{
return new Promise(function (resolve) {
let p=from.pipe(to);
let stream=new PassThrough();
from.pipe(stream);
p.on("finish",function () {
const originalReqData = [];
let size = 0;
stream.on("data",function (chunk) {
originalReqData.push(chunk);
size += chunk.length;
})
stream.on("end",function () {
resolve(Buffer.concat(originalReqData, size).toString());
})
})
})
}
export default class GateWay extends Application {
override async config() {
await init()
let cacheService=new CacheService()
cacheService.start()
await this.initKoa();
}
async initKoa() {
var root=await import("../routes/root")
app.keys=["teamlinker"]
app.use(session({
maxAge: 86400000,
overwrite: true,
httpOnly: true,
signed: true,
rolling: false,
renew: false,
key: 'teamlinker'
},app))
let apiMap={}
for(let obj of apis){
let baseUrl=obj.baseUrl.substr(1)
if(!apiMap[baseUrl])
{
apiMap[baseUrl]={}
}
for(let key in obj.routes) {
let objApi=obj.routes[key];
apiMap[baseUrl][objApi.method+" "+objApi.path]=baseUrl;
}
}
app.use(async (ctx, next) => {
if (ctx.headers['content-type'] && ctx.headers['content-type'].split(';')[0] === 'multipart/form-data') {
const maxLength = 1024 * 1024 * 5;
if (ctx.headers && ctx.headers['content-length'] && Number(ctx.headers['content-length']) > maxLength) {
ctx.body = generateHttpErrorResponse(ERROR.overUploadFileSize)
return;
}
let stream=new PassThrough()
let ret=await pipe(ctx.req,stream)
let arr = parseFormData(ret);
let obj=<{
[param:string]:string|IServer_Common_Http_Req_File
}>{}
for(let o of arr) {
if(o.isFile) {
obj[o.name]={
data:o.data,
fileName:o.fileName
}
} else {
obj[o.name]=o.data
}
}
ctx.state.formData=obj
await next();
} else {
await next()
}
})
app.use(body());
app.use(root.routes());
app.use(root.allowedMethods());
http.createServer(app.callback()).listen(single.config.port,function(){
app.use(async (ctx, next) => {
let path = ctx.path
let method = ctx.req.method;
let baseUrl = path.substring(1, path.indexOf("/", 1))
let apiPath = path.substr(1 + baseUrl.length)
if (apiMap[baseUrl] && apiMap[baseUrl][method + " " + apiPath]) {
let microServer = apiMap[baseUrl][method + " " + apiPath]
let obj = <IServer_Common_Http_Proxy>{}
if (ctx.req.method == "POST" || ctx.req.method == "PUT" || ctx.req.method == "PATCH") {
if (!ctx.state.p) {
ctx.state.p = ctx.request.body;
}
}
else {
ctx.state.p = ctx.request.query;
}
obj.method=ctx.req.method
obj.headers=<any>ctx.req.headers
obj.data=ctx.state.formData??ctx.state.p
obj.path=apiPath
if(ctx.state.formData) {
obj.bodyType=EServer_Common_Http_Body_Type.FORMDATA
}
let ret=await proxyRequest(obj,microServer)
ctx.response.status=ret.status;
for(let key in ret.headers){
if(key=="set-cookie"){
let obj=JSON.parse(ret.headers[key])
for(let o of obj) {
ctx.set("set-cookie",o)
}
} else {
ctx.set(key,ret.headers[key]);
}
}
ctx.body=ret.data;
await next()
} else {
await next()
}
})
http.createServer(app.callback()).listen(getNacosInstance().serverPort,function(){
console.log(`start`);
setTimeout(async () => {
var obj=new userApi()
var obj=new userCall()
let ret=await obj.a({
name:"dd",
age:23
@ -42,3 +138,4 @@ export default class GateWay extends Application {
}
}

View File

@ -9,6 +9,9 @@ export class CacheService {
private timerCount:number=5000
private instanceTTL:number=10*1000
private nacos:InstanceType<typeof Nacos>
private instanceMap:{
[param:string]:string
}={}
constructor(){
this.nacos=getNacosInstance();
this.redis=getRedisInstance()
@ -18,13 +21,18 @@ export class CacheService {
}
private async handle(){
let ret=await this.nacos.getInstances()
this.instanceMap={}
for(let key in ret) {
let obj=ret[key]
this.instanceMap[key]=obj[0].ip
let objRedis=REDIS_GATEWAY.instance(key)
await objRedis.set(obj,this.instanceTTL)
}
this.timer=setTimeout(this.handle.bind(this),this.timerCount)
}
private getInstanceMap() {
return this.instanceMap
}
stop(){
if(this.timer)
{

View File

@ -1,16 +0,0 @@
import { HttpApi, HttpController, HttpCookies, HttpReqHeader, HttpReqParam, HttpReqParamRequired } from "../../../common/decorator/http"
import * as userApi from "../../../../common/routes/user"
import { ICommon_Http_User_Test_Res } from "../../../../common/routes/userRes"
import * as Cookies from "cookies"
@HttpController(userApi)
class UserController {
@HttpApi(userApi.routes.test)
async test(@HttpCookies cookies:Cookies):Promise<ICommon_Http_User_Test_Res>{
cookies.set("sx","234")
return {
name:"aaa",
age:11,
}
}
}
export default new UserController

View File

@ -1,59 +0,0 @@
import {getRouteApi, handleHttpCall} from "../../common/decorator/http"
import * as path from "path"
import * as Router from "koa-router"
import {Context} from "koa";
async function route(category:string,instance:any) {
var router=new Router();
router.all("*",async function(ctx:Context,next:any)
{
let req=ctx.request;
var bFind=false;
var index;
for(var key in instance)
{
if(instance[key].method==ctx.req.method && `/api/${category}${instance[key].path}`===(<any>ctx.req)._parsedUrl.pathname)
{
bFind=true;
index=key;
break;
}
}
if(!bFind)
{
await next();
return;
}
if(ctx.req.method=="POST" || ctx.req.method=="PUT" || ctx.req.method=="PATCH")
{
if(!ctx.state.p)
{
ctx.state.p=req.body;
}
if(!ctx.state.f && (<any>req).files)
{
let obj={},objP={}
for(let key in (<any>req).files)
{
obj[key]=(<any>req).files[key].path
let filePath=obj[key]
let i=filePath.lastIndexOf(path.sep);
i=filePath.lastIndexOf(path.sep,i-1);
filePath=filePath.substring(i).replace(/\\/g,"/");
objP[key]=filePath
}
ctx.state.f=obj
ctx.state.p=Object.assign({},ctx.state.p,objP)
}
}
else
{
ctx.state.p=req.query;
}
ctx.body=await handleHttpCall(instance[index],ctx,instance);
});
return router;
}
export default route

View File

@ -1,16 +0,0 @@
import * as Router from "koa-router"
import check from "./check"
import user from "./api/user"
import { getRouteApi } from "../../common/decorator/http";
let root=new Router();
let arr=[user];
(async function()
{
for(let obj of arr)
{
const [category,inter]=getRouteApi(obj);
let route=await check(category,inter)
root.use(`/api/${category}`,route.routes(),route.allowedMethods());
}
})()
export=root;

View File

@ -1,12 +1,9 @@
import { EServer_Common_Config_Services } from './../../common/types/config';
import IServer_Common_RPC_User, { IAAA } from "../../common/rpc/api/user";
import {RPCSend} from "../../common/rpc/rpc"
import {DRPCSend} from "../../common/rpc/rpc"
export default class RpcUserApi implements IServer_Common_RPC_User {
@RPCSend(EServer_Common_Config_Services.User)
@DRPCSend(EServer_Common_Config_Services.User)
async a(obj:IAAA):Promise<IAAA> {
return {
name:"sd",
age:33
}
return null
}
}

View File

@ -17,7 +17,7 @@
},
"include": [
"./**/*"
, "../common/rpc/api", "../common/rpc/rpc.ts" ],
, "../common/rpc/api", "../common/rpc/rpc.ts", "../user/http/user.ts" ],
"exclude": [
"node_modules"
]

View File

@ -1,7 +0,0 @@
import { Redis } from '../../common/cache/redis';
import {IServer_GateWay_Config} from "../types/config"
var obj={
config:<IServer_GateWay_Config>{},
redis:<InstanceType<typeof Redis>>{}
};
export default obj

View File

@ -1,5 +1,37 @@
import { CacheService } from './../cache/service';
export async function init() {
let cacheService=new CacheService()
cacheService.start()
export interface IServer_GateWay_FormData {
isFile:boolean,
name:string,
fileName:string,
data:string
}
export function parseFormData(str:string) :IServer_GateWay_FormData[]{
if(!str) {
return null;
}
let ret:IServer_GateWay_FormData[]=[];
let flag=str.substring(0,str.indexOf("\r\n"))
let reg=new RegExp(`^${flag}\r\n([\\w\\W]*)\r\n${flag}\-\-\r\n$`)
let match=str.match(reg)
let matchText=match[1];
let arr=matchText.split(`\r\n${flag}\r\n`)
for(let obj of arr) {
let headerText=obj.substring(0,obj.indexOf("\r\n\r\n"))
let content=obj.substr(headerText.length+4)
let arrHeader=headerText.split("; ")
let objForm=<IServer_GateWay_FormData>{}
for(let obj of arrHeader){
let arr=obj.split("=")
let key=arr[0]
let value=arr[1]
if(key=="filename"){
objForm.isFile=true;
objForm.fileName=value.split("\r\n")[0].replace(/[\'\"]/g,"");
} else if(key=="name") {
objForm.name=value.replace(/[\'\"]/g,"");
}
}
objForm.data=content;
ret.push(objForm)
}
return ret;
}

View File

@ -0,0 +1,11 @@
import * as Koa from "koa"
import * as body from 'koa-bodyparser';
import Application from "../../common/app/app"
import "../http/user"
export default class User extends Application {
override async config() {
}
}

View File

@ -0,0 +1,16 @@
import { IServer_Common_Http_Req_File } from './../../common/types/http';
import { DHttpApi, DHttpContext, DHttpReqParam, DHttpReqParamFile,DHttpContent } from "../../common/http/http"
import * as userApi from "../../../common/routes/user"
import { ICommon_Http_User_Test_Res } from "../../../common/routes/userRes"
import HttpContext from "../../common/http/context"
class UserController {
@DHttpApi(userApi.routes.test)
async test(@DHttpContent content:typeof userApi.routes.test.req,@DHttpContext ctx:HttpContext):Promise<ICommon_Http_User_Test_Res>{
console.log(content)
return {
name:"",
age:11,
}
}
}
export default new UserController

View File

@ -1,18 +1,8 @@
import { Rpc } from './../common/rpc/rpc';
import * as Koa from "koa"
import * as body from 'koa-bodyparser';
import form from "koa2-formidable"
import * as session from 'koa-session2';
import * as http from "http"
import single from "./util/single";
import { init } from "./util/util";
var app = new Koa();
(async function(){
await init()
Rpc.start(single.config.port)
})()
import User from "./app/app";
var application = new User()
application.start();
export = app;

View File

@ -1,8 +1,8 @@
import IServer_Common_RPC_User, { IAAA } from "../../common/rpc/api/user";
import {RPCRecieve} from "../../common/rpc/rpc"
import {DRPCRecieve} from "../../common/rpc/rpc"
export default class RpcUserApi implements IServer_Common_RPC_User {
@RPCRecieve
@DRPCRecieve
async a(obj:IAAA):Promise<IAAA> {
return {
name:obj.name+"xxx",

View File

@ -1,6 +0,0 @@
import { Redis } from '../../common/cache/redis';
import {IServer_User_Config} from "../types/config"
var obj={
config:<IServer_User_Config>{}
};
export default obj

View File

@ -1,14 +0,0 @@
import { Redis, } from "../../common/cache/redis";
import Nacos from "../../common/nacos/nacos"
import single from "./single";
import {cacheRedisType} from "../../common/types/cache"
import { IServer_Common_Nacos_Instance_List } from '../../common/types/nacos';
import {IServer_User_Config} from "../types/config"
import {Rpc} from "../../common/rpc/rpc"
import "../rpc/user"
export async function init() {
let nacos=new Nacos<IServer_User_Config>(process.env.nacosUrl,Number(process.env.nacosPort),process.env.nacosName,process.env.nacosId,process.env.nacosNamespace)
await nacos.init()
single.config=nacos.configInfo
new Redis(nacos.redisInfo);
}