typespeed 2.4.11 → 2.5.1

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.
Files changed (90) hide show
  1. package/CHANGELOG.md +8 -2
  2. package/dist/bind.decorator.js +50 -0
  3. package/dist/core.decorator.js +113 -26
  4. package/dist/database.decorator.js +122 -16
  5. package/dist/decorator-utils.js +42 -0
  6. package/dist/default/rabbitmq.class.js +18 -1
  7. package/dist/default/redis.class.js +14 -1
  8. package/dist/default/socket-io.class.js +53 -4
  9. package/dist/route.decorator.js +175 -10
  10. package/dist/typespeed.d.ts +35 -31
  11. package/dist/typespeed.js +31 -3
  12. package/package.json +6 -2
  13. package/.github/workflows/test.yml +0 -50
  14. package/app/nodemon.json +0 -5
  15. package/app/package.json +0 -17
  16. package/app/src/aop-test.class.ts +0 -29
  17. package/app/src/config-development.json +0 -26
  18. package/app/src/config-production.json +0 -15
  19. package/app/src/config.json +0 -50
  20. package/app/src/custom-log.class.ts +0 -33
  21. package/app/src/entities/mutil-users.class.ts +0 -5
  22. package/app/src/entities/user-dto.class.ts +0 -3
  23. package/app/src/first-page.class.ts +0 -46
  24. package/app/src/jwt-authentication.class.ts +0 -30
  25. package/app/src/main.ts +0 -24
  26. package/app/src/second-page.class.ts +0 -43
  27. package/app/src/test-database.class.ts +0 -81
  28. package/app/src/test-log.class.ts +0 -11
  29. package/app/src/test-mq.class.ts +0 -21
  30. package/app/src/test-orm.class.ts +0 -63
  31. package/app/src/test-redis.class.ts +0 -45
  32. package/app/src/test-request.class.ts +0 -37
  33. package/app/src/test-socket.class.ts +0 -56
  34. package/app/src/user-model.class.ts +0 -50
  35. package/app/src/views/index.html +0 -1
  36. package/app/src/views/socket.html +0 -23
  37. package/app/src/views/upload.html +0 -14
  38. package/app/static/favicon.ico +0 -0
  39. package/app/static/k.jpg +0 -0
  40. package/app/tsconfig.json +0 -20
  41. package/introduction/decorator/example-import.class.ts +0 -6
  42. package/introduction/decorator/main-app.ts +0 -6
  43. package/introduction/decorator/main-decorator.ts +0 -108
  44. package/introduction/decorator/main-import.ts +0 -1
  45. package/introduction/decorator/main-reflect.ts +0 -25
  46. package/introduction/tsconfig.json +0 -20
  47. package/introduction/web-services/db-init.ts +0 -39
  48. package/introduction/web-services/db-singleton.ts +0 -59
  49. package/introduction/web-services/http-if.ts +0 -10
  50. package/introduction/web-services/http-init.ts +0 -6
  51. package/introduction/web-services/http-router.ts +0 -28
  52. package/src/core.decorator.ts +0 -98
  53. package/src/database.decorator.ts +0 -342
  54. package/src/default/default-authentication.class.ts +0 -10
  55. package/src/default/express-server.class.ts +0 -150
  56. package/src/default/log-default.class.ts +0 -9
  57. package/src/default/node-cache.class.ts +0 -40
  58. package/src/default/pages/404.html +0 -226
  59. package/src/default/pages/500.html +0 -713
  60. package/src/default/rabbitmq.class.ts +0 -61
  61. package/src/default/read-write-db.class.ts +0 -53
  62. package/src/default/redis.class.ts +0 -79
  63. package/src/default/socket-io.class.ts +0 -81
  64. package/src/factory/authentication-factory.class.ts +0 -9
  65. package/src/factory/cache-factory.class.ts +0 -7
  66. package/src/factory/data-source-factory.class.ts +0 -4
  67. package/src/factory/log-factory.class.ts +0 -8
  68. package/src/factory/server-factory.class.ts +0 -6
  69. package/src/route.decorator.ts +0 -175
  70. package/src/scaffold/command.ts +0 -40
  71. package/src/scaffold/templates/front-page.class.ts.tpl +0 -12
  72. package/src/scaffold/templates/main.ts.tpl +0 -13
  73. package/src/scaffold/templates/nodemon.json.tpl +0 -7
  74. package/src/scaffold/templates/package.json.tpl +0 -16
  75. package/src/scaffold/templates/tsconfig.json.tpl +0 -17
  76. package/src/typespeed.d.ts +0 -399
  77. package/src/typespeed.ts +0 -110
  78. package/test/database.test.ts +0 -76
  79. package/test/first-page.test.ts +0 -42
  80. package/test/hooks.ts +0 -13
  81. package/test/mq.test.ts +0 -17
  82. package/test/orm.test.ts +0 -66
  83. package/test/redis.test.ts +0 -48
  84. package/test/request.test.ts +0 -51
  85. package/test/second-page.test.ts +0 -50
  86. package/test/socket.test.ts +0 -60
  87. package/test-env/docker-compose.test.yml +0 -31
  88. package/test-env/mysql-init/init.sql +0 -8
  89. package/test-env//346/234/254/345/234/260Docker/346/265/213/350/257/225/346/226/271/346/241/210.md +0 -69
  90. package/tsconfig.json +0 -25
@@ -4,6 +4,8 @@ exports.jwt = exports.upload = exports.setRouter = exports.requestMapping = expo
4
4
  const multiparty = require("multiparty");
5
5
  const express_jwt_1 = require("express-jwt");
6
6
  const core_decorator_1 = require("./core.decorator");
7
+ const decorator_utils_1 = require("./decorator-utils");
8
+ const bind_decorator_1 = require("./bind.decorator");
7
9
  const routerMapper = {
8
10
  "get": {},
9
11
  "post": {},
@@ -28,7 +30,53 @@ function setRouter(app) {
28
30
  }
29
31
  exports.setRouter = setRouter;
30
32
  function mapperFunction(method, value) {
31
- return (target, propertyKey) => {
33
+ return (...args) => {
34
+ if ((0, decorator_utils_1.isStd)(args)) {
35
+ const [methodFn, ctx] = (0, decorator_utils_1.getStdArgs)(args);
36
+ ctx.addInitializer(function () {
37
+ const className = this.constructor.name;
38
+ const propertyKey = String(ctx.name);
39
+ applyRouteBind(className, propertyKey, methodFn);
40
+ routerMapper[method][value] = {
41
+ "path": value,
42
+ "name": [className, propertyKey].toString(),
43
+ "target": this.constructor,
44
+ "propertyKey": propertyKey,
45
+ "invoker": async (req, res, next) => {
46
+ const routerBean = (0, core_decorator_1.getComponent)(this.constructor);
47
+ try {
48
+ let paramTotal = routerBean[propertyKey].length;
49
+ if (routerParamsTotal[[className, propertyKey].toString()]) {
50
+ paramTotal = Math.max(paramTotal, routerParamsTotal[[className, propertyKey].toString()]);
51
+ }
52
+ const callArgs = [req, res, next];
53
+ if (paramTotal > 0) {
54
+ for (let i = 0; i < paramTotal; i++) {
55
+ if (routerParams[[className, propertyKey, i].toString()]) {
56
+ callArgs[i] = routerParams[[className, propertyKey, i].toString()](req, res, next);
57
+ }
58
+ }
59
+ }
60
+ const testResult = await routerBean[propertyKey].apply(routerBean, callArgs);
61
+ if (typeof testResult === "object") {
62
+ res.json(testResult);
63
+ }
64
+ else if (typeof testResult !== "undefined") {
65
+ res.send(testResult);
66
+ }
67
+ return testResult;
68
+ }
69
+ catch (err) {
70
+ next(err);
71
+ }
72
+ }
73
+ };
74
+ });
75
+ return;
76
+ }
77
+ const target = args[0];
78
+ const propertyKey = args[1];
79
+ applyRouteBind(target.constructor.name, propertyKey, target[propertyKey]);
32
80
  routerMapper[method][value] = {
33
81
  "path": value,
34
82
  "name": [target.constructor.name, propertyKey].toString(),
@@ -65,7 +113,22 @@ function mapperFunction(method, value) {
65
113
  };
66
114
  };
67
115
  }
68
- function upload(target, propertyKey) {
116
+ function upload(...args) {
117
+ if ((0, decorator_utils_1.isStd)(args)) {
118
+ const [, ctx] = (0, decorator_utils_1.getStdArgs)(args);
119
+ ctx.addInitializer(function () {
120
+ const key = [this.constructor.name, String(ctx.name)].toString();
121
+ if (routerMiddleware[key]) {
122
+ routerMiddleware[key].push(uploadMiddleware);
123
+ }
124
+ else {
125
+ routerMiddleware[key] = [uploadMiddleware];
126
+ }
127
+ });
128
+ return;
129
+ }
130
+ const target = args[0];
131
+ const propertyKey = args[1];
69
132
  const key = [target.constructor.name, propertyKey].toString();
70
133
  if (routerMiddleware[key]) {
71
134
  routerMiddleware[key].push(uploadMiddleware);
@@ -83,7 +146,22 @@ function uploadMiddleware(req, res, next) {
83
146
  });
84
147
  }
85
148
  function jwt(jwtConfig) {
86
- return (target, propertyKey) => {
149
+ return (...args) => {
150
+ if ((0, decorator_utils_1.isStd)(args)) {
151
+ const [, ctx] = (0, decorator_utils_1.getStdArgs)(args);
152
+ ctx.addInitializer(function () {
153
+ const key = [this.constructor.name, String(ctx.name)].toString();
154
+ if (routerMiddleware[key]) {
155
+ routerMiddleware[key].push((0, express_jwt_1.expressjwt)(jwtConfig));
156
+ }
157
+ else {
158
+ routerMiddleware[key] = [(0, express_jwt_1.expressjwt)(jwtConfig)];
159
+ }
160
+ });
161
+ return;
162
+ }
163
+ const target = args[0];
164
+ const propertyKey = args[1];
87
165
  const key = [target.constructor.name, propertyKey].toString();
88
166
  if (routerMiddleware[key]) {
89
167
  routerMiddleware[key].push((0, express_jwt_1.expressjwt)(jwtConfig));
@@ -96,15 +174,34 @@ function jwt(jwtConfig) {
96
174
  exports.jwt = jwt;
97
175
  function before(constructorFunction, methodName) {
98
176
  const targetBean = (0, core_decorator_1.getComponent)(constructorFunction);
99
- return function (target, propertyKey) {
177
+ return function (...args) {
178
+ if ((0, decorator_utils_1.isStd)(args)) {
179
+ const [, ctx] = (0, decorator_utils_1.getStdArgs)(args);
180
+ const hookKey = String(ctx.name);
181
+ ctx.addInitializer(function () {
182
+ const currentMethod = this[methodName];
183
+ if (currentMethod && currentMethod.length > 0) {
184
+ routerParamsTotal[[constructorFunction.name, methodName].toString()] = currentMethod.length;
185
+ }
186
+ Object.assign(this, {
187
+ [methodName]: function (...innerArgs) {
188
+ this[hookKey](...innerArgs);
189
+ return currentMethod.apply(this, innerArgs);
190
+ }
191
+ });
192
+ });
193
+ return;
194
+ }
195
+ const target = args[0];
196
+ const propertyKey = args[1];
100
197
  const currentMethod = targetBean[methodName];
101
198
  if (currentMethod.length > 0) {
102
199
  routerParamsTotal[[constructorFunction.name, methodName].toString()] = currentMethod.length;
103
200
  }
104
201
  Object.assign(targetBean, {
105
- [methodName]: function (...args) {
106
- target[propertyKey](...args);
107
- return currentMethod.apply(targetBean, args);
202
+ [methodName]: function (...innerArgs) {
203
+ target[propertyKey](...innerArgs);
204
+ return currentMethod.apply(targetBean, innerArgs);
108
205
  }
109
206
  });
110
207
  };
@@ -112,14 +209,34 @@ function before(constructorFunction, methodName) {
112
209
  exports.before = before;
113
210
  function after(constructorFunction, methodName) {
114
211
  const targetBean = (0, core_decorator_1.getComponent)(constructorFunction);
115
- return function (target, propertyKey) {
212
+ return function (...args) {
213
+ if ((0, decorator_utils_1.isStd)(args)) {
214
+ const [, ctx] = (0, decorator_utils_1.getStdArgs)(args);
215
+ const hookKey = String(ctx.name);
216
+ ctx.addInitializer(function () {
217
+ const currentMethod = this[methodName];
218
+ if (currentMethod && currentMethod.length > 0) {
219
+ routerParamsTotal[[constructorFunction.name, methodName].toString()] = currentMethod.length;
220
+ }
221
+ Object.assign(this, {
222
+ [methodName]: function (...innerArgs) {
223
+ const result = currentMethod.apply(this, innerArgs);
224
+ const afterResult = this[hookKey](result);
225
+ return afterResult !== null && afterResult !== void 0 ? afterResult : result;
226
+ }
227
+ });
228
+ });
229
+ return;
230
+ }
231
+ const target = args[0];
232
+ const propertyKey = args[1];
116
233
  const currentMethod = targetBean[methodName];
117
234
  if (currentMethod.length > 0) {
118
235
  routerParamsTotal[[constructorFunction.name, methodName].toString()] = currentMethod.length;
119
236
  }
120
237
  Object.assign(targetBean, {
121
- [methodName]: function (...args) {
122
- const result = currentMethod.apply(targetBean, args);
238
+ [methodName]: function (...innerArgs) {
239
+ const result = currentMethod.apply(targetBean, innerArgs);
123
240
  const afterResult = target[propertyKey](result);
124
241
  return afterResult !== null && afterResult !== void 0 ? afterResult : result;
125
242
  }
@@ -160,6 +277,54 @@ function getParamInFunction(fn, index) {
160
277
  const result = code.slice(code.indexOf('(') + 1, code.indexOf(')')).match(/([^\s,]+)/g);
161
278
  return result[index] || null;
162
279
  }
280
+ /** 解析函数参数名列表(供 route @bind 做「参数名 → 索引」映射) */
281
+ function getParamNames(fn) {
282
+ const code = fn.toString().replace(/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg, '').replace(/=>.*$/mg, '').replace(/=[^,)]+/g, '');
283
+ const paramsStr = code.slice(code.indexOf('(') + 1, code.indexOf(')'));
284
+ if (!paramsStr.trim())
285
+ return [];
286
+ return paramsStr.split(',').map(p => {
287
+ const matched = p.trim().match(/([A-Za-z_$][\w$]*)/);
288
+ return matched ? matched[1] : p.trim();
289
+ }).filter(Boolean);
290
+ }
291
+ /** 把 route @bind 的「来源字符串」转成参数解析器 */
292
+ function getRouteSourceResolver(source, paramName) {
293
+ switch (source) {
294
+ case "req": return (req, res, next) => req;
295
+ case "res": return (req, res, next) => res;
296
+ case "next": return (req, res, next) => next;
297
+ case "reqBody": return (req, res, next) => req.body;
298
+ case "reqParam": return (req, res, next) => req.params[paramName];
299
+ case "reqQuery": return (req, res, next) => req.query[paramName];
300
+ case "reqForm": return (req, res, next) => req.body[paramName];
301
+ default: return null;
302
+ }
303
+ }
304
+ /** 读取 @bind 声明,把「参数名 → 来源」转成 routerParams 的「索引 → 解析器」 */
305
+ function applyRouteBind(className, propertyKey, method) {
306
+ const bindMapping = (0, bind_decorator_1.getBindMapping)(className, propertyKey);
307
+ if (!bindMapping)
308
+ return;
309
+ const paramNames = getParamNames(method);
310
+ const nameToIndex = {};
311
+ paramNames.forEach((paramName, index) => {
312
+ if (paramName && nameToIndex[paramName] === undefined)
313
+ nameToIndex[paramName] = index;
314
+ });
315
+ for (const bindName in bindMapping) {
316
+ const source = bindMapping[bindName];
317
+ if (typeof source !== "string")
318
+ continue; // 跳过 database 的数值映射
319
+ const index = nameToIndex[bindName];
320
+ if (index === undefined)
321
+ continue;
322
+ const resolver = getRouteSourceResolver(source, bindName);
323
+ if (resolver) {
324
+ routerParams[[className, propertyKey, index].toString()] = resolver;
325
+ }
326
+ }
327
+ }
163
328
  function reqQuery(target, propertyKey, parameterIndex) {
164
329
  const key = [target.constructor.name, propertyKey, parameterIndex].toString();
165
330
  const paramName = getParamInFunction(target[propertyKey], parameterIndex);
@@ -5,68 +5,74 @@ import "reflect-metadata";
5
5
 
6
6
  /**设置路由中间件 */
7
7
  declare function setRouter(app: express.Application): void;
8
- /**上传文件装饰器,装饰页面具备解析上传文件的能力 */
9
- declare function upload(target: any, propertyKey: string): void;
8
+ /**上传文件装饰器,装饰页面具备解析上传文件的能力(legacy 方法装饰器;2.5.x 起兼容标准 (value, context) 签名) */
9
+ declare function upload(...args: any[]): any;
10
10
  /**
11
11
  * 页面支持 JWT 鉴权能力
12
12
  * @param jwtConfig jwt 配置
13
13
  */
14
- declare function jwt(jwtConfig: any): (target: any, propertyKey: string) => void;
14
+ declare function jwt(jwtConfig: any): (...args: any[]) => any;
15
15
  /**
16
16
  * GET 请求装饰器
17
17
  * @param value 请求路径
18
18
  */
19
- declare const getMapping: (value: string) => (target: any, propertyKey: string) => void;
19
+ declare const getMapping: (value: string) => (...args: any[]) => any;
20
20
  /**
21
21
  * POST 请求装饰器
22
22
  * @param value 请求路径
23
23
  */
24
- declare const postMapping: (value: string) => (target: any, propertyKey: string) => void;
24
+ declare const postMapping: (value: string) => (...args: any[]) => any;
25
25
  /**
26
26
  * 请求装饰器,不区分请求类型
27
27
  * @param value 请求路径
28
28
  */
29
- declare const requestMapping: (value: string) => (target: any, propertyKey: string) => void;
29
+ declare const requestMapping: (value: string) => (...args: any[]) => any;
30
30
  /**
31
31
  * INSERT 装饰器
32
32
  * 将方法作为 INSERT SQL 使用
33
33
  * @param sql INSERT SQL 语句
34
34
  */
35
- declare function insert(sql: string): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
35
+ declare function insert(sql: string): (...args: any[]) => any;
36
36
  /**
37
37
  * UPDATE 装饰器
38
38
  * 将方法作为 UPDATE SQL 使用
39
39
  * @param sql UPDATE SQL 语句
40
40
  */
41
- declare function update(sql: string): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
41
+ declare function update(sql: string): (...args: any[]) => any;
42
42
  /**
43
43
  * DELETE 装饰器
44
44
  * 将方法作为 DELETE SQL 使用
45
45
  * @param sql DELETE SQL 语句
46
46
  */
47
- declare function remove(sql: string): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
47
+ declare function remove(sql: string): (...args: any[]) => any;
48
48
  /**
49
49
  * SELECT 装饰器
50
50
  * 将方法作为 SELECT SQL 使用
51
51
  * @param sql SELECT SQL 语句
52
52
  */
53
- declare function select(sql: string): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void;
53
+ declare function select(sql: string): (...args: any[]) => any;
54
54
  /**
55
55
  * SELECT 结果类型装饰器,和 @select 配合使用
56
56
  * @param dataClass 结果类型
57
57
  */
58
- declare function resultType(dataClass: any): (target: any, propertyKey: string) => void;
58
+ declare function resultType(dataClass: any): (...args: any[]) => any;
59
59
  /**
60
60
  * SQL 参数装饰器,标注 SQL 语句的绑定参数值,和 @select @insert @update @remove 配合使用
61
61
  * @param name 参数在 SQL 语句内的标记值
62
62
  */
63
63
  declare function param(name: string): (target: any, propertyKey: string | symbol, parameterIndex: number) => void;
64
+ /**
65
+ * 方法级参数绑定装饰器(标准装饰器删除了参数装饰器后的替代,legacy 模式也可用)。
66
+ * database 场景映射 SQL 占位符 → 参数索引(值为 number);route 场景映射参数名 → 请求来源(值为 string)。
67
+ * @param mapping 绑定声明,如 { name: 0, id: 1 } 或 { id: "reqParam", body: "reqBody" }
68
+ */
69
+ declare function bind(mapping: Record<string, string | number>): (...args: any[]) => any;
64
70
  /**
65
71
  * SELECT 缓存装饰器,自动缓存 SELECT 查询结果,和 @select 配合使用
66
72
  * 当执行 @insert @update @remove 时,会自动清除缓存。
67
73
  * @param ttl 缓存时间,单位秒
68
74
  */
69
- declare function cache(ttl: number): (target: any, propertyKey: string) => void;
75
+ declare function cache(ttl: number): (...args: any[]) => any;
70
76
  /**模型数据操作类 */
71
77
  declare class Model {
72
78
  /**分页数据 */
@@ -139,23 +145,21 @@ declare class Model {
139
145
  *
140
146
  * 被装饰的类将作为应用程序入口,框架将启动该类的 main 方法
141
147
  */
142
- declare function app<T extends {
143
- new(...args: any[]): {};
144
- }>(constructor: T): void;
148
+ declare function app(...args: any[]): any;
145
149
  /**获取配置文件中的配置项 */
146
150
  declare function config(node: string): any;
147
- /**组件装饰器,被装饰的类可以通过 @autoware 取得实例 */
148
- declare function component(constructorFunction: any): void;
151
+ /**组件装饰器,被装饰的类可以通过 @autoware 取得实例(legacy 类装饰器;2.5.x 起兼容标准 (value, context) 签名) */
152
+ declare function component(...args: any[]): any;
149
153
  /**获取组件实例函数,返回结果同 @autoware */
150
154
  declare function getComponent(constructorFunction: any): any;
151
- /**提供对象装饰器,框架将使用 @bean 装饰的方法来获取对象实例 */
152
- declare function bean(target: any, propertyKey: string): void;
155
+ /**提供对象装饰器,框架将使用 @bean 装饰的方法来获取对象实例(legacy 方法装饰器;2.5.x 起兼容标准签名) */
156
+ declare function bean(...args: any[]): any;
153
157
  /**获取对象实例函数,返回结果由 @bean 装饰的方法提供 */
154
158
  declare function getBean(mappingClass: Function): any;
155
159
  /**配置装饰器,装饰类成员变量值,获取配置文件中的配置项 */
156
160
  declare function value(configPath: string): any;
157
161
  /**自动装配装饰器,无参数版本,被装饰的类成员变量将自动注入实例 */
158
- declare function autoware(target: any, propertyKey: string): void;
162
+ declare function autoware(...args: any[]): any;
159
163
  /**自动装配装饰器,带参数版本,可输入参数作为实例初始化参数,被装饰的类成员变量将自动注入实例 */
160
164
  declare function resource(...args: any[]): any;
161
165
  /**日志函数,输出打印日志 */
@@ -165,15 +169,15 @@ declare function logx(message: any): void;
165
169
  /**错误日志函数,输出打印错误日志 */
166
170
  declare function error(message?: any, ...optionalParams: any[]): void;
167
171
  /**路由页面前置执行装饰器,参数指向路由页面方法,被装饰的方法将在路由页面之前执行 */
168
- declare function before(constructorFunction: any, methodName: string): (target: any, propertyKey: string) => void;
172
+ declare function before(constructorFunction: any, methodName: string): (...args: any[]) => any;
169
173
  /**路由页面后置执行装饰器,参数指向路由页面方法,被装饰的方法将在路由页面之后执行 */
170
- declare function after(constructorFunction: any, methodName: string): (target: any, propertyKey: string) => void;
174
+ declare function after(constructorFunction: any, methodName: string): (...args: any[]) => any;
171
175
  /**定时程序装饰器,参数支持 crontab 格式字符串,可根据参数定时执行被装饰的方法 */
172
- declare function schedule(cronTime: string | Date): (target: any, propertyKey: string) => void;
176
+ declare function schedule(cronTime: string | Date): (...args: any[]) => any;
173
177
  /**RabbitMQ 监听装饰器,参数是监听的队列名称,当接受到消息时将执行被装饰方法 */
174
- declare function rabbitListener(queue: string): (target: any, propertyKey: string) => void;
175
- /**Redis 监听装饰器,参数是监听的队列名称,当接受到消息时将执行被装饰方法 */
176
- declare function redisSubscriber(target: any, propertyKey: string): void;
178
+ declare function rabbitListener(queue: string): (...args: any[]) => any;
179
+ /**Redis 监听装饰器,参数是监听的频道名称,当接受到消息时将执行被装饰方法 */
180
+ declare function redisSubscriber(channel: string): (...args: any[]) => any;
177
181
  /** request 对象装饰器,作为路由页面方法参数,获取 request 对象 */
178
182
  declare function req(target: any, propertyKey: string, parameterIndex: number): void;
179
183
  /** response 对象装饰器,作为路由页面方法参数,获取 response 对象 */
@@ -385,15 +389,15 @@ declare class SocketIo {
385
389
  * Socket IO 事件装饰器
386
390
  * @param event 事件名称
387
391
  */
388
- public static onEvent(event: string): (target: any, propertyKey: string) => void;
392
+ public static onEvent(event: string): (...args: any[]) => any;
389
393
  /**Socket IO 错误捕获装饰器 */
390
- public static onError(target: any, propertyKey: string): void;
394
+ public static onError(...args: any[]): any;
391
395
  /**Socket IO 客户端断开连接事件装饰器 */
392
- public static onDisconnect(target: any, propertyKey: string): void;
396
+ public static onDisconnect(...args: any[]): any;
393
397
  /**Socket IO 客户端连接成功事件装饰器 */
394
- public static onConnected(target: any, propertyKey: string): void;
398
+ public static onConnected(...args: any[]): any;
395
399
  }
396
400
  /**Socket IO 服务实现类 */
397
401
  declare const io: IoServer;
398
402
 
399
- 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, logx, app, before, after, value, error, config, autoware, getBean, getComponent, schedule, getMapping, postMapping, requestMapping, setRouter, upload, jwt, insert, update, remove, select, param, resultType, cache, Model, SocketIo, io };
403
+ 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, logx, app, before, after, value, error, config, autoware, getBean, getComponent, schedule, getMapping, postMapping, requestMapping, setRouter, upload, jwt, insert, update, remove, select, param, bind, resultType, cache, Model, SocketIo, io };
package/dist/typespeed.js CHANGED
@@ -19,6 +19,7 @@ require("reflect-metadata");
19
19
  const fs = require("fs");
20
20
  const path = require("path");
21
21
  const walkSync = require("walk-sync");
22
+ const decorator_utils_1 = require("./decorator-utils");
22
23
  let globalConfig = {};
23
24
  const corePath = __dirname;
24
25
  const mainPath = path.dirname(getRootPath(new Error().stack.split("\n")) || process.argv[1]);
@@ -33,7 +34,18 @@ if (fs.existsSync(configFile)) {
33
34
  }
34
35
  globalConfig["MAIN_PATH"] = mainPath;
35
36
  globalConfig["CORE_PATH"] = corePath;
36
- function app(constructor) {
37
+ function app(...args) {
38
+ if ((0, decorator_utils_1.isStd)(args)) {
39
+ const [, ctx] = (0, decorator_utils_1.getStdArgs)(args);
40
+ ctx.addInitializer(function () {
41
+ startApp(this.constructor);
42
+ });
43
+ return;
44
+ }
45
+ startApp(args[0]);
46
+ }
47
+ exports.app = app;
48
+ function startApp(constructor) {
37
49
  const coreFiles = walkSync(corePath, { globs: ['**/*.ts'], ignore: ['**/*.d.ts', 'scaffold/**'] });
38
50
  const mainFiles = walkSync(mainPath, { globs: ['**/*.ts'] });
39
51
  (async function () {
@@ -56,13 +68,28 @@ function app(constructor) {
56
68
  main["main"]();
57
69
  }());
58
70
  }
59
- exports.app = app;
60
71
  function config(node) {
61
72
  return globalConfig[node] || null;
62
73
  }
63
74
  exports.config = config;
64
75
  function value(configPath) {
65
- return function (target, propertyKey) {
76
+ return function (...args) {
77
+ if ((0, decorator_utils_1.isStd)(args)) {
78
+ // 标准 field 装饰器:返回 initializer 注入配置值(标准模式下无 design:type)。
79
+ return (initialValue) => {
80
+ if (globalConfig === undefined) {
81
+ return initialValue;
82
+ }
83
+ let pathNodes = configPath.split(".");
84
+ let nodeValue = globalConfig;
85
+ for (let i = 0; i < pathNodes.length; i++) {
86
+ nodeValue = nodeValue[pathNodes[i]];
87
+ }
88
+ return nodeValue === undefined ? initialValue : nodeValue;
89
+ };
90
+ }
91
+ const target = args[0];
92
+ const propertyKey = args[1];
66
93
  if (globalConfig === undefined) {
67
94
  Object.defineProperty(target, propertyKey, {
68
95
  get: () => {
@@ -108,6 +135,7 @@ function getRootPath(lines) {
108
135
  __exportStar(require("./core.decorator"), exports);
109
136
  __exportStar(require("./route.decorator"), exports);
110
137
  __exportStar(require("./database.decorator"), exports);
138
+ __exportStar(require("./bind.decorator"), exports);
111
139
  var log_factory_class_1 = require("./factory/log-factory.class");
112
140
  Object.defineProperty(exports, "LogFactory", { enumerable: true, get: function () { return log_factory_class_1.default; } });
113
141
  var cache_factory_class_1 = require("./factory/cache-factory.class");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typespeed",
3
- "version": "2.4.11",
3
+ "version": "2.5.1",
4
4
  "description": "A new Framework for TypeScript.",
5
5
  "author": "speedphp",
6
6
  "license": "MIT License",
@@ -13,8 +13,12 @@
13
13
  "prebuild": "rm -rf dist"
14
14
  },
15
15
  "main": "dist/typespeed.js",
16
+ "files": [
17
+ "dist",
18
+ "CHANGELOG.md"
19
+ ],
16
20
  "bin": {
17
- "typespeed": "./dist/scaffold/command.js"
21
+ "typespeed": "dist/scaffold/command.js"
18
22
  },
19
23
  "homepage": "https://github.com/speedphp/typespeed#readme",
20
24
  "repository": {
@@ -1,50 +0,0 @@
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/checkout@v4
25
- - uses: actions/setup-node@v4
26
- with:
27
- node-version: 22
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@v4
36
- with:
37
- path: ~/.npm
38
- key: ${{ runner.os }}-node-v22-${{ hashFiles('**/package.json') }}
39
- restore-keys: |
40
- ${{ runner.os }}-node-v22-
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/app/nodemon.json DELETED
@@ -1,5 +0,0 @@
1
- {
2
- "watch": ["src", "../dist", "../src", "../test"],
3
- "ext": "ts,json",
4
- "exec": "npm test"
5
- }
package/app/package.json DELETED
@@ -1,17 +0,0 @@
1
- {
2
- "name": "test-typespeed",
3
- "version": "1.0.0",
4
- "description": "",
5
- "scripts": {
6
- "watch": "nodemon",
7
- "test": "ts-node src/main.ts",
8
- "build": "tsc -p ."
9
- },
10
- "author": "",
11
- "license": "ISC",
12
- "dependencies": {
13
- "@types/node": "^18.0.6",
14
- "tracer": "^1.1.6"
15
- }
16
- }
17
-
@@ -1,29 +0,0 @@
1
- import { before, log, component, after } from "../../src/typespeed";
2
- import FirstPage from "./first-page.class";
3
-
4
- @component
5
- export default class AopTest {
6
-
7
- @before(FirstPage, "index")
8
- public FirstIndex() {
9
- log("Before FirstPage index run, at AopTest FirstIndex.");
10
- log("AopTest FirstIndex run over." + this.getWordsFromAopTest());
11
- return "FirstIndex";
12
- }
13
-
14
- public getWordsFromAopTest() {
15
- return "getWordsFromAopTest";
16
- }
17
-
18
- @before(FirstPage, "getTestFromFirstPage")
19
- public testGetTestFromFirstPage() {
20
- log("AopTest testGetTestFromFirstPage run over.");
21
- }
22
-
23
- @after(FirstPage, "index")
24
- public testFirstIndexAfter(result) {
25
- log("AopTest testFirstIndexAfter run over, result: " + result);
26
- log(result);
27
- }
28
-
29
- }
@@ -1,26 +0,0 @@
1
- {
2
- "view": {
3
- "engine": "mustache",
4
- "path": "/views/",
5
- "suffix": "html"
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
- },
18
- "rabbitmq": {
19
- "protocol": "amqp",
20
- "hostname": "127.0.0.1",
21
- "port": 5672,
22
- "username": "guest",
23
- "password": "guest"
24
- },
25
- "socket":{}
26
- }
@@ -1,15 +0,0 @@
1
- {
2
- "server": {
3
- "port": "8081"
4
- },
5
- "database": {
6
- "host": "localhost",
7
- "port": "27017",
8
- "name": "test"
9
- },
10
- "view": {
11
- "engine": "mustache",
12
- "path": "./views",
13
- "suffix": "html"
14
- }
15
- }