@ruiapp/rapid-core 0.11.6 → 0.11.8
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/pluginManager.d.ts +2 -0
- package/dist/core/server.d.ts +3 -0
- package/dist/dataAccess/entityManager.d.ts +3 -3
- package/dist/index.js +96 -18
- package/dist/server.d.ts +1 -0
- package/dist/types.d.ts +2 -0
- package/package.json +1 -1
- package/src/core/pluginManager.ts +9 -0
- package/src/core/routesBuilder.ts +11 -4
- package/src/core/server.ts +3 -0
- package/src/dataAccess/entityManager.ts +60 -10
- package/src/plugins/dataManage/actionHandlers/addEntityRelations.ts +2 -2
- package/src/plugins/dataManage/actionHandlers/deleteCollectionEntities.ts +4 -2
- package/src/plugins/dataManage/actionHandlers/deleteCollectionEntityById.ts +2 -2
- package/src/plugins/dataManage/actionHandlers/removeEntityRelations.ts +2 -2
- package/src/server.ts +13 -2
- package/src/types.ts +2 -0
|
@@ -40,6 +40,8 @@ declare class PluginManager {
|
|
|
40
40
|
beforeRunRouteActions(handlerContext: ActionHandlerContext): Promise<void>;
|
|
41
41
|
/** 在执行 action hanlder 前调用。 */
|
|
42
42
|
beforeRunActionHandler(handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig): Promise<void>;
|
|
43
|
+
/** 在执行 action handler 后调用。 */
|
|
44
|
+
afterRunActionHandler(handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig, error?: Error): Promise<void>;
|
|
43
45
|
/** 在创建实体前调用。 */
|
|
44
46
|
beforeCreateEntity(model: RpdDataModel, options: CreateEntityOptions): Promise<void>;
|
|
45
47
|
/** 在更新实体前调用。 */
|
package/dist/core/server.d.ts
CHANGED
|
@@ -34,6 +34,7 @@ export interface IRpdServer {
|
|
|
34
34
|
runActionHandlers(handlerContext: ActionHandlerContext, actions: RpdRouteActionConfig[]): Promise<void>;
|
|
35
35
|
beforeRunRouteActions(handlerContext: ActionHandlerContext): Promise<void>;
|
|
36
36
|
beforeRunActionHandler(handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig): Promise<void>;
|
|
37
|
+
afterRunActionHandler(handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig, error?: Error): Promise<void>;
|
|
37
38
|
beforeCreateEntity(model: RpdDataModel, options: CreateEntityOptions): Promise<void>;
|
|
38
39
|
beforeUpdateEntity(model: RpdDataModel, options: UpdateEntityByIdOptions, currentEntity: any): Promise<void>;
|
|
39
40
|
registerCronJob(job: CronJobConfiguration): void;
|
|
@@ -112,6 +113,8 @@ export interface RapidPlugin {
|
|
|
112
113
|
beforeRunRouteActions?: (server: IRpdServer, handlerContext: ActionHandlerContext) => Promise<any>;
|
|
113
114
|
/** 在执行 action hanlder 前调用。 */
|
|
114
115
|
beforeRunActionHandler?: (server: IRpdServer, handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig) => Promise<any>;
|
|
116
|
+
/** 在执行 action handler 后调用。 */
|
|
117
|
+
afterRunActionHandler?: (server: IRpdServer, handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig, error?: Error) => Promise<any>;
|
|
115
118
|
/** 在创建实体前调用。 */
|
|
116
119
|
beforeCreateEntity?: (server: IRpdServer, model: RpdDataModel, options: CreateEntityOptions) => Promise<any>;
|
|
117
120
|
/** 在更新实体前调用。 */
|
|
@@ -33,7 +33,7 @@ export default class EntityManager<TEntity = any> {
|
|
|
33
33
|
createEntity(options: CreateEntityOptions, plugin?: RapidPlugin): Promise<TEntity>;
|
|
34
34
|
updateEntityById(options: UpdateEntityByIdOptions, plugin?: RapidPlugin): Promise<TEntity>;
|
|
35
35
|
count(options: CountEntityOptions): Promise<number>;
|
|
36
|
-
deleteById(options: DeleteEntityByIdOptions | string | number, plugin?: RapidPlugin): Promise<
|
|
37
|
-
addRelations(options: AddEntityRelationsOptions, plugin?: RapidPlugin): Promise<
|
|
38
|
-
removeRelations(options: RemoveEntityRelationsOptions, plugin?: RapidPlugin): Promise<
|
|
36
|
+
deleteById(options: DeleteEntityByIdOptions | string | number, plugin?: RapidPlugin): Promise<TEntity>;
|
|
37
|
+
addRelations(options: AddEntityRelationsOptions, plugin?: RapidPlugin): Promise<any>;
|
|
38
|
+
removeRelations(options: RemoveEntityRelationsOptions, plugin?: RapidPlugin): Promise<any>;
|
|
39
39
|
}
|
package/dist/index.js
CHANGED
|
@@ -936,6 +936,14 @@ class PluginManager {
|
|
|
936
936
|
}
|
|
937
937
|
}
|
|
938
938
|
}
|
|
939
|
+
/** 在执行 action handler 后调用。 */
|
|
940
|
+
async afterRunActionHandler(handlerContext, actionConfig, error) {
|
|
941
|
+
for (const plugin of this.#plugins) {
|
|
942
|
+
if (plugin.afterRunActionHandler) {
|
|
943
|
+
await plugin.afterRunActionHandler(this.#server, handlerContext, actionConfig, error);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
}
|
|
939
947
|
/** 在创建实体前调用。 */
|
|
940
948
|
async beforeCreateEntity(model, options) {
|
|
941
949
|
for (const plugin of this.#plugins) {
|
|
@@ -1044,9 +1052,19 @@ async function executeHandlerOfActions(server, routeConfig, handlerContext) {
|
|
|
1044
1052
|
throw new Error("Unknown handler: " + actionCode);
|
|
1045
1053
|
}
|
|
1046
1054
|
await server.beforeRunActionHandler(handlerContext, actionConfig);
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1055
|
+
let err;
|
|
1056
|
+
try {
|
|
1057
|
+
const result = handler(handlerContext, actionConfig.config);
|
|
1058
|
+
if (result instanceof Promise) {
|
|
1059
|
+
await result;
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
catch (error) {
|
|
1063
|
+
err = error;
|
|
1064
|
+
throw error;
|
|
1065
|
+
}
|
|
1066
|
+
finally {
|
|
1067
|
+
await server.afterRunActionHandler(handlerContext, actionConfig, err);
|
|
1050
1068
|
}
|
|
1051
1069
|
}
|
|
1052
1070
|
}
|
|
@@ -2957,6 +2975,17 @@ async function findEntities(server, dataAccessor, options) {
|
|
|
2957
2975
|
else {
|
|
2958
2976
|
propertiesToSelect = getEntityPropertiesIncludingBase(server, model).filter((property) => options.properties.includes(property.code) || relationPropertyCodes.includes(property.code));
|
|
2959
2977
|
}
|
|
2978
|
+
const isEntitySoftDeleteEnabled = baseModel ? baseModel.softDelete || model.softDelete : model.softDelete;
|
|
2979
|
+
if (options.includingSoftDeleted && isEntitySoftDeleteEnabled) {
|
|
2980
|
+
const deletedAtProp = getEntityPropertyByCode(server, model, "deletedAt");
|
|
2981
|
+
if (deletedAtProp && !lodash.find(propertiesToSelect, (p) => p.code === "deletedAt")) {
|
|
2982
|
+
propertiesToSelect.push(deletedAtProp);
|
|
2983
|
+
}
|
|
2984
|
+
const deletedByProp = getEntityPropertyByCode(server, model, "deletedBy");
|
|
2985
|
+
if (deletedByProp && !lodash.find(propertiesToSelect, (p) => p.code === "deletedBy")) {
|
|
2986
|
+
propertiesToSelect.push(deletedByProp);
|
|
2987
|
+
}
|
|
2988
|
+
}
|
|
2960
2989
|
const columnsToSelect = [];
|
|
2961
2990
|
const relationPropertiesToSelect = [];
|
|
2962
2991
|
lodash.forEach(propertiesToSelect, (property) => {
|
|
@@ -3174,7 +3203,7 @@ const UNDELETED_ENTITY_FILTER_OPTIONS = {
|
|
|
3174
3203
|
field: "deletedAt",
|
|
3175
3204
|
};
|
|
3176
3205
|
function tryAddUndeletedEntityFilter(model, baseModel, filters) {
|
|
3177
|
-
let isEntitySoftDeleteEnabled = baseModel ?
|
|
3206
|
+
let isEntitySoftDeleteEnabled = baseModel ? baseModel.softDelete || model.softDelete : model.softDelete;
|
|
3178
3207
|
if (!isEntitySoftDeleteEnabled) {
|
|
3179
3208
|
return filters;
|
|
3180
3209
|
}
|
|
@@ -3426,6 +3455,7 @@ async function findManyRelationLinksViaLinkTable(options) {
|
|
|
3426
3455
|
},
|
|
3427
3456
|
],
|
|
3428
3457
|
keepNonPropertyFields: true,
|
|
3458
|
+
includingSoftDeleted: true,
|
|
3429
3459
|
};
|
|
3430
3460
|
if (selectRelationOptions) {
|
|
3431
3461
|
if (typeof selectRelationOptions !== "boolean") {
|
|
@@ -3479,6 +3509,7 @@ async function findManyRelatedEntitiesViaIdPropertyCode(options) {
|
|
|
3479
3509
|
],
|
|
3480
3510
|
extraColumnsToSelect: [relationProperty.selfIdColumnName],
|
|
3481
3511
|
keepNonPropertyFields: true,
|
|
3512
|
+
includingSoftDeleted: true,
|
|
3482
3513
|
};
|
|
3483
3514
|
if (selectRelationOptions) {
|
|
3484
3515
|
if (typeof selectRelationOptions !== "boolean") {
|
|
@@ -3522,6 +3553,7 @@ async function findOneRelatedEntitiesViaIdPropertyCode(options) {
|
|
|
3522
3553
|
},
|
|
3523
3554
|
],
|
|
3524
3555
|
keepNonPropertyFields: true,
|
|
3556
|
+
includingSoftDeleted: true,
|
|
3525
3557
|
};
|
|
3526
3558
|
if (selectRelationOptions) {
|
|
3527
3559
|
if (typeof selectRelationOptions !== "boolean") {
|
|
@@ -4298,7 +4330,7 @@ async function deleteEntityById(server, dataAccessor, options, plugin) {
|
|
|
4298
4330
|
if (!entity) {
|
|
4299
4331
|
return;
|
|
4300
4332
|
}
|
|
4301
|
-
const isEntitySoftDeleteEnabled = model.base ?
|
|
4333
|
+
const isEntitySoftDeleteEnabled = model.base ? baseModel.softDelete || model.softDelete : model.softDelete;
|
|
4302
4334
|
if (isEntitySoftDeleteEnabled) {
|
|
4303
4335
|
if (entity.deletedAt) {
|
|
4304
4336
|
return;
|
|
@@ -4423,6 +4455,7 @@ async function deleteEntityById(server, dataAccessor, options, plugin) {
|
|
|
4423
4455
|
sender: plugin,
|
|
4424
4456
|
routeContext,
|
|
4425
4457
|
});
|
|
4458
|
+
return entity;
|
|
4426
4459
|
}
|
|
4427
4460
|
class EntityManager {
|
|
4428
4461
|
#server;
|
|
@@ -4491,6 +4524,8 @@ class EntityManager {
|
|
|
4491
4524
|
throw new Error(`Operation 'addRelations' is only supported on property of 'many' relation`);
|
|
4492
4525
|
}
|
|
4493
4526
|
const { queryBuilder } = server;
|
|
4527
|
+
const targetEntityManager = server.getEntityManager(relationProperty.targetSingularCode);
|
|
4528
|
+
const relationTargetEntities = [];
|
|
4494
4529
|
if (relationProperty.linkTableName) {
|
|
4495
4530
|
for (const relation of relations) {
|
|
4496
4531
|
const command = `INSERT INTO ${queryBuilder.quoteTable({
|
|
@@ -4504,17 +4539,24 @@ class EntityManager {
|
|
|
4504
4539
|
)`;
|
|
4505
4540
|
const targetId = relation[relationProperty.targetIdColumnName] || relation.id;
|
|
4506
4541
|
const params = [selfId, targetId];
|
|
4507
|
-
await server.queryDatabaseObject(command, params, routeContext?.getDbTransactionClient());
|
|
4542
|
+
const result = await server.queryDatabaseObject(command, params, routeContext?.getDbTransactionClient());
|
|
4543
|
+
if (result?.length > 0) {
|
|
4544
|
+
const targetEntity = await targetEntityManager.findById({
|
|
4545
|
+
routeContext,
|
|
4546
|
+
id: targetId,
|
|
4547
|
+
});
|
|
4548
|
+
relationTargetEntities.push(targetEntity);
|
|
4549
|
+
}
|
|
4508
4550
|
}
|
|
4509
4551
|
}
|
|
4510
4552
|
else {
|
|
4511
|
-
const targetEntityManager = server.getEntityManager(relationProperty.targetSingularCode);
|
|
4512
4553
|
for (const relation of relations) {
|
|
4513
4554
|
relation[relationProperty.selfIdColumnName] = selfId;
|
|
4514
|
-
await targetEntityManager.createEntity({
|
|
4555
|
+
const targetEntity = await targetEntityManager.createEntity({
|
|
4515
4556
|
routeContext,
|
|
4516
4557
|
entity: relation,
|
|
4517
4558
|
});
|
|
4559
|
+
relationTargetEntities.push(targetEntity);
|
|
4518
4560
|
}
|
|
4519
4561
|
}
|
|
4520
4562
|
await server.emitEvent({
|
|
@@ -4525,10 +4567,17 @@ class EntityManager {
|
|
|
4525
4567
|
entity,
|
|
4526
4568
|
property,
|
|
4527
4569
|
relations,
|
|
4570
|
+
relationTargetEntities,
|
|
4528
4571
|
},
|
|
4529
4572
|
sender: plugin,
|
|
4530
4573
|
routeContext: options.routeContext,
|
|
4531
4574
|
});
|
|
4575
|
+
return {
|
|
4576
|
+
entity,
|
|
4577
|
+
property,
|
|
4578
|
+
relations,
|
|
4579
|
+
relationTargetEntities,
|
|
4580
|
+
};
|
|
4532
4581
|
}
|
|
4533
4582
|
async removeRelations(options, plugin) {
|
|
4534
4583
|
const server = this.#server;
|
|
@@ -4549,12 +4598,21 @@ class EntityManager {
|
|
|
4549
4598
|
throw new Error(`Operation 'removeRelations' is only supported on property of 'many' relation`);
|
|
4550
4599
|
}
|
|
4551
4600
|
const { queryBuilder } = server;
|
|
4601
|
+
const targetEntityManager = server.getEntityManager(relationProperty.targetSingularCode);
|
|
4602
|
+
const relationTargetEntities = [];
|
|
4552
4603
|
if (relationProperty.linkTableName) {
|
|
4553
4604
|
for (const relation of relations) {
|
|
4554
4605
|
const command = `DELETE FROM ${queryBuilder.quoteTable({ schema: relationProperty.linkSchema, tableName: relationProperty.linkTableName })}
|
|
4555
4606
|
WHERE ${queryBuilder.quoteObject(relationProperty.selfIdColumnName)}=$1 AND ${queryBuilder.quoteObject(relationProperty.targetIdColumnName)}=$2;`;
|
|
4556
4607
|
const params = [id, relation.id];
|
|
4557
|
-
await server.queryDatabaseObject(command, params, routeContext?.getDbTransactionClient());
|
|
4608
|
+
const result = await server.queryDatabaseObject(command, params, routeContext?.getDbTransactionClient());
|
|
4609
|
+
if (result?.length > 0) {
|
|
4610
|
+
const targetEntity = await targetEntityManager.findById({
|
|
4611
|
+
routeContext,
|
|
4612
|
+
id: relation.id,
|
|
4613
|
+
});
|
|
4614
|
+
relationTargetEntities.push(targetEntity);
|
|
4615
|
+
}
|
|
4558
4616
|
}
|
|
4559
4617
|
}
|
|
4560
4618
|
await server.emitEvent({
|
|
@@ -4565,10 +4623,17 @@ class EntityManager {
|
|
|
4565
4623
|
entity,
|
|
4566
4624
|
property,
|
|
4567
4625
|
relations,
|
|
4626
|
+
relationTargetEntities,
|
|
4568
4627
|
},
|
|
4569
4628
|
sender: plugin,
|
|
4570
4629
|
routeContext: options.routeContext,
|
|
4571
4630
|
});
|
|
4631
|
+
return {
|
|
4632
|
+
entity,
|
|
4633
|
+
property,
|
|
4634
|
+
relations,
|
|
4635
|
+
relationTargetEntities,
|
|
4636
|
+
};
|
|
4572
4637
|
}
|
|
4573
4638
|
}
|
|
4574
4639
|
|
|
@@ -5017,7 +5082,15 @@ class RapidServer {
|
|
|
5017
5082
|
throw new Error("Unknown handler: " + actionCode);
|
|
5018
5083
|
}
|
|
5019
5084
|
await this.beforeRunActionHandler(handlerContext, action);
|
|
5020
|
-
|
|
5085
|
+
try {
|
|
5086
|
+
await handler(handlerContext, action.config);
|
|
5087
|
+
}
|
|
5088
|
+
catch (error) {
|
|
5089
|
+
throw error;
|
|
5090
|
+
}
|
|
5091
|
+
finally {
|
|
5092
|
+
await this.afterRunActionHandler(handlerContext, action);
|
|
5093
|
+
}
|
|
5021
5094
|
}
|
|
5022
5095
|
}
|
|
5023
5096
|
async beforeRunRouteActions(handlerContext) {
|
|
@@ -5026,6 +5099,9 @@ class RapidServer {
|
|
|
5026
5099
|
async beforeRunActionHandler(handlerContext, actionConfig) {
|
|
5027
5100
|
await this.#pluginManager.beforeRunActionHandler(handlerContext, actionConfig);
|
|
5028
5101
|
}
|
|
5102
|
+
async afterRunActionHandler(handlerContext, actionConfig, error) {
|
|
5103
|
+
await this.#pluginManager.afterRunActionHandler(handlerContext, actionConfig, error);
|
|
5104
|
+
}
|
|
5029
5105
|
async beforeCreateEntity(model, options) {
|
|
5030
5106
|
await this.#pluginManager.beforeCreateEntity(model, options);
|
|
5031
5107
|
}
|
|
@@ -6449,13 +6525,15 @@ async function handler$o(plugin, ctx, options) {
|
|
|
6449
6525
|
routeContext: routeContext,
|
|
6450
6526
|
filters,
|
|
6451
6527
|
});
|
|
6528
|
+
const outputs = [];
|
|
6452
6529
|
for (const entity of entities) {
|
|
6453
|
-
await entityManager.deleteById({
|
|
6530
|
+
const output = await entityManager.deleteById({
|
|
6454
6531
|
routeContext,
|
|
6455
6532
|
id: entity.id,
|
|
6456
6533
|
}, plugin);
|
|
6534
|
+
outputs.push(output);
|
|
6457
6535
|
}
|
|
6458
|
-
return
|
|
6536
|
+
return outputs;
|
|
6459
6537
|
});
|
|
6460
6538
|
}
|
|
6461
6539
|
|
|
@@ -6469,11 +6547,11 @@ const code$n = "deleteCollectionEntityById";
|
|
|
6469
6547
|
async function handler$n(plugin, ctx, options) {
|
|
6470
6548
|
await runCollectionEntityActionHandler(ctx, options, code$n, true, true, async (entityManager, input) => {
|
|
6471
6549
|
const { routerContext: routeContext } = ctx;
|
|
6472
|
-
await entityManager.deleteById({
|
|
6550
|
+
const output = await entityManager.deleteById({
|
|
6473
6551
|
id: input.id,
|
|
6474
6552
|
routeContext,
|
|
6475
6553
|
}, plugin);
|
|
6476
|
-
return
|
|
6554
|
+
return output;
|
|
6477
6555
|
});
|
|
6478
6556
|
}
|
|
6479
6557
|
|
|
@@ -6488,8 +6566,8 @@ async function handler$m(plugin, ctx, options) {
|
|
|
6488
6566
|
await runCollectionEntityActionHandler(ctx, options, code$m, true, true, async (entityManager, input) => {
|
|
6489
6567
|
const { routerContext: routeContext } = ctx;
|
|
6490
6568
|
input.routeContext = routeContext;
|
|
6491
|
-
await entityManager.addRelations(input, plugin);
|
|
6492
|
-
return
|
|
6569
|
+
const result = await entityManager.addRelations(input, plugin);
|
|
6570
|
+
return result;
|
|
6493
6571
|
});
|
|
6494
6572
|
}
|
|
6495
6573
|
|
|
@@ -6504,8 +6582,8 @@ async function handler$l(plugin, ctx, options) {
|
|
|
6504
6582
|
await runCollectionEntityActionHandler(ctx, options, code$l, true, true, async (entityManager, input) => {
|
|
6505
6583
|
const { routerContext: routeContext } = ctx;
|
|
6506
6584
|
input.routeContext = routeContext;
|
|
6507
|
-
await entityManager.removeRelations(input, plugin);
|
|
6508
|
-
return
|
|
6585
|
+
const result = await entityManager.removeRelations(input, plugin);
|
|
6586
|
+
return result;
|
|
6509
6587
|
});
|
|
6510
6588
|
}
|
|
6511
6589
|
|
package/dist/server.d.ts
CHANGED
|
@@ -60,6 +60,7 @@ export declare class RapidServer implements IRpdServer {
|
|
|
60
60
|
runActionHandlers(handlerContext: ActionHandlerContext, actions: RpdRouteActionConfig[]): Promise<void>;
|
|
61
61
|
beforeRunRouteActions(handlerContext: ActionHandlerContext): Promise<void>;
|
|
62
62
|
beforeRunActionHandler(handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig): Promise<void>;
|
|
63
|
+
afterRunActionHandler(handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig, error?: Error): Promise<void>;
|
|
63
64
|
beforeCreateEntity(model: RpdDataModel, options: CreateEntityOptions): Promise<void>;
|
|
64
65
|
beforeUpdateEntity(model: RpdDataModel, options: UpdateEntityByIdOptions, currentEntity: any): Promise<void>;
|
|
65
66
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -147,6 +147,7 @@ export interface RpdEntityAddRelationsEventPayload {
|
|
|
147
147
|
entity: any;
|
|
148
148
|
property: string;
|
|
149
149
|
relations: any[];
|
|
150
|
+
relationTargetEntities: any[];
|
|
150
151
|
}
|
|
151
152
|
export interface RpdEntityRemoveRelationsEventPayload {
|
|
152
153
|
namespace: string;
|
|
@@ -155,6 +156,7 @@ export interface RpdEntityRemoveRelationsEventPayload {
|
|
|
155
156
|
entity: any;
|
|
156
157
|
property: string;
|
|
157
158
|
relations: any[];
|
|
159
|
+
relationTargetEntities: any[];
|
|
158
160
|
}
|
|
159
161
|
export interface RpdEntityBeforeResponseEventPayload {
|
|
160
162
|
namespace: string;
|
package/package.json
CHANGED
|
@@ -171,6 +171,15 @@ class PluginManager {
|
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
+
/** 在执行 action handler 后调用。 */
|
|
175
|
+
async afterRunActionHandler(handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig, error?: Error) {
|
|
176
|
+
for (const plugin of this.#plugins) {
|
|
177
|
+
if (plugin.afterRunActionHandler) {
|
|
178
|
+
await plugin.afterRunActionHandler(this.#server, handlerContext, actionConfig, error);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
174
183
|
/** 在创建实体前调用。 */
|
|
175
184
|
async beforeCreateEntity(model: RpdDataModel, options: CreateEntityOptions) {
|
|
176
185
|
for (const plugin of this.#plugins) {
|
|
@@ -32,10 +32,17 @@ async function executeHandlerOfActions(server: IRpdServer, routeConfig: RpdRoute
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
await server.beforeRunActionHandler(handlerContext, actionConfig);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
let err: any;
|
|
36
|
+
try {
|
|
37
|
+
const result = handler(handlerContext, actionConfig.config);
|
|
38
|
+
if (result instanceof Promise) {
|
|
39
|
+
await result;
|
|
40
|
+
}
|
|
41
|
+
} catch (error) {
|
|
42
|
+
err = error;
|
|
43
|
+
throw error;
|
|
44
|
+
} finally {
|
|
45
|
+
await server.afterRunActionHandler(handlerContext, actionConfig, err);
|
|
39
46
|
}
|
|
40
47
|
}
|
|
41
48
|
}
|
package/src/core/server.ts
CHANGED
|
@@ -57,6 +57,7 @@ export interface IRpdServer {
|
|
|
57
57
|
runActionHandlers(handlerContext: ActionHandlerContext, actions: RpdRouteActionConfig[]): Promise<void>;
|
|
58
58
|
beforeRunRouteActions(handlerContext: ActionHandlerContext): Promise<void>;
|
|
59
59
|
beforeRunActionHandler(handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig): Promise<void>;
|
|
60
|
+
afterRunActionHandler(handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig, error?: Error): Promise<void>;
|
|
60
61
|
beforeCreateEntity(model: RpdDataModel, options: CreateEntityOptions): Promise<void>;
|
|
61
62
|
beforeUpdateEntity(model: RpdDataModel, options: UpdateEntityByIdOptions, currentEntity: any): Promise<void>;
|
|
62
63
|
|
|
@@ -151,6 +152,8 @@ export interface RapidPlugin {
|
|
|
151
152
|
beforeRunRouteActions?: (server: IRpdServer, handlerContext: ActionHandlerContext) => Promise<any>;
|
|
152
153
|
/** 在执行 action hanlder 前调用。 */
|
|
153
154
|
beforeRunActionHandler?: (server: IRpdServer, handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig) => Promise<any>;
|
|
155
|
+
/** 在执行 action handler 后调用。 */
|
|
156
|
+
afterRunActionHandler?: (server: IRpdServer, handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig, error?: Error) => Promise<any>;
|
|
154
157
|
/** 在创建实体前调用。 */
|
|
155
158
|
beforeCreateEntity?: (server: IRpdServer, model: RpdDataModel, options: CreateEntityOptions) => Promise<any>;
|
|
156
159
|
/** 在更新实体前调用。 */
|
|
@@ -170,6 +170,18 @@ async function findEntities(server: IRpdServer, dataAccessor: IRpdDataAccessor,
|
|
|
170
170
|
);
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
+
const isEntitySoftDeleteEnabled = baseModel ? baseModel.softDelete || model.softDelete : model.softDelete;
|
|
174
|
+
if (options.includingSoftDeleted && isEntitySoftDeleteEnabled) {
|
|
175
|
+
const deletedAtProp = getEntityPropertyByCode(server, model, "deletedAt");
|
|
176
|
+
if (deletedAtProp && !find(propertiesToSelect, (p) => p.code === "deletedAt")) {
|
|
177
|
+
propertiesToSelect.push(deletedAtProp);
|
|
178
|
+
}
|
|
179
|
+
const deletedByProp = getEntityPropertyByCode(server, model, "deletedBy");
|
|
180
|
+
if (deletedByProp && !find(propertiesToSelect, (p) => p.code === "deletedBy")) {
|
|
181
|
+
propertiesToSelect.push(deletedByProp);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
173
185
|
const columnsToSelect: ColumnSelectOptions[] = [];
|
|
174
186
|
|
|
175
187
|
const relationPropertiesToSelect: RpdDataModelProperty[] = [];
|
|
@@ -401,7 +413,7 @@ const UNDELETED_ENTITY_FILTER_OPTIONS: EntityFilterOptions = {
|
|
|
401
413
|
};
|
|
402
414
|
|
|
403
415
|
function tryAddUndeletedEntityFilter(model: RpdDataModel, baseModel: RpdDataModel, filters: EntityFilterOptions[] | undefined) {
|
|
404
|
-
let isEntitySoftDeleteEnabled = baseModel ?
|
|
416
|
+
let isEntitySoftDeleteEnabled = baseModel ? baseModel.softDelete || model.softDelete : model.softDelete;
|
|
405
417
|
if (!isEntitySoftDeleteEnabled) {
|
|
406
418
|
return filters;
|
|
407
419
|
}
|
|
@@ -678,6 +690,7 @@ async function findManyRelationLinksViaLinkTable(options: FindManyRelationEntiti
|
|
|
678
690
|
},
|
|
679
691
|
],
|
|
680
692
|
keepNonPropertyFields: true,
|
|
693
|
+
includingSoftDeleted: true,
|
|
681
694
|
};
|
|
682
695
|
|
|
683
696
|
if (selectRelationOptions) {
|
|
@@ -737,6 +750,7 @@ async function findManyRelatedEntitiesViaIdPropertyCode(options: FindManyRelatio
|
|
|
737
750
|
],
|
|
738
751
|
extraColumnsToSelect: [relationProperty.selfIdColumnName],
|
|
739
752
|
keepNonPropertyFields: true,
|
|
753
|
+
includingSoftDeleted: true,
|
|
740
754
|
};
|
|
741
755
|
|
|
742
756
|
if (selectRelationOptions) {
|
|
@@ -785,6 +799,7 @@ async function findOneRelatedEntitiesViaIdPropertyCode(options: FindOneRelationE
|
|
|
785
799
|
},
|
|
786
800
|
],
|
|
787
801
|
keepNonPropertyFields: true,
|
|
802
|
+
includingSoftDeleted: true,
|
|
788
803
|
};
|
|
789
804
|
|
|
790
805
|
if (selectRelationOptions) {
|
|
@@ -1630,7 +1645,7 @@ async function deleteEntityById(
|
|
|
1630
1645
|
dataAccessor: IRpdDataAccessor,
|
|
1631
1646
|
options: DeleteEntityByIdOptions | string | number,
|
|
1632
1647
|
plugin?: RapidPlugin,
|
|
1633
|
-
): Promise<
|
|
1648
|
+
): Promise<any> {
|
|
1634
1649
|
// options is id
|
|
1635
1650
|
if (!isObject(options)) {
|
|
1636
1651
|
options = {
|
|
@@ -1662,7 +1677,7 @@ async function deleteEntityById(
|
|
|
1662
1677
|
return;
|
|
1663
1678
|
}
|
|
1664
1679
|
|
|
1665
|
-
const isEntitySoftDeleteEnabled = model.base ?
|
|
1680
|
+
const isEntitySoftDeleteEnabled = model.base ? baseModel.softDelete || model.softDelete : model.softDelete;
|
|
1666
1681
|
if (isEntitySoftDeleteEnabled) {
|
|
1667
1682
|
if (entity.deletedAt) {
|
|
1668
1683
|
return;
|
|
@@ -1826,6 +1841,7 @@ async function deleteEntityById(
|
|
|
1826
1841
|
sender: plugin,
|
|
1827
1842
|
routeContext,
|
|
1828
1843
|
});
|
|
1844
|
+
return entity;
|
|
1829
1845
|
}
|
|
1830
1846
|
|
|
1831
1847
|
export default class EntityManager<TEntity = any> {
|
|
@@ -1882,11 +1898,11 @@ export default class EntityManager<TEntity = any> {
|
|
|
1882
1898
|
return await this.#dataAccessor.count(countRowOptions, routeContext?.getDbTransactionClient());
|
|
1883
1899
|
}
|
|
1884
1900
|
|
|
1885
|
-
async deleteById(options: DeleteEntityByIdOptions | string | number, plugin?: RapidPlugin): Promise<
|
|
1901
|
+
async deleteById(options: DeleteEntityByIdOptions | string | number, plugin?: RapidPlugin): Promise<TEntity> {
|
|
1886
1902
|
return await deleteEntityById(this.#server, this.#dataAccessor, options, plugin);
|
|
1887
1903
|
}
|
|
1888
1904
|
|
|
1889
|
-
async addRelations(options: AddEntityRelationsOptions, plugin?: RapidPlugin): Promise<
|
|
1905
|
+
async addRelations(options: AddEntityRelationsOptions, plugin?: RapidPlugin): Promise<any> {
|
|
1890
1906
|
const server = this.#server;
|
|
1891
1907
|
const model = this.getModel();
|
|
1892
1908
|
const { id: selfId, property, relations, routeContext } = options;
|
|
@@ -1908,6 +1924,8 @@ export default class EntityManager<TEntity = any> {
|
|
|
1908
1924
|
}
|
|
1909
1925
|
|
|
1910
1926
|
const { queryBuilder } = server;
|
|
1927
|
+
const targetEntityManager = server.getEntityManager(relationProperty.targetSingularCode);
|
|
1928
|
+
const relationTargetEntities = [];
|
|
1911
1929
|
if (relationProperty.linkTableName) {
|
|
1912
1930
|
for (const relation of relations) {
|
|
1913
1931
|
const command = `INSERT INTO ${queryBuilder.quoteTable({
|
|
@@ -1922,16 +1940,23 @@ export default class EntityManager<TEntity = any> {
|
|
|
1922
1940
|
|
|
1923
1941
|
const targetId = relation[relationProperty.targetIdColumnName!] || relation.id;
|
|
1924
1942
|
const params = [selfId, targetId];
|
|
1925
|
-
await server.queryDatabaseObject(command, params, routeContext?.getDbTransactionClient());
|
|
1943
|
+
const result = await server.queryDatabaseObject(command, params, routeContext?.getDbTransactionClient());
|
|
1944
|
+
if (result?.length > 0) {
|
|
1945
|
+
const targetEntity = await targetEntityManager.findById({
|
|
1946
|
+
routeContext,
|
|
1947
|
+
id: targetId,
|
|
1948
|
+
});
|
|
1949
|
+
relationTargetEntities.push(targetEntity);
|
|
1950
|
+
}
|
|
1926
1951
|
}
|
|
1927
1952
|
} else {
|
|
1928
|
-
const targetEntityManager = server.getEntityManager(relationProperty.targetSingularCode);
|
|
1929
1953
|
for (const relation of relations) {
|
|
1930
1954
|
relation[relationProperty.selfIdColumnName!] = selfId;
|
|
1931
|
-
await targetEntityManager.createEntity({
|
|
1955
|
+
const targetEntity = await targetEntityManager.createEntity({
|
|
1932
1956
|
routeContext,
|
|
1933
1957
|
entity: relation,
|
|
1934
1958
|
});
|
|
1959
|
+
relationTargetEntities.push(targetEntity);
|
|
1935
1960
|
}
|
|
1936
1961
|
}
|
|
1937
1962
|
|
|
@@ -1943,13 +1968,21 @@ export default class EntityManager<TEntity = any> {
|
|
|
1943
1968
|
entity,
|
|
1944
1969
|
property,
|
|
1945
1970
|
relations,
|
|
1971
|
+
relationTargetEntities,
|
|
1946
1972
|
},
|
|
1947
1973
|
sender: plugin,
|
|
1948
1974
|
routeContext: options.routeContext,
|
|
1949
1975
|
});
|
|
1976
|
+
|
|
1977
|
+
return {
|
|
1978
|
+
entity,
|
|
1979
|
+
property,
|
|
1980
|
+
relations,
|
|
1981
|
+
relationTargetEntities,
|
|
1982
|
+
};
|
|
1950
1983
|
}
|
|
1951
1984
|
|
|
1952
|
-
async removeRelations(options: RemoveEntityRelationsOptions, plugin?: RapidPlugin): Promise<
|
|
1985
|
+
async removeRelations(options: RemoveEntityRelationsOptions, plugin?: RapidPlugin): Promise<any> {
|
|
1953
1986
|
const server = this.#server;
|
|
1954
1987
|
const model = this.getModel();
|
|
1955
1988
|
const { id, property, relations, routeContext } = options;
|
|
@@ -1971,12 +2004,21 @@ export default class EntityManager<TEntity = any> {
|
|
|
1971
2004
|
}
|
|
1972
2005
|
|
|
1973
2006
|
const { queryBuilder } = server;
|
|
2007
|
+
const targetEntityManager = server.getEntityManager(relationProperty.targetSingularCode);
|
|
2008
|
+
const relationTargetEntities = [];
|
|
1974
2009
|
if (relationProperty.linkTableName) {
|
|
1975
2010
|
for (const relation of relations) {
|
|
1976
2011
|
const command = `DELETE FROM ${queryBuilder.quoteTable({ schema: relationProperty.linkSchema, tableName: relationProperty.linkTableName })}
|
|
1977
2012
|
WHERE ${queryBuilder.quoteObject(relationProperty.selfIdColumnName!)}=$1 AND ${queryBuilder.quoteObject(relationProperty.targetIdColumnName!)}=$2;`;
|
|
1978
2013
|
const params = [id, relation.id];
|
|
1979
|
-
await server.queryDatabaseObject(command, params, routeContext?.getDbTransactionClient());
|
|
2014
|
+
const result = await server.queryDatabaseObject(command, params, routeContext?.getDbTransactionClient());
|
|
2015
|
+
if (result?.length > 0) {
|
|
2016
|
+
const targetEntity = await targetEntityManager.findById({
|
|
2017
|
+
routeContext,
|
|
2018
|
+
id: relation.id,
|
|
2019
|
+
});
|
|
2020
|
+
relationTargetEntities.push(targetEntity);
|
|
2021
|
+
}
|
|
1980
2022
|
}
|
|
1981
2023
|
}
|
|
1982
2024
|
|
|
@@ -1988,9 +2030,17 @@ export default class EntityManager<TEntity = any> {
|
|
|
1988
2030
|
entity,
|
|
1989
2031
|
property,
|
|
1990
2032
|
relations,
|
|
2033
|
+
relationTargetEntities,
|
|
1991
2034
|
},
|
|
1992
2035
|
sender: plugin,
|
|
1993
2036
|
routeContext: options.routeContext,
|
|
1994
2037
|
});
|
|
2038
|
+
|
|
2039
|
+
return {
|
|
2040
|
+
entity,
|
|
2041
|
+
property,
|
|
2042
|
+
relations,
|
|
2043
|
+
relationTargetEntities,
|
|
2044
|
+
};
|
|
1995
2045
|
}
|
|
1996
2046
|
}
|
|
@@ -9,7 +9,7 @@ export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, op
|
|
|
9
9
|
await runCollectionEntityActionHandler(ctx, options, code, true, true, async (entityManager, input: AddEntityRelationsOptions): Promise<any> => {
|
|
10
10
|
const { routerContext: routeContext } = ctx;
|
|
11
11
|
input.routeContext = routeContext;
|
|
12
|
-
await entityManager.addRelations(input, plugin);
|
|
13
|
-
return
|
|
12
|
+
const result = await entityManager.addRelations(input, plugin);
|
|
13
|
+
return result;
|
|
14
14
|
});
|
|
15
15
|
}
|
|
@@ -30,16 +30,18 @@ export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, op
|
|
|
30
30
|
routeContext: routeContext,
|
|
31
31
|
filters,
|
|
32
32
|
});
|
|
33
|
+
const outputs = [];
|
|
33
34
|
for (const entity of entities) {
|
|
34
|
-
await entityManager.deleteById(
|
|
35
|
+
const output = await entityManager.deleteById(
|
|
35
36
|
{
|
|
36
37
|
routeContext,
|
|
37
38
|
id: entity.id,
|
|
38
39
|
},
|
|
39
40
|
plugin,
|
|
40
41
|
);
|
|
42
|
+
outputs.push(output);
|
|
41
43
|
}
|
|
42
|
-
return
|
|
44
|
+
return outputs;
|
|
43
45
|
},
|
|
44
46
|
);
|
|
45
47
|
}
|
|
@@ -8,13 +8,13 @@ export const code = "deleteCollectionEntityById";
|
|
|
8
8
|
export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: RunEntityActionHandlerOptions) {
|
|
9
9
|
await runCollectionEntityActionHandler(ctx, options, code, true, true, async (entityManager, input: any): Promise<any> => {
|
|
10
10
|
const { routerContext: routeContext } = ctx;
|
|
11
|
-
await entityManager.deleteById(
|
|
11
|
+
const output = await entityManager.deleteById(
|
|
12
12
|
{
|
|
13
13
|
id: input.id,
|
|
14
14
|
routeContext,
|
|
15
15
|
},
|
|
16
16
|
plugin,
|
|
17
17
|
);
|
|
18
|
-
return
|
|
18
|
+
return output;
|
|
19
19
|
});
|
|
20
20
|
}
|
|
@@ -9,7 +9,7 @@ export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, op
|
|
|
9
9
|
await runCollectionEntityActionHandler(ctx, options, code, true, true, async (entityManager, input: any): Promise<any> => {
|
|
10
10
|
const { routerContext: routeContext } = ctx;
|
|
11
11
|
input.routeContext = routeContext;
|
|
12
|
-
await entityManager.removeRelations(input, plugin);
|
|
13
|
-
return
|
|
12
|
+
const result = await entityManager.removeRelations(input, plugin);
|
|
13
|
+
return result;
|
|
14
14
|
});
|
|
15
15
|
}
|
package/src/server.ts
CHANGED
|
@@ -494,9 +494,16 @@ export class RapidServer implements IRpdServer {
|
|
|
494
494
|
if (!handler) {
|
|
495
495
|
throw new Error("Unknown handler: " + actionCode);
|
|
496
496
|
}
|
|
497
|
-
|
|
497
|
+
let err: any;
|
|
498
498
|
await this.beforeRunActionHandler(handlerContext, action);
|
|
499
|
-
|
|
499
|
+
try {
|
|
500
|
+
await handler(handlerContext, action.config);
|
|
501
|
+
} catch (error) {
|
|
502
|
+
err = error;
|
|
503
|
+
throw error;
|
|
504
|
+
} finally {
|
|
505
|
+
await this.afterRunActionHandler(handlerContext, action);
|
|
506
|
+
}
|
|
500
507
|
}
|
|
501
508
|
}
|
|
502
509
|
|
|
@@ -508,6 +515,10 @@ export class RapidServer implements IRpdServer {
|
|
|
508
515
|
await this.#pluginManager.beforeRunActionHandler(handlerContext, actionConfig);
|
|
509
516
|
}
|
|
510
517
|
|
|
518
|
+
async afterRunActionHandler(handlerContext: ActionHandlerContext, actionConfig: RpdRouteActionConfig, error?: Error) {
|
|
519
|
+
await this.#pluginManager.afterRunActionHandler(handlerContext, actionConfig, error);
|
|
520
|
+
}
|
|
521
|
+
|
|
511
522
|
async beforeCreateEntity(model: RpdDataModel, options: CreateEntityOptions) {
|
|
512
523
|
await this.#pluginManager.beforeCreateEntity(model, options);
|
|
513
524
|
}
|
package/src/types.ts
CHANGED
|
@@ -172,6 +172,7 @@ export interface RpdEntityAddRelationsEventPayload {
|
|
|
172
172
|
entity: any;
|
|
173
173
|
property: string;
|
|
174
174
|
relations: any[];
|
|
175
|
+
relationTargetEntities: any[];
|
|
175
176
|
}
|
|
176
177
|
|
|
177
178
|
export interface RpdEntityRemoveRelationsEventPayload {
|
|
@@ -181,6 +182,7 @@ export interface RpdEntityRemoveRelationsEventPayload {
|
|
|
181
182
|
entity: any;
|
|
182
183
|
property: string;
|
|
183
184
|
relations: any[];
|
|
185
|
+
relationTargetEntities: any[];
|
|
184
186
|
}
|
|
185
187
|
|
|
186
188
|
export interface RpdEntityBeforeResponseEventPayload {
|