@ruiapp/rapid-core 0.1.53 → 0.1.55
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/server.d.ts +2 -2
- package/dist/dataAccess/entityManager.d.ts +3 -3
- package/dist/index.js +213 -85
- package/dist/server.d.ts +2 -2
- package/dist/types.d.ts +35 -9
- package/package.json +1 -1
- package/src/core/server.ts +2 -2
- package/src/dataAccess/entityManager.ts +121 -65
- package/src/plugins/dataManage/actionHandlers/addEntityRelations.ts +3 -2
- package/src/plugins/dataManage/actionHandlers/countCollectionEntities.ts +3 -2
- package/src/plugins/dataManage/actionHandlers/createCollectionEntitiesBatch.ts +1 -0
- package/src/plugins/dataManage/actionHandlers/createCollectionEntity.ts +1 -0
- package/src/plugins/dataManage/actionHandlers/deleteCollectionEntityById.ts +4 -1
- package/src/plugins/dataManage/actionHandlers/findCollectionEntities.ts +1 -0
- package/src/plugins/dataManage/actionHandlers/findCollectionEntityById.ts +4 -1
- package/src/plugins/dataManage/actionHandlers/removeEntityRelations.ts +3 -2
- package/src/plugins/dataManage/actionHandlers/updateCollectionEntityById.ts +9 -2
- package/src/plugins/metaManage/MetaManagePlugin.ts +33 -2
- package/src/server.ts +6 -4
- package/src/types.ts +38 -9
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { RouteContext } from "./core/routeContext";
|
|
1
2
|
import { IRpdServer, RapidPlugin } from "./core/server";
|
|
2
3
|
import { CountRowOptions, FindRowOptions } from "./dataAccess/dataAccessTypes";
|
|
3
4
|
export type RapidServerConfig = {
|
|
@@ -55,15 +56,15 @@ export interface GetModelOptions {
|
|
|
55
56
|
singularCode: string;
|
|
56
57
|
}
|
|
57
58
|
export type RpdServerEventTypes = {
|
|
58
|
-
"entity.beforeCreate": [RapidPlugin, RpdEntityBeforeCreateEventPayload];
|
|
59
|
-
"entity.create": [RapidPlugin, RpdEntityCreateEventPayload];
|
|
60
|
-
"entity.beforeUpdate": [RapidPlugin, RpdEntityBeforeUpdateEventPayload];
|
|
61
|
-
"entity.update": [RapidPlugin, RpdEntityUpdateEventPayload];
|
|
62
|
-
"entity.beforeDelete": [RapidPlugin, RpdEntityBeforeDeleteEventPayload];
|
|
63
|
-
"entity.delete": [RapidPlugin, RpdEntityDeleteEventPayload];
|
|
64
|
-
"entity.addRelations": [RapidPlugin, RpdEntityAddRelationsEventPayload];
|
|
65
|
-
"entity.removeRelations": [RapidPlugin, RpdEntityRemoveRelationsEventPayload];
|
|
66
|
-
"entity.beforeResponse": [RapidPlugin, RpdEntityBeforeResponseEventPayload];
|
|
59
|
+
"entity.beforeCreate": [RapidPlugin, RpdEntityBeforeCreateEventPayload, RouteContext?];
|
|
60
|
+
"entity.create": [RapidPlugin, RpdEntityCreateEventPayload, RouteContext?];
|
|
61
|
+
"entity.beforeUpdate": [RapidPlugin, RpdEntityBeforeUpdateEventPayload, RouteContext?];
|
|
62
|
+
"entity.update": [RapidPlugin, RpdEntityUpdateEventPayload, RouteContext?];
|
|
63
|
+
"entity.beforeDelete": [RapidPlugin, RpdEntityBeforeDeleteEventPayload, RouteContext?];
|
|
64
|
+
"entity.delete": [RapidPlugin, RpdEntityDeleteEventPayload, RouteContext?];
|
|
65
|
+
"entity.addRelations": [RapidPlugin, RpdEntityAddRelationsEventPayload, RouteContext?];
|
|
66
|
+
"entity.removeRelations": [RapidPlugin, RpdEntityRemoveRelationsEventPayload, RouteContext?];
|
|
67
|
+
"entity.beforeResponse": [RapidPlugin, RpdEntityBeforeResponseEventPayload, RouteContext?];
|
|
67
68
|
};
|
|
68
69
|
export interface RpdEntityBeforeCreateEventPayload {
|
|
69
70
|
namespace: string;
|
|
@@ -126,6 +127,12 @@ export interface RpdEntityBeforeResponseEventPayload {
|
|
|
126
127
|
baseModelSingularCode?: string;
|
|
127
128
|
entities: any[];
|
|
128
129
|
}
|
|
130
|
+
export type EmitServerEventOptions<TEventName extends keyof RpdServerEventTypes> = {
|
|
131
|
+
eventName: TEventName;
|
|
132
|
+
payload: RpdServerEventTypes[TEventName][1];
|
|
133
|
+
sender?: RapidPlugin;
|
|
134
|
+
routeContext?: RouteContext;
|
|
135
|
+
};
|
|
129
136
|
export interface QuoteTableOptions {
|
|
130
137
|
schema?: string;
|
|
131
138
|
tableName: string;
|
|
@@ -335,12 +342,19 @@ export type EntityFilterOperators = EntityFilterRelationalOperators | EntityFilt
|
|
|
335
342
|
export type EntityFilterOptions = FindEntityRelationalFilterOptions | FindEntitySetFilterOptions | FindEntityLogicalFilterOptions | FindEntityUnaryFilterOptions | FindEntityExistenceFilterOptions;
|
|
336
343
|
export type EntityNonRelationPropertyFilterOptions = FindEntityRelationalFilterOptions | FindEntitySetFilterOptions | FindEntityUnaryFilterOptions;
|
|
337
344
|
export interface FindEntityOptions {
|
|
345
|
+
routeContext?: RouteContext;
|
|
338
346
|
filters?: EntityFilterOptions[];
|
|
339
347
|
orderBy?: FindEntityOrderByOptions[];
|
|
340
348
|
pagination?: FindEntityPaginationOptions;
|
|
341
349
|
properties?: string[];
|
|
342
350
|
keepNonPropertyFields?: boolean;
|
|
343
351
|
}
|
|
352
|
+
export interface FindEntityByIdOptions {
|
|
353
|
+
routeContext?: RouteContext;
|
|
354
|
+
id: any;
|
|
355
|
+
properties?: string[];
|
|
356
|
+
keepNonPropertyFields?: boolean;
|
|
357
|
+
}
|
|
344
358
|
export interface FindEntityRelationalFilterOptions {
|
|
345
359
|
field: string;
|
|
346
360
|
operator: EntityFilterRelationalOperators;
|
|
@@ -375,28 +389,38 @@ export interface FindEntityOrderByOptions {
|
|
|
375
389
|
desc?: boolean;
|
|
376
390
|
}
|
|
377
391
|
export interface CountEntityOptions {
|
|
392
|
+
routeContext?: RouteContext;
|
|
378
393
|
filters?: EntityFilterOptions[];
|
|
379
394
|
}
|
|
380
395
|
export interface CountEntityResult {
|
|
381
396
|
count: number;
|
|
382
397
|
}
|
|
398
|
+
export interface DeleteEntityByIdOptions {
|
|
399
|
+
routeContext?: RouteContext;
|
|
400
|
+
id: any;
|
|
401
|
+
}
|
|
383
402
|
export interface CreateEntityOptions {
|
|
403
|
+
routeContext?: RouteContext;
|
|
384
404
|
entity: any;
|
|
385
405
|
}
|
|
386
406
|
export interface UpdateEntityOptions {
|
|
407
|
+
routeContext?: RouteContext;
|
|
387
408
|
filters?: EntityFilterOptions[];
|
|
388
409
|
entity: any;
|
|
389
410
|
}
|
|
390
411
|
export interface UpdateEntityByIdOptions {
|
|
412
|
+
routeContext?: RouteContext;
|
|
391
413
|
id: any;
|
|
392
414
|
entityToSave: any;
|
|
393
415
|
operation?: any;
|
|
394
416
|
stateProperties?: string[];
|
|
395
417
|
}
|
|
396
418
|
export interface DeleteEntityOptions {
|
|
419
|
+
routeContext?: RouteContext;
|
|
397
420
|
filters?: EntityFilterOptions[];
|
|
398
421
|
}
|
|
399
422
|
export interface AddEntityRelationsOptions {
|
|
423
|
+
routeContext?: RouteContext;
|
|
400
424
|
id: number;
|
|
401
425
|
property: string;
|
|
402
426
|
relations: {
|
|
@@ -405,6 +429,7 @@ export interface AddEntityRelationsOptions {
|
|
|
405
429
|
}[];
|
|
406
430
|
}
|
|
407
431
|
export interface RemoveEntityRelationsOptions {
|
|
432
|
+
routeContext?: RouteContext;
|
|
408
433
|
id: number;
|
|
409
434
|
property: string;
|
|
410
435
|
relations: {
|
|
@@ -422,6 +447,7 @@ export type EntityWatchHandler<TEventName extends keyof RpdServerEventTypes> = (
|
|
|
422
447
|
export type EntityWatchHandlerContext<TEventName extends keyof RpdServerEventTypes> = {
|
|
423
448
|
server: IRpdServer;
|
|
424
449
|
payload: RpdServerEventTypes[TEventName][1];
|
|
450
|
+
routerContext?: RouteContext;
|
|
425
451
|
};
|
|
426
452
|
export interface EntityWatchPluginInitOptions {
|
|
427
453
|
watchers: EntityWatcherType[];
|
package/package.json
CHANGED
package/src/core/server.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CreateEntityOptions, EntityWatcherType, GetDataAccessorOptions, GetModelOptions, IDatabaseConfig, IQueryBuilder, IRpdDataAccessor, RapidServerConfig, RpdApplicationConfig, RpdDataModel, RpdDataModelProperty, RpdServerEventTypes, UpdateEntityByIdOptions } from "~/types";
|
|
1
|
+
import { CreateEntityOptions, EmitServerEventOptions, EntityWatcherType, GetDataAccessorOptions, GetModelOptions, IDatabaseConfig, IQueryBuilder, IRpdDataAccessor, RapidServerConfig, RpdApplicationConfig, RpdDataModel, RpdDataModelProperty, RpdServerEventTypes, UpdateEntityByIdOptions } from "~/types";
|
|
2
2
|
import { IPluginActionHandler, ActionHandler, ActionHandlerContext } from "./actionHandler";
|
|
3
3
|
import { Next, RouteContext } from "./routeContext";
|
|
4
4
|
import EntityManager from "~/dataAccess/entityManager";
|
|
@@ -30,7 +30,7 @@ export interface IRpdServer {
|
|
|
30
30
|
getModel(options: GetModelOptions): RpdDataModel | undefined;
|
|
31
31
|
registerEventHandler<K extends keyof RpdServerEventTypes>(eventName: K, listener: (...args: RpdServerEventTypes[K]) => void);
|
|
32
32
|
registerEntityWatcher(entityWatcher: EntityWatcherType);
|
|
33
|
-
emitEvent<
|
|
33
|
+
emitEvent<TEventName extends keyof RpdServerEventTypes>(event: EmitServerEventOptions<TEventName>): void;
|
|
34
34
|
handleRequest(request: Request, next: Next): Promise<Response>;
|
|
35
35
|
beforeRunRouteActions(handlerContext: ActionHandlerContext): Promise<void>;
|
|
36
36
|
beforeCreateEntity(model: RpdDataModel, options: CreateEntityOptions): Promise<void>;
|
|
@@ -3,9 +3,11 @@ import {
|
|
|
3
3
|
CountEntityOptions,
|
|
4
4
|
CountEntityResult,
|
|
5
5
|
CreateEntityOptions,
|
|
6
|
+
DeleteEntityByIdOptions,
|
|
6
7
|
EntityFilterOperators,
|
|
7
8
|
EntityFilterOptions,
|
|
8
9
|
EntityNonRelationPropertyFilterOptions,
|
|
10
|
+
FindEntityByIdOptions,
|
|
9
11
|
FindEntityOptions,
|
|
10
12
|
FindEntityOrderByOptions,
|
|
11
13
|
IRpdDataAccessor,
|
|
@@ -24,6 +26,7 @@ import { filter, find, first, forEach, isArray, isObject, keys, map, reject, uni
|
|
|
24
26
|
import { getEntityPropertiesIncludingBase, getEntityProperty, getEntityPropertyByCode } from "./metaHelper";
|
|
25
27
|
import { ColumnQueryOptions, CountRowOptions, FindRowOptions, FindRowOrderByOptions, RowFilterOptions } from "./dataAccessTypes";
|
|
26
28
|
import { newEntityOperationError } from "~/utilities/errorUtility";
|
|
29
|
+
import { RouteContext } from "~/core/routeContext";
|
|
27
30
|
|
|
28
31
|
function convertEntityOrderByToRowOrderBy(server: IRpdServer, model: RpdDataModel, baseModel?: RpdDataModel, orderByList?: FindEntityOrderByOptions[]) {
|
|
29
32
|
if (!orderByList) {
|
|
@@ -151,7 +154,7 @@ async function findEntities(server: IRpdServer, dataAccessor: IRpdDataAccessor,
|
|
|
151
154
|
forEach(rows, (row: any) => {
|
|
152
155
|
row[relationProperty.code] = filter(relationLinks, (link: any) => {
|
|
153
156
|
return link[relationProperty.selfIdColumnName!] == row["id"];
|
|
154
|
-
}).map((link) => mapDbRowToEntity(server, targetModel, link.targetEntity,
|
|
157
|
+
}).map((link) => mapDbRowToEntity(server, targetModel, link.targetEntity, options.keepNonPropertyFields));
|
|
155
158
|
});
|
|
156
159
|
}
|
|
157
160
|
} else {
|
|
@@ -175,7 +178,7 @@ async function findEntities(server: IRpdServer, dataAccessor: IRpdDataAccessor,
|
|
|
175
178
|
if (isManyRelation) {
|
|
176
179
|
row[relationProperty.code] = filter(relatedEntities, (relatedEntity: any) => {
|
|
177
180
|
return relatedEntity[relationProperty.selfIdColumnName!] == row.id;
|
|
178
|
-
}).map((item) => mapDbRowToEntity(server, targetModel!, item,
|
|
181
|
+
}).map((item) => mapDbRowToEntity(server, targetModel!, item, options.keepNonPropertyFields));
|
|
179
182
|
} else {
|
|
180
183
|
row[relationProperty.code] = mapDbRowToEntity(
|
|
181
184
|
server,
|
|
@@ -184,7 +187,7 @@ async function findEntities(server: IRpdServer, dataAccessor: IRpdDataAccessor,
|
|
|
184
187
|
// TODO: id property code should be configurable.
|
|
185
188
|
return relatedEntity["id"] == row[relationProperty.targetIdColumnName!];
|
|
186
189
|
}),
|
|
187
|
-
|
|
190
|
+
options.keepNonPropertyFields,
|
|
188
191
|
);
|
|
189
192
|
}
|
|
190
193
|
});
|
|
@@ -193,16 +196,17 @@ async function findEntities(server: IRpdServer, dataAccessor: IRpdDataAccessor,
|
|
|
193
196
|
}
|
|
194
197
|
const entities = rows.map((item) => mapDbRowToEntity(server, model, item, options.keepNonPropertyFields));
|
|
195
198
|
|
|
196
|
-
await server.emitEvent(
|
|
197
|
-
"entity.beforeResponse",
|
|
198
|
-
{
|
|
199
|
+
await server.emitEvent({
|
|
200
|
+
eventName: "entity.beforeResponse",
|
|
201
|
+
payload: {
|
|
199
202
|
namespace: model.namespace,
|
|
200
203
|
modelSingularCode: model.singularCode,
|
|
201
204
|
baseModelSingularCode: model.base,
|
|
202
205
|
entities,
|
|
203
206
|
},
|
|
204
|
-
null,
|
|
205
|
-
|
|
207
|
+
sender: null,
|
|
208
|
+
routeContext: options.routeContext,
|
|
209
|
+
});
|
|
206
210
|
|
|
207
211
|
return entities;
|
|
208
212
|
}
|
|
@@ -212,7 +216,8 @@ async function findEntity(server: IRpdServer, dataAccessor: IRpdDataAccessor, op
|
|
|
212
216
|
return first(entities);
|
|
213
217
|
}
|
|
214
218
|
|
|
215
|
-
async function findById(server: IRpdServer, dataAccessor: IRpdDataAccessor,
|
|
219
|
+
async function findById(server: IRpdServer, dataAccessor: IRpdDataAccessor, options: FindEntityByIdOptions): Promise<any> {
|
|
220
|
+
const { id, properties, keepNonPropertyFields, routeContext } = options;
|
|
216
221
|
return await findEntity(server, dataAccessor, {
|
|
217
222
|
filters: [
|
|
218
223
|
{
|
|
@@ -221,7 +226,9 @@ async function findById(server: IRpdServer, dataAccessor: IRpdDataAccessor, id:
|
|
|
221
226
|
value: id,
|
|
222
227
|
},
|
|
223
228
|
],
|
|
229
|
+
properties,
|
|
224
230
|
keepNonPropertyFields,
|
|
231
|
+
routeContext,
|
|
225
232
|
});
|
|
226
233
|
}
|
|
227
234
|
|
|
@@ -505,20 +512,21 @@ async function createEntity(server: IRpdServer, dataAccessor: IRpdDataAccessor,
|
|
|
505
512
|
throw newEntityOperationError("Create base entity directly is not allowed.");
|
|
506
513
|
}
|
|
507
514
|
|
|
508
|
-
const { entity } = options;
|
|
515
|
+
const { entity, routeContext } = options;
|
|
509
516
|
|
|
510
517
|
await server.beforeCreateEntity(model, options);
|
|
511
518
|
|
|
512
|
-
await server.emitEvent(
|
|
513
|
-
"entity.beforeCreate",
|
|
514
|
-
{
|
|
519
|
+
await server.emitEvent({
|
|
520
|
+
eventName: "entity.beforeCreate",
|
|
521
|
+
payload: {
|
|
515
522
|
namespace: model.namespace,
|
|
516
523
|
modelSingularCode: model.singularCode,
|
|
517
524
|
baseModelSingularCode: model.base,
|
|
518
525
|
before: entity,
|
|
519
526
|
},
|
|
520
|
-
plugin,
|
|
521
|
-
|
|
527
|
+
sender: plugin,
|
|
528
|
+
routeContext,
|
|
529
|
+
});
|
|
522
530
|
|
|
523
531
|
const oneRelationPropertiesToCreate: RpdDataModelProperty[] = [];
|
|
524
532
|
const manyRelationPropertiesToCreate: RpdDataModelProperty[] = [];
|
|
@@ -558,7 +566,10 @@ async function createEntity(server: IRpdServer, dataAccessor: IRpdDataAccessor,
|
|
|
558
566
|
newEntityOneRelationProps[property.code] = newTargetEntity;
|
|
559
567
|
targetRow[property.targetIdColumnName!] = newTargetEntity["id"];
|
|
560
568
|
} else {
|
|
561
|
-
const targetEntity = await findById(server, targetDataAccessor,
|
|
569
|
+
const targetEntity = await findById(server, targetDataAccessor, {
|
|
570
|
+
id: targetEntityId,
|
|
571
|
+
routeContext,
|
|
572
|
+
});
|
|
562
573
|
if (!targetEntity) {
|
|
563
574
|
throw newEntityOperationError(`Create ${model.singularCode} entity failed. Property '${property.code}' was invalid. Related ${property.targetSingularCode} entity with id '${targetEntityId}' was not found.`);
|
|
564
575
|
}
|
|
@@ -568,7 +579,10 @@ async function createEntity(server: IRpdServer, dataAccessor: IRpdDataAccessor,
|
|
|
568
579
|
} else {
|
|
569
580
|
// fieldValue is id;
|
|
570
581
|
const targetEntityId = fieldValue;
|
|
571
|
-
const targetEntity = await findById(server, targetDataAccessor,
|
|
582
|
+
const targetEntity = await findById(server, targetDataAccessor, {
|
|
583
|
+
id: targetEntityId,
|
|
584
|
+
routeContext,
|
|
585
|
+
});
|
|
572
586
|
if (!targetEntity) {
|
|
573
587
|
throw newEntityOperationError(`Create ${model.singularCode} entity failed. Property '${property.code}' was invalid. Related ${property.targetSingularCode} entity with id '${targetEntityId}' was not found.`);
|
|
574
588
|
}
|
|
@@ -662,28 +676,32 @@ async function createEntity(server: IRpdServer, dataAccessor: IRpdDataAccessor,
|
|
|
662
676
|
}
|
|
663
677
|
}
|
|
664
678
|
|
|
665
|
-
await server.emitEvent(
|
|
666
|
-
"entity.create",
|
|
667
|
-
{
|
|
679
|
+
await server.emitEvent({
|
|
680
|
+
eventName: "entity.create",
|
|
681
|
+
payload: {
|
|
668
682
|
namespace: model.namespace,
|
|
669
683
|
modelSingularCode: model.singularCode,
|
|
670
684
|
baseModelSingularCode: model.base,
|
|
671
685
|
after: newEntity,
|
|
672
686
|
},
|
|
673
|
-
plugin,
|
|
674
|
-
|
|
687
|
+
sender: plugin,
|
|
688
|
+
routeContext,
|
|
689
|
+
});
|
|
675
690
|
|
|
676
691
|
return newEntity;
|
|
677
692
|
}
|
|
678
693
|
|
|
679
694
|
async function updateEntityById(server: IRpdServer, dataAccessor: IRpdDataAccessor, options: UpdateEntityByIdOptions, plugin?: RapidPlugin) {
|
|
680
695
|
const model = dataAccessor.getModel();
|
|
681
|
-
const { id, entityToSave } = options;
|
|
696
|
+
const { id, entityToSave, routeContext } = options;
|
|
682
697
|
if (!id) {
|
|
683
698
|
throw new Error("Id is required when updating an entity.");
|
|
684
699
|
}
|
|
685
700
|
|
|
686
|
-
const entity = await findById(server, dataAccessor,
|
|
701
|
+
const entity = await findById(server, dataAccessor, {
|
|
702
|
+
id,
|
|
703
|
+
routeContext,
|
|
704
|
+
});
|
|
687
705
|
if (!entity) {
|
|
688
706
|
throw new Error(`${model.namespace}.${model.singularCode} with id "${id}" was not found.`);
|
|
689
707
|
}
|
|
@@ -696,16 +714,17 @@ async function updateEntityById(server: IRpdServer, dataAccessor: IRpdDataAccess
|
|
|
696
714
|
options.entityToSave = changes || {};
|
|
697
715
|
await server.beforeUpdateEntity(model, options, entity);
|
|
698
716
|
|
|
699
|
-
await server.emitEvent(
|
|
700
|
-
"entity.beforeUpdate",
|
|
701
|
-
{
|
|
717
|
+
await server.emitEvent({
|
|
718
|
+
eventName: "entity.beforeUpdate",
|
|
719
|
+
payload: {
|
|
702
720
|
namespace: model.namespace,
|
|
703
721
|
modelSingularCode: model.singularCode,
|
|
704
722
|
before: entity,
|
|
705
723
|
changes: options.entityToSave,
|
|
706
724
|
},
|
|
707
|
-
plugin,
|
|
708
|
-
|
|
725
|
+
sender: plugin,
|
|
726
|
+
routeContext: options.routeContext,
|
|
727
|
+
});
|
|
709
728
|
|
|
710
729
|
changes = getEntityPartChanges(entity, options.entityToSave);
|
|
711
730
|
|
|
@@ -747,7 +766,10 @@ async function updateEntityById(server: IRpdServer, dataAccessor: IRpdDataAccess
|
|
|
747
766
|
updatedEntityOneRelationProps[property.code] = newTargetEntity;
|
|
748
767
|
targetRow[property.targetIdColumnName!] = newTargetEntity["id"];
|
|
749
768
|
} else {
|
|
750
|
-
const targetEntity = await findById(server, targetDataAccessor,
|
|
769
|
+
const targetEntity = await findById(server, targetDataAccessor, {
|
|
770
|
+
id: targetEntityId,
|
|
771
|
+
routeContext,
|
|
772
|
+
});
|
|
751
773
|
if (!targetEntity) {
|
|
752
774
|
throw newEntityOperationError(`Create ${model.singularCode} entity failed. Property '${property.code}' was invalid. Related ${property.targetSingularCode} entity with id '${targetEntityId}' was not found.`);
|
|
753
775
|
}
|
|
@@ -757,7 +779,10 @@ async function updateEntityById(server: IRpdServer, dataAccessor: IRpdDataAccess
|
|
|
757
779
|
} else {
|
|
758
780
|
// fieldValue is id;
|
|
759
781
|
const targetEntityId = fieldValue;
|
|
760
|
-
const targetEntity = await findById(server, targetDataAccessor,
|
|
782
|
+
const targetEntity = await findById(server, targetDataAccessor, {
|
|
783
|
+
id: targetEntityId,
|
|
784
|
+
routeContext,
|
|
785
|
+
});
|
|
761
786
|
if (!targetEntity) {
|
|
762
787
|
throw newEntityOperationError(`Create ${model.singularCode} entity failed. Property '${property.code}' was invalid. Related ${property.targetSingularCode} entity with id '${targetEntityId}' was not found.`);
|
|
763
788
|
}
|
|
@@ -859,9 +884,9 @@ async function updateEntityById(server: IRpdServer, dataAccessor: IRpdDataAccess
|
|
|
859
884
|
updatedEntity[property.code] = relatedEntities;
|
|
860
885
|
}
|
|
861
886
|
|
|
862
|
-
await server.emitEvent(
|
|
863
|
-
"entity.update",
|
|
864
|
-
{
|
|
887
|
+
await server.emitEvent({
|
|
888
|
+
eventName: "entity.update",
|
|
889
|
+
payload: {
|
|
865
890
|
namespace: model.namespace,
|
|
866
891
|
modelSingularCode: model.singularCode,
|
|
867
892
|
// TODO: should not emit event on base model if it's not effected.
|
|
@@ -870,8 +895,10 @@ async function updateEntityById(server: IRpdServer, dataAccessor: IRpdDataAccess
|
|
|
870
895
|
after: updatedEntity,
|
|
871
896
|
changes: changes,
|
|
872
897
|
},
|
|
873
|
-
plugin,
|
|
874
|
-
|
|
898
|
+
sender: plugin,
|
|
899
|
+
routeContext: options.routeContext,
|
|
900
|
+
});
|
|
901
|
+
|
|
875
902
|
return updatedEntity;
|
|
876
903
|
}
|
|
877
904
|
|
|
@@ -896,8 +923,14 @@ export default class EntityManager<TEntity = any> {
|
|
|
896
923
|
return await findEntity(this.#server, this.#dataAccessor, options);
|
|
897
924
|
}
|
|
898
925
|
|
|
899
|
-
async findById(
|
|
900
|
-
|
|
926
|
+
async findById(options: FindEntityByIdOptions): Promise<TEntity | null> {
|
|
927
|
+
// options is id
|
|
928
|
+
if (!isObject(options)) {
|
|
929
|
+
options = {
|
|
930
|
+
id: options,
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
return await findById(this.#server, this.#dataAccessor, options);
|
|
901
934
|
}
|
|
902
935
|
|
|
903
936
|
async createEntity(options: CreateEntityOptions, plugin?: RapidPlugin): Promise<TEntity> {
|
|
@@ -922,26 +955,41 @@ export default class EntityManager<TEntity = any> {
|
|
|
922
955
|
return await this.#dataAccessor.count(countRowOptions);
|
|
923
956
|
}
|
|
924
957
|
|
|
925
|
-
async deleteById(
|
|
958
|
+
async deleteById(options: DeleteEntityByIdOptions, plugin?: RapidPlugin): Promise<void> {
|
|
959
|
+
// options is id
|
|
960
|
+
if (!isObject(options)) {
|
|
961
|
+
options = {
|
|
962
|
+
id: options,
|
|
963
|
+
};
|
|
964
|
+
}
|
|
965
|
+
|
|
926
966
|
const model = this.getModel();
|
|
927
967
|
if (model.derivedTypePropertyCode) {
|
|
928
968
|
throw newEntityOperationError("Delete base entity directly is not allowed.");
|
|
929
969
|
}
|
|
930
970
|
|
|
931
|
-
const
|
|
971
|
+
const { id, routeContext } = options;
|
|
972
|
+
|
|
973
|
+
const entity = await this.findById({
|
|
974
|
+
id,
|
|
975
|
+
keepNonPropertyFields: true,
|
|
976
|
+
routeContext,
|
|
977
|
+
});
|
|
978
|
+
|
|
932
979
|
if (!entity) {
|
|
933
980
|
return;
|
|
934
981
|
}
|
|
935
982
|
|
|
936
|
-
await this.#server.emitEvent(
|
|
937
|
-
"entity.beforeDelete",
|
|
938
|
-
{
|
|
983
|
+
await this.#server.emitEvent({
|
|
984
|
+
eventName: "entity.beforeDelete",
|
|
985
|
+
payload: {
|
|
939
986
|
namespace: model.namespace,
|
|
940
987
|
modelSingularCode: model.singularCode,
|
|
941
988
|
before: entity,
|
|
942
989
|
},
|
|
943
|
-
plugin,
|
|
944
|
-
|
|
990
|
+
sender: plugin,
|
|
991
|
+
routeContext,
|
|
992
|
+
});
|
|
945
993
|
|
|
946
994
|
await this.#dataAccessor.deleteById(id);
|
|
947
995
|
if (model.base) {
|
|
@@ -951,23 +999,26 @@ export default class EntityManager<TEntity = any> {
|
|
|
951
999
|
await baseDataAccessor.deleteById(id);
|
|
952
1000
|
}
|
|
953
1001
|
|
|
954
|
-
await this.#server.emitEvent(
|
|
955
|
-
"entity.delete",
|
|
956
|
-
{
|
|
1002
|
+
await this.#server.emitEvent({
|
|
1003
|
+
eventName: "entity.delete",
|
|
1004
|
+
payload: {
|
|
957
1005
|
namespace: model.namespace,
|
|
958
1006
|
modelSingularCode: model.singularCode,
|
|
959
|
-
baseModelSingularCode: model.base,
|
|
960
1007
|
before: entity,
|
|
961
1008
|
},
|
|
962
|
-
plugin,
|
|
963
|
-
|
|
1009
|
+
sender: plugin,
|
|
1010
|
+
routeContext,
|
|
1011
|
+
});
|
|
964
1012
|
}
|
|
965
1013
|
|
|
966
1014
|
async addRelations(options: AddEntityRelationsOptions, plugin?: RapidPlugin): Promise<void> {
|
|
967
1015
|
const server = this.#server;
|
|
968
1016
|
const model = this.getModel();
|
|
969
|
-
const { id, property, relations } = options;
|
|
970
|
-
const entity = await this.findById(
|
|
1017
|
+
const { id, property, relations, routeContext } = options;
|
|
1018
|
+
const entity = await this.findById({
|
|
1019
|
+
id,
|
|
1020
|
+
routeContext,
|
|
1021
|
+
});
|
|
971
1022
|
if (!entity) {
|
|
972
1023
|
throw new Error(`${model.namespace}.${model.singularCode} with id "${id}" was not found.`);
|
|
973
1024
|
}
|
|
@@ -995,24 +1046,28 @@ export default class EntityManager<TEntity = any> {
|
|
|
995
1046
|
}
|
|
996
1047
|
}
|
|
997
1048
|
|
|
998
|
-
await server.emitEvent(
|
|
999
|
-
"entity.addRelations",
|
|
1000
|
-
{
|
|
1049
|
+
await server.emitEvent({
|
|
1050
|
+
eventName: "entity.addRelations",
|
|
1051
|
+
payload: {
|
|
1001
1052
|
namespace: model.namespace,
|
|
1002
1053
|
modelSingularCode: model.singularCode,
|
|
1003
1054
|
entity,
|
|
1004
1055
|
property,
|
|
1005
1056
|
relations,
|
|
1006
1057
|
},
|
|
1007
|
-
plugin,
|
|
1008
|
-
|
|
1058
|
+
sender: plugin,
|
|
1059
|
+
routeContext: options.routeContext,
|
|
1060
|
+
});
|
|
1009
1061
|
}
|
|
1010
1062
|
|
|
1011
1063
|
async removeRelations(options: RemoveEntityRelationsOptions, plugin?: RapidPlugin): Promise<void> {
|
|
1012
1064
|
const server = this.#server;
|
|
1013
1065
|
const model = this.getModel();
|
|
1014
|
-
const { id, property, relations } = options;
|
|
1015
|
-
const entity = await this.findById(
|
|
1066
|
+
const { id, property, relations, routeContext } = options;
|
|
1067
|
+
const entity = await this.findById({
|
|
1068
|
+
id,
|
|
1069
|
+
routeContext,
|
|
1070
|
+
});
|
|
1016
1071
|
if (!entity) {
|
|
1017
1072
|
throw new Error(`${model.namespace}.${model.singularCode} with id "${id}" was not found.`);
|
|
1018
1073
|
}
|
|
@@ -1036,16 +1091,17 @@ export default class EntityManager<TEntity = any> {
|
|
|
1036
1091
|
}
|
|
1037
1092
|
}
|
|
1038
1093
|
|
|
1039
|
-
await server.emitEvent(
|
|
1040
|
-
"entity.removeRelations",
|
|
1041
|
-
{
|
|
1094
|
+
await server.emitEvent({
|
|
1095
|
+
eventName: "entity.removeRelations",
|
|
1096
|
+
payload: {
|
|
1042
1097
|
namespace: model.namespace,
|
|
1043
1098
|
modelSingularCode: model.singularCode,
|
|
1044
1099
|
entity,
|
|
1045
1100
|
property,
|
|
1046
1101
|
relations,
|
|
1047
1102
|
},
|
|
1048
|
-
plugin,
|
|
1049
|
-
|
|
1103
|
+
sender: plugin,
|
|
1104
|
+
routeContext: options.routeContext,
|
|
1105
|
+
});
|
|
1050
1106
|
}
|
|
1051
1107
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RunEntityActionHandlerOptions } from "~/types";
|
|
1
|
+
import { AddEntityRelationsOptions, RunEntityActionHandlerOptions } from "~/types";
|
|
2
2
|
import { mergeInput } from "~/helpers/inputHelper";
|
|
3
3
|
import { ActionHandlerContext } from "~/core/actionHandler";
|
|
4
4
|
import { RapidPlugin } from "~/core/server";
|
|
@@ -9,10 +9,11 @@ export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, op
|
|
|
9
9
|
const { logger, server, input } = ctx;
|
|
10
10
|
|
|
11
11
|
const { defaultInput, fixedInput } = options;
|
|
12
|
-
const mergedInput = mergeInput(defaultInput, input, fixedInput);
|
|
12
|
+
const mergedInput: AddEntityRelationsOptions = mergeInput(defaultInput, input, fixedInput);
|
|
13
13
|
logger.debug(`Running ${code} handler...`, { defaultInput, fixedInput, mergedInput });
|
|
14
14
|
|
|
15
15
|
const entityManager = server.getEntityManager(options.singularCode);
|
|
16
|
+
mergedInput.routeContext = ctx.routerContext;
|
|
16
17
|
await entityManager.addRelations(mergedInput, plugin);
|
|
17
18
|
|
|
18
19
|
ctx.output = {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RunEntityActionHandlerOptions } from "~/types";
|
|
1
|
+
import { CountEntityOptions, RunEntityActionHandlerOptions } from "~/types";
|
|
2
2
|
import runCollectionEntityActionHandler from "~/helpers/runCollectionEntityActionHandler";
|
|
3
3
|
import { removeFiltersWithNullValue } from "~/dataAccess/filterHelper";
|
|
4
4
|
import { ActionHandlerContext } from "~/core/actionHandler";
|
|
@@ -7,8 +7,9 @@ import { RapidPlugin } from "~/core/server";
|
|
|
7
7
|
export const code = "countCollectionEntities";
|
|
8
8
|
|
|
9
9
|
export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: RunEntityActionHandlerOptions) {
|
|
10
|
-
await runCollectionEntityActionHandler(ctx, options, code, (entityManager, input) => {
|
|
10
|
+
await runCollectionEntityActionHandler(ctx, options, code, (entityManager, input: CountEntityOptions) => {
|
|
11
11
|
input.filters = removeFiltersWithNullValue(input.filters);
|
|
12
|
+
input.routeContext = ctx.routerContext;
|
|
12
13
|
return entityManager.count(input);
|
|
13
14
|
});
|
|
14
15
|
}
|
|
@@ -9,7 +9,10 @@ export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, op
|
|
|
9
9
|
logger.debug(`Running ${code} handler...`);
|
|
10
10
|
|
|
11
11
|
const entityManager = server.getEntityManager(options.singularCode);
|
|
12
|
-
await entityManager.deleteById(
|
|
12
|
+
await entityManager.deleteById({
|
|
13
|
+
id: input.id,
|
|
14
|
+
routeContext: ctx.routerContext,
|
|
15
|
+
}, plugin);
|
|
13
16
|
|
|
14
17
|
ctx.status = 200;
|
|
15
18
|
ctx.output = {};
|
|
@@ -9,6 +9,7 @@ export const code = "findCollectionEntities";
|
|
|
9
9
|
export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: RunEntityActionHandlerOptions) {
|
|
10
10
|
await runCollectionEntityActionHandler(ctx, options, code, async (entityManager, input: FindEntityOptions) => {
|
|
11
11
|
input.filters = removeFiltersWithNullValue(input.filters);
|
|
12
|
+
input.routeContext = ctx.routerContext;
|
|
12
13
|
const entities = await entityManager.findEntities(input);
|
|
13
14
|
const result: {
|
|
14
15
|
list: any;
|
|
@@ -10,7 +10,10 @@ export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, op
|
|
|
10
10
|
const { id } = input;
|
|
11
11
|
|
|
12
12
|
const entityManager = server.getEntityManager(options.singularCode);
|
|
13
|
-
const entity = await entityManager.findById(
|
|
13
|
+
const entity = await entityManager.findById({
|
|
14
|
+
id,
|
|
15
|
+
routeContext: ctx.routerContext,
|
|
16
|
+
});
|
|
14
17
|
if (!entity) {
|
|
15
18
|
throw new Error(`${options.namespace}.${options.singularCode} with id "${id}" was not found.`);
|
|
16
19
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RunEntityActionHandlerOptions } from "~/types";
|
|
1
|
+
import { RemoveEntityRelationsOptions, RunEntityActionHandlerOptions } from "~/types";
|
|
2
2
|
import { mergeInput } from "~/helpers/inputHelper";
|
|
3
3
|
import { ActionHandlerContext } from "~/core/actionHandler";
|
|
4
4
|
import { RapidPlugin } from "~/core/server";
|
|
@@ -9,8 +9,9 @@ export async function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, op
|
|
|
9
9
|
const { logger, server, input } = ctx;
|
|
10
10
|
const { defaultInput, fixedInput } = options;
|
|
11
11
|
|
|
12
|
-
const mergedInput = mergeInput(defaultInput, input, fixedInput);
|
|
12
|
+
const mergedInput: RemoveEntityRelationsOptions = mergeInput(defaultInput, input, fixedInput);
|
|
13
13
|
logger.debug(`Running ${code} handler...`, { defaultInput, fixedInput, mergedInput });
|
|
14
|
+
mergedInput.routeContext = ctx.routerContext;
|
|
14
15
|
|
|
15
16
|
const entityManager = server.getEntityManager(options.singularCode);
|
|
16
17
|
await entityManager.removeRelations(mergedInput, plugin);
|