@ruiapp/rapid-core 0.10.3 → 0.10.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/ExpressionInterpreter.d.ts +2 -0
- package/dist/core/actionHandler.d.ts +3 -3
- package/dist/core/server.d.ts +1 -0
- package/dist/index.js +168 -71
- package/dist/plugins/dataManage/actionHandlers/saveEntity.d.ts +8 -0
- package/dist/server.d.ts +1 -0
- package/dist/types.d.ts +7 -0
- package/package.json +1 -1
- package/src/bootstrapApplicationConfig.ts +7 -0
- package/src/core/ExpressionInterpreter.ts +45 -0
- package/src/core/actionHandler.ts +3 -2
- package/src/core/http/formDataParser.ts +0 -2
- package/src/core/request.ts +1 -1
- package/src/core/routesBuilder.ts +1 -1
- package/src/core/server.ts +2 -0
- package/src/plugins/cronJob/services/CronJobService.ts +1 -2
- package/src/plugins/dataManage/DataManagePlugin.ts +2 -0
- package/src/plugins/dataManage/actionHandlers/saveEntity.ts +46 -0
- package/src/plugins/fileManage/actionHandlers/downloadDocument.ts +1 -1
- package/src/plugins/fileManage/actionHandlers/downloadFile.ts +1 -1
- package/src/plugins/fileManage/actionHandlers/uploadFile.ts +1 -1
- package/src/plugins/metaManage/actionHandlers/listMetaModels.ts +2 -1
- package/src/plugins/metaManage/actionHandlers/listMetaRoutes.ts +2 -1
- package/src/server.ts +22 -0
- package/src/types.ts +8 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { RpdApplicationConfig } from "../types";
|
|
2
1
|
import { IRpdServer, RapidPlugin } from "./server";
|
|
3
2
|
import { Next, RouteContext } from "./routeContext";
|
|
4
3
|
import { Logger } from "../facilities/log/LogFacility";
|
|
5
4
|
export interface ActionHandlerContext {
|
|
6
5
|
logger: Logger;
|
|
7
6
|
routerContext: RouteContext;
|
|
8
|
-
next
|
|
7
|
+
next?: Next;
|
|
9
8
|
server: IRpdServer;
|
|
10
|
-
|
|
9
|
+
vars?: Record<string, any>;
|
|
11
10
|
input?: any;
|
|
12
11
|
output?: any;
|
|
12
|
+
results: any[];
|
|
13
13
|
status?: Response["status"];
|
|
14
14
|
}
|
|
15
15
|
export type ActionHandler = (ctx: ActionHandlerContext, options: any) => void | Promise<void>;
|
package/dist/core/server.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ export interface IRpdServer {
|
|
|
31
31
|
registerEntityWatcher(entityWatcher: EntityWatcherType): any;
|
|
32
32
|
emitEvent<TEventName extends keyof RpdServerEventTypes>(event: EmitServerEventOptions<TEventName>): void;
|
|
33
33
|
handleRequest(request: RapidRequest, next: Next): Promise<Response>;
|
|
34
|
+
runActionHandlers(handlerContext: ActionHandlerContext, actions: RpdRouteActionConfig[]): Promise<void>;
|
|
34
35
|
beforeRunRouteActions(handlerContext: ActionHandlerContext): Promise<void>;
|
|
35
36
|
beforeRunActionHandler(handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig): Promise<void>;
|
|
36
37
|
beforeCreateEntity(model: RpdDataModel, options: CreateEntityOptions): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -1028,8 +1028,8 @@ async function buildRoutes(server, applicationConfig) {
|
|
|
1028
1028
|
routerContext,
|
|
1029
1029
|
next,
|
|
1030
1030
|
server,
|
|
1031
|
-
applicationConfig,
|
|
1032
1031
|
input,
|
|
1032
|
+
results: [],
|
|
1033
1033
|
};
|
|
1034
1034
|
await server.beforeRunRouteActions(handlerContext);
|
|
1035
1035
|
let handler = routeConfig.handler;
|
|
@@ -1582,6 +1582,13 @@ var bootstrapApplicationConfig = {
|
|
|
1582
1582
|
type: "text",
|
|
1583
1583
|
required: false,
|
|
1584
1584
|
},
|
|
1585
|
+
{
|
|
1586
|
+
name: "target type column name",
|
|
1587
|
+
code: "targetTypeColumnName",
|
|
1588
|
+
columnName: "target_type_column_name",
|
|
1589
|
+
type: "text",
|
|
1590
|
+
required: false,
|
|
1591
|
+
},
|
|
1585
1592
|
{
|
|
1586
1593
|
name: "target id column name",
|
|
1587
1594
|
code: "targetIdColumnName",
|
|
@@ -4110,14 +4117,51 @@ var healthz = {
|
|
|
4110
4117
|
type: "RESTful",
|
|
4111
4118
|
method: "GET",
|
|
4112
4119
|
endpoint: "/healthz",
|
|
4113
|
-
handler: handler$
|
|
4120
|
+
handler: handler$y,
|
|
4114
4121
|
};
|
|
4115
|
-
async function handler$
|
|
4122
|
+
async function handler$y(ctx) {
|
|
4116
4123
|
ctx.output = {};
|
|
4117
4124
|
}
|
|
4118
4125
|
|
|
4119
4126
|
var coreRoutes = [healthz];
|
|
4120
4127
|
|
|
4128
|
+
const genExpression = lodash.memoize((varNames, expressionString) => {
|
|
4129
|
+
// eslint-disable-next-line no-new-func
|
|
4130
|
+
return new Function(...varNames, `return (${expressionString})`);
|
|
4131
|
+
}, (varNames, expressionString) => {
|
|
4132
|
+
return varNames.join(",") + ":" + expressionString;
|
|
4133
|
+
});
|
|
4134
|
+
function interpreteExpression(expressionString, rootVars) {
|
|
4135
|
+
const varNames = [];
|
|
4136
|
+
const varValues = [];
|
|
4137
|
+
for (const name in rootVars) {
|
|
4138
|
+
varNames.push(name);
|
|
4139
|
+
varValues.push(rootVars[name]);
|
|
4140
|
+
}
|
|
4141
|
+
let result;
|
|
4142
|
+
try {
|
|
4143
|
+
const expression = genExpression(varNames, expressionString);
|
|
4144
|
+
result = expression(...varValues);
|
|
4145
|
+
}
|
|
4146
|
+
catch (err) {
|
|
4147
|
+
console.error(`Expression interprete error. expression: '${expressionString}', error:`, err.message);
|
|
4148
|
+
}
|
|
4149
|
+
return result;
|
|
4150
|
+
}
|
|
4151
|
+
function interpreteConfigExpressions(config, vars) {
|
|
4152
|
+
if (!config) {
|
|
4153
|
+
return;
|
|
4154
|
+
}
|
|
4155
|
+
const propExpressions = config.$exps;
|
|
4156
|
+
if (!propExpressions) {
|
|
4157
|
+
return;
|
|
4158
|
+
}
|
|
4159
|
+
for (const propName in propExpressions) {
|
|
4160
|
+
const propValue = interpreteExpression(propExpressions[propName], vars);
|
|
4161
|
+
lodash.set(config, propName, propValue);
|
|
4162
|
+
}
|
|
4163
|
+
}
|
|
4164
|
+
|
|
4121
4165
|
class RapidServer {
|
|
4122
4166
|
#logger;
|
|
4123
4167
|
#facilityFactories;
|
|
@@ -4484,6 +4528,22 @@ class RapidServer {
|
|
|
4484
4528
|
}
|
|
4485
4529
|
return response.getResponse();
|
|
4486
4530
|
}
|
|
4531
|
+
async runActionHandlers(handlerContext, actions) {
|
|
4532
|
+
if (!actions) {
|
|
4533
|
+
return;
|
|
4534
|
+
}
|
|
4535
|
+
for (const action of actions) {
|
|
4536
|
+
const actionCode = action.code;
|
|
4537
|
+
interpreteConfigExpressions(action.config, handlerContext.vars);
|
|
4538
|
+
const handler = this.getActionHandlerByCode(actionCode);
|
|
4539
|
+
if (!handler) {
|
|
4540
|
+
throw new Error("Unknown handler: " + actionCode);
|
|
4541
|
+
}
|
|
4542
|
+
await this.beforeRunActionHandler(handlerContext, action);
|
|
4543
|
+
const result = await handler(handlerContext, action.config);
|
|
4544
|
+
handlerContext.results.push(result);
|
|
4545
|
+
}
|
|
4546
|
+
}
|
|
4487
4547
|
async beforeRunRouteActions(handlerContext) {
|
|
4488
4548
|
await this.#pluginManager.beforeRunRouteActions(handlerContext);
|
|
4489
4549
|
}
|
|
@@ -4996,7 +5056,7 @@ class RapidRequest {
|
|
|
4996
5056
|
else if (contentType.startsWith("multipart/form-data")) {
|
|
4997
5057
|
this.#body = {
|
|
4998
5058
|
type: "form-data",
|
|
4999
|
-
value: await parseFormDataBody(req),
|
|
5059
|
+
value: await parseFormDataBody(req, { all: true }),
|
|
5000
5060
|
};
|
|
5001
5061
|
}
|
|
5002
5062
|
this.#bodyParsed = true;
|
|
@@ -5491,32 +5551,34 @@ class CacheFactory {
|
|
|
5491
5551
|
}
|
|
5492
5552
|
}
|
|
5493
5553
|
|
|
5494
|
-
const code$
|
|
5495
|
-
async function handler$
|
|
5496
|
-
const {
|
|
5554
|
+
const code$x = "listMetaModels";
|
|
5555
|
+
async function handler$x(plugin, ctx, options) {
|
|
5556
|
+
const { server } = ctx;
|
|
5557
|
+
const applicationConfig = server.getApplicationConfig();
|
|
5497
5558
|
ctx.output = { list: applicationConfig.models };
|
|
5498
5559
|
}
|
|
5499
5560
|
|
|
5500
5561
|
var listMetaModels = /*#__PURE__*/Object.freeze({
|
|
5501
5562
|
__proto__: null,
|
|
5502
|
-
code: code$
|
|
5503
|
-
handler: handler$
|
|
5563
|
+
code: code$x,
|
|
5564
|
+
handler: handler$x
|
|
5504
5565
|
});
|
|
5505
5566
|
|
|
5506
|
-
const code$
|
|
5507
|
-
async function handler$
|
|
5508
|
-
const {
|
|
5567
|
+
const code$w = "listMetaRoutes";
|
|
5568
|
+
async function handler$w(plugin, ctx, options) {
|
|
5569
|
+
const { server } = ctx;
|
|
5570
|
+
const applicationConfig = server.getApplicationConfig();
|
|
5509
5571
|
ctx.output = { list: applicationConfig.routes };
|
|
5510
5572
|
}
|
|
5511
5573
|
|
|
5512
5574
|
var listMetaRoutes = /*#__PURE__*/Object.freeze({
|
|
5513
5575
|
__proto__: null,
|
|
5514
|
-
code: code$
|
|
5515
|
-
handler: handler$
|
|
5576
|
+
code: code$w,
|
|
5577
|
+
handler: handler$w
|
|
5516
5578
|
});
|
|
5517
5579
|
|
|
5518
|
-
const code$
|
|
5519
|
-
async function handler$
|
|
5580
|
+
const code$v = "getMetaModelDetail";
|
|
5581
|
+
async function handler$v(plugin, ctx, options) {
|
|
5520
5582
|
const { server, input } = ctx;
|
|
5521
5583
|
const model = server.getModel(input);
|
|
5522
5584
|
ctx.output = model;
|
|
@@ -5524,8 +5586,8 @@ async function handler$u(plugin, ctx, options) {
|
|
|
5524
5586
|
|
|
5525
5587
|
var getMetaModelDetail = /*#__PURE__*/Object.freeze({
|
|
5526
5588
|
__proto__: null,
|
|
5527
|
-
code: code$
|
|
5528
|
-
handler: handler$
|
|
5589
|
+
code: code$v,
|
|
5590
|
+
handler: handler$v
|
|
5529
5591
|
});
|
|
5530
5592
|
|
|
5531
5593
|
function removeFiltersWithNullValue(filters) {
|
|
@@ -6114,9 +6176,9 @@ async function runCollectionEntityActionHandler(ctx, options, code, autoMergeInp
|
|
|
6114
6176
|
}
|
|
6115
6177
|
}
|
|
6116
6178
|
|
|
6117
|
-
const code$
|
|
6118
|
-
async function handler$
|
|
6119
|
-
await runCollectionEntityActionHandler(ctx, options, code$
|
|
6179
|
+
const code$u = "findCollectionEntities";
|
|
6180
|
+
async function handler$u(plugin, ctx, options) {
|
|
6181
|
+
await runCollectionEntityActionHandler(ctx, options, code$u, true, false, async (entityManager, input) => {
|
|
6120
6182
|
const { routerContext: routeContext } = ctx;
|
|
6121
6183
|
input.filters = removeFiltersWithNullValue(input.filters);
|
|
6122
6184
|
input.routeContext = routeContext;
|
|
@@ -6133,13 +6195,13 @@ async function handler$t(plugin, ctx, options) {
|
|
|
6133
6195
|
|
|
6134
6196
|
var findCollectionEntities = /*#__PURE__*/Object.freeze({
|
|
6135
6197
|
__proto__: null,
|
|
6136
|
-
code: code$
|
|
6137
|
-
handler: handler$
|
|
6198
|
+
code: code$u,
|
|
6199
|
+
handler: handler$u
|
|
6138
6200
|
});
|
|
6139
6201
|
|
|
6140
|
-
const code$
|
|
6141
|
-
async function handler$
|
|
6142
|
-
await runCollectionEntityActionHandler(ctx, options, code$
|
|
6202
|
+
const code$t = "findCollectionEntityById";
|
|
6203
|
+
async function handler$t(plugin, ctx, options) {
|
|
6204
|
+
await runCollectionEntityActionHandler(ctx, options, code$t, true, true, async (entityManager, input) => {
|
|
6143
6205
|
const { routerContext: routeContext } = ctx;
|
|
6144
6206
|
const { id } = input;
|
|
6145
6207
|
const entity = await entityManager.findById({
|
|
@@ -6161,13 +6223,13 @@ async function handler$s(plugin, ctx, options) {
|
|
|
6161
6223
|
|
|
6162
6224
|
var findCollectionEntityById = /*#__PURE__*/Object.freeze({
|
|
6163
6225
|
__proto__: null,
|
|
6164
|
-
code: code$
|
|
6165
|
-
handler: handler$
|
|
6226
|
+
code: code$t,
|
|
6227
|
+
handler: handler$t
|
|
6166
6228
|
});
|
|
6167
6229
|
|
|
6168
|
-
const code$
|
|
6169
|
-
async function handler$
|
|
6170
|
-
await runCollectionEntityActionHandler(ctx, options, code$
|
|
6230
|
+
const code$s = "countCollectionEntities";
|
|
6231
|
+
async function handler$s(plugin, ctx, options) {
|
|
6232
|
+
await runCollectionEntityActionHandler(ctx, options, code$s, true, false, async (entityManager, input) => {
|
|
6171
6233
|
const { routerContext: routeContext } = ctx;
|
|
6172
6234
|
input.filters = removeFiltersWithNullValue(input.filters);
|
|
6173
6235
|
input.routeContext = routeContext;
|
|
@@ -6178,13 +6240,13 @@ async function handler$r(plugin, ctx, options) {
|
|
|
6178
6240
|
|
|
6179
6241
|
var countCollectionEntities = /*#__PURE__*/Object.freeze({
|
|
6180
6242
|
__proto__: null,
|
|
6181
|
-
code: code$
|
|
6182
|
-
handler: handler$
|
|
6243
|
+
code: code$s,
|
|
6244
|
+
handler: handler$s
|
|
6183
6245
|
});
|
|
6184
6246
|
|
|
6185
|
-
const code$
|
|
6186
|
-
async function handler$
|
|
6187
|
-
await runCollectionEntityActionHandler(ctx, options, code$
|
|
6247
|
+
const code$r = "createCollectionEntity";
|
|
6248
|
+
async function handler$r(plugin, ctx, options) {
|
|
6249
|
+
await runCollectionEntityActionHandler(ctx, options, code$r, true, true, async (entityManager, input) => {
|
|
6188
6250
|
const { routerContext: routeContext } = ctx;
|
|
6189
6251
|
const output = await entityManager.createEntity({
|
|
6190
6252
|
entity: input,
|
|
@@ -6196,16 +6258,16 @@ async function handler$q(plugin, ctx, options) {
|
|
|
6196
6258
|
|
|
6197
6259
|
var createCollectionEntity = /*#__PURE__*/Object.freeze({
|
|
6198
6260
|
__proto__: null,
|
|
6199
|
-
code: code$
|
|
6200
|
-
handler: handler$
|
|
6261
|
+
code: code$r,
|
|
6262
|
+
handler: handler$r
|
|
6201
6263
|
});
|
|
6202
6264
|
|
|
6203
|
-
const code$
|
|
6204
|
-
async function handler$
|
|
6265
|
+
const code$q = "createCollectionEntitiesBatch";
|
|
6266
|
+
async function handler$q(plugin, ctx, options) {
|
|
6205
6267
|
const { input } = ctx;
|
|
6206
6268
|
const { noTransaction } = input;
|
|
6207
6269
|
const { defaultInput, fixedInput } = options;
|
|
6208
|
-
await runCollectionEntityActionHandler(ctx, options, code$
|
|
6270
|
+
await runCollectionEntityActionHandler(ctx, options, code$q, false, !noTransaction, async (entityManager, input) => {
|
|
6209
6271
|
const { routerContext: routeContext } = ctx;
|
|
6210
6272
|
const { entities } = input;
|
|
6211
6273
|
if (!lodash.isArray(entities)) {
|
|
@@ -6243,13 +6305,13 @@ async function createEntities(options) {
|
|
|
6243
6305
|
|
|
6244
6306
|
var createCollectionEntitiesBatch = /*#__PURE__*/Object.freeze({
|
|
6245
6307
|
__proto__: null,
|
|
6246
|
-
code: code$
|
|
6247
|
-
handler: handler$
|
|
6308
|
+
code: code$q,
|
|
6309
|
+
handler: handler$q
|
|
6248
6310
|
});
|
|
6249
6311
|
|
|
6250
|
-
const code$
|
|
6251
|
-
async function handler$
|
|
6252
|
-
await runCollectionEntityActionHandler(ctx, options, code$
|
|
6312
|
+
const code$p = "updateCollectionEntityById";
|
|
6313
|
+
async function handler$p(plugin, ctx, options) {
|
|
6314
|
+
await runCollectionEntityActionHandler(ctx, options, code$p, true, true, async (entityManager, input) => {
|
|
6253
6315
|
const { routerContext: routeContext } = ctx;
|
|
6254
6316
|
const operation = input.$operation;
|
|
6255
6317
|
if (operation) {
|
|
@@ -6278,15 +6340,15 @@ async function handler$o(plugin, ctx, options) {
|
|
|
6278
6340
|
|
|
6279
6341
|
var updateCollectionEntityById = /*#__PURE__*/Object.freeze({
|
|
6280
6342
|
__proto__: null,
|
|
6281
|
-
code: code$
|
|
6282
|
-
handler: handler$
|
|
6343
|
+
code: code$p,
|
|
6344
|
+
handler: handler$p
|
|
6283
6345
|
});
|
|
6284
6346
|
|
|
6285
|
-
const code$
|
|
6286
|
-
async function handler$
|
|
6347
|
+
const code$o = "deleteCollectionEntities";
|
|
6348
|
+
async function handler$o(plugin, ctx, options) {
|
|
6287
6349
|
const { input } = ctx;
|
|
6288
6350
|
const { noTransaction } = input;
|
|
6289
|
-
await runCollectionEntityActionHandler(ctx, options, code$
|
|
6351
|
+
await runCollectionEntityActionHandler(ctx, options, code$o, true, !noTransaction, async (entityManager, input) => {
|
|
6290
6352
|
const { routerContext: routeContext } = ctx;
|
|
6291
6353
|
const { filters } = input;
|
|
6292
6354
|
if (!filters || !filters.length) {
|
|
@@ -6308,13 +6370,13 @@ async function handler$n(plugin, ctx, options) {
|
|
|
6308
6370
|
|
|
6309
6371
|
var deleteCollectionEntities = /*#__PURE__*/Object.freeze({
|
|
6310
6372
|
__proto__: null,
|
|
6311
|
-
code: code$
|
|
6312
|
-
handler: handler$
|
|
6373
|
+
code: code$o,
|
|
6374
|
+
handler: handler$o
|
|
6313
6375
|
});
|
|
6314
6376
|
|
|
6315
|
-
const code$
|
|
6316
|
-
async function handler$
|
|
6317
|
-
await runCollectionEntityActionHandler(ctx, options, code$
|
|
6377
|
+
const code$n = "deleteCollectionEntityById";
|
|
6378
|
+
async function handler$n(plugin, ctx, options) {
|
|
6379
|
+
await runCollectionEntityActionHandler(ctx, options, code$n, true, true, async (entityManager, input) => {
|
|
6318
6380
|
const { routerContext: routeContext } = ctx;
|
|
6319
6381
|
await entityManager.deleteById({
|
|
6320
6382
|
id: input.id,
|
|
@@ -6326,13 +6388,13 @@ async function handler$m(plugin, ctx, options) {
|
|
|
6326
6388
|
|
|
6327
6389
|
var deleteCollectionEntityById = /*#__PURE__*/Object.freeze({
|
|
6328
6390
|
__proto__: null,
|
|
6329
|
-
code: code$
|
|
6330
|
-
handler: handler$
|
|
6391
|
+
code: code$n,
|
|
6392
|
+
handler: handler$n
|
|
6331
6393
|
});
|
|
6332
6394
|
|
|
6333
|
-
const code$
|
|
6334
|
-
async function handler$
|
|
6335
|
-
await runCollectionEntityActionHandler(ctx, options, code$
|
|
6395
|
+
const code$m = "addEntityRelations";
|
|
6396
|
+
async function handler$m(plugin, ctx, options) {
|
|
6397
|
+
await runCollectionEntityActionHandler(ctx, options, code$m, true, true, async (entityManager, input) => {
|
|
6336
6398
|
const { routerContext: routeContext } = ctx;
|
|
6337
6399
|
input.routeContext = routeContext;
|
|
6338
6400
|
await entityManager.addRelations(input, plugin);
|
|
@@ -6342,13 +6404,13 @@ async function handler$l(plugin, ctx, options) {
|
|
|
6342
6404
|
|
|
6343
6405
|
var addEntityRelations = /*#__PURE__*/Object.freeze({
|
|
6344
6406
|
__proto__: null,
|
|
6345
|
-
code: code$
|
|
6346
|
-
handler: handler$
|
|
6407
|
+
code: code$m,
|
|
6408
|
+
handler: handler$m
|
|
6347
6409
|
});
|
|
6348
6410
|
|
|
6349
|
-
const code$
|
|
6350
|
-
async function handler$
|
|
6351
|
-
await runCollectionEntityActionHandler(ctx, options, code$
|
|
6411
|
+
const code$l = "removeEntityRelations";
|
|
6412
|
+
async function handler$l(plugin, ctx, options) {
|
|
6413
|
+
await runCollectionEntityActionHandler(ctx, options, code$l, true, true, async (entityManager, input) => {
|
|
6352
6414
|
const { routerContext: routeContext } = ctx;
|
|
6353
6415
|
input.routeContext = routeContext;
|
|
6354
6416
|
await entityManager.removeRelations(input, plugin);
|
|
@@ -6357,6 +6419,41 @@ async function handler$k(plugin, ctx, options) {
|
|
|
6357
6419
|
}
|
|
6358
6420
|
|
|
6359
6421
|
var removeEntityRelations = /*#__PURE__*/Object.freeze({
|
|
6422
|
+
__proto__: null,
|
|
6423
|
+
code: code$l,
|
|
6424
|
+
handler: handler$l
|
|
6425
|
+
});
|
|
6426
|
+
|
|
6427
|
+
const code$k = "saveEntity";
|
|
6428
|
+
async function handler$k(plugin, ctx, options) {
|
|
6429
|
+
const { server, routerContext: routeContext, vars } = ctx;
|
|
6430
|
+
interpreteConfigExpressions(options, vars || {});
|
|
6431
|
+
const input = options.entity;
|
|
6432
|
+
const operation = input.$operation;
|
|
6433
|
+
if (operation) {
|
|
6434
|
+
delete input.$operation;
|
|
6435
|
+
}
|
|
6436
|
+
const stateProperties = input.$stateProperties;
|
|
6437
|
+
if (stateProperties) {
|
|
6438
|
+
delete input.$stateProperties;
|
|
6439
|
+
}
|
|
6440
|
+
const relationPropertiesToUpdate = input.$relationPropertiesToUpdate;
|
|
6441
|
+
if (relationPropertiesToUpdate) {
|
|
6442
|
+
delete input.$relationPropertiesToUpdate;
|
|
6443
|
+
}
|
|
6444
|
+
const entityManager = server.getEntityManager(options.singularCode);
|
|
6445
|
+
const updateEntityByIdOptions = {
|
|
6446
|
+
id: input.id,
|
|
6447
|
+
entityToSave: input,
|
|
6448
|
+
operation,
|
|
6449
|
+
stateProperties,
|
|
6450
|
+
relationPropertiesToUpdate,
|
|
6451
|
+
routeContext,
|
|
6452
|
+
};
|
|
6453
|
+
ctx.output = await entityManager.updateEntityById(updateEntityByIdOptions, plugin);
|
|
6454
|
+
}
|
|
6455
|
+
|
|
6456
|
+
var saveEntity = /*#__PURE__*/Object.freeze({
|
|
6360
6457
|
__proto__: null,
|
|
6361
6458
|
code: code$k,
|
|
6362
6459
|
handler: handler$k
|
|
@@ -6477,6 +6574,7 @@ class DataManager {
|
|
|
6477
6574
|
server.registerActionHandler(this, removeEntityRelations);
|
|
6478
6575
|
server.registerActionHandler(this, deleteCollectionEntities);
|
|
6479
6576
|
server.registerActionHandler(this, deleteCollectionEntityById);
|
|
6577
|
+
server.registerActionHandler(this, saveEntity);
|
|
6480
6578
|
server.registerActionHandler(this, queryDatabase);
|
|
6481
6579
|
}
|
|
6482
6580
|
async configureRoutes(server, applicationConfig) {
|
|
@@ -7672,7 +7770,7 @@ function getFileBaseName(pathname) {
|
|
|
7672
7770
|
|
|
7673
7771
|
const code$a = "downloadDocument";
|
|
7674
7772
|
async function handler$a(plugin, ctx, options) {
|
|
7675
|
-
const { server,
|
|
7773
|
+
const { server, routerContext: routeContext, input } = ctx;
|
|
7676
7774
|
const { request, response } = routeContext;
|
|
7677
7775
|
const documentDataAccessor = ctx.server.getDataAccessor({
|
|
7678
7776
|
singularCode: "ecm_document",
|
|
@@ -7733,7 +7831,7 @@ var downloadDocumentActionHandler = /*#__PURE__*/Object.freeze({
|
|
|
7733
7831
|
|
|
7734
7832
|
const code$9 = "downloadFile";
|
|
7735
7833
|
async function handler$9(plugin, ctx, options) {
|
|
7736
|
-
const { server,
|
|
7834
|
+
const { server, routerContext: routeContext } = ctx;
|
|
7737
7835
|
const { request, response } = routeContext;
|
|
7738
7836
|
//TODO: only public files can download by this handler
|
|
7739
7837
|
const input = ctx.input;
|
|
@@ -7764,7 +7862,7 @@ var downloadFileActionHandler = /*#__PURE__*/Object.freeze({
|
|
|
7764
7862
|
|
|
7765
7863
|
const code$8 = "uploadFile";
|
|
7766
7864
|
async function handler$8(plugin, ctx, options) {
|
|
7767
|
-
const { server,
|
|
7865
|
+
const { server, routerContext, input } = ctx;
|
|
7768
7866
|
let file = input.file || input.files;
|
|
7769
7867
|
if (lodash.isArray(file)) {
|
|
7770
7868
|
file = file[0];
|
|
@@ -9390,10 +9488,9 @@ class CronJobService {
|
|
|
9390
9488
|
let handlerContext = {
|
|
9391
9489
|
logger,
|
|
9392
9490
|
routerContext: RouteContext.newSystemOperationContext(server),
|
|
9393
|
-
next: null,
|
|
9394
9491
|
server,
|
|
9395
|
-
applicationConfig: null,
|
|
9396
9492
|
input,
|
|
9493
|
+
results: [],
|
|
9397
9494
|
};
|
|
9398
9495
|
let result;
|
|
9399
9496
|
let lastErrorMessage;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ActionHandlerContext } from "../../../core/actionHandler";
|
|
2
|
+
import { RapidPlugin } from "../../../core/server";
|
|
3
|
+
export declare const code = "saveEntity";
|
|
4
|
+
export type SaveEntityActionHandlerOptions = {
|
|
5
|
+
singularCode: string;
|
|
6
|
+
entity?: Record<string, any>;
|
|
7
|
+
};
|
|
8
|
+
export declare function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: SaveEntityActionHandlerOptions): Promise<void>;
|
package/dist/server.d.ts
CHANGED
|
@@ -57,6 +57,7 @@ export declare class RapidServer implements IRpdServer {
|
|
|
57
57
|
tryQueryDatabaseObject(sql: string, params?: unknown[] | Record<string, unknown>, client?: IDatabaseClient, dropErrorLog?: boolean): Promise<any[]>;
|
|
58
58
|
get middlewares(): any[];
|
|
59
59
|
handleRequest(rapidRequest: RapidRequest, next: Next): Promise<Response>;
|
|
60
|
+
runActionHandlers(handlerContext: ActionHandlerContext, actions: RpdRouteActionConfig[]): Promise<void>;
|
|
60
61
|
beforeRunRouteActions(handlerContext: ActionHandlerContext): Promise<void>;
|
|
61
62
|
beforeRunActionHandler(handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig): Promise<void>;
|
|
62
63
|
beforeCreateEntity(model: RpdDataModel, options: CreateEntityOptions): Promise<void>;
|
package/dist/types.d.ts
CHANGED
|
@@ -29,6 +29,9 @@ export interface IDatabaseAccessor {
|
|
|
29
29
|
getClient(): Promise<IDatabaseClient>;
|
|
30
30
|
queryDatabaseObject: (sql: string, params?: unknown[] | Record<string, unknown>, client?: IDatabaseClient) => Promise<any[]>;
|
|
31
31
|
}
|
|
32
|
+
export type RunActionHandlersOptions = {
|
|
33
|
+
actions: RpdRouteActionConfig[];
|
|
34
|
+
};
|
|
32
35
|
export interface RunEntityActionHandlerOptions {
|
|
33
36
|
/** 模型所在的命名空间 */
|
|
34
37
|
namespace: string;
|
|
@@ -315,6 +318,10 @@ export interface RpdDataModelProperty {
|
|
|
315
318
|
* 关联实体的singular code,不管 relation 为 one 或者 many 都需要设置。
|
|
316
319
|
*/
|
|
317
320
|
targetSingularCode?: string;
|
|
321
|
+
/**
|
|
322
|
+
* 保存关联实体类型的字段名。当设置 targetTypeColumnName 时,表示关联实体类型不固定,可以关联不同类型的实体。
|
|
323
|
+
*/
|
|
324
|
+
targetTypeColumnName?: string;
|
|
318
325
|
/**
|
|
319
326
|
* 当 relation 为 one 时,设置当前模型表中表示关联实体 id 的列名。
|
|
320
327
|
* 当 relation 为 many,并且使用关联关系表保存关联信息时,设置关联关系表中表示关联实体 id 的列名。
|
package/package.json
CHANGED
|
@@ -350,6 +350,13 @@ export default {
|
|
|
350
350
|
type: "text",
|
|
351
351
|
required: false,
|
|
352
352
|
},
|
|
353
|
+
{
|
|
354
|
+
name: "target type column name",
|
|
355
|
+
code: "targetTypeColumnName",
|
|
356
|
+
columnName: "target_type_column_name",
|
|
357
|
+
type: "text",
|
|
358
|
+
required: false,
|
|
359
|
+
},
|
|
353
360
|
{
|
|
354
361
|
name: "target id column name",
|
|
355
362
|
code: "targetIdColumnName",
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { memoize, set } from "lodash";
|
|
2
|
+
|
|
3
|
+
const genExpression = memoize(
|
|
4
|
+
(varNames: string[], expressionString: string) => {
|
|
5
|
+
// eslint-disable-next-line no-new-func
|
|
6
|
+
return new Function(...varNames, `return (${expressionString})`);
|
|
7
|
+
},
|
|
8
|
+
(varNames, expressionString) => {
|
|
9
|
+
return varNames.join(",") + ":" + expressionString;
|
|
10
|
+
},
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
export function interpreteExpression(expressionString: string, rootVars: Record<string, any>) {
|
|
14
|
+
const varNames = [];
|
|
15
|
+
const varValues = [];
|
|
16
|
+
for (const name in rootVars) {
|
|
17
|
+
varNames.push(name);
|
|
18
|
+
varValues.push(rootVars[name]);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let result;
|
|
22
|
+
try {
|
|
23
|
+
const expression = genExpression(varNames, expressionString);
|
|
24
|
+
result = expression(...varValues);
|
|
25
|
+
} catch (err: any) {
|
|
26
|
+
console.error(`Expression interprete error. expression: '${expressionString}', error:`, err.message);
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function interpreteConfigExpressions(config: Record<string, any>, vars: Record<string, any>) {
|
|
32
|
+
if (!config) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const propExpressions = config.$exps;
|
|
37
|
+
if (!propExpressions) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (const propName in propExpressions) {
|
|
42
|
+
const propValue = interpreteExpression(propExpressions[propName], vars);
|
|
43
|
+
set(config, propName, propValue);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -7,11 +7,12 @@ import { CronJobConfiguration } from "~/types/cron-job-types";
|
|
|
7
7
|
export interface ActionHandlerContext {
|
|
8
8
|
logger: Logger;
|
|
9
9
|
routerContext: RouteContext;
|
|
10
|
-
next
|
|
10
|
+
next?: Next;
|
|
11
11
|
server: IRpdServer;
|
|
12
|
-
|
|
12
|
+
vars?: Record<string, any>;
|
|
13
13
|
input?: any;
|
|
14
14
|
output?: any;
|
|
15
|
+
results: any[];
|
|
15
16
|
status?: Response["status"];
|
|
16
17
|
}
|
|
17
18
|
|
package/src/core/request.ts
CHANGED
|
@@ -66,7 +66,7 @@ export class RapidRequest {
|
|
|
66
66
|
} else if (contentType.startsWith("multipart/form-data")) {
|
|
67
67
|
this.#body = {
|
|
68
68
|
type: "form-data",
|
|
69
|
-
value: await parseFormDataBody(req),
|
|
69
|
+
value: await parseFormDataBody(req, { all: true }),
|
|
70
70
|
};
|
|
71
71
|
}
|
|
72
72
|
this.#bodyParsed = true;
|
package/src/core/server.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
RpdDataModelProperty,
|
|
16
16
|
RpdRouteActionConfig,
|
|
17
17
|
RpdServerEventTypes,
|
|
18
|
+
RunActionHandlersOptions,
|
|
18
19
|
UpdateEntityByIdOptions,
|
|
19
20
|
} from "~/types";
|
|
20
21
|
import { IPluginActionHandler, ActionHandler, ActionHandlerContext } from "./actionHandler";
|
|
@@ -53,6 +54,7 @@ export interface IRpdServer {
|
|
|
53
54
|
registerEntityWatcher(entityWatcher: EntityWatcherType);
|
|
54
55
|
emitEvent<TEventName extends keyof RpdServerEventTypes>(event: EmitServerEventOptions<TEventName>): void;
|
|
55
56
|
handleRequest(request: RapidRequest, next: Next): Promise<Response>;
|
|
57
|
+
runActionHandlers(handlerContext: ActionHandlerContext, actions: RpdRouteActionConfig[]): Promise<void>;
|
|
56
58
|
beforeRunRouteActions(handlerContext: ActionHandlerContext): Promise<void>;
|
|
57
59
|
beforeRunActionHandler(handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig): Promise<void>;
|
|
58
60
|
beforeCreateEntity(model: RpdDataModel, options: CreateEntityOptions): Promise<void>;
|
|
@@ -133,10 +133,9 @@ export default class CronJobService {
|
|
|
133
133
|
let handlerContext: ActionHandlerContext = {
|
|
134
134
|
logger,
|
|
135
135
|
routerContext: RouteContext.newSystemOperationContext(server),
|
|
136
|
-
next: null,
|
|
137
136
|
server,
|
|
138
|
-
applicationConfig: null,
|
|
139
137
|
input,
|
|
138
|
+
results: [],
|
|
140
139
|
};
|
|
141
140
|
|
|
142
141
|
let result: JobRunningResult;
|
|
@@ -16,6 +16,7 @@ import * as deleteCollectionEntities from "./actionHandlers/deleteCollectionEnti
|
|
|
16
16
|
import * as deleteCollectionEntityById from "./actionHandlers/deleteCollectionEntityById";
|
|
17
17
|
import * as addEntityRelations from "./actionHandlers/addEntityRelations";
|
|
18
18
|
import * as removeEntityRelations from "./actionHandlers/removeEntityRelations";
|
|
19
|
+
import * as saveEntity from "./actionHandlers/saveEntity";
|
|
19
20
|
import * as queryDatabase from "./actionHandlers/queryDatabase";
|
|
20
21
|
import {
|
|
21
22
|
RpdServerPluginExtendingAbilities,
|
|
@@ -125,6 +126,7 @@ class DataManager implements RapidPlugin {
|
|
|
125
126
|
server.registerActionHandler(this, removeEntityRelations);
|
|
126
127
|
server.registerActionHandler(this, deleteCollectionEntities);
|
|
127
128
|
server.registerActionHandler(this, deleteCollectionEntityById);
|
|
129
|
+
server.registerActionHandler(this, saveEntity);
|
|
128
130
|
server.registerActionHandler(this, queryDatabase);
|
|
129
131
|
}
|
|
130
132
|
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { RunEntityActionHandlerOptions, UpdateEntityByIdOptions } from "~/types";
|
|
2
|
+
import { ActionHandlerContext } from "~/core/actionHandler";
|
|
3
|
+
import { RapidPlugin } from "~/core/server";
|
|
4
|
+
import runCollectionEntityActionHandler from "~/helpers/runCollectionEntityActionHandler";
|
|
5
|
+
import { interpreteConfigExpressions } from "~/core/ExpressionInterpreter";
|
|
6
|
+
|
|
7
|
+
export const code = "saveEntity";
|
|
8
|
+
|
|
9
|
+
export type SaveEntityActionHandlerOptions = {
|
|
10
|
+
singularCode: string;
|
|
11
|
+
entity?: Record<string, any>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: SaveEntityActionHandlerOptions) {
|
|
15
|
+
const { server, routerContext: routeContext, vars } = ctx;
|
|
16
|
+
|
|
17
|
+
interpreteConfigExpressions(options, vars || {});
|
|
18
|
+
|
|
19
|
+
const input = options.entity;
|
|
20
|
+
|
|
21
|
+
const operation = input.$operation;
|
|
22
|
+
if (operation) {
|
|
23
|
+
delete input.$operation;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const stateProperties = input.$stateProperties;
|
|
27
|
+
if (stateProperties) {
|
|
28
|
+
delete input.$stateProperties;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const relationPropertiesToUpdate = input.$relationPropertiesToUpdate;
|
|
32
|
+
if (relationPropertiesToUpdate) {
|
|
33
|
+
delete input.$relationPropertiesToUpdate;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const entityManager = server.getEntityManager(options.singularCode);
|
|
37
|
+
const updateEntityByIdOptions: UpdateEntityByIdOptions = {
|
|
38
|
+
id: input.id,
|
|
39
|
+
entityToSave: input,
|
|
40
|
+
operation,
|
|
41
|
+
stateProperties,
|
|
42
|
+
relationPropertiesToUpdate,
|
|
43
|
+
routeContext,
|
|
44
|
+
};
|
|
45
|
+
ctx.output = await entityManager.updateEntityById(updateEntityByIdOptions, plugin);
|
|
46
|
+
}
|
|
@@ -7,7 +7,7 @@ import { getFileBaseName } from "~/utilities/pathUtility";
|
|
|
7
7
|
export const code = "downloadDocument";
|
|
8
8
|
|
|
9
9
|
export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: any) {
|
|
10
|
-
const { server,
|
|
10
|
+
const { server, routerContext: routeContext, input } = ctx;
|
|
11
11
|
const { request, response } = routeContext;
|
|
12
12
|
|
|
13
13
|
const documentDataAccessor = ctx.server.getDataAccessor({
|
|
@@ -13,7 +13,7 @@ export type DownloadFileInput = {
|
|
|
13
13
|
export const code = "downloadFile";
|
|
14
14
|
|
|
15
15
|
export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: any) {
|
|
16
|
-
const { server,
|
|
16
|
+
const { server, routerContext: routeContext } = ctx;
|
|
17
17
|
const { request, response } = routeContext;
|
|
18
18
|
//TODO: only public files can download by this handler
|
|
19
19
|
|
|
@@ -8,7 +8,7 @@ import { RapidPlugin } from "~/core/server";
|
|
|
8
8
|
export const code = "uploadFile";
|
|
9
9
|
|
|
10
10
|
export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: any) {
|
|
11
|
-
const { server,
|
|
11
|
+
const { server, routerContext, input } = ctx;
|
|
12
12
|
const { request, response } = routerContext;
|
|
13
13
|
|
|
14
14
|
let file: File | File[] | null = input.file || input.files;
|
|
@@ -4,6 +4,7 @@ import { RapidPlugin } from "~/core/server";
|
|
|
4
4
|
export const code = "listMetaModels";
|
|
5
5
|
|
|
6
6
|
export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: any) {
|
|
7
|
-
const {
|
|
7
|
+
const { server } = ctx;
|
|
8
|
+
const applicationConfig = server.getApplicationConfig();
|
|
8
9
|
ctx.output = { list: applicationConfig.models };
|
|
9
10
|
}
|
|
@@ -4,6 +4,7 @@ import { RapidPlugin } from "~/core/server";
|
|
|
4
4
|
export const code = "listMetaRoutes";
|
|
5
5
|
|
|
6
6
|
export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: any) {
|
|
7
|
-
const {
|
|
7
|
+
const { server } = ctx;
|
|
8
|
+
const applicationConfig = server.getApplicationConfig();
|
|
8
9
|
ctx.output = { list: applicationConfig.routes };
|
|
9
10
|
}
|
package/src/server.ts
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
EmitServerEventOptions,
|
|
20
20
|
IDatabaseClient,
|
|
21
21
|
RpdRouteActionConfig,
|
|
22
|
+
RunActionHandlersOptions,
|
|
22
23
|
} from "./types";
|
|
23
24
|
|
|
24
25
|
import QueryBuilder from "./queryBuilder/queryBuilder";
|
|
@@ -36,6 +37,7 @@ import { Logger } from "./facilities/log/LogFacility";
|
|
|
36
37
|
import { FacilityFactory } from "./core/facility";
|
|
37
38
|
import { CronJobConfiguration } from "./types/cron-job-types";
|
|
38
39
|
import coreRoutes from "./core/routes";
|
|
40
|
+
import { interpreteConfigExpressions } from "./core/ExpressionInterpreter";
|
|
39
41
|
|
|
40
42
|
export interface InitServerOptions {
|
|
41
43
|
logger: Logger;
|
|
@@ -474,6 +476,26 @@ export class RapidServer implements IRpdServer {
|
|
|
474
476
|
return response.getResponse();
|
|
475
477
|
}
|
|
476
478
|
|
|
479
|
+
async runActionHandlers(handlerContext: ActionHandlerContext, actions: RpdRouteActionConfig[]) {
|
|
480
|
+
if (!actions) {
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
for (const action of actions) {
|
|
484
|
+
const actionCode = action.code;
|
|
485
|
+
interpreteConfigExpressions(action.config, handlerContext.vars);
|
|
486
|
+
|
|
487
|
+
const handler = this.getActionHandlerByCode(actionCode);
|
|
488
|
+
if (!handler) {
|
|
489
|
+
throw new Error("Unknown handler: " + actionCode);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
await this.beforeRunActionHandler(handlerContext, action);
|
|
493
|
+
|
|
494
|
+
const result = await handler(handlerContext, action.config);
|
|
495
|
+
handlerContext.results.push(result);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
477
499
|
async beforeRunRouteActions(handlerContext: ActionHandlerContext) {
|
|
478
500
|
await this.#pluginManager.beforeRunRouteActions(handlerContext);
|
|
479
501
|
}
|
package/src/types.ts
CHANGED
|
@@ -35,6 +35,10 @@ export interface IDatabaseAccessor {
|
|
|
35
35
|
queryDatabaseObject: (sql: string, params?: unknown[] | Record<string, unknown>, client?: IDatabaseClient) => Promise<any[]>;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
export type RunActionHandlersOptions = {
|
|
39
|
+
actions: RpdRouteActionConfig[];
|
|
40
|
+
};
|
|
41
|
+
|
|
38
42
|
export interface RunEntityActionHandlerOptions {
|
|
39
43
|
/** 模型所在的命名空间 */
|
|
40
44
|
namespace: string;
|
|
@@ -359,6 +363,10 @@ export interface RpdDataModelProperty {
|
|
|
359
363
|
* 关联实体的singular code,不管 relation 为 one 或者 many 都需要设置。
|
|
360
364
|
*/
|
|
361
365
|
targetSingularCode?: string;
|
|
366
|
+
/**
|
|
367
|
+
* 保存关联实体类型的字段名。当设置 targetTypeColumnName 时,表示关联实体类型不固定,可以关联不同类型的实体。
|
|
368
|
+
*/
|
|
369
|
+
targetTypeColumnName?: string;
|
|
362
370
|
/**
|
|
363
371
|
* 当 relation 为 one 时,设置当前模型表中表示关联实体 id 的列名。
|
|
364
372
|
* 当 relation 为 many,并且使用关联关系表保存关联信息时,设置关联关系表中表示关联实体 id 的列名。
|