koatty 3.10.4 → 3.11.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.
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-04 07:59:12
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,127 @@ 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-04 07:43:03
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
+ /**
267
+ * check is implements Aspect Interface
268
+ * @param cls
269
+ * @returns
270
+ */
271
+ function implementsAspectInterface(cls) {
272
+ return 'app' in cls && 'run' in cls && Helper.isFunction(cls.run);
273
+ }
274
+
240
275
  /*
241
276
  * @Description: framework constants
242
277
  * @Usage:
@@ -263,7 +298,7 @@ https://github.com/koatty
263
298
  * @Usage:
264
299
  * @Author: richen
265
300
  * @Date: 2023-12-09 22:55:49
266
- * @LastEditTime: 2023-12-24 10:10:52
301
+ * @LastEditTime: 2024-01-04 05:52:31
267
302
  * @License: BSD (3-Clause)
268
303
  * @Copyright (c): <richenlin(at)gmail.com>
269
304
  */
@@ -508,6 +543,10 @@ class Loader {
508
543
  item.id = (item.id ?? "").replace("MIDDLEWARE:", "");
509
544
  if (item.id && Helper.isClass(item.target)) {
510
545
  IOCContainer.reg(item.id, item.target, { scope: "Prototype", type: "MIDDLEWARE", args: [] });
546
+ const ctl = IOCContainer.getInsByClass(item.target);
547
+ if (!implementsMiddlewareInterface(ctl)) {
548
+ throw Error(`The middleware ${item.id} must implements interface 'IMiddleware'.`);
549
+ }
511
550
  }
512
551
  });
513
552
  const middlewareConfList = middlewareConf.list || [];
@@ -559,8 +598,8 @@ class Loader {
559
598
  // registering to IOC
560
599
  IOCContainer.reg(item.id, item.target, { scope: "Prototype", type: "CONTROLLER", args: [] });
561
600
  const ctl = IOCContainer.getInsByClass(item.target);
562
- if (!(ctl instanceof BaseController)) {
563
- throw Error(`Controller class ${item.id} does not inherit from BaseController`);
601
+ if (!implementsControllerInterface(ctl)) {
602
+ throw Error(`The controller ${item.id} must implements interface 'IController'.`);
564
603
  }
565
604
  controllers.push(item.id);
566
605
  }
@@ -582,6 +621,10 @@ class Loader {
582
621
  Logger.Debug(`Load service: ${item.id}`);
583
622
  // registering to IOC
584
623
  IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "SERVICE", args: [] });
624
+ const ctl = IOCContainer.getInsByClass(item.target);
625
+ if (!implementsServiceInterface(ctl)) {
626
+ throw Error(`The service ${item.id} must implements interface 'IService'.`);
627
+ }
585
628
  }
586
629
  });
587
630
  }
@@ -616,11 +659,21 @@ class Loader {
616
659
  componentList.forEach(async (item) => {
617
660
  item.id = (item.id ?? "").replace("COMPONENT:", "");
618
661
  if (Helper.isClass(item.target)) {
662
+ // registering to IOC
663
+ IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "COMPONENT", args: [] });
619
664
  if (item.id && (item.id).endsWith("Plugin")) {
665
+ const ctl = IOCContainer.getInsByClass(item.target);
666
+ if (!implementsPluginInterface(ctl)) {
667
+ throw Error(`The plugin ${item.id} must implements interface 'IPlugin'.`);
668
+ }
620
669
  pluginList.push(item.id);
621
670
  }
622
- // registering to IOC
623
- IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "COMPONENT", args: [] });
671
+ if (item.id && (item.id).endsWith("Aspect")) {
672
+ const ctl = IOCContainer.getInsByClass(item.target);
673
+ if (!implementsAspectInterface(ctl)) {
674
+ throw Error(`The aspect ${item.id} must implements interface 'IAspect'.`);
675
+ }
676
+ }
624
677
  }
625
678
  });
626
679
  // load plugin config
@@ -648,7 +701,7 @@ class Loader {
648
701
  }
649
702
  }
650
703
 
651
- var version = "3.10.4";
704
+ var version = "3.11.1";
652
705
  var engines = {
653
706
  node: ">12.0.0"
654
707
  };
@@ -911,119 +964,169 @@ function BindEventHook(eventName, eventFunc, target) {
911
964
  }
912
965
 
913
966
  /*
914
- * @Description: component interface
967
+ * @Description: base service
915
968
  * @Usage:
916
969
  * @Author: richen
917
970
  * @Date: 2023-12-09 21:56:32
918
- * @LastEditTime: 2023-12-23 11:40:44
971
+ * @LastEditTime: 2024-01-03 21:57:26
919
972
  * @License: BSD (3-Clause)
920
973
  * @Copyright (c): <richenlin(at)gmail.com>
921
974
  */
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
975
  /**
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
- /**
977
- * Indicates that an decorated class is a "plugin".
976
+ * Base service
978
977
  *
979
978
  * @export
980
- * @param {string} [identifier] class name
981
- * @returns {ClassDecorator}
979
+ * @deprecated When the framework version is > 3.10.5, do not need to inherit the Base class.
980
+ * @class Base
982
981
  */
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
- };
982
+ class BaseService {
983
+ /**
984
+ * instance of BaseController.
985
+ * @param {Koatty} app
986
+ * @param {KoattyContext} ctx
987
+ * @memberof BaseController
988
+ */
989
+ constructor(...arg) {
990
+ this.init(arg);
991
+ }
992
+ /**
993
+ * init
994
+ *
995
+ * @protected
996
+ * @memberof BaseController
997
+ */
998
+ init(...arg) {
999
+ }
992
1000
  }
993
1001
 
994
1002
  /*
995
- * @Description: base service
1003
+ * @Description: base controller
996
1004
  * @Usage:
997
1005
  * @Author: richen
998
1006
  * @Date: 2023-12-09 21:56:32
999
- * @LastEditTime: 2023-12-09 23:03:23
1007
+ * @LastEditTime: 2024-01-03 21:57:20
1000
1008
  * @License: BSD (3-Clause)
1001
1009
  * @Copyright (c): <richenlin(at)gmail.com>
1002
1010
  */
1003
1011
  /**
1004
- * Base service
1012
+ * Base controller
1005
1013
  *
1006
1014
  * @export
1007
- * @class Base
1015
+ * @deprecated When the framework version is > 3.10.5, do not need to inherit the Base class.
1016
+ * @class BaseController
1017
+ * @implements {IController}
1008
1018
  */
1009
- class BaseService {
1019
+ class BaseController {
1010
1020
  /**
1011
1021
  * instance of BaseController.
1012
1022
  * @param {Koatty} app
1013
1023
  * @param {KoattyContext} ctx
1014
1024
  * @memberof BaseController
1015
1025
  */
1016
- constructor(...arg) {
1026
+ constructor(ctx, ...arg) {
1027
+ this.ctx = ctx;
1017
1028
  this.init(arg);
1018
1029
  }
1019
1030
  /**
1020
1031
  * init
1021
1032
  *
1022
- * @protected
1023
1033
  * @memberof BaseController
1024
1034
  */
1025
1035
  init(...arg) {
1026
1036
  }
1037
+ /**
1038
+ * Response to normalize json format content for success
1039
+ *
1040
+ * @deprecated 使用 Output.ok 代替
1041
+ * @param {(string | ApiInput)} msg 待处理的message消息
1042
+ * @param {*} [data] 待处理的数据
1043
+ * @param {number} [code=200] 错误码,默认0
1044
+ * @returns {*}
1045
+ * @memberof BaseController
1046
+ */
1047
+ ok(msg, data, code = 0) {
1048
+ const obj = formatApiData(msg, data, code);
1049
+ return Promise.resolve(obj);
1050
+ }
1051
+ /**
1052
+ * Response to normalize json format content for fail
1053
+ *
1054
+ * @deprecated 使用 Output.fail 代替
1055
+ * @param {(string | ApiInput)} msg
1056
+ * @param {*} [data]
1057
+ * @param {number} [code=1]
1058
+ * @returns {*}
1059
+ * @memberof BaseController
1060
+ */
1061
+ fail(msg, data, code = 1) {
1062
+ const obj = formatApiData(msg, data, code);
1063
+ this.ctx.body = obj.data;
1064
+ this.ctx.throw(obj.message, obj.code, 200);
1065
+ }
1066
+ }
1067
+ // const properties = ["constructor", "init"];
1068
+ // export const BaseController = new Proxy(Base, {
1069
+ // set(target, key, value, receiver) {
1070
+ // if (Reflect.get(target, key, receiver) === undefined) {
1071
+ // return Reflect.set(target, key, value, receiver);
1072
+ // } else if (key === "init") {
1073
+ // return Reflect.set(target, key, value, receiver);
1074
+ // } else {
1075
+ // throw Error("Cannot redefine getter-only property");
1076
+ // }
1077
+ // },
1078
+ // deleteProperty(target, key) {
1079
+ // throw Error("Cannot delete getter-only property");
1080
+ // },
1081
+ // construct(target, args, newTarget) {
1082
+ // Reflect.ownKeys(target.prototype).map((n) => {
1083
+ // if (newTarget.prototype.hasOwnProperty(n) && !properties.includes(Helper.toString(n))) {
1084
+ // throw Error(`Cannot override the final method "${Helper.toString(n)}"`);
1085
+ // }
1086
+ // });
1087
+ // return Reflect.construct(target, args, newTarget);
1088
+ // }
1089
+ // });
1090
+
1091
+ /*
1092
+ * @Description: output data
1093
+ * @Usage:
1094
+ * @Author: richen
1095
+ * @Date: 2024-01-03 22:03:34
1096
+ * @LastEditTime: 2024-01-03 22:07:20
1097
+ * @License: BSD (3-Clause)
1098
+ * @Copyright (c): <richenlin(at)gmail.com>
1099
+ */
1100
+ class Output {
1101
+ /**
1102
+ * Response to normalize json format content for success
1103
+ *
1104
+ * @param {KoattyContext} ctx
1105
+ * @param {(string | ApiInput)} msg 待处理的message消息
1106
+ * @param {*} [data] 待处理的数据
1107
+ * @param {number} [code=200] 错误码,默认0
1108
+ * @returns {*}
1109
+ * @memberof BaseController
1110
+ */
1111
+ static ok(ctx, msg, data, code = 0) {
1112
+ const obj = formatApiData(msg, data, code);
1113
+ return Promise.resolve(obj);
1114
+ }
1115
+ /**
1116
+ * Response to normalize json format content for fail
1117
+ *
1118
+ * @param {KoattyContext} ctx
1119
+ * @param {(string | ApiInput)} msg
1120
+ * @param {*} [data]
1121
+ * @param {number} [code=1]
1122
+ * @returns {*}
1123
+ * @memberof BaseController
1124
+ */
1125
+ static fail(ctx, msg, data, code = 1) {
1126
+ const obj = formatApiData(msg, data, code);
1127
+ ctx.body = obj.data;
1128
+ ctx.throw(obj.message, obj.code, 200);
1129
+ }
1027
1130
  }
1028
1131
 
1029
- export { BaseController, BaseService, BindEventHook, Bootstrap, Component, ComponentScan, ConfigurationScan, Controller, ExecBootStrap, Logger, Middleware, Plugin, Service };
1132
+ export { BaseController, BaseService, BindEventHook, Bootstrap, Component, ComponentScan, ConfigurationScan, Controller, ExecBootStrap, Logger, Middleware, Output, Plugin, Service, implementsAspectInterface, 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.1",
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.1",
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
  }