@ruiapp/rapid-core 0.11.2 → 0.11.4

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.js CHANGED
@@ -983,8 +983,119 @@ function isNullOrUndefinedOrEmpty(val) {
983
983
  return isNull(val) || isUndefined(val) || val === "";
984
984
  }
985
985
 
986
- async function buildRoutes(server, applicationConfig) {
986
+ /**
987
+ * 在事务中执行`func`
988
+ * @param routeContext
989
+ * @param func
990
+ * @returns
991
+ */
992
+ async function executeInDbTransaction(routeContext, func) {
993
+ if (!routeContext) {
994
+ throw new Error(`Patameter "routeContext" is required if you want run in transaction.`);
995
+ }
996
+ let transactionDbClient;
997
+ try {
998
+ transactionDbClient = await routeContext.initDbTransactionClient();
999
+ await routeContext.beginDbTransaction();
1000
+ const result = await func();
1001
+ await routeContext.commitDbTransaction();
1002
+ return result;
1003
+ }
1004
+ catch (ex) {
1005
+ await routeContext.rollbackDbTransaction();
1006
+ throw ex;
1007
+ }
1008
+ finally {
1009
+ if (transactionDbClient) {
1010
+ transactionDbClient.release();
1011
+ }
1012
+ }
1013
+ }
1014
+ async function executeInRouteContext(routeContext, inDbTransaction, func) {
1015
+ if (inDbTransaction) {
1016
+ return await executeInDbTransaction(routeContext, func);
1017
+ }
1018
+ else {
1019
+ return await func();
1020
+ }
1021
+ }
1022
+
1023
+ async function executeHandlerOfActions(server, routeConfig, handlerContext) {
1024
+ let handler = routeConfig.handler;
1025
+ if (handler) {
1026
+ if (lodash.isString(handler)) {
1027
+ handler = new Function(`return (${routeConfig.handler})`);
1028
+ }
1029
+ if (lodash.isFunction(handler)) {
1030
+ const result = handler(handlerContext);
1031
+ if (result instanceof Promise) {
1032
+ await result;
1033
+ }
1034
+ }
1035
+ else {
1036
+ throw new Error(`Invalid handler for route ${routeConfig.code}: ${routeConfig.handler}`);
1037
+ }
1038
+ }
1039
+ else if (routeConfig.actions) {
1040
+ for (const actionConfig of routeConfig.actions) {
1041
+ const actionCode = actionConfig.code;
1042
+ const handler = server.getActionHandlerByCode(actionCode);
1043
+ if (!handler) {
1044
+ throw new Error("Unknown handler: " + actionCode);
1045
+ }
1046
+ await server.beforeRunActionHandler(handlerContext, actionConfig);
1047
+ const result = handler(handlerContext, actionConfig.config);
1048
+ if (result instanceof Promise) {
1049
+ await result;
1050
+ }
1051
+ }
1052
+ }
1053
+ }
1054
+ async function handleRouteRequest(routeContext, next, server, routeConfig) {
1055
+ if (!routeConfig.handler && !routeConfig.actions) {
1056
+ throw new Error(`No handler or actions defined for route ${routeConfig.code}`);
1057
+ }
987
1058
  const logger = server.getLogger();
1059
+ routeConfig = lodash.cloneDeep(routeConfig);
1060
+ routeContext.routeConfig = routeConfig;
1061
+ const { request, params } = routeContext;
1062
+ let search = request.url.search;
1063
+ if (search && search.startsWith("?")) {
1064
+ search = search.substring(1);
1065
+ }
1066
+ const query = qs__default["default"].parse(search);
1067
+ const input = Object.assign({}, params, query);
1068
+ const requestMethod = request.method;
1069
+ if (requestMethod === "POST" || requestMethod === "PUT" || requestMethod === "PATCH") {
1070
+ const body = request.body;
1071
+ if (body) {
1072
+ Object.assign(input, body.value);
1073
+ }
1074
+ }
1075
+ // Normalize input value
1076
+ logger.debug("Processing rapid request.", {
1077
+ method: requestMethod,
1078
+ url: request.url.toString(),
1079
+ input,
1080
+ });
1081
+ routeContext.response.status = 200;
1082
+ let handlerContext = {
1083
+ logger,
1084
+ routerContext: routeContext,
1085
+ next,
1086
+ server,
1087
+ input,
1088
+ results: [],
1089
+ };
1090
+ await server.beforeRunRouteActions(handlerContext);
1091
+ await executeInRouteContext(routeContext, routeConfig.executeInDbTransaction, async () => {
1092
+ await executeHandlerOfActions(server, routeConfig, handlerContext);
1093
+ });
1094
+ if (!isNullOrUndefined(handlerContext.output)) {
1095
+ routeContext.json(handlerContext.output, handlerContext.status);
1096
+ }
1097
+ }
1098
+ async function buildRoutes(server, applicationConfig) {
988
1099
  const router = new Router__default["default"]();
989
1100
  let baseUrl = server.config.baseUrl;
990
1101
  if (baseUrl) {
@@ -1000,74 +1111,7 @@ async function buildRoutes(server, applicationConfig) {
1000
1111
  return;
1001
1112
  }
1002
1113
  const routePath = baseUrl + routeConfig.endpoint;
1003
- router[routeConfig.method.toLowerCase()](routePath, async (routerContext, next) => {
1004
- routerContext.routeConfig = lodash.cloneDeep(routeConfig);
1005
- const { request, params } = routerContext;
1006
- let search = request.url.search;
1007
- if (search && search.startsWith("?")) {
1008
- search = search.substring(1);
1009
- }
1010
- const query = qs__default["default"].parse(search);
1011
- const input = Object.assign({}, params, query);
1012
- const requestMethod = request.method;
1013
- if (requestMethod === "POST" || requestMethod === "PUT" || requestMethod === "PATCH") {
1014
- const body = request.body;
1015
- if (body) {
1016
- Object.assign(input, body.value);
1017
- }
1018
- }
1019
- // Normalize input value
1020
- logger.debug("Processing rapid request.", {
1021
- method: requestMethod,
1022
- url: request.url.toString(),
1023
- input,
1024
- });
1025
- routerContext.response.status = 200;
1026
- let handlerContext = {
1027
- logger,
1028
- routerContext,
1029
- next,
1030
- server,
1031
- input,
1032
- results: [],
1033
- };
1034
- await server.beforeRunRouteActions(handlerContext);
1035
- let handler = routeConfig.handler;
1036
- if (handler) {
1037
- if (lodash.isString(handler)) {
1038
- handler = new Function(`return (${routeConfig.handler})`);
1039
- }
1040
- if (lodash.isFunction(handler)) {
1041
- const result = handler(handlerContext);
1042
- if (result instanceof Promise) {
1043
- await result;
1044
- }
1045
- }
1046
- else {
1047
- throw new Error(`Invalid handler for route ${routeConfig.code}: ${routeConfig.handler}`);
1048
- }
1049
- }
1050
- else if (routeConfig.actions) {
1051
- for (const actionConfig of routeConfig.actions) {
1052
- const actionCode = actionConfig.code;
1053
- const handler = server.getActionHandlerByCode(actionCode);
1054
- if (!handler) {
1055
- throw new Error("Unknown handler: " + actionCode);
1056
- }
1057
- await server.beforeRunActionHandler(handlerContext, actionConfig);
1058
- const result = handler(handlerContext, actionConfig.config);
1059
- if (result instanceof Promise) {
1060
- await result;
1061
- }
1062
- }
1063
- }
1064
- else {
1065
- throw new Error(`No handler or actions defined for route ${routeConfig.code}`);
1066
- }
1067
- if (!isNullOrUndefined(handlerContext.output)) {
1068
- routerContext.json(handlerContext.output, handlerContext.status);
1069
- }
1070
- });
1114
+ router[routeConfig.method.toLowerCase()](routePath, (routeContext, next) => handleRouteRequest(routeContext, next, server, routeConfig));
1071
1115
  });
1072
1116
  return router.routes();
1073
1117
  }
@@ -3516,6 +3560,13 @@ async function createEntity(server, dataAccessor, options, plugin) {
3516
3560
  if (createdAtProperty) {
3517
3561
  entity.createdAt = getNowStringWithTimezone();
3518
3562
  }
3563
+ let baseModel;
3564
+ if (model.base) {
3565
+ baseModel = server.getModel({
3566
+ singularCode: model.base,
3567
+ });
3568
+ entity[baseModel.derivedTypePropertyCode] = model.derivedType;
3569
+ }
3519
3570
  await server.beforeCreateEntity(model, options);
3520
3571
  await server.emitEvent({
3521
3572
  eventName: "entity.beforeCreate",
@@ -5504,43 +5555,6 @@ var licenseHelper = /*#__PURE__*/Object.freeze({
5504
5555
  tryValidateLicense: tryValidateLicense
5505
5556
  });
5506
5557
 
5507
- /**
5508
- * 在事务中执行`func`
5509
- * @param routeContext
5510
- * @param func
5511
- * @returns
5512
- */
5513
- async function executeInDbTransaction(routeContext, func) {
5514
- if (!routeContext) {
5515
- throw new Error(`Patameter "routeContext" is required if you want run in transaction.`);
5516
- }
5517
- let transactionDbClient;
5518
- try {
5519
- transactionDbClient = await routeContext.initDbTransactionClient();
5520
- await routeContext.beginDbTransaction();
5521
- const result = await func();
5522
- await routeContext.commitDbTransaction();
5523
- return result;
5524
- }
5525
- catch (ex) {
5526
- await routeContext.rollbackDbTransaction();
5527
- throw ex;
5528
- }
5529
- finally {
5530
- if (transactionDbClient) {
5531
- transactionDbClient.release();
5532
- }
5533
- }
5534
- }
5535
- async function executeInRouteContext(routeContext, inDbTransaction, func) {
5536
- if (inDbTransaction) {
5537
- return await executeInDbTransaction(routeContext, func);
5538
- }
5539
- else {
5540
- return await func();
5541
- }
5542
- }
5543
-
5544
5558
  const values = new Map();
5545
5559
  async function set(key, value, options) {
5546
5560
  let expireAt = -1;
package/dist/types.d.ts CHANGED
@@ -494,6 +494,7 @@ export interface RpdRoute {
494
494
  type: "RESTful";
495
495
  method: RpdHttpMethod;
496
496
  endpoint: string;
497
+ executeInDbTransaction?: boolean;
497
498
  actions?: RpdRouteActionConfig[];
498
499
  handler?: string | ((ctx: ActionHandlerContext) => Promise<void>);
499
500
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ruiapp/rapid-core",
3
- "version": "0.11.2",
3
+ "version": "0.11.4",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -2,13 +2,101 @@ import Router from "koa-tree-router";
2
2
  import qs from "qs";
3
3
  import { ActionHandlerContext } from "~/core/actionHandler";
4
4
  import { IRpdServer } from "~/core/server";
5
- import { RpdApplicationConfig } from "~/types";
5
+ import { RpdApplicationConfig, RpdRoute } from "~/types";
6
6
  import { isNullOrUndefined } from "~/utilities/typeUtility";
7
7
  import { Next, RouteContext } from "./routeContext";
8
8
  import { cloneDeep, isFunction, isString } from "lodash";
9
+ import { executeInRouteContext } from "~/helpers/dbTransactionHelper";
10
+
11
+ async function executeHandlerOfActions(server: IRpdServer, routeConfig: RpdRoute, handlerContext: ActionHandlerContext) {
12
+ let handler = routeConfig.handler as any;
13
+ if (handler) {
14
+ if (isString(handler)) {
15
+ handler = new Function(`return (${routeConfig.handler})`) as any;
16
+ }
17
+
18
+ if (isFunction(handler)) {
19
+ const result = handler(handlerContext);
20
+ if (result instanceof Promise) {
21
+ await result;
22
+ }
23
+ } else {
24
+ throw new Error(`Invalid handler for route ${routeConfig.code}: ${routeConfig.handler}`);
25
+ }
26
+ } else if (routeConfig.actions) {
27
+ for (const actionConfig of routeConfig.actions) {
28
+ const actionCode = actionConfig.code;
29
+ const handler = server.getActionHandlerByCode(actionCode);
30
+ if (!handler) {
31
+ throw new Error("Unknown handler: " + actionCode);
32
+ }
33
+
34
+ await server.beforeRunActionHandler(handlerContext, actionConfig);
35
+
36
+ const result = handler(handlerContext, actionConfig.config);
37
+ if (result instanceof Promise) {
38
+ await result;
39
+ }
40
+ }
41
+ }
42
+ }
43
+
44
+ async function handleRouteRequest(routeContext: RouteContext, next: Next, server: IRpdServer, routeConfig: RpdRoute) {
45
+ if (!routeConfig.handler && !routeConfig.actions) {
46
+ throw new Error(`No handler or actions defined for route ${routeConfig.code}`);
47
+ }
9
48
 
10
- export async function buildRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig) {
11
49
  const logger = server.getLogger();
50
+ routeConfig = cloneDeep(routeConfig);
51
+ routeContext.routeConfig = routeConfig;
52
+ const { request, params } = routeContext;
53
+
54
+ let search = request.url.search;
55
+ if (search && search.startsWith("?")) {
56
+ search = search.substring(1);
57
+ }
58
+ const query = qs.parse(search);
59
+ const input = Object.assign({}, params, query);
60
+
61
+ const requestMethod = request.method;
62
+ if (requestMethod === "POST" || requestMethod === "PUT" || requestMethod === "PATCH") {
63
+ const body = request.body;
64
+ if (body) {
65
+ Object.assign(input, body.value);
66
+ }
67
+ }
68
+
69
+ // Normalize input value
70
+
71
+ logger.debug("Processing rapid request.", {
72
+ method: requestMethod,
73
+ url: request.url.toString(),
74
+ input,
75
+ });
76
+
77
+ routeContext.response.status = 200;
78
+
79
+ let handlerContext: ActionHandlerContext = {
80
+ logger,
81
+ routerContext: routeContext,
82
+ next,
83
+ server,
84
+ input,
85
+ results: [],
86
+ };
87
+
88
+ await server.beforeRunRouteActions(handlerContext);
89
+
90
+ await executeInRouteContext(routeContext, routeConfig.executeInDbTransaction, async () => {
91
+ await executeHandlerOfActions(server, routeConfig, handlerContext);
92
+ });
93
+
94
+ if (!isNullOrUndefined(handlerContext.output)) {
95
+ routeContext.json(handlerContext.output, handlerContext.status);
96
+ }
97
+ }
98
+
99
+ export async function buildRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig) {
12
100
  const router = new Router();
13
101
 
14
102
  let baseUrl = server.config.baseUrl;
@@ -27,83 +115,7 @@ export async function buildRoutes(server: IRpdServer, applicationConfig: RpdAppl
27
115
 
28
116
  const routePath = baseUrl + routeConfig.endpoint;
29
117
 
30
- (router as any)[routeConfig.method.toLowerCase()](routePath, async (routerContext: RouteContext, next: Next) => {
31
- routerContext.routeConfig = cloneDeep(routeConfig);
32
- const { request, params } = routerContext;
33
-
34
- let search = request.url.search;
35
- if (search && search.startsWith("?")) {
36
- search = search.substring(1);
37
- }
38
- const query = qs.parse(search);
39
- const input = Object.assign({}, params, query);
40
-
41
- const requestMethod = request.method;
42
- if (requestMethod === "POST" || requestMethod === "PUT" || requestMethod === "PATCH") {
43
- const body = request.body;
44
- if (body) {
45
- Object.assign(input, body.value);
46
- }
47
- }
48
-
49
- // Normalize input value
50
-
51
- logger.debug("Processing rapid request.", {
52
- method: requestMethod,
53
- url: request.url.toString(),
54
- input,
55
- });
56
-
57
- routerContext.response.status = 200;
58
-
59
- let handlerContext: ActionHandlerContext = {
60
- logger,
61
- routerContext,
62
- next,
63
- server,
64
- input,
65
- results: [],
66
- };
67
-
68
- await server.beforeRunRouteActions(handlerContext);
69
-
70
- let handler = routeConfig.handler as any;
71
- if (handler) {
72
- if (isString(handler)) {
73
- handler = new Function(`return (${routeConfig.handler})`) as any;
74
- }
75
-
76
- if (isFunction(handler)) {
77
- const result = handler(handlerContext);
78
- if (result instanceof Promise) {
79
- await result;
80
- }
81
- } else {
82
- throw new Error(`Invalid handler for route ${routeConfig.code}: ${routeConfig.handler}`);
83
- }
84
- } else if (routeConfig.actions) {
85
- for (const actionConfig of routeConfig.actions) {
86
- const actionCode = actionConfig.code;
87
- const handler = server.getActionHandlerByCode(actionCode);
88
- if (!handler) {
89
- throw new Error("Unknown handler: " + actionCode);
90
- }
91
-
92
- await server.beforeRunActionHandler(handlerContext, actionConfig);
93
-
94
- const result = handler(handlerContext, actionConfig.config);
95
- if (result instanceof Promise) {
96
- await result;
97
- }
98
- }
99
- } else {
100
- throw new Error(`No handler or actions defined for route ${routeConfig.code}`);
101
- }
102
-
103
- if (!isNullOrUndefined(handlerContext.output)) {
104
- routerContext.json(handlerContext.output, handlerContext.status);
105
- }
106
- });
118
+ (router as any)[routeConfig.method.toLowerCase()](routePath, (routeContext, next) => handleRouteRequest(routeContext, next, server, routeConfig));
107
119
  });
108
120
 
109
121
  return router.routes();
@@ -829,6 +829,14 @@ async function createEntity(server: IRpdServer, dataAccessor: IRpdDataAccessor,
829
829
  entity.createdAt = getNowStringWithTimezone();
830
830
  }
831
831
 
832
+ let baseModel: RpdDataModel | undefined;
833
+ if (model.base) {
834
+ baseModel = server.getModel({
835
+ singularCode: model.base,
836
+ });
837
+ entity[baseModel.derivedTypePropertyCode] = model.derivedType;
838
+ }
839
+
832
840
  await server.beforeCreateEntity(model, options);
833
841
 
834
842
  await server.emitEvent({
package/src/types.ts CHANGED
@@ -600,6 +600,7 @@ export interface RpdRoute {
600
600
  type: "RESTful";
601
601
  method: RpdHttpMethod;
602
602
  endpoint: string;
603
+ executeInDbTransaction?: boolean;
603
604
  actions?: RpdRouteActionConfig[];
604
605
  handler?: string | ((ctx: ActionHandlerContext) => Promise<void>);
605
606
  }