typespeed 2.3.3 → 2.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/test.yml +50 -0
- package/README.md +4 -2
- package/app/src/aop-test.class.ts +1 -1
- package/app/src/config-development.json +12 -9
- package/app/src/custom-log.class.ts +3 -2
- package/app/src/first-page.class.ts +1 -1
- package/app/src/jwt-authentication.class.ts +2 -2
- package/app/src/main.ts +1 -1
- package/app/src/second-page.class.ts +1 -1
- package/app/src/test-database.class.ts +10 -14
- package/app/src/test-log.class.ts +1 -1
- package/app/src/test-mq.class.ts +2 -47
- package/app/src/test-orm.class.ts +1 -12
- package/app/src/test-redis.class.ts +45 -0
- package/app/src/test-request.class.ts +1 -1
- package/app/src/user-model.class.ts +6 -2
- package/dist/default/express-server.class.js +1 -1
- package/dist/default/redis.class.js +55 -6
- package/dist/typespeed.d.ts +28 -11
- package/dist/typespeed.js +3 -2
- package/package.json +2 -2
- package/src/default/express-server.class.ts +1 -1
- package/src/default/redis.class.ts +59 -7
- package/src/typespeed.d.ts +28 -11
- package/src/typespeed.ts +1 -1
- package/test/database.test.ts +19 -12
- package/test/first-page.test.ts +2 -1
- package/test/hooks.ts +5 -2
- package/test/mq.test.ts +3 -20
- package/test/orm.test.ts +10 -9
- package/test/redis.test.ts +48 -0
- package/test/request.test.ts +6 -5
- package/test/second-page.test.ts +6 -7
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
'on':
|
|
3
|
+
push:
|
|
4
|
+
branches:
|
|
5
|
+
- main
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
name: 'Test TypeSpeed'
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
services:
|
|
12
|
+
redis:
|
|
13
|
+
image: redis
|
|
14
|
+
ports:
|
|
15
|
+
- 6379:6379
|
|
16
|
+
rabbitmq:
|
|
17
|
+
image: rabbitmq:3.8
|
|
18
|
+
env:
|
|
19
|
+
RABBITMQ_DEFAULT_USER: guest
|
|
20
|
+
RABBITMQ_DEFAULT_PASS: guest
|
|
21
|
+
ports:
|
|
22
|
+
- 5672
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/setup-node@v1
|
|
25
|
+
with:
|
|
26
|
+
node-version: 16
|
|
27
|
+
- uses: actions/checkout@v2
|
|
28
|
+
- name: Setup MySQL
|
|
29
|
+
run: |
|
|
30
|
+
sudo /etc/init.d/mysql start
|
|
31
|
+
mysql -e 'CREATE DATABASE test;USE test; \
|
|
32
|
+
CREATE TABLE `user` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(100) DEFAULT NULL,PRIMARY KEY (`id`)) \
|
|
33
|
+
ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;SHOW TABLES;' -uroot -proot
|
|
34
|
+
- name: 'Cache node_modules'
|
|
35
|
+
uses: actions/cache@v2
|
|
36
|
+
with:
|
|
37
|
+
path: ~/.npm
|
|
38
|
+
key: ${{ runner.os }}-node-v18-${{ hashFiles('**/package.json') }}
|
|
39
|
+
restore-keys: |
|
|
40
|
+
${{ runner.os }}-node-v18-
|
|
41
|
+
- name: Install Dependencies
|
|
42
|
+
run: npm install
|
|
43
|
+
- name: Run Tests with Coverage
|
|
44
|
+
run: npm run test-with-coverage
|
|
45
|
+
env:
|
|
46
|
+
LOCAL_HOST: localhost
|
|
47
|
+
- name: Upload coverage reports to Codecov
|
|
48
|
+
uses: codecov/codecov-action@v3
|
|
49
|
+
env:
|
|
50
|
+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
package/README.md
CHANGED
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/typespeed)
|
|
4
4
|
[](https://www.npmjs.com/package/typespeed)
|
|
5
|
-
[](https://github.com/SpeedPHP/typespeed/commits/main)
|
|
6
5
|
[](https://www.npmjs.com/package/typespeed)
|
|
7
6
|
[](https://github.com/SpeedPHP/typespeed/blob/main/LICENSE)
|
|
7
|
+
[](https://github.com/SpeedPHP/typespeed/commits/main)
|
|
8
|
+
[
|
|
9
|
+
](https://codecov.io/gh/SpeedPHP/typespeed)
|
|
8
10
|
|
|
9
11
|
### 特点
|
|
10
12
|
|
|
11
13
|
- 遵循 MIT 许可的开源项目。
|
|
12
|
-
- 提供
|
|
14
|
+
- 提供 31 个 TypeScript 装饰器,这些装饰器构成了完整的 Web 框架功能,包括对象管理、Web 路由、数据库操作等。
|
|
13
15
|
- 通过命令行脚手架,可以快速创建项目,零配置启动。
|
|
14
16
|
- 基于依赖注入、AOP、中间件和启动扫描等编程理念开发实现。
|
|
15
17
|
- 底层采用 ExpressJS 实现,提供稳定、快速的 Web 服务。
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
"server": {
|
|
3
|
-
"port": "8081"
|
|
4
|
-
},
|
|
5
|
-
"database": {
|
|
6
|
-
"host": "localhost",
|
|
7
|
-
"port": "4455",
|
|
8
|
-
"name": "test"
|
|
9
|
-
},
|
|
10
2
|
"view": {
|
|
11
3
|
"engine": "mustache",
|
|
12
4
|
"path": "/app/src/views",
|
|
13
5
|
"suffix": "html"
|
|
14
6
|
},
|
|
7
|
+
"mysql": {
|
|
8
|
+
"host": "127.0.0.1",
|
|
9
|
+
"user": "root",
|
|
10
|
+
"password": "root",
|
|
11
|
+
"database": "test"
|
|
12
|
+
},
|
|
13
|
+
"redis": {
|
|
14
|
+
"host": "127.0.0.1",
|
|
15
|
+
"port": "6379",
|
|
16
|
+
"db": 0
|
|
17
|
+
},
|
|
15
18
|
"rabbitmq": {
|
|
16
19
|
"protocol": "amqp",
|
|
17
|
-
"hostname": "
|
|
20
|
+
"hostname": "127.0.0.1",
|
|
18
21
|
"port": 5672,
|
|
19
22
|
"username": "guest",
|
|
20
23
|
"password": "guest"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as tracer from "tracer";
|
|
2
|
-
import { bean, LogFactory } from "../../";
|
|
2
|
+
import { bean, LogFactory } from "../../src/typespeed";
|
|
3
3
|
|
|
4
4
|
export default class CustomLog extends LogFactory {
|
|
5
5
|
private logger = tracer.console({
|
|
@@ -17,7 +17,8 @@ export default class CustomLog extends LogFactory {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
public log(message?: any, ...optionalParams: any[]) : void{
|
|
20
|
-
|
|
20
|
+
if(process.env.LOG === "CLOSE") return;
|
|
21
|
+
this.logger.log(message, ...optionalParams);
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
public error(message?: any, ...optionalParams: any[]) : void {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AuthenticationFactory, bean, config } from "../../";
|
|
1
|
+
import { AuthenticationFactory, bean, config } from "../../src/typespeed";
|
|
2
2
|
import express from "express";
|
|
3
3
|
import { expressjwt, GetVerificationKey } from "express-jwt";
|
|
4
4
|
import * as jwt from 'jsonwebtoken';
|
|
@@ -23,8 +23,8 @@ export default class JwtAuthentication extends AuthenticationFactory {
|
|
|
23
23
|
if (err) {
|
|
24
24
|
//next(err);
|
|
25
25
|
}
|
|
26
|
-
next();
|
|
27
26
|
});
|
|
28
27
|
}
|
|
28
|
+
next();
|
|
29
29
|
}
|
|
30
30
|
}
|
package/app/src/main.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { insert, update, select, param, resultType, cache, CacheFactory, getMapping, component, log, autoware } from "../../";
|
|
1
|
+
import { insert, update, select, param, resultType, cache, CacheFactory, getMapping, component, log, autoware } from "../../src/typespeed";
|
|
2
2
|
import UserDto from "./entities/user-dto.class";
|
|
3
3
|
|
|
4
4
|
@component
|
|
@@ -11,24 +11,22 @@ export default class TestDatabase {
|
|
|
11
11
|
async insert(req, res) {
|
|
12
12
|
const id = req.query.id || 1;
|
|
13
13
|
const newId = await this.addRow("new name " + id, id);
|
|
14
|
-
|
|
15
|
-
res.send("Insert success");
|
|
14
|
+
res.send("Insert success: " + newId);
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
@getMapping("/db/insert2")
|
|
19
18
|
async insertByObject(req, res) {
|
|
20
19
|
const newId = await this.addRowByObject({
|
|
21
|
-
"id":
|
|
20
|
+
"id": req.query.id, "name": "new name " + req.query.id
|
|
22
21
|
});
|
|
23
|
-
|
|
24
|
-
res.send("Insert success");
|
|
22
|
+
res.send("Insert success: " + newId);
|
|
25
23
|
}
|
|
26
24
|
|
|
27
25
|
@getMapping("/db/update")
|
|
28
26
|
async update(req, res) {
|
|
29
|
-
const affectedRows = await this.editRow();
|
|
27
|
+
const affectedRows = await this.editRow(req.query.id);
|
|
30
28
|
log("Update rows: " + affectedRows);
|
|
31
|
-
res.send("update success");
|
|
29
|
+
res.send("update success: " + affectedRows);
|
|
32
30
|
}
|
|
33
31
|
|
|
34
32
|
@getMapping("/db/select")
|
|
@@ -38,17 +36,15 @@ export default class TestDatabase {
|
|
|
38
36
|
res.send(rows);
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
@getMapping("/db/
|
|
39
|
+
@getMapping("/db/select-row")
|
|
42
40
|
async selectById(req, res) {
|
|
43
|
-
const row = await this.findRow(req.query.id
|
|
44
|
-
log("select rows: " + row);
|
|
41
|
+
const row = await this.findRow(req.query.id);
|
|
45
42
|
res.send(row);
|
|
46
43
|
}
|
|
47
44
|
|
|
48
45
|
@getMapping("/db/select-user")
|
|
49
46
|
async selectUser(req, res) {
|
|
50
47
|
const users: UserDto[] = await this.findUsers();
|
|
51
|
-
log("select users: " + users);
|
|
52
48
|
res.send(users);
|
|
53
49
|
}
|
|
54
50
|
|
|
@@ -69,8 +65,8 @@ export default class TestDatabase {
|
|
|
69
65
|
@insert("Insert into `user` (id, name) values (#{id}, #{name})")
|
|
70
66
|
private async addRowByObject(myParams: object) { }
|
|
71
67
|
|
|
72
|
-
@update("Update `user` set `name` = 'test5' where id =
|
|
73
|
-
private async editRow() { }
|
|
68
|
+
@update("Update `user` set `name` = 'test5' where id = #{id}")
|
|
69
|
+
private async editRow(@param("id") id: number) { }
|
|
74
70
|
|
|
75
71
|
@select("Select * from `user`")
|
|
76
72
|
private async selectRow() { }
|
package/app/src/test-mq.class.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { component, getMapping, autoware, log, RabbitMQ, rabbitListener } from "../../";
|
|
1
|
+
import { component, getMapping, autoware, log, RabbitMQ, rabbitListener } from "../../src/typespeed";
|
|
2
2
|
import { connect } from "amqplib";
|
|
3
3
|
|
|
4
4
|
|
|
@@ -16,51 +16,6 @@ export default class TestMq {
|
|
|
16
16
|
@getMapping("/mq/sendByMQClass")
|
|
17
17
|
async sendByMQClass() {
|
|
18
18
|
this.rabbitMQ.send("myqueues", "hello world, by MQClass");
|
|
19
|
-
return "
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
@getMapping("/mq/sendByQueue")
|
|
23
|
-
async sendMq() {
|
|
24
|
-
const queue = 'myqueues';
|
|
25
|
-
const text = "hello world, by queue";
|
|
26
|
-
const connection = await connect({
|
|
27
|
-
protocol: 'amqp',
|
|
28
|
-
hostname: 'localhost',
|
|
29
|
-
port: 5672,
|
|
30
|
-
username: 'guest',
|
|
31
|
-
password: 'guest'
|
|
32
|
-
});
|
|
33
|
-
const channel = await connection.createChannel();
|
|
34
|
-
await channel.assertQueue(queue);
|
|
35
|
-
channel.sendToQueue(queue, Buffer.from(text));
|
|
36
|
-
await channel.close();
|
|
37
|
-
return "sent by queue";
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
@getMapping("/mq/sendByExchange")
|
|
41
|
-
async sendMq2() {
|
|
42
|
-
const exchange = 'myexchanges';
|
|
43
|
-
const text = "hello world, by exchange";
|
|
44
|
-
const connection = await connect('amqp://localhost');
|
|
45
|
-
const channel = await connection.createChannel();
|
|
46
|
-
await channel.checkExchange(exchange);
|
|
47
|
-
channel.publish(exchange, '', Buffer.from(text));
|
|
48
|
-
await channel.close();
|
|
49
|
-
return "sent by exchange";
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
@getMapping("/mq/listen")
|
|
53
|
-
async testMq() {
|
|
54
|
-
const connection = await connect('amqp://localhost');
|
|
55
|
-
const channel = await connection.createChannel();
|
|
56
|
-
const queue = 'myqueues';
|
|
57
|
-
const queue2 = 'myqueues2';
|
|
58
|
-
await channel.checkQueue(queue);
|
|
59
|
-
await channel.checkQueue(queue2);
|
|
60
|
-
await channel.consume(queue, (message) => {
|
|
61
|
-
}, { noAck: true });
|
|
62
|
-
await channel.consume(queue2, (message) => {
|
|
63
|
-
}, { noAck: true });
|
|
64
|
-
return "ok";
|
|
19
|
+
return "Sent by MQClass";
|
|
65
20
|
}
|
|
66
21
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resource, component, log, autoware, schedule, getMapping, postMapping, Redis } from "../../";
|
|
1
|
+
import { resource, component, log, autoware, schedule, getMapping, postMapping, Redis } from "../../src/typespeed";
|
|
2
2
|
import UserModel from "./user-model.class";
|
|
3
3
|
|
|
4
4
|
@component
|
|
@@ -7,17 +7,6 @@ export default class TestOrm {
|
|
|
7
7
|
@resource("user")
|
|
8
8
|
private userModel: UserModel;
|
|
9
9
|
|
|
10
|
-
@autoware
|
|
11
|
-
private redisObj: Redis;
|
|
12
|
-
|
|
13
|
-
@getMapping("/redis")
|
|
14
|
-
async redisTest() {
|
|
15
|
-
await this.redisObj.set("redisKey", "Hello World");
|
|
16
|
-
const value = await this.redisObj.get("redisKey");
|
|
17
|
-
log(value)
|
|
18
|
-
return "get from redis: " + value;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
10
|
@getMapping("/orm/first")
|
|
22
11
|
async firstTest(req, res) {
|
|
23
12
|
const results = await this.userModel.getUsers();
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Redis, component, redisSubscriber, autoware, getMapping, log, reqQuery } from "../../src/typespeed";
|
|
2
|
+
|
|
3
|
+
@component
|
|
4
|
+
export default class TestRedis {
|
|
5
|
+
@autoware
|
|
6
|
+
private redisObj: Redis;
|
|
7
|
+
|
|
8
|
+
@redisSubscriber("mychannel")
|
|
9
|
+
public listen(message) {
|
|
10
|
+
log("Received by Decorator '%s'", message);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@getMapping("/redis/publish")
|
|
14
|
+
async redisPublish() {
|
|
15
|
+
await this.redisObj.publish("mychannel", "Hello World");
|
|
16
|
+
return "Published!";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@getMapping("/redis")
|
|
20
|
+
async redisString() {
|
|
21
|
+
await this.redisObj.set("redisKey", "Hello World");
|
|
22
|
+
const value = await this.redisObj.get("redisKey");
|
|
23
|
+
return "get from redis: " + value;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@getMapping("/redis/add")
|
|
27
|
+
async addZset(@reqQuery name: string, @reqQuery score: number) {
|
|
28
|
+
log("add zset: %s, %s", name, score)
|
|
29
|
+
await this.redisObj.zadd("scoreSet", score, name);
|
|
30
|
+
return "add zset success";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@getMapping("/redis/ranking")
|
|
34
|
+
async listRanking() {
|
|
35
|
+
const list = await this.redisObj.zrevranking("scoreSet", 0, -1);
|
|
36
|
+
return Object.fromEntries(list);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@getMapping("/redis/list")
|
|
40
|
+
async listZset() {
|
|
41
|
+
const list = await this.redisObj.zranking("scoreSet", 0, -1);
|
|
42
|
+
log("list zset: %s", JSON.stringify(Object.fromEntries(list)));
|
|
43
|
+
return Object.fromEntries(list);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { component, getMapping, postMapping, log, req, res, reqQuery, reqBody, reqForm, reqParam } from "../../";
|
|
1
|
+
import { component, getMapping, postMapping, log, req, res, reqQuery, reqBody, reqForm, reqParam } from "../../src/typespeed";
|
|
2
2
|
import MutilUsers from "./entities/mutil-users.class";
|
|
3
3
|
import UserDto from "./entities/user-dto.class";
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { log, Model } from "../../";
|
|
1
|
+
import { log, Model } from "../../src/typespeed";
|
|
2
2
|
import UserDto from "./entities/user-dto.class";
|
|
3
3
|
|
|
4
4
|
export default class UserModel extends Model {
|
|
@@ -20,7 +20,7 @@ export default class UserModel extends Model {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
async newUsers() {
|
|
23
|
-
const newId =
|
|
23
|
+
const newId = this.random(1000, 2000);
|
|
24
24
|
await this.create([
|
|
25
25
|
new UserDto(newId, "UserDto " + newId),
|
|
26
26
|
new UserDto(newId+1, "UserDto " + (newId+1)),
|
|
@@ -43,4 +43,8 @@ export default class UserModel extends Model {
|
|
|
43
43
|
const effectRows = await this.update({ id: id }, { name: name });
|
|
44
44
|
return effectRows;
|
|
45
45
|
}
|
|
46
|
+
|
|
47
|
+
private random(min, max) {
|
|
48
|
+
return Math.round(Math.random() * (max - min)) + min;
|
|
49
|
+
}
|
|
46
50
|
}
|
|
@@ -138,7 +138,7 @@ __decorate([
|
|
|
138
138
|
], ExpressServer.prototype, "redisConfig", void 0);
|
|
139
139
|
__decorate([
|
|
140
140
|
core_decorator_1.autoware,
|
|
141
|
-
__metadata("design:type", redis_class_1.
|
|
141
|
+
__metadata("design:type", redis_class_1.Redis)
|
|
142
142
|
], ExpressServer.prototype, "redisClient", void 0);
|
|
143
143
|
__decorate([
|
|
144
144
|
core_decorator_1.autoware,
|
|
@@ -9,24 +9,73 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
9
9
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.redisSubscriber = exports.Redis = void 0;
|
|
12
13
|
const core_decorator_1 = require("../core.decorator");
|
|
13
14
|
const ioredis_1 = require("ioredis");
|
|
14
15
|
const typespeed_1 = require("../typespeed");
|
|
15
|
-
|
|
16
|
+
const redisSubscribers = {};
|
|
17
|
+
class Redis extends ioredis_1.Redis {
|
|
16
18
|
getRedis() {
|
|
19
|
+
return Redis.getInstanceOfRedis("pub");
|
|
20
|
+
}
|
|
21
|
+
async zrevranking(key, start, stop) {
|
|
22
|
+
const list = await this.zrevrange(key, start, stop, "WITHSCORES");
|
|
23
|
+
const map = new Map();
|
|
24
|
+
for (let i = 0; i < list.length; i = i + 2) {
|
|
25
|
+
map.set(list[i], Number(list[i + 1]));
|
|
26
|
+
}
|
|
27
|
+
return map;
|
|
28
|
+
}
|
|
29
|
+
async zranking(key, start, stop) {
|
|
30
|
+
const list = await this.zrange(key, start, stop, "WITHSCORES");
|
|
31
|
+
const map = new Map();
|
|
32
|
+
for (let i = 0; i < list.length; i = i + 2) {
|
|
33
|
+
map.set(list[i], Number(list[i + 1]));
|
|
34
|
+
}
|
|
35
|
+
return map;
|
|
36
|
+
}
|
|
37
|
+
static getInstanceOfRedis(mode) {
|
|
17
38
|
if (!(0, typespeed_1.config)("redis")) {
|
|
18
39
|
return null;
|
|
19
40
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
41
|
+
if (mode === "sub") {
|
|
42
|
+
this.pubObj = this.pubObj || new Redis((0, typespeed_1.config)("redis"));
|
|
43
|
+
return this.pubObj;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.subObj = this.subObj || new Redis((0, typespeed_1.config)("redis"));
|
|
47
|
+
return this.subObj;
|
|
48
|
+
}
|
|
24
49
|
}
|
|
25
50
|
}
|
|
51
|
+
Redis.pubObj = null;
|
|
52
|
+
Redis.subObj = null;
|
|
26
53
|
__decorate([
|
|
27
54
|
core_decorator_1.bean,
|
|
28
55
|
__metadata("design:type", Function),
|
|
29
56
|
__metadata("design:paramtypes", []),
|
|
30
57
|
__metadata("design:returntype", Redis)
|
|
31
58
|
], Redis.prototype, "getRedis", null);
|
|
32
|
-
exports.
|
|
59
|
+
exports.Redis = Redis;
|
|
60
|
+
function redisSubscriber(channel) {
|
|
61
|
+
if (!(0, typespeed_1.config)("redis"))
|
|
62
|
+
return;
|
|
63
|
+
Redis.getInstanceOfRedis("sub").subscribe(channel, function (err, count) {
|
|
64
|
+
if (err) {
|
|
65
|
+
console.error(err);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
return function (target, propertyKey) {
|
|
69
|
+
redisSubscribers[channel] = target[propertyKey];
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
exports.redisSubscriber = redisSubscriber;
|
|
73
|
+
if ((0, typespeed_1.config)("redis")) {
|
|
74
|
+
Redis.getInstanceOfRedis("sub").on("message", function (channel, message) {
|
|
75
|
+
redisSubscribers[channel](message);
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
process.once('SIGINT', () => {
|
|
79
|
+
Redis.getInstanceOfRedis("sub") || Redis.getInstanceOfRedis("sub").disconnect();
|
|
80
|
+
Redis.getInstanceOfRedis("pub") || Redis.getInstanceOfRedis("pub").disconnect();
|
|
81
|
+
});
|
package/dist/typespeed.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as express from "express";
|
|
2
|
-
import IoRedis from "ioredis";
|
|
2
|
+
import { Redis as IoRedis, RedisKey } from "ioredis";
|
|
3
3
|
import "reflect-metadata";
|
|
4
4
|
|
|
5
5
|
/**设置路由中间件 */
|
|
@@ -139,7 +139,7 @@ declare class Model {
|
|
|
139
139
|
* 被装饰的类将作为应用程序入口,框架将启动该类的 main 方法
|
|
140
140
|
*/
|
|
141
141
|
declare function app<T extends {
|
|
142
|
-
new
|
|
142
|
+
new(...args: any[]): {};
|
|
143
143
|
}>(constructor: T): void;
|
|
144
144
|
/**获取配置文件中的配置项 */
|
|
145
145
|
declare function config(node: string): any;
|
|
@@ -169,20 +169,22 @@ declare function after(constructorFunction: any, methodName: string): (target: a
|
|
|
169
169
|
declare function schedule(cronTime: string | Date): (target: any, propertyKey: string) => void;
|
|
170
170
|
/**RabbitMQ 监听装饰器,参数是监听的队列名称,当接受到消息时将执行被装饰方法 */
|
|
171
171
|
declare function rabbitListener(queue: string): (target: any, propertyKey: string) => void;
|
|
172
|
+
/**Redis 监听装饰器,参数是监听的队列名称,当接受到消息时将执行被装饰方法 */
|
|
173
|
+
declare function redisSubscriber(target: any, propertyKey: string): void;
|
|
172
174
|
/** request 对象装饰器,作为路由页面方法参数,获取 request 对象 */
|
|
173
|
-
declare function req(target: any, propertyKey: string, parameterIndex: number)
|
|
175
|
+
declare function req(target: any, propertyKey: string, parameterIndex: number): void;
|
|
174
176
|
/** response 对象装饰器,作为路由页面方法参数,获取 response 对象 */
|
|
175
|
-
declare function res(target: any, propertyKey: string, parameterIndex: number)
|
|
177
|
+
declare function res(target: any, propertyKey: string, parameterIndex: number): void;
|
|
176
178
|
/** next 函数装饰器,作为路由页面方法参数,获取 next 函数 */
|
|
177
|
-
declare function next(target: any, propertyKey: string, parameterIndex: number)
|
|
179
|
+
declare function next(target: any, propertyKey: string, parameterIndex: number): void;
|
|
178
180
|
/** request.body 对象装饰器,作为路由页面方法参数,获取 request.body 对象 */
|
|
179
|
-
declare function reqBody(target: any, propertyKey: string, parameterIndex: number)
|
|
181
|
+
declare function reqBody(target: any, propertyKey: string, parameterIndex: number): void;
|
|
180
182
|
/** request.param 值装饰器,作为路由页面方法参数,获取 request.params 内容 */
|
|
181
|
-
declare function reqParam(target: any, propertyKey: string, parameterIndex: number)
|
|
183
|
+
declare function reqParam(target: any, propertyKey: string, parameterIndex: number): void;
|
|
182
184
|
/** request.query 值装饰器,作为路由页面方法参数,获取 request.query 内容 */
|
|
183
|
-
declare function reqQuery(target: any, propertyKey: string, parameterIndex: number)
|
|
185
|
+
declare function reqQuery(target: any, propertyKey: string, parameterIndex: number): void;
|
|
184
186
|
/** request 表单值装饰器,作为路由页面方法参数,获取 request.body 表单内容 */
|
|
185
|
-
declare function reqForm(paramName: string)
|
|
187
|
+
declare function reqForm(paramName: string): (target: any, propertyKey: string, parameterIndex: number) => void;
|
|
186
188
|
|
|
187
189
|
/**框架 Web 服务工厂类 */
|
|
188
190
|
declare abstract class ServerFactory {
|
|
@@ -275,7 +277,22 @@ declare abstract class AuthenticationFactory {
|
|
|
275
277
|
declare class Redis extends IoRedis {
|
|
276
278
|
/**获取 Redis 实例 */
|
|
277
279
|
getRedis(): Redis;
|
|
278
|
-
|
|
280
|
+
/**
|
|
281
|
+
* 获取有序集合(sorted set),按照分数从大到小排序,返回 Map 对象
|
|
282
|
+
* @param key 键
|
|
283
|
+
* @param start 开始位置,0 表示第一个元素,-1 表示最后一个元素
|
|
284
|
+
* @param stop 结束位置,0 表示第一个元素,-1 表示最后一个元素
|
|
285
|
+
* @returns Map 对象,key 为有序集合的成员,value 为成员的分数
|
|
286
|
+
*/
|
|
287
|
+
zrevranking(key: RedisKey, start: number | string, stop: number | string): Promise<Map<string, number>>;
|
|
288
|
+
/**
|
|
289
|
+
* 获取有序集合(sorted set),按照分数从小到大排序,返回 Map 对象
|
|
290
|
+
* @param key 键
|
|
291
|
+
* @param start 开始位置,0 表示第一个元素,-1 表示最后一个元素
|
|
292
|
+
* @param stop 结束位置,0 表示第一个元素,-1 表示最后一个元素
|
|
293
|
+
* @returns Map 对象,key 为有序集合的成员,value 为成员的分数
|
|
294
|
+
*/
|
|
295
|
+
zranking(key: RedisKey, start: number | string, stop: number | string): Promise<Map<string, number>>;
|
|
279
296
|
}
|
|
280
297
|
/**读写数据源实现类 */
|
|
281
298
|
declare class ReadWriteDb extends DataSourceFactory {
|
|
@@ -359,4 +376,4 @@ declare class ExpressServer extends ServerFactory {
|
|
|
359
376
|
private setDefaultMiddleware;
|
|
360
377
|
}
|
|
361
378
|
|
|
362
|
-
export { ExpressServer, LogDefault, NodeCache, RabbitMQ, rabbitListener, ReadWriteDb, Redis, CacheFactory, DataSourceFactory, LogFactory, ServerFactory, AuthenticationFactory, next, reqBody, reqQuery, reqForm, reqParam, req, req as request, res, res as response, component, bean, resource, log, app, before, after, value, error, config, autoware, getBean, getComponent, schedule, getMapping, postMapping, requestMapping, setRouter, upload, jwt, insert, update, remove, select, param, resultType, cache, Model};
|
|
379
|
+
export { ExpressServer, LogDefault, NodeCache, RabbitMQ, rabbitListener, redisSubscriber, ReadWriteDb, Redis, CacheFactory, DataSourceFactory, LogFactory, ServerFactory, AuthenticationFactory, next, reqBody, reqQuery, reqForm, reqParam, req, req as request, res, res as response, component, bean, resource, log, app, before, after, value, error, config, autoware, getBean, getComponent, schedule, getMapping, postMapping, requestMapping, setRouter, upload, jwt, insert, update, remove, select, param, resultType, cache, Model };
|
package/dist/typespeed.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.ReadWriteDb = exports.Redis = exports.NodeCache = exports.LogDefault = exports.ExpressServer = exports.AuthenticationFactory = exports.ServerFactory = exports.DataSourceFactory = exports.CacheFactory = exports.LogFactory = exports.config = exports.value = exports.app = void 0;
|
|
17
|
+
exports.ReadWriteDb = exports.redisSubscriber = exports.Redis = exports.NodeCache = exports.LogDefault = exports.ExpressServer = exports.AuthenticationFactory = exports.ServerFactory = exports.DataSourceFactory = exports.CacheFactory = exports.LogFactory = exports.config = exports.value = exports.app = void 0;
|
|
18
18
|
require("reflect-metadata");
|
|
19
19
|
const fs = require("fs");
|
|
20
20
|
const path = require("path");
|
|
@@ -119,7 +119,8 @@ Object.defineProperty(exports, "LogDefault", { enumerable: true, get: function (
|
|
|
119
119
|
var node_cache_class_1 = require("./default/node-cache.class");
|
|
120
120
|
Object.defineProperty(exports, "NodeCache", { enumerable: true, get: function () { return node_cache_class_1.default; } });
|
|
121
121
|
var redis_class_1 = require("./default/redis.class");
|
|
122
|
-
Object.defineProperty(exports, "Redis", { enumerable: true, get: function () { return redis_class_1.
|
|
122
|
+
Object.defineProperty(exports, "Redis", { enumerable: true, get: function () { return redis_class_1.Redis; } });
|
|
123
|
+
Object.defineProperty(exports, "redisSubscriber", { enumerable: true, get: function () { return redis_class_1.redisSubscriber; } });
|
|
123
124
|
var read_write_db_class_1 = require("./default/read-write-db.class");
|
|
124
125
|
Object.defineProperty(exports, "ReadWriteDb", { enumerable: true, get: function () { return read_write_db_class_1.default; } });
|
|
125
126
|
__exportStar(require("./default/rabbitmq.class"), exports);
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "typespeed",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.5",
|
|
4
4
|
"description": "A new Framework for TypeScript.",
|
|
5
5
|
"author": "speedphp",
|
|
6
6
|
"license": "MIT License",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"test": "mocha --require ts-node/register test/**/*.ts --exit",
|
|
9
|
-
"test-with-coverage": "nyc --reporter=
|
|
9
|
+
"test-with-coverage": "nyc --reporter=lcov npm test",
|
|
10
10
|
"start": "ts-node --transpile-only app/src/main.ts",
|
|
11
11
|
"build": "tsc -p .",
|
|
12
12
|
"postbuild": "cp src/typespeed.d.ts dist/typespeed.d.ts && cp -r src/default/pages dist/default/pages && cp -r src/scaffold/templates dist/scaffold/templates",
|
|
@@ -10,7 +10,7 @@ import ServerFactory from "../factory/server-factory.class";
|
|
|
10
10
|
import { setRouter } from "../route.decorator";
|
|
11
11
|
import { value } from "../typespeed";
|
|
12
12
|
import { bean, log, error, autoware } from "../core.decorator";
|
|
13
|
-
import Redis from "./redis.class";
|
|
13
|
+
import { Redis } from "./redis.class";
|
|
14
14
|
import AuthenticationFactory from "../factory/authentication-factory.class";
|
|
15
15
|
|
|
16
16
|
export default class ExpressServer extends ServerFactory {
|
|
@@ -1,18 +1,70 @@
|
|
|
1
1
|
import { bean } from "../core.decorator";
|
|
2
|
-
import IoRedis from "ioredis";
|
|
2
|
+
import { Redis as IoRedis, RedisKey} from "ioredis";
|
|
3
3
|
import { config } from "../typespeed";
|
|
4
|
-
|
|
4
|
+
const redisSubscribers = {};
|
|
5
|
+
|
|
6
|
+
class Redis extends IoRedis {
|
|
7
|
+
private static pubObj: Redis = null;
|
|
8
|
+
private static subObj: Redis = null;
|
|
5
9
|
|
|
6
10
|
@bean
|
|
7
11
|
public getRedis(): Redis {
|
|
12
|
+
return Redis.getInstanceOfRedis("pub");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public async zrevranking(key: RedisKey, start: number | string, stop: number | string): Promise<Map<string, number>> {
|
|
16
|
+
const list = await this.zrevrange(key, start, stop, "WITHSCORES");
|
|
17
|
+
const map = new Map<string, number>();
|
|
18
|
+
for (let i = 0; i < list.length; i = i + 2) {
|
|
19
|
+
map.set(list[i], Number(list[i + 1]));
|
|
20
|
+
}
|
|
21
|
+
return map;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
public async zranking(key: RedisKey, start: number | string, stop: number | string): Promise<Map<string, number>> {
|
|
25
|
+
const list = await this.zrange(key, start, stop, "WITHSCORES");
|
|
26
|
+
const map = new Map<string, number>();
|
|
27
|
+
for (let i = 0; i < list.length; i = i + 2) {
|
|
28
|
+
map.set(list[i], Number(list[i + 1]));
|
|
29
|
+
}
|
|
30
|
+
return map;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static getInstanceOfRedis(mode: "sub" | "pub") {
|
|
8
34
|
if (!config("redis")) {
|
|
9
35
|
return null;
|
|
10
36
|
}
|
|
11
|
-
|
|
37
|
+
if (mode === "sub") {
|
|
38
|
+
this.pubObj = this.pubObj || new Redis(config("redis"));
|
|
39
|
+
return this.pubObj;
|
|
40
|
+
} else {
|
|
41
|
+
this.subObj = this.subObj || new Redis(config("redis"));
|
|
42
|
+
return this.subObj;
|
|
43
|
+
}
|
|
12
44
|
}
|
|
45
|
+
}
|
|
13
46
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
47
|
+
function redisSubscriber(channel: string) {
|
|
48
|
+
if (!config("redis")) return;
|
|
49
|
+
Redis.getInstanceOfRedis("sub").subscribe(channel, function (err, count) {
|
|
50
|
+
if (err) {
|
|
51
|
+
console.error(err);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
return function (target: any, propertyKey: string) {
|
|
55
|
+
redisSubscribers[channel] = target[propertyKey];
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (config("redis")) {
|
|
60
|
+
Redis.getInstanceOfRedis("sub").on("message", function (channel, message) {
|
|
61
|
+
redisSubscribers[channel](message);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
process.once('SIGINT', () => {
|
|
66
|
+
Redis.getInstanceOfRedis("sub") || Redis.getInstanceOfRedis("sub").disconnect();
|
|
67
|
+
Redis.getInstanceOfRedis("pub") || Redis.getInstanceOfRedis("pub").disconnect();
|
|
68
|
+
});
|
|
17
69
|
|
|
18
|
-
}
|
|
70
|
+
export { Redis, redisSubscriber };
|
package/src/typespeed.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as express from "express";
|
|
2
|
-
import IoRedis from "ioredis";
|
|
2
|
+
import { Redis as IoRedis, RedisKey } from "ioredis";
|
|
3
3
|
import "reflect-metadata";
|
|
4
4
|
|
|
5
5
|
/**设置路由中间件 */
|
|
@@ -139,7 +139,7 @@ declare class Model {
|
|
|
139
139
|
* 被装饰的类将作为应用程序入口,框架将启动该类的 main 方法
|
|
140
140
|
*/
|
|
141
141
|
declare function app<T extends {
|
|
142
|
-
new
|
|
142
|
+
new(...args: any[]): {};
|
|
143
143
|
}>(constructor: T): void;
|
|
144
144
|
/**获取配置文件中的配置项 */
|
|
145
145
|
declare function config(node: string): any;
|
|
@@ -169,20 +169,22 @@ declare function after(constructorFunction: any, methodName: string): (target: a
|
|
|
169
169
|
declare function schedule(cronTime: string | Date): (target: any, propertyKey: string) => void;
|
|
170
170
|
/**RabbitMQ 监听装饰器,参数是监听的队列名称,当接受到消息时将执行被装饰方法 */
|
|
171
171
|
declare function rabbitListener(queue: string): (target: any, propertyKey: string) => void;
|
|
172
|
+
/**Redis 监听装饰器,参数是监听的队列名称,当接受到消息时将执行被装饰方法 */
|
|
173
|
+
declare function redisSubscriber(target: any, propertyKey: string): void;
|
|
172
174
|
/** request 对象装饰器,作为路由页面方法参数,获取 request 对象 */
|
|
173
|
-
declare function req(target: any, propertyKey: string, parameterIndex: number)
|
|
175
|
+
declare function req(target: any, propertyKey: string, parameterIndex: number): void;
|
|
174
176
|
/** response 对象装饰器,作为路由页面方法参数,获取 response 对象 */
|
|
175
|
-
declare function res(target: any, propertyKey: string, parameterIndex: number)
|
|
177
|
+
declare function res(target: any, propertyKey: string, parameterIndex: number): void;
|
|
176
178
|
/** next 函数装饰器,作为路由页面方法参数,获取 next 函数 */
|
|
177
|
-
declare function next(target: any, propertyKey: string, parameterIndex: number)
|
|
179
|
+
declare function next(target: any, propertyKey: string, parameterIndex: number): void;
|
|
178
180
|
/** request.body 对象装饰器,作为路由页面方法参数,获取 request.body 对象 */
|
|
179
|
-
declare function reqBody(target: any, propertyKey: string, parameterIndex: number)
|
|
181
|
+
declare function reqBody(target: any, propertyKey: string, parameterIndex: number): void;
|
|
180
182
|
/** request.param 值装饰器,作为路由页面方法参数,获取 request.params 内容 */
|
|
181
|
-
declare function reqParam(target: any, propertyKey: string, parameterIndex: number)
|
|
183
|
+
declare function reqParam(target: any, propertyKey: string, parameterIndex: number): void;
|
|
182
184
|
/** request.query 值装饰器,作为路由页面方法参数,获取 request.query 内容 */
|
|
183
|
-
declare function reqQuery(target: any, propertyKey: string, parameterIndex: number)
|
|
185
|
+
declare function reqQuery(target: any, propertyKey: string, parameterIndex: number): void;
|
|
184
186
|
/** request 表单值装饰器,作为路由页面方法参数,获取 request.body 表单内容 */
|
|
185
|
-
declare function reqForm(paramName: string)
|
|
187
|
+
declare function reqForm(paramName: string): (target: any, propertyKey: string, parameterIndex: number) => void;
|
|
186
188
|
|
|
187
189
|
/**框架 Web 服务工厂类 */
|
|
188
190
|
declare abstract class ServerFactory {
|
|
@@ -275,7 +277,22 @@ declare abstract class AuthenticationFactory {
|
|
|
275
277
|
declare class Redis extends IoRedis {
|
|
276
278
|
/**获取 Redis 实例 */
|
|
277
279
|
getRedis(): Redis;
|
|
278
|
-
|
|
280
|
+
/**
|
|
281
|
+
* 获取有序集合(sorted set),按照分数从大到小排序,返回 Map 对象
|
|
282
|
+
* @param key 键
|
|
283
|
+
* @param start 开始位置,0 表示第一个元素,-1 表示最后一个元素
|
|
284
|
+
* @param stop 结束位置,0 表示第一个元素,-1 表示最后一个元素
|
|
285
|
+
* @returns Map 对象,key 为有序集合的成员,value 为成员的分数
|
|
286
|
+
*/
|
|
287
|
+
zrevranking(key: RedisKey, start: number | string, stop: number | string): Promise<Map<string, number>>;
|
|
288
|
+
/**
|
|
289
|
+
* 获取有序集合(sorted set),按照分数从小到大排序,返回 Map 对象
|
|
290
|
+
* @param key 键
|
|
291
|
+
* @param start 开始位置,0 表示第一个元素,-1 表示最后一个元素
|
|
292
|
+
* @param stop 结束位置,0 表示第一个元素,-1 表示最后一个元素
|
|
293
|
+
* @returns Map 对象,key 为有序集合的成员,value 为成员的分数
|
|
294
|
+
*/
|
|
295
|
+
zranking(key: RedisKey, start: number | string, stop: number | string): Promise<Map<string, number>>;
|
|
279
296
|
}
|
|
280
297
|
/**读写数据源实现类 */
|
|
281
298
|
declare class ReadWriteDb extends DataSourceFactory {
|
|
@@ -359,4 +376,4 @@ declare class ExpressServer extends ServerFactory {
|
|
|
359
376
|
private setDefaultMiddleware;
|
|
360
377
|
}
|
|
361
378
|
|
|
362
|
-
export { ExpressServer, LogDefault, NodeCache, RabbitMQ, rabbitListener, ReadWriteDb, Redis, CacheFactory, DataSourceFactory, LogFactory, ServerFactory, AuthenticationFactory, next, reqBody, reqQuery, reqForm, reqParam, req, req as request, res, res as response, component, bean, resource, log, app, before, after, value, error, config, autoware, getBean, getComponent, schedule, getMapping, postMapping, requestMapping, setRouter, upload, jwt, insert, update, remove, select, param, resultType, cache, Model};
|
|
379
|
+
export { ExpressServer, LogDefault, NodeCache, RabbitMQ, rabbitListener, redisSubscriber, ReadWriteDb, Redis, CacheFactory, DataSourceFactory, LogFactory, ServerFactory, AuthenticationFactory, next, reqBody, reqQuery, reqForm, reqParam, req, req as request, res, res as response, component, bean, resource, log, app, before, after, value, error, config, autoware, getBean, getComponent, schedule, getMapping, postMapping, requestMapping, setRouter, upload, jwt, insert, update, remove, select, param, resultType, cache, Model };
|
package/src/typespeed.ts
CHANGED
|
@@ -97,6 +97,6 @@ export { default as AuthenticationFactory} from "./factory/authentication-factor
|
|
|
97
97
|
export { default as ExpressServer} from "./default/express-server.class";
|
|
98
98
|
export { default as LogDefault} from "./default/log-default.class";
|
|
99
99
|
export { default as NodeCache} from "./default/node-cache.class";
|
|
100
|
-
export {
|
|
100
|
+
export { Redis, redisSubscriber } from "./default/redis.class";
|
|
101
101
|
export { default as ReadWriteDb} from "./default/read-write-db.class";
|
|
102
102
|
export * from "./default/rabbitmq.class";
|
package/test/database.test.ts
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
|
+
|
|
1
2
|
const chaiObj = require('chai');
|
|
2
3
|
chaiObj.use(require("chai-http"));
|
|
3
4
|
const expect = chaiObj.expect;
|
|
4
5
|
describe("Test Database", () => {
|
|
6
|
+
const randomId = random(3000, 5000);
|
|
7
|
+
const testAddr = `http://${process.env.LOCAL_HOST || "localhost"}:8081`;
|
|
5
8
|
const testDatabase = [
|
|
6
9
|
{
|
|
7
|
-
"url": "/db/insert?id=" +
|
|
8
|
-
"expect": "Insert success",
|
|
10
|
+
"url": "/db/insert?id=" + randomId,
|
|
11
|
+
"expect": "Insert success: " + randomId,
|
|
9
12
|
},
|
|
10
13
|
{
|
|
11
|
-
"url": "/db/insert2",
|
|
12
|
-
"expect": "Insert success",
|
|
14
|
+
"url": "/db/insert2?id=" + (randomId + 1),
|
|
15
|
+
"expect": "Insert success: " + (randomId + 1),
|
|
13
16
|
},
|
|
14
17
|
{
|
|
15
|
-
"url": "/db/update",
|
|
16
|
-
"expect": "update success",
|
|
18
|
+
"url": "/db/update?id=" + randomId,
|
|
19
|
+
"expect": "update success: 1",
|
|
17
20
|
},
|
|
18
21
|
{
|
|
19
22
|
"url": "/db/set-cache?value=zzz",
|
|
@@ -26,22 +29,22 @@ describe("Test Database", () => {
|
|
|
26
29
|
]
|
|
27
30
|
testDatabase.forEach((testRequest) => {
|
|
28
31
|
it(testRequest.url, (done) => {
|
|
29
|
-
chaiObj.request(
|
|
32
|
+
chaiObj.request(testAddr).get(testRequest.url).end((err, res) => {
|
|
30
33
|
chaiObj.assert.equal(testRequest.expect, res.text);
|
|
31
34
|
return done();
|
|
32
35
|
});
|
|
33
36
|
});
|
|
34
37
|
});
|
|
35
|
-
it("/db/
|
|
36
|
-
chaiObj.request(
|
|
38
|
+
it("/db/select-row", (done) => {
|
|
39
|
+
chaiObj.request(testAddr).get("/db/select-row?id=" + randomId).end((err, res) => {
|
|
37
40
|
const dataList = JSON.parse(res.text);
|
|
38
41
|
expect(dataList).to.be.an('array');
|
|
39
|
-
expect(dataList[0]).to.have.property("id").which.is.a("number").equal(
|
|
42
|
+
expect(dataList[0]).to.have.property("id").which.is.a("number").equal(randomId);
|
|
40
43
|
done();
|
|
41
44
|
});
|
|
42
45
|
});
|
|
43
46
|
it("/db/select", (done) => {
|
|
44
|
-
chaiObj.request(
|
|
47
|
+
chaiObj.request(testAddr).get("/db/select").end((err, res) => {
|
|
45
48
|
const dataList = JSON.parse(res.text);
|
|
46
49
|
expect(dataList).to.be.an('array');
|
|
47
50
|
expect(dataList[0]).to.have.property('id');
|
|
@@ -49,7 +52,7 @@ describe("Test Database", () => {
|
|
|
49
52
|
});
|
|
50
53
|
});
|
|
51
54
|
it("/db/select-user", (done) => {
|
|
52
|
-
chaiObj.request(
|
|
55
|
+
chaiObj.request(testAddr).get("/db/select-user").end((err, res) => {
|
|
53
56
|
const dataList = JSON.parse(res.text);
|
|
54
57
|
expect(dataList).to.be.an('array');
|
|
55
58
|
expect(dataList[0]).to.have.property('id');
|
|
@@ -58,4 +61,8 @@ describe("Test Database", () => {
|
|
|
58
61
|
});
|
|
59
62
|
});
|
|
60
63
|
|
|
64
|
+
function random(min, max) {
|
|
65
|
+
return Math.round(Math.random() * (max - min)) + min;
|
|
66
|
+
}
|
|
67
|
+
|
|
61
68
|
export {};
|
package/test/first-page.test.ts
CHANGED
|
@@ -2,6 +2,7 @@ const chaiObj = require('chai');
|
|
|
2
2
|
chaiObj.use(require("chai-http"));
|
|
3
3
|
|
|
4
4
|
describe("Test First page", () => {
|
|
5
|
+
const testAddr = `http://${process.env.LOCAL_HOST || "localhost"}:8081`;
|
|
5
6
|
const firstPageRequests = [
|
|
6
7
|
{
|
|
7
8
|
"url": "/first",
|
|
@@ -29,7 +30,7 @@ describe("Test First page", () => {
|
|
|
29
30
|
]
|
|
30
31
|
firstPageRequests.forEach((testRequest) => {
|
|
31
32
|
it(testRequest.url, (done) => {
|
|
32
|
-
chaiObj.request(
|
|
33
|
+
chaiObj.request(testAddr).get(testRequest.url).end((err, res) => {
|
|
33
34
|
chaiObj.assert.equal(testRequest.expect, res.text);
|
|
34
35
|
return done();
|
|
35
36
|
});
|
package/test/hooks.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
let appClose;
|
|
2
|
-
before(()
|
|
2
|
+
before(function () {
|
|
3
|
+
this.timeout(50000);
|
|
4
|
+
process.env["LOG"] = "CLOSE";
|
|
3
5
|
appClose = require("../app/src/main");
|
|
4
6
|
});
|
|
5
7
|
|
|
6
|
-
after(() => {
|
|
8
|
+
after((done) => {
|
|
7
9
|
if(appClose != null){
|
|
8
10
|
appClose.default();
|
|
9
11
|
}
|
|
12
|
+
done();
|
|
10
13
|
});
|
package/test/mq.test.ts
CHANGED
|
@@ -5,27 +5,10 @@ chaiObj.use(require("chai-http"));
|
|
|
5
5
|
const expect = chaiObj.expect;
|
|
6
6
|
|
|
7
7
|
describe("Test RabbitMQ", () => {
|
|
8
|
-
|
|
9
|
-
chaiObj.request("http://localhost:8081").get("/mq/listen").end((err, res) => {
|
|
10
|
-
expect(res.text).to.be.equal("ok");
|
|
11
|
-
done();
|
|
12
|
-
});
|
|
13
|
-
});
|
|
8
|
+
const testAddr = `http://${process.env.LOCAL_HOST || "localhost"}:8081`;
|
|
14
9
|
it("/mq/sendByMQClass", (done) => {
|
|
15
|
-
chaiObj.request(
|
|
16
|
-
expect(res.text).to.be.equal("
|
|
17
|
-
done();
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
it("/mq/sendByQueue", (done) => {
|
|
21
|
-
chaiObj.request("http://localhost:8081").get("/mq/sendByQueue").end((err, res) => {
|
|
22
|
-
expect(res.text).to.be.equal("sent by queue");
|
|
23
|
-
done();
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
it("/mq/sendByExchange", (done) => {
|
|
27
|
-
chaiObj.request("http://localhost:8081").get("/mq/sendByExchange").end((err, res) => {
|
|
28
|
-
expect(res.text).to.be.equal("sent by exchange");
|
|
10
|
+
chaiObj.request(testAddr).get("/mq/sendByMQClass").end((err, res) => {
|
|
11
|
+
expect(res.text).to.be.equal("Sent by MQClass");
|
|
29
12
|
done();
|
|
30
13
|
});
|
|
31
14
|
});
|
package/test/orm.test.ts
CHANGED
|
@@ -3,56 +3,57 @@ chaiObj.use(require("chai-http"));
|
|
|
3
3
|
const expect = chaiObj.expect;
|
|
4
4
|
|
|
5
5
|
describe("Test Request Paramters", () => {
|
|
6
|
+
const testAddr = `http://${process.env.LOCAL_HOST || "localhost"}:8081`;
|
|
6
7
|
it("/redis", (done) => {
|
|
7
|
-
chaiObj.request(
|
|
8
|
+
chaiObj.request(testAddr).get("/redis").end((err, res) => {
|
|
8
9
|
expect(res.text).to.be.equal("get from redis: " + "Hello World");
|
|
9
10
|
done();
|
|
10
11
|
});
|
|
11
12
|
});
|
|
12
13
|
it("/orm/first", (done) => {
|
|
13
|
-
chaiObj.request(
|
|
14
|
+
chaiObj.request(testAddr).get("/orm/first").end((err, res) => {
|
|
14
15
|
expect(res.text).to.be.equal("first test, to getUsers");
|
|
15
16
|
done();
|
|
16
17
|
});
|
|
17
18
|
});
|
|
18
19
|
it("/orm/one", (done) => {
|
|
19
|
-
chaiObj.request(
|
|
20
|
+
chaiObj.request(testAddr).get("/orm/one?id=1").end((err, res) => {
|
|
20
21
|
expect(res.text).to.be.equal("find one test, to getUser");
|
|
21
22
|
done();
|
|
22
23
|
});
|
|
23
24
|
});
|
|
24
25
|
it("/orm/delete", (done) => {
|
|
25
|
-
chaiObj.request(
|
|
26
|
+
chaiObj.request(testAddr).get("/orm/delete?id=0").end((err, res) => {
|
|
26
27
|
expect(res.text).to.be.equal("remove user, results: remove rows: 0");
|
|
27
28
|
done();
|
|
28
29
|
});
|
|
29
30
|
});
|
|
30
31
|
it("/orm/count", (done) => {
|
|
31
|
-
chaiObj.request(
|
|
32
|
+
chaiObj.request(testAddr).get("/orm/count").end((err, res) => {
|
|
32
33
|
expect(JSON.parse(res.text)).to.have.property("count").which.is.a("number").above(0);
|
|
33
34
|
done();
|
|
34
35
|
});
|
|
35
36
|
});
|
|
36
37
|
it("/orm/new", (done) => {
|
|
37
|
-
chaiObj.request(
|
|
38
|
+
chaiObj.request(testAddr).get("/orm/new").end((err, res) => {
|
|
38
39
|
expect(JSON.parse(res.text)).to.have.property("newId").which.is.a("number").above(0);
|
|
39
40
|
done();
|
|
40
41
|
});
|
|
41
42
|
});
|
|
42
43
|
it("/orm/page/calculate", (done) => {
|
|
43
|
-
chaiObj.request(
|
|
44
|
+
chaiObj.request(testAddr).get("/orm/page/calculate").end((err, res) => {
|
|
44
45
|
expect(JSON.parse(res.text)).to.have.property("totalPage").which.is.a("number").equal(38);
|
|
45
46
|
done();
|
|
46
47
|
});
|
|
47
48
|
});
|
|
48
49
|
it("/orm/pages", (done) => {
|
|
49
|
-
chaiObj.request(
|
|
50
|
+
chaiObj.request(testAddr).get("/orm/pages/1").end((err, res) => {
|
|
50
51
|
expect(JSON.parse(res.text)).is.a("array").lengthOf(3);
|
|
51
52
|
done();
|
|
52
53
|
});
|
|
53
54
|
});
|
|
54
55
|
it("/orm/edit", (done) => {
|
|
55
|
-
chaiObj.request(
|
|
56
|
+
chaiObj.request(testAddr).post("/orm/edit")
|
|
56
57
|
.type("form")
|
|
57
58
|
.send({ id: 1, name: "new name" })
|
|
58
59
|
.end((err, res) => {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const chaiObj = require('chai');
|
|
2
|
+
chaiObj.use(require("chai-http"));
|
|
3
|
+
const expect = chaiObj.expect;
|
|
4
|
+
|
|
5
|
+
describe("Test Redis", () => {
|
|
6
|
+
const testAddr = `http://${process.env.LOCAL_HOST || "localhost"}:8081`;
|
|
7
|
+
const ranking = {
|
|
8
|
+
"zhangsan": 93, "lisi": 99, "wangwu": 96, "zhaoliu": 97, "qianqi": 98, "sunba": 92, "zhoujiu": 94, "wushi": 95
|
|
9
|
+
};
|
|
10
|
+
it("/redis", (done) => {
|
|
11
|
+
chaiObj.request(testAddr).get("/redis").end((err, res) => {
|
|
12
|
+
expect(res.text).to.be.equal("get from redis: " + "Hello World");
|
|
13
|
+
done();
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
it("/redis/publish", (done) => {
|
|
17
|
+
chaiObj.request(testAddr).get("/redis/publish").end((err, res) => {
|
|
18
|
+
expect(res.text).to.be.equal("Published!");
|
|
19
|
+
done();
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
Object.keys(ranking).forEach((item) => {
|
|
23
|
+
it("/redis/add " + item, (done) => {
|
|
24
|
+
chaiObj.request(testAddr).get(`/redis/add?name=${item}&score=${ranking[item]}`).end((err, res) => {
|
|
25
|
+
expect(res.text).to.be.equal("add zset success");
|
|
26
|
+
done();
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
it("/redis/list", (done) => {
|
|
31
|
+
chaiObj.request(testAddr).get("/redis/list").end((err, res) => {
|
|
32
|
+
const dataList = JSON.parse(res.text);
|
|
33
|
+
const rankingAsc = Object.fromEntries(Object.entries(ranking).sort((a, b) => a[1] - b[1]));
|
|
34
|
+
expect(JSON.stringify(dataList)).to.be.equal(JSON.stringify(rankingAsc));
|
|
35
|
+
done();
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
it("/redis/ranking", (done) => {
|
|
39
|
+
chaiObj.request(testAddr).get("/redis/ranking").end((err, res) => {
|
|
40
|
+
const dataList = JSON.parse(res.text);
|
|
41
|
+
const rankingDesc = Object.fromEntries(Object.entries(ranking).sort((a, b) => b[1] - a[1]));
|
|
42
|
+
expect(JSON.stringify(dataList)).to.be.equal(JSON.stringify(rankingDesc));
|
|
43
|
+
done();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export { };
|
package/test/request.test.ts
CHANGED
|
@@ -5,14 +5,15 @@ chaiObj.use(require("chai-http"));
|
|
|
5
5
|
const expect = chaiObj.expect;
|
|
6
6
|
|
|
7
7
|
describe("Test Request Paramters", () => {
|
|
8
|
+
const testAddr = `http://${process.env.LOCAL_HOST || "localhost"}:8081`;
|
|
8
9
|
it("/request/res", (done) => {
|
|
9
|
-
chaiObj.request(
|
|
10
|
+
chaiObj.request(testAddr).get("/request/res").end((err, res) => {
|
|
10
11
|
expect(res.text).to.be.equal("test res");
|
|
11
12
|
done();
|
|
12
13
|
});
|
|
13
14
|
});
|
|
14
15
|
it("/request/query", (done) => {
|
|
15
|
-
chaiObj.request(
|
|
16
|
+
chaiObj.request(testAddr).get("/request/query?id=100").end((err, res) => {
|
|
16
17
|
expect(res.text).to.be.equal(JSON.stringify(
|
|
17
18
|
new MutilUsers("group", [new UserDto(1, "name"), new UserDto(2, "name")]
|
|
18
19
|
)));
|
|
@@ -21,7 +22,7 @@ describe("Test Request Paramters", () => {
|
|
|
21
22
|
});
|
|
22
23
|
it("/request/body", (done) => {
|
|
23
24
|
const sendUser = new UserDto(100, "name100");
|
|
24
|
-
chaiObj.request(
|
|
25
|
+
chaiObj.request(testAddr).post("/request/body")
|
|
25
26
|
.send(sendUser)
|
|
26
27
|
.end((err, res) => {
|
|
27
28
|
expect(res.text).to.be.equal(JSON.stringify(new MutilUsers("group", [sendUser])));
|
|
@@ -30,7 +31,7 @@ describe("Test Request Paramters", () => {
|
|
|
30
31
|
});
|
|
31
32
|
it("/request/form", (done) => {
|
|
32
33
|
const sendName = "name200";
|
|
33
|
-
chaiObj.request(
|
|
34
|
+
chaiObj.request(testAddr).post("/request/form")
|
|
34
35
|
.type("form")
|
|
35
36
|
.send({ name: sendName })
|
|
36
37
|
.end((err, res) => {
|
|
@@ -40,7 +41,7 @@ describe("Test Request Paramters", () => {
|
|
|
40
41
|
});
|
|
41
42
|
it("/request/param", (done) => {
|
|
42
43
|
const sendId = 200;
|
|
43
|
-
chaiObj.request(
|
|
44
|
+
chaiObj.request(testAddr).get("/request/param/" + sendId).end((err, res) => {
|
|
44
45
|
expect(res.text).to.be.equal("test param: " + sendId);
|
|
45
46
|
done();
|
|
46
47
|
});
|
package/test/second-page.test.ts
CHANGED
|
@@ -1,34 +1,33 @@
|
|
|
1
1
|
import * as jwttoken from "jsonwebtoken";
|
|
2
2
|
import * as fs from "fs";
|
|
3
3
|
const chaiObj = require('chai');
|
|
4
|
-
|
|
5
4
|
chaiObj.use(require("chai-http"));
|
|
6
5
|
|
|
7
|
-
|
|
8
6
|
describe("Test Sencond Page", () => {
|
|
7
|
+
const testAddr = `http://${process.env.LOCAL_HOST || "localhost"}:8081`;
|
|
9
8
|
it("/second/setCookie", (done) => {
|
|
10
|
-
chaiObj.request(
|
|
9
|
+
chaiObj.request(testAddr).get("/second/setCookie").end((err, res) => {
|
|
11
10
|
chaiObj.assert.equal(res.headers["set-cookie"].includes("name=zzz; Path=/"), true);
|
|
12
11
|
done();
|
|
13
12
|
});
|
|
14
13
|
});
|
|
15
14
|
it("/second/getCookie", (done) => {
|
|
16
15
|
const cookieSet = "mycookie"
|
|
17
|
-
chaiObj.request(
|
|
16
|
+
chaiObj.request(testAddr).get("/second/getCookie")
|
|
18
17
|
.set("Cookie", "name=" + cookieSet).end((err, res) => {
|
|
19
18
|
chaiObj.assert.equal(res.text, "getCookie: " + cookieSet);
|
|
20
19
|
done();
|
|
21
20
|
});
|
|
22
21
|
});
|
|
23
22
|
it("/second/testSession", (done) => {
|
|
24
|
-
chaiObj.request(
|
|
23
|
+
chaiObj.request(testAddr).get("/second/testSession").end((err, res) => {
|
|
25
24
|
chaiObj.assert.equal(res.text, "testForSession: 1");
|
|
26
25
|
done();
|
|
27
26
|
});
|
|
28
27
|
});
|
|
29
28
|
it("/upload", (done) => {
|
|
30
29
|
const uploadfile = "./app/static/k.jpg";
|
|
31
|
-
chaiObj.request(
|
|
30
|
+
chaiObj.request(testAddr).post("/upload")
|
|
32
31
|
.set('Content-Type', 'multipart/form-data')
|
|
33
32
|
.attach("file", uploadfile)
|
|
34
33
|
.end((err, res) => {
|
|
@@ -39,7 +38,7 @@ describe("Test Sencond Page", () => {
|
|
|
39
38
|
it("/form", (done) => {
|
|
40
39
|
const token = jwttoken.sign({ foo: 'bar' }, 'shhhhhhared-secret');
|
|
41
40
|
const fileContents = fs.readFileSync("./app/src/views/upload.html", "utf8");
|
|
42
|
-
chaiObj.request(
|
|
41
|
+
chaiObj.request(testAddr).post("/form")
|
|
43
42
|
.set({ "Authorization": `Bearer ${token}` })
|
|
44
43
|
.end((err, res) => {
|
|
45
44
|
chaiObj.assert.equal(res.text, fileContents);
|