koatty 3.10.4 → 3.11.0

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/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [3.11.0](https://github.com/thinkkoa/koatty/compare/v3.10.4...v3.11.0) (2024-01-03)
6
+
7
+
8
+ ### Features
9
+
10
+ * 增加Output类 ([09e43c4](https://github.com/thinkkoa/koatty/commit/09e43c49e2e6bc6c9cb85cd03081bd5f25134c5b))
11
+
5
12
  ### [3.10.4](https://github.com/thinkkoa/koatty/compare/v3.10.4-5...v3.10.4) (2023-12-24)
6
13
 
7
14
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * @Author: richen
3
- * @Date: 2023-12-24 10:16:31
3
+ * @Date: 2024-01-03 23:02:24
4
4
  * @License: BSD (3-Clause)
5
5
  * @Copyright (c) - <richenlin(at)gmail.com>
6
6
  * @HomePage: https://koatty.org/
@@ -37,6 +37,7 @@ export declare interface ApiOutput {
37
37
  * Base controller
38
38
  *
39
39
  * @export
40
+ * @deprecated When the framework version is > 3.10.5, do not need to inherit the Base class.
40
41
  * @class BaseController
41
42
  * @implements {IController}
42
43
  */
@@ -58,6 +59,7 @@ export declare class BaseController implements IController {
58
59
  /**
59
60
  * Response to normalize json format content for success
60
61
  *
62
+ * @deprecated 使用 Output.ok 代替
61
63
  * @param {(string | ApiInput)} msg 待处理的message消息
62
64
  * @param {*} [data] 待处理的数据
63
65
  * @param {number} [code=200] 错误码,默认0
@@ -68,6 +70,7 @@ export declare class BaseController implements IController {
68
70
  /**
69
71
  * Response to normalize json format content for fail
70
72
  *
73
+ * @deprecated 使用 Output.fail 代替
71
74
  * @param {(string | ApiInput)} msg
72
75
  * @param {*} [data]
73
76
  * @param {number} [code=1]
@@ -81,6 +84,7 @@ export declare class BaseController implements IController {
81
84
  * Base service
82
85
  *
83
86
  * @export
87
+ * @deprecated When the framework version is > 3.10.5, do not need to inherit the Base class.
84
88
  * @class Base
85
89
  */
86
90
  export declare class BaseService implements IService {
@@ -182,9 +186,6 @@ export { Helper }
182
186
  export declare interface IController {
183
187
  readonly app: Koatty;
184
188
  readonly ctx: KoattyContext;
185
- init(...arg: any[]): void;
186
- ok(msg: string | ApiInput, data?: any, code?: number): Promise<ApiOutput>;
187
- fail(msg: Error | string | ApiInput, data?: any, code?: number): void;
188
189
  }
189
190
 
190
191
  /**
@@ -194,6 +195,34 @@ export declare interface IMiddleware {
194
195
  run: (options: any, app: Koatty) => KoattyMiddleware;
195
196
  }
196
197
 
198
+ /**
199
+ * check is implements Controller Interface
200
+ * @param cls
201
+ * @returns
202
+ */
203
+ export declare function implementsControllerInterface(cls: any): cls is IController;
204
+
205
+ /**
206
+ * check is implements Middleware Interface
207
+ * @param cls
208
+ * @returns
209
+ */
210
+ export declare function implementsMiddlewareInterface(cls: any): cls is IMiddleware;
211
+
212
+ /**
213
+ * check is implements Plugin Interface
214
+ * @param cls
215
+ * @returns
216
+ */
217
+ export declare function implementsPluginInterface(cls: any): cls is IPlugin;
218
+
219
+ /**
220
+ * check is implements Service Interface
221
+ * @param cls
222
+ * @returns
223
+ */
224
+ export declare function implementsServiceInterface(cls: any): cls is IService;
225
+
197
226
  /**
198
227
  * Interface for Plugin
199
228
  */
@@ -226,6 +255,31 @@ export declare const Logger: Logger_2;
226
255
  */
227
256
  export declare function Middleware(identifier?: string): ClassDecorator;
228
257
 
258
+ export declare class Output {
259
+ /**
260
+ * Response to normalize json format content for success
261
+ *
262
+ * @param {KoattyContext} ctx
263
+ * @param {(string | ApiInput)} msg 待处理的message消息
264
+ * @param {*} [data] 待处理的数据
265
+ * @param {number} [code=200] 错误码,默认0
266
+ * @returns {*}
267
+ * @memberof BaseController
268
+ */
269
+ static ok(ctx: KoattyContext, msg: string | ApiInput, data?: any, code?: number): Promise<ApiOutput>;
270
+ /**
271
+ * Response to normalize json format content for fail
272
+ *
273
+ * @param {KoattyContext} ctx
274
+ * @param {(string | ApiInput)} msg
275
+ * @param {*} [data]
276
+ * @param {number} [code=1]
277
+ * @returns {*}
278
+ * @memberof BaseController
279
+ */
280
+ static fail(ctx: KoattyContext, msg: Error | string | ApiInput, data?: any, code?: number): void;
281
+ }
282
+
229
283
  /**
230
284
  * Indicates that an decorated class is a "plugin".
231
285
  *
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * @Author: richen
3
- * @Date: 2023-12-24 10:16:17
3
+ * @Date: 2024-01-03 23:02:11
4
4
  * @License: BSD (3-Clause)
5
5
  * @Copyright (c) - <richenlin(at)gmail.com>
6
6
  * @HomePage: https://koatty.org/
@@ -131,92 +131,6 @@ function formatApiData(msg, data, defaultCode) {
131
131
  return obj;
132
132
  }
133
133
 
134
- /*
135
- * @Description: base controller
136
- * @Usage:
137
- * @Author: richen
138
- * @Date: 2023-12-09 21:56:32
139
- * @LastEditTime: 2023-12-09 23:03:09
140
- * @License: BSD (3-Clause)
141
- * @Copyright (c): <richenlin(at)gmail.com>
142
- */
143
- /**
144
- * Base controller
145
- *
146
- * @export
147
- * @class BaseController
148
- * @implements {IController}
149
- */
150
- class BaseController {
151
- /**
152
- * instance of BaseController.
153
- * @param {Koatty} app
154
- * @param {KoattyContext} ctx
155
- * @memberof BaseController
156
- */
157
- constructor(ctx, ...arg) {
158
- this.ctx = ctx;
159
- this.init(arg);
160
- }
161
- /**
162
- * init
163
- *
164
- * @memberof BaseController
165
- */
166
- init(...arg) {
167
- }
168
- /**
169
- * Response to normalize json format content for success
170
- *
171
- * @param {(string | ApiInput)} msg 待处理的message消息
172
- * @param {*} [data] 待处理的数据
173
- * @param {number} [code=200] 错误码,默认0
174
- * @returns {*}
175
- * @memberof BaseController
176
- */
177
- ok(msg, data, code = 0) {
178
- const obj = formatApiData(msg, data, code);
179
- return Promise.resolve(obj);
180
- }
181
- /**
182
- * Response to normalize json format content for fail
183
- *
184
- * @param {(string | ApiInput)} msg
185
- * @param {*} [data]
186
- * @param {number} [code=1]
187
- * @returns {*}
188
- * @memberof BaseController
189
- */
190
- fail(msg, data, code = 1) {
191
- const obj = formatApiData(msg, data, code);
192
- this.ctx.body = obj.data;
193
- this.ctx.throw(obj.message, obj.code, 200);
194
- }
195
- }
196
- // const properties = ["constructor", "init"];
197
- // export const BaseController = new Proxy(Base, {
198
- // set(target, key, value, receiver) {
199
- // if (Reflect.get(target, key, receiver) === undefined) {
200
- // return Reflect.set(target, key, value, receiver);
201
- // } else if (key === "init") {
202
- // return Reflect.set(target, key, value, receiver);
203
- // } else {
204
- // throw Error("Cannot redefine getter-only property");
205
- // }
206
- // },
207
- // deleteProperty(target, key) {
208
- // throw Error("Cannot delete getter-only property");
209
- // },
210
- // construct(target, args, newTarget) {
211
- // Reflect.ownKeys(target.prototype).map((n) => {
212
- // if (newTarget.prototype.hasOwnProperty(n) && !properties.includes(Helper.toString(n))) {
213
- // throw Error(`Cannot override the final method "${Helper.toString(n)}"`);
214
- // }
215
- // });
216
- // return Reflect.construct(target, args, newTarget);
217
- // }
218
- // });
219
-
220
134
  /*
221
135
  * @Description: framework logger
222
136
  * @Usage:
@@ -252,6 +166,119 @@ function SetLogger(app, config) {
252
166
  }
253
167
  }
254
168
 
169
+ /*
170
+ * @Description: component interface
171
+ * @Usage:
172
+ * @Author: richen
173
+ * @Date: 2023-12-09 21:56:32
174
+ * @LastEditTime: 2024-01-03 21:27:20
175
+ * @License: BSD (3-Clause)
176
+ * @Copyright (c): <richenlin(at)gmail.com>
177
+ */
178
+ // tslint:disable-next-line: no-import-side-effect
179
+ /**
180
+ * Indicates that an decorated class is a "component".
181
+ *
182
+ * @export
183
+ * @param {string} [identifier] component name
184
+ * @returns {ClassDecorator}
185
+ */
186
+ function Component(identifier) {
187
+ return (target) => {
188
+ identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
189
+ koatty_container.IOCContainer.saveClass("COMPONENT", target, identifier);
190
+ };
191
+ }
192
+ /**
193
+ * Indicates that an decorated class is a "controller".
194
+ *
195
+ * @export
196
+ * @param {string} [path] controller router path
197
+ * @returns {ClassDecorator}
198
+ */
199
+ function Controller(path = "") {
200
+ return (target) => {
201
+ const identifier = koatty_container.IOCContainer.getIdentifier(target);
202
+ koatty_container.IOCContainer.saveClass("CONTROLLER", target, identifier);
203
+ koatty_container.IOCContainer.savePropertyData(koatty_serve.CONTROLLER_ROUTER, path, target, identifier);
204
+ };
205
+ }
206
+ /**
207
+ * Indicates that an decorated class is a "middleware".
208
+ *
209
+ * @export
210
+ * @param {string} [identifier] class name
211
+ * @returns {ClassDecorator}
212
+ */
213
+ function Middleware(identifier) {
214
+ return (target) => {
215
+ identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
216
+ koatty_container.IOCContainer.saveClass("MIDDLEWARE", target, identifier);
217
+ };
218
+ }
219
+ /**
220
+ * Indicates that an decorated class is a "service".
221
+ *
222
+ * @export
223
+ * @param {string} [identifier] class name
224
+ * @returns {ClassDecorator}
225
+ */
226
+ function Service(identifier) {
227
+ return (target) => {
228
+ identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
229
+ koatty_container.IOCContainer.saveClass("SERVICE", target, identifier);
230
+ };
231
+ }
232
+ /**
233
+ * Indicates that an decorated class is a "plugin".
234
+ *
235
+ * @export
236
+ * @param {string} [identifier] class name
237
+ * @returns {ClassDecorator}
238
+ */
239
+ function Plugin(identifier) {
240
+ return (target) => {
241
+ identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
242
+ //
243
+ if (!identifier.endsWith("Plugin")) {
244
+ throw Error("Plugin class name must be 'Plugin' suffix.");
245
+ }
246
+ koatty_container.IOCContainer.saveClass("COMPONENT", target, `${identifier}`);
247
+ };
248
+ }
249
+ /**
250
+ * check is implements Middleware Interface
251
+ * @param cls
252
+ * @returns
253
+ */
254
+ function implementsMiddlewareInterface(cls) {
255
+ return 'run' in cls && koatty_lib.Helper.isFunction(cls.run);
256
+ }
257
+ /**
258
+ * check is implements Controller Interface
259
+ * @param cls
260
+ * @returns
261
+ */
262
+ function implementsControllerInterface(cls) {
263
+ return 'app' in cls && 'ctx' in cls;
264
+ }
265
+ /**
266
+ * check is implements Service Interface
267
+ * @param cls
268
+ * @returns
269
+ */
270
+ function implementsServiceInterface(cls) {
271
+ return 'app' in cls;
272
+ }
273
+ /**
274
+ * check is implements Plugin Interface
275
+ * @param cls
276
+ * @returns
277
+ */
278
+ function implementsPluginInterface(cls) {
279
+ return 'run' in cls && koatty_lib.Helper.isFunction(cls.run);
280
+ }
281
+
255
282
  /*
256
283
  * @Description: framework constants
257
284
  * @Usage:
@@ -278,7 +305,7 @@ https://github.com/koatty
278
305
  * @Usage:
279
306
  * @Author: richen
280
307
  * @Date: 2023-12-09 22:55:49
281
- * @LastEditTime: 2023-12-24 10:10:52
308
+ * @LastEditTime: 2024-01-03 21:56:07
282
309
  * @License: BSD (3-Clause)
283
310
  * @Copyright (c): <richenlin(at)gmail.com>
284
311
  */
@@ -523,6 +550,10 @@ class Loader {
523
550
  item.id = (item.id ?? "").replace("MIDDLEWARE:", "");
524
551
  if (item.id && koatty_lib.Helper.isClass(item.target)) {
525
552
  koatty_container.IOCContainer.reg(item.id, item.target, { scope: "Prototype", type: "MIDDLEWARE", args: [] });
553
+ const ctl = koatty_container.IOCContainer.getInsByClass(item.target);
554
+ if (!implementsMiddlewareInterface(ctl)) {
555
+ throw Error(`The middleware ${item.id} must implements interface 'IMiddleware'.`);
556
+ }
526
557
  }
527
558
  });
528
559
  const middlewareConfList = middlewareConf.list || [];
@@ -574,8 +605,8 @@ class Loader {
574
605
  // registering to IOC
575
606
  koatty_container.IOCContainer.reg(item.id, item.target, { scope: "Prototype", type: "CONTROLLER", args: [] });
576
607
  const ctl = koatty_container.IOCContainer.getInsByClass(item.target);
577
- if (!(ctl instanceof BaseController)) {
578
- throw Error(`Controller class ${item.id} does not inherit from BaseController`);
608
+ if (!implementsControllerInterface(ctl)) {
609
+ throw Error(`The controller ${item.id} must implements interface 'IController'.`);
579
610
  }
580
611
  controllers.push(item.id);
581
612
  }
@@ -597,6 +628,10 @@ class Loader {
597
628
  Logger.Debug(`Load service: ${item.id}`);
598
629
  // registering to IOC
599
630
  koatty_container.IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "SERVICE", args: [] });
631
+ const ctl = koatty_container.IOCContainer.getInsByClass(item.target);
632
+ if (!implementsServiceInterface(ctl)) {
633
+ throw Error(`The service ${item.id} must implements interface 'IService'.`);
634
+ }
600
635
  }
601
636
  });
602
637
  }
@@ -631,11 +666,15 @@ class Loader {
631
666
  componentList.forEach(async (item) => {
632
667
  item.id = (item.id ?? "").replace("COMPONENT:", "");
633
668
  if (koatty_lib.Helper.isClass(item.target)) {
669
+ // registering to IOC
670
+ koatty_container.IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "COMPONENT", args: [] });
634
671
  if (item.id && (item.id).endsWith("Plugin")) {
672
+ const ctl = koatty_container.IOCContainer.getInsByClass(item.target);
673
+ if (!implementsPluginInterface(ctl)) {
674
+ throw Error(`The plugin ${item.id} must implements interface 'IPlugin'.`);
675
+ }
635
676
  pluginList.push(item.id);
636
677
  }
637
- // registering to IOC
638
- koatty_container.IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "COMPONENT", args: [] });
639
678
  }
640
679
  });
641
680
  // load plugin config
@@ -663,7 +702,7 @@ class Loader {
663
702
  }
664
703
  }
665
704
 
666
- var version = "3.10.4";
705
+ var version = "3.11.0";
667
706
  var engines = {
668
707
  node: ">12.0.0"
669
708
  };
@@ -926,119 +965,169 @@ function BindEventHook(eventName, eventFunc, target) {
926
965
  }
927
966
 
928
967
  /*
929
- * @Description: component interface
968
+ * @Description: base service
930
969
  * @Usage:
931
970
  * @Author: richen
932
971
  * @Date: 2023-12-09 21:56:32
933
- * @LastEditTime: 2023-12-23 11:40:44
972
+ * @LastEditTime: 2024-01-03 21:57:26
934
973
  * @License: BSD (3-Clause)
935
974
  * @Copyright (c): <richenlin(at)gmail.com>
936
975
  */
937
- // tslint:disable-next-line: no-import-side-effect
938
- /**
939
- * Indicates that an decorated class is a "component".
940
- *
941
- * @export
942
- * @param {string} [identifier] component name
943
- * @returns {ClassDecorator}
944
- */
945
- function Component(identifier) {
946
- return (target) => {
947
- identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
948
- koatty_container.IOCContainer.saveClass("COMPONENT", target, identifier);
949
- };
950
- }
951
- /**
952
- * Indicates that an decorated class is a "controller".
953
- *
954
- * @export
955
- * @param {string} [path] controller router path
956
- * @returns {ClassDecorator}
957
- */
958
- function Controller(path = "") {
959
- return (target) => {
960
- const identifier = koatty_container.IOCContainer.getIdentifier(target);
961
- koatty_container.IOCContainer.saveClass("CONTROLLER", target, identifier);
962
- koatty_container.IOCContainer.savePropertyData(koatty_serve.CONTROLLER_ROUTER, path, target, identifier);
963
- };
964
- }
965
- /**
966
- * Indicates that an decorated class is a "middleware".
967
- *
968
- * @export
969
- * @param {string} [identifier] class name
970
- * @returns {ClassDecorator}
971
- */
972
- function Middleware(identifier) {
973
- return (target) => {
974
- identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
975
- koatty_container.IOCContainer.saveClass("MIDDLEWARE", target, identifier);
976
- };
977
- }
978
- /**
979
- * Indicates that an decorated class is a "service".
980
- *
981
- * @export
982
- * @param {string} [identifier] class name
983
- * @returns {ClassDecorator}
984
- */
985
- function Service(identifier) {
986
- return (target) => {
987
- identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
988
- koatty_container.IOCContainer.saveClass("SERVICE", target, identifier);
989
- };
990
- }
991
976
  /**
992
- * Indicates that an decorated class is a "plugin".
977
+ * Base service
993
978
  *
994
979
  * @export
995
- * @param {string} [identifier] class name
996
- * @returns {ClassDecorator}
980
+ * @deprecated When the framework version is > 3.10.5, do not need to inherit the Base class.
981
+ * @class Base
997
982
  */
998
- function Plugin(identifier) {
999
- return (target) => {
1000
- identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
1001
- //
1002
- if (!identifier.endsWith("Plugin")) {
1003
- throw Error("Plugin class name must be 'Plugin' suffix.");
1004
- }
1005
- koatty_container.IOCContainer.saveClass("COMPONENT", target, `${identifier}`);
1006
- };
983
+ class BaseService {
984
+ /**
985
+ * instance of BaseController.
986
+ * @param {Koatty} app
987
+ * @param {KoattyContext} ctx
988
+ * @memberof BaseController
989
+ */
990
+ constructor(...arg) {
991
+ this.init(arg);
992
+ }
993
+ /**
994
+ * init
995
+ *
996
+ * @protected
997
+ * @memberof BaseController
998
+ */
999
+ init(...arg) {
1000
+ }
1007
1001
  }
1008
1002
 
1009
1003
  /*
1010
- * @Description: base service
1004
+ * @Description: base controller
1011
1005
  * @Usage:
1012
1006
  * @Author: richen
1013
1007
  * @Date: 2023-12-09 21:56:32
1014
- * @LastEditTime: 2023-12-09 23:03:23
1008
+ * @LastEditTime: 2024-01-03 21:57:20
1015
1009
  * @License: BSD (3-Clause)
1016
1010
  * @Copyright (c): <richenlin(at)gmail.com>
1017
1011
  */
1018
1012
  /**
1019
- * Base service
1013
+ * Base controller
1020
1014
  *
1021
1015
  * @export
1022
- * @class Base
1016
+ * @deprecated When the framework version is > 3.10.5, do not need to inherit the Base class.
1017
+ * @class BaseController
1018
+ * @implements {IController}
1023
1019
  */
1024
- class BaseService {
1020
+ class BaseController {
1025
1021
  /**
1026
1022
  * instance of BaseController.
1027
1023
  * @param {Koatty} app
1028
1024
  * @param {KoattyContext} ctx
1029
1025
  * @memberof BaseController
1030
1026
  */
1031
- constructor(...arg) {
1027
+ constructor(ctx, ...arg) {
1028
+ this.ctx = ctx;
1032
1029
  this.init(arg);
1033
1030
  }
1034
1031
  /**
1035
1032
  * init
1036
1033
  *
1037
- * @protected
1038
1034
  * @memberof BaseController
1039
1035
  */
1040
1036
  init(...arg) {
1041
1037
  }
1038
+ /**
1039
+ * Response to normalize json format content for success
1040
+ *
1041
+ * @deprecated 使用 Output.ok 代替
1042
+ * @param {(string | ApiInput)} msg 待处理的message消息
1043
+ * @param {*} [data] 待处理的数据
1044
+ * @param {number} [code=200] 错误码,默认0
1045
+ * @returns {*}
1046
+ * @memberof BaseController
1047
+ */
1048
+ ok(msg, data, code = 0) {
1049
+ const obj = formatApiData(msg, data, code);
1050
+ return Promise.resolve(obj);
1051
+ }
1052
+ /**
1053
+ * Response to normalize json format content for fail
1054
+ *
1055
+ * @deprecated 使用 Output.fail 代替
1056
+ * @param {(string | ApiInput)} msg
1057
+ * @param {*} [data]
1058
+ * @param {number} [code=1]
1059
+ * @returns {*}
1060
+ * @memberof BaseController
1061
+ */
1062
+ fail(msg, data, code = 1) {
1063
+ const obj = formatApiData(msg, data, code);
1064
+ this.ctx.body = obj.data;
1065
+ this.ctx.throw(obj.message, obj.code, 200);
1066
+ }
1067
+ }
1068
+ // const properties = ["constructor", "init"];
1069
+ // export const BaseController = new Proxy(Base, {
1070
+ // set(target, key, value, receiver) {
1071
+ // if (Reflect.get(target, key, receiver) === undefined) {
1072
+ // return Reflect.set(target, key, value, receiver);
1073
+ // } else if (key === "init") {
1074
+ // return Reflect.set(target, key, value, receiver);
1075
+ // } else {
1076
+ // throw Error("Cannot redefine getter-only property");
1077
+ // }
1078
+ // },
1079
+ // deleteProperty(target, key) {
1080
+ // throw Error("Cannot delete getter-only property");
1081
+ // },
1082
+ // construct(target, args, newTarget) {
1083
+ // Reflect.ownKeys(target.prototype).map((n) => {
1084
+ // if (newTarget.prototype.hasOwnProperty(n) && !properties.includes(Helper.toString(n))) {
1085
+ // throw Error(`Cannot override the final method "${Helper.toString(n)}"`);
1086
+ // }
1087
+ // });
1088
+ // return Reflect.construct(target, args, newTarget);
1089
+ // }
1090
+ // });
1091
+
1092
+ /*
1093
+ * @Description: output data
1094
+ * @Usage:
1095
+ * @Author: richen
1096
+ * @Date: 2024-01-03 22:03:34
1097
+ * @LastEditTime: 2024-01-03 22:07:20
1098
+ * @License: BSD (3-Clause)
1099
+ * @Copyright (c): <richenlin(at)gmail.com>
1100
+ */
1101
+ class Output {
1102
+ /**
1103
+ * Response to normalize json format content for success
1104
+ *
1105
+ * @param {KoattyContext} ctx
1106
+ * @param {(string | ApiInput)} msg 待处理的message消息
1107
+ * @param {*} [data] 待处理的数据
1108
+ * @param {number} [code=200] 错误码,默认0
1109
+ * @returns {*}
1110
+ * @memberof BaseController
1111
+ */
1112
+ static ok(ctx, msg, data, code = 0) {
1113
+ const obj = formatApiData(msg, data, code);
1114
+ return Promise.resolve(obj);
1115
+ }
1116
+ /**
1117
+ * Response to normalize json format content for fail
1118
+ *
1119
+ * @param {KoattyContext} ctx
1120
+ * @param {(string | ApiInput)} msg
1121
+ * @param {*} [data]
1122
+ * @param {number} [code=1]
1123
+ * @returns {*}
1124
+ * @memberof BaseController
1125
+ */
1126
+ static fail(ctx, msg, data, code = 1) {
1127
+ const obj = formatApiData(msg, data, code);
1128
+ ctx.body = obj.data;
1129
+ ctx.throw(obj.message, obj.code, 200);
1130
+ }
1042
1131
  }
1043
1132
 
1044
1133
  Object.defineProperty(exports, 'Config', {
@@ -1064,8 +1153,13 @@ exports.Controller = Controller;
1064
1153
  exports.ExecBootStrap = ExecBootStrap;
1065
1154
  exports.Logger = Logger;
1066
1155
  exports.Middleware = Middleware;
1156
+ exports.Output = Output;
1067
1157
  exports.Plugin = Plugin;
1068
1158
  exports.Service = Service;
1159
+ exports.implementsControllerInterface = implementsControllerInterface;
1160
+ exports.implementsMiddlewareInterface = implementsMiddlewareInterface;
1161
+ exports.implementsPluginInterface = implementsPluginInterface;
1162
+ exports.implementsServiceInterface = implementsServiceInterface;
1069
1163
  Object.keys(koatty_container).forEach(function (k) {
1070
1164
  if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
1071
1165
  enumerable: true,
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * @Author: richen
3
- * @Date: 2023-12-24 10:16:17
3
+ * @Date: 2024-01-03 23:02:11
4
4
  * @License: BSD (3-Clause)
5
5
  * @Copyright (c) - <richenlin(at)gmail.com>
6
6
  * @HomePage: https://koatty.org/
@@ -9,7 +9,7 @@ import { IOCContainer, TAGGED_CLS } from 'koatty_container';
9
9
  export * from 'koatty_container';
10
10
  import { AppEventArr, Koatty } from 'koatty_core';
11
11
  export * from 'koatty_core';
12
- import { NewServe, NewRouter, BindProcessEvent, CONTROLLER_ROUTER } from 'koatty_serve';
12
+ import { CONTROLLER_ROUTER, NewServe, NewRouter, BindProcessEvent } from 'koatty_serve';
13
13
  export * from 'koatty_serve';
14
14
  import * as path from 'path';
15
15
  import { Load } from 'koatty_loader';
@@ -116,92 +116,6 @@ function formatApiData(msg, data, defaultCode) {
116
116
  return obj;
117
117
  }
118
118
 
119
- /*
120
- * @Description: base controller
121
- * @Usage:
122
- * @Author: richen
123
- * @Date: 2023-12-09 21:56:32
124
- * @LastEditTime: 2023-12-09 23:03:09
125
- * @License: BSD (3-Clause)
126
- * @Copyright (c): <richenlin(at)gmail.com>
127
- */
128
- /**
129
- * Base controller
130
- *
131
- * @export
132
- * @class BaseController
133
- * @implements {IController}
134
- */
135
- class BaseController {
136
- /**
137
- * instance of BaseController.
138
- * @param {Koatty} app
139
- * @param {KoattyContext} ctx
140
- * @memberof BaseController
141
- */
142
- constructor(ctx, ...arg) {
143
- this.ctx = ctx;
144
- this.init(arg);
145
- }
146
- /**
147
- * init
148
- *
149
- * @memberof BaseController
150
- */
151
- init(...arg) {
152
- }
153
- /**
154
- * Response to normalize json format content for success
155
- *
156
- * @param {(string | ApiInput)} msg 待处理的message消息
157
- * @param {*} [data] 待处理的数据
158
- * @param {number} [code=200] 错误码,默认0
159
- * @returns {*}
160
- * @memberof BaseController
161
- */
162
- ok(msg, data, code = 0) {
163
- const obj = formatApiData(msg, data, code);
164
- return Promise.resolve(obj);
165
- }
166
- /**
167
- * Response to normalize json format content for fail
168
- *
169
- * @param {(string | ApiInput)} msg
170
- * @param {*} [data]
171
- * @param {number} [code=1]
172
- * @returns {*}
173
- * @memberof BaseController
174
- */
175
- fail(msg, data, code = 1) {
176
- const obj = formatApiData(msg, data, code);
177
- this.ctx.body = obj.data;
178
- this.ctx.throw(obj.message, obj.code, 200);
179
- }
180
- }
181
- // const properties = ["constructor", "init"];
182
- // export const BaseController = new Proxy(Base, {
183
- // set(target, key, value, receiver) {
184
- // if (Reflect.get(target, key, receiver) === undefined) {
185
- // return Reflect.set(target, key, value, receiver);
186
- // } else if (key === "init") {
187
- // return Reflect.set(target, key, value, receiver);
188
- // } else {
189
- // throw Error("Cannot redefine getter-only property");
190
- // }
191
- // },
192
- // deleteProperty(target, key) {
193
- // throw Error("Cannot delete getter-only property");
194
- // },
195
- // construct(target, args, newTarget) {
196
- // Reflect.ownKeys(target.prototype).map((n) => {
197
- // if (newTarget.prototype.hasOwnProperty(n) && !properties.includes(Helper.toString(n))) {
198
- // throw Error(`Cannot override the final method "${Helper.toString(n)}"`);
199
- // }
200
- // });
201
- // return Reflect.construct(target, args, newTarget);
202
- // }
203
- // });
204
-
205
119
  /*
206
120
  * @Description: framework logger
207
121
  * @Usage:
@@ -237,6 +151,119 @@ function SetLogger(app, config) {
237
151
  }
238
152
  }
239
153
 
154
+ /*
155
+ * @Description: component interface
156
+ * @Usage:
157
+ * @Author: richen
158
+ * @Date: 2023-12-09 21:56:32
159
+ * @LastEditTime: 2024-01-03 21:27:20
160
+ * @License: BSD (3-Clause)
161
+ * @Copyright (c): <richenlin(at)gmail.com>
162
+ */
163
+ // tslint:disable-next-line: no-import-side-effect
164
+ /**
165
+ * Indicates that an decorated class is a "component".
166
+ *
167
+ * @export
168
+ * @param {string} [identifier] component name
169
+ * @returns {ClassDecorator}
170
+ */
171
+ function Component(identifier) {
172
+ return (target) => {
173
+ identifier = identifier || IOCContainer.getIdentifier(target);
174
+ IOCContainer.saveClass("COMPONENT", target, identifier);
175
+ };
176
+ }
177
+ /**
178
+ * Indicates that an decorated class is a "controller".
179
+ *
180
+ * @export
181
+ * @param {string} [path] controller router path
182
+ * @returns {ClassDecorator}
183
+ */
184
+ function Controller(path = "") {
185
+ return (target) => {
186
+ const identifier = IOCContainer.getIdentifier(target);
187
+ IOCContainer.saveClass("CONTROLLER", target, identifier);
188
+ IOCContainer.savePropertyData(CONTROLLER_ROUTER, path, target, identifier);
189
+ };
190
+ }
191
+ /**
192
+ * Indicates that an decorated class is a "middleware".
193
+ *
194
+ * @export
195
+ * @param {string} [identifier] class name
196
+ * @returns {ClassDecorator}
197
+ */
198
+ function Middleware(identifier) {
199
+ return (target) => {
200
+ identifier = identifier || IOCContainer.getIdentifier(target);
201
+ IOCContainer.saveClass("MIDDLEWARE", target, identifier);
202
+ };
203
+ }
204
+ /**
205
+ * Indicates that an decorated class is a "service".
206
+ *
207
+ * @export
208
+ * @param {string} [identifier] class name
209
+ * @returns {ClassDecorator}
210
+ */
211
+ function Service(identifier) {
212
+ return (target) => {
213
+ identifier = identifier || IOCContainer.getIdentifier(target);
214
+ IOCContainer.saveClass("SERVICE", target, identifier);
215
+ };
216
+ }
217
+ /**
218
+ * Indicates that an decorated class is a "plugin".
219
+ *
220
+ * @export
221
+ * @param {string} [identifier] class name
222
+ * @returns {ClassDecorator}
223
+ */
224
+ function Plugin(identifier) {
225
+ return (target) => {
226
+ identifier = identifier || IOCContainer.getIdentifier(target);
227
+ //
228
+ if (!identifier.endsWith("Plugin")) {
229
+ throw Error("Plugin class name must be 'Plugin' suffix.");
230
+ }
231
+ IOCContainer.saveClass("COMPONENT", target, `${identifier}`);
232
+ };
233
+ }
234
+ /**
235
+ * check is implements Middleware Interface
236
+ * @param cls
237
+ * @returns
238
+ */
239
+ function implementsMiddlewareInterface(cls) {
240
+ return 'run' in cls && Helper.isFunction(cls.run);
241
+ }
242
+ /**
243
+ * check is implements Controller Interface
244
+ * @param cls
245
+ * @returns
246
+ */
247
+ function implementsControllerInterface(cls) {
248
+ return 'app' in cls && 'ctx' in cls;
249
+ }
250
+ /**
251
+ * check is implements Service Interface
252
+ * @param cls
253
+ * @returns
254
+ */
255
+ function implementsServiceInterface(cls) {
256
+ return 'app' in cls;
257
+ }
258
+ /**
259
+ * check is implements Plugin Interface
260
+ * @param cls
261
+ * @returns
262
+ */
263
+ function implementsPluginInterface(cls) {
264
+ return 'run' in cls && Helper.isFunction(cls.run);
265
+ }
266
+
240
267
  /*
241
268
  * @Description: framework constants
242
269
  * @Usage:
@@ -263,7 +290,7 @@ https://github.com/koatty
263
290
  * @Usage:
264
291
  * @Author: richen
265
292
  * @Date: 2023-12-09 22:55:49
266
- * @LastEditTime: 2023-12-24 10:10:52
293
+ * @LastEditTime: 2024-01-03 21:56:07
267
294
  * @License: BSD (3-Clause)
268
295
  * @Copyright (c): <richenlin(at)gmail.com>
269
296
  */
@@ -508,6 +535,10 @@ class Loader {
508
535
  item.id = (item.id ?? "").replace("MIDDLEWARE:", "");
509
536
  if (item.id && Helper.isClass(item.target)) {
510
537
  IOCContainer.reg(item.id, item.target, { scope: "Prototype", type: "MIDDLEWARE", args: [] });
538
+ const ctl = IOCContainer.getInsByClass(item.target);
539
+ if (!implementsMiddlewareInterface(ctl)) {
540
+ throw Error(`The middleware ${item.id} must implements interface 'IMiddleware'.`);
541
+ }
511
542
  }
512
543
  });
513
544
  const middlewareConfList = middlewareConf.list || [];
@@ -559,8 +590,8 @@ class Loader {
559
590
  // registering to IOC
560
591
  IOCContainer.reg(item.id, item.target, { scope: "Prototype", type: "CONTROLLER", args: [] });
561
592
  const ctl = IOCContainer.getInsByClass(item.target);
562
- if (!(ctl instanceof BaseController)) {
563
- throw Error(`Controller class ${item.id} does not inherit from BaseController`);
593
+ if (!implementsControllerInterface(ctl)) {
594
+ throw Error(`The controller ${item.id} must implements interface 'IController'.`);
564
595
  }
565
596
  controllers.push(item.id);
566
597
  }
@@ -582,6 +613,10 @@ class Loader {
582
613
  Logger.Debug(`Load service: ${item.id}`);
583
614
  // registering to IOC
584
615
  IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "SERVICE", args: [] });
616
+ const ctl = IOCContainer.getInsByClass(item.target);
617
+ if (!implementsServiceInterface(ctl)) {
618
+ throw Error(`The service ${item.id} must implements interface 'IService'.`);
619
+ }
585
620
  }
586
621
  });
587
622
  }
@@ -616,11 +651,15 @@ class Loader {
616
651
  componentList.forEach(async (item) => {
617
652
  item.id = (item.id ?? "").replace("COMPONENT:", "");
618
653
  if (Helper.isClass(item.target)) {
654
+ // registering to IOC
655
+ IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "COMPONENT", args: [] });
619
656
  if (item.id && (item.id).endsWith("Plugin")) {
657
+ const ctl = IOCContainer.getInsByClass(item.target);
658
+ if (!implementsPluginInterface(ctl)) {
659
+ throw Error(`The plugin ${item.id} must implements interface 'IPlugin'.`);
660
+ }
620
661
  pluginList.push(item.id);
621
662
  }
622
- // registering to IOC
623
- IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "COMPONENT", args: [] });
624
663
  }
625
664
  });
626
665
  // load plugin config
@@ -648,7 +687,7 @@ class Loader {
648
687
  }
649
688
  }
650
689
 
651
- var version = "3.10.4";
690
+ var version = "3.11.0";
652
691
  var engines = {
653
692
  node: ">12.0.0"
654
693
  };
@@ -911,119 +950,169 @@ function BindEventHook(eventName, eventFunc, target) {
911
950
  }
912
951
 
913
952
  /*
914
- * @Description: component interface
953
+ * @Description: base service
915
954
  * @Usage:
916
955
  * @Author: richen
917
956
  * @Date: 2023-12-09 21:56:32
918
- * @LastEditTime: 2023-12-23 11:40:44
957
+ * @LastEditTime: 2024-01-03 21:57:26
919
958
  * @License: BSD (3-Clause)
920
959
  * @Copyright (c): <richenlin(at)gmail.com>
921
960
  */
922
- // tslint:disable-next-line: no-import-side-effect
923
- /**
924
- * Indicates that an decorated class is a "component".
925
- *
926
- * @export
927
- * @param {string} [identifier] component name
928
- * @returns {ClassDecorator}
929
- */
930
- function Component(identifier) {
931
- return (target) => {
932
- identifier = identifier || IOCContainer.getIdentifier(target);
933
- IOCContainer.saveClass("COMPONENT", target, identifier);
934
- };
935
- }
936
- /**
937
- * Indicates that an decorated class is a "controller".
938
- *
939
- * @export
940
- * @param {string} [path] controller router path
941
- * @returns {ClassDecorator}
942
- */
943
- function Controller(path = "") {
944
- return (target) => {
945
- const identifier = IOCContainer.getIdentifier(target);
946
- IOCContainer.saveClass("CONTROLLER", target, identifier);
947
- IOCContainer.savePropertyData(CONTROLLER_ROUTER, path, target, identifier);
948
- };
949
- }
950
- /**
951
- * Indicates that an decorated class is a "middleware".
952
- *
953
- * @export
954
- * @param {string} [identifier] class name
955
- * @returns {ClassDecorator}
956
- */
957
- function Middleware(identifier) {
958
- return (target) => {
959
- identifier = identifier || IOCContainer.getIdentifier(target);
960
- IOCContainer.saveClass("MIDDLEWARE", target, identifier);
961
- };
962
- }
963
- /**
964
- * Indicates that an decorated class is a "service".
965
- *
966
- * @export
967
- * @param {string} [identifier] class name
968
- * @returns {ClassDecorator}
969
- */
970
- function Service(identifier) {
971
- return (target) => {
972
- identifier = identifier || IOCContainer.getIdentifier(target);
973
- IOCContainer.saveClass("SERVICE", target, identifier);
974
- };
975
- }
976
961
  /**
977
- * Indicates that an decorated class is a "plugin".
962
+ * Base service
978
963
  *
979
964
  * @export
980
- * @param {string} [identifier] class name
981
- * @returns {ClassDecorator}
965
+ * @deprecated When the framework version is > 3.10.5, do not need to inherit the Base class.
966
+ * @class Base
982
967
  */
983
- function Plugin(identifier) {
984
- return (target) => {
985
- identifier = identifier || IOCContainer.getIdentifier(target);
986
- //
987
- if (!identifier.endsWith("Plugin")) {
988
- throw Error("Plugin class name must be 'Plugin' suffix.");
989
- }
990
- IOCContainer.saveClass("COMPONENT", target, `${identifier}`);
991
- };
968
+ class BaseService {
969
+ /**
970
+ * instance of BaseController.
971
+ * @param {Koatty} app
972
+ * @param {KoattyContext} ctx
973
+ * @memberof BaseController
974
+ */
975
+ constructor(...arg) {
976
+ this.init(arg);
977
+ }
978
+ /**
979
+ * init
980
+ *
981
+ * @protected
982
+ * @memberof BaseController
983
+ */
984
+ init(...arg) {
985
+ }
992
986
  }
993
987
 
994
988
  /*
995
- * @Description: base service
989
+ * @Description: base controller
996
990
  * @Usage:
997
991
  * @Author: richen
998
992
  * @Date: 2023-12-09 21:56:32
999
- * @LastEditTime: 2023-12-09 23:03:23
993
+ * @LastEditTime: 2024-01-03 21:57:20
1000
994
  * @License: BSD (3-Clause)
1001
995
  * @Copyright (c): <richenlin(at)gmail.com>
1002
996
  */
1003
997
  /**
1004
- * Base service
998
+ * Base controller
1005
999
  *
1006
1000
  * @export
1007
- * @class Base
1001
+ * @deprecated When the framework version is > 3.10.5, do not need to inherit the Base class.
1002
+ * @class BaseController
1003
+ * @implements {IController}
1008
1004
  */
1009
- class BaseService {
1005
+ class BaseController {
1010
1006
  /**
1011
1007
  * instance of BaseController.
1012
1008
  * @param {Koatty} app
1013
1009
  * @param {KoattyContext} ctx
1014
1010
  * @memberof BaseController
1015
1011
  */
1016
- constructor(...arg) {
1012
+ constructor(ctx, ...arg) {
1013
+ this.ctx = ctx;
1017
1014
  this.init(arg);
1018
1015
  }
1019
1016
  /**
1020
1017
  * init
1021
1018
  *
1022
- * @protected
1023
1019
  * @memberof BaseController
1024
1020
  */
1025
1021
  init(...arg) {
1026
1022
  }
1023
+ /**
1024
+ * Response to normalize json format content for success
1025
+ *
1026
+ * @deprecated 使用 Output.ok 代替
1027
+ * @param {(string | ApiInput)} msg 待处理的message消息
1028
+ * @param {*} [data] 待处理的数据
1029
+ * @param {number} [code=200] 错误码,默认0
1030
+ * @returns {*}
1031
+ * @memberof BaseController
1032
+ */
1033
+ ok(msg, data, code = 0) {
1034
+ const obj = formatApiData(msg, data, code);
1035
+ return Promise.resolve(obj);
1036
+ }
1037
+ /**
1038
+ * Response to normalize json format content for fail
1039
+ *
1040
+ * @deprecated 使用 Output.fail 代替
1041
+ * @param {(string | ApiInput)} msg
1042
+ * @param {*} [data]
1043
+ * @param {number} [code=1]
1044
+ * @returns {*}
1045
+ * @memberof BaseController
1046
+ */
1047
+ fail(msg, data, code = 1) {
1048
+ const obj = formatApiData(msg, data, code);
1049
+ this.ctx.body = obj.data;
1050
+ this.ctx.throw(obj.message, obj.code, 200);
1051
+ }
1052
+ }
1053
+ // const properties = ["constructor", "init"];
1054
+ // export const BaseController = new Proxy(Base, {
1055
+ // set(target, key, value, receiver) {
1056
+ // if (Reflect.get(target, key, receiver) === undefined) {
1057
+ // return Reflect.set(target, key, value, receiver);
1058
+ // } else if (key === "init") {
1059
+ // return Reflect.set(target, key, value, receiver);
1060
+ // } else {
1061
+ // throw Error("Cannot redefine getter-only property");
1062
+ // }
1063
+ // },
1064
+ // deleteProperty(target, key) {
1065
+ // throw Error("Cannot delete getter-only property");
1066
+ // },
1067
+ // construct(target, args, newTarget) {
1068
+ // Reflect.ownKeys(target.prototype).map((n) => {
1069
+ // if (newTarget.prototype.hasOwnProperty(n) && !properties.includes(Helper.toString(n))) {
1070
+ // throw Error(`Cannot override the final method "${Helper.toString(n)}"`);
1071
+ // }
1072
+ // });
1073
+ // return Reflect.construct(target, args, newTarget);
1074
+ // }
1075
+ // });
1076
+
1077
+ /*
1078
+ * @Description: output data
1079
+ * @Usage:
1080
+ * @Author: richen
1081
+ * @Date: 2024-01-03 22:03:34
1082
+ * @LastEditTime: 2024-01-03 22:07:20
1083
+ * @License: BSD (3-Clause)
1084
+ * @Copyright (c): <richenlin(at)gmail.com>
1085
+ */
1086
+ class Output {
1087
+ /**
1088
+ * Response to normalize json format content for success
1089
+ *
1090
+ * @param {KoattyContext} ctx
1091
+ * @param {(string | ApiInput)} msg 待处理的message消息
1092
+ * @param {*} [data] 待处理的数据
1093
+ * @param {number} [code=200] 错误码,默认0
1094
+ * @returns {*}
1095
+ * @memberof BaseController
1096
+ */
1097
+ static ok(ctx, msg, data, code = 0) {
1098
+ const obj = formatApiData(msg, data, code);
1099
+ return Promise.resolve(obj);
1100
+ }
1101
+ /**
1102
+ * Response to normalize json format content for fail
1103
+ *
1104
+ * @param {KoattyContext} ctx
1105
+ * @param {(string | ApiInput)} msg
1106
+ * @param {*} [data]
1107
+ * @param {number} [code=1]
1108
+ * @returns {*}
1109
+ * @memberof BaseController
1110
+ */
1111
+ static fail(ctx, msg, data, code = 1) {
1112
+ const obj = formatApiData(msg, data, code);
1113
+ ctx.body = obj.data;
1114
+ ctx.throw(obj.message, obj.code, 200);
1115
+ }
1027
1116
  }
1028
1117
 
1029
- export { BaseController, BaseService, BindEventHook, Bootstrap, Component, ComponentScan, ConfigurationScan, Controller, ExecBootStrap, Logger, Middleware, Plugin, Service };
1118
+ export { BaseController, BaseService, BindEventHook, Bootstrap, Component, ComponentScan, ConfigurationScan, Controller, ExecBootStrap, Logger, Middleware, Output, Plugin, Service, implementsControllerInterface, implementsMiddlewareInterface, implementsPluginInterface, implementsServiceInterface };
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koatty",
3
- "version": "3.10.4",
3
+ "version": "3.11.0",
4
4
  "description": "Koa2 + Typescript = koatty. Use Typescript's decorator implement auto injection.",
5
5
  "scripts": {
6
6
  "build": "npm run build:js && npm run build:dts && npm run build:doc && npm run build:cp",
@@ -82,7 +82,7 @@
82
82
  "typescript": "^5.x.x"
83
83
  },
84
84
  "dependencies": {
85
- "koa": "^2.14.2",
85
+ "koa": "^2.15.0",
86
86
  "koatty_config": "^1.1.6",
87
87
  "koatty_container": "^1.8.10",
88
88
  "koatty_core": "^1.8.4",
@@ -93,6 +93,6 @@
93
93
  "koatty_proto": "^1.1.12",
94
94
  "koatty_serve": "2.1.0",
95
95
  "koatty_trace": "^1.10.4",
96
- "koatty_validation": "^1.2.10"
96
+ "koatty_validation": "^1.3.0"
97
97
  }
98
98
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koatty",
3
- "version": "3.10.4",
3
+ "version": "3.11.0",
4
4
  "description": "Koa2 + Typescript = koatty. Use Typescript's decorator implement auto injection.",
5
5
  "scripts": {
6
6
  "build": "npm run build:js && npm run build:dts && npm run build:doc && npm run build:cp",
@@ -82,7 +82,7 @@
82
82
  "typescript": "^5.x.x"
83
83
  },
84
84
  "dependencies": {
85
- "koa": "^2.14.2",
85
+ "koa": "^2.15.0",
86
86
  "koatty_config": "^1.1.6",
87
87
  "koatty_container": "^1.8.10",
88
88
  "koatty_core": "^1.8.4",
@@ -93,6 +93,6 @@
93
93
  "koatty_proto": "^1.1.12",
94
94
  "koatty_serve": "2.1.0",
95
95
  "koatty_trace": "^1.10.4",
96
- "koatty_validation": "^1.2.10"
96
+ "koatty_validation": "^1.3.0"
97
97
  }
98
98
  }