@ruiapp/rapid-core 0.1.12 → 0.1.13
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/eventManager.d.ts +1 -2
- package/dist/dataAccess/entityManager.d.ts +8 -6
- package/dist/index.d.ts +4 -0
- package/dist/index.js +402 -233
- package/dist/plugins/entityWatch/EntityWatchPlugin.d.ts +15 -0
- package/dist/plugins/entityWatch/EntityWatchPluginTypes.d.ts +15 -0
- package/dist/plugins/serverOperation/ServerOperationPlugin.d.ts +25 -0
- package/dist/plugins/serverOperation/ServerOperationPluginTypes.d.ts +11 -0
- package/dist/plugins/serverOperation/actionHandlers/index.d.ts +3 -0
- package/dist/plugins/serverOperation/actionHandlers/runServerOperation.d.ts +6 -0
- package/dist/types.d.ts +17 -2
- package/package.json +1 -1
- package/src/core/eventManager.ts +3 -4
- package/src/dataAccess/entityManager.ts +153 -10
- package/src/index.ts +5 -1
- package/src/plugins/dataManage/actionHandlers/addEntityRelations.ts +2 -50
- package/src/plugins/dataManage/actionHandlers/createCollectionEntitiesBatch.ts +1 -12
- package/src/plugins/dataManage/actionHandlers/createCollectionEntity.ts +1 -11
- package/src/plugins/dataManage/actionHandlers/deleteCollectionEntityById.ts +1 -20
- package/src/plugins/dataManage/actionHandlers/removeEntityRelations.ts +2 -48
- package/src/plugins/dataManage/actionHandlers/updateCollectionEntityById.ts +1 -25
- package/src/plugins/entityWatch/EntityWatchPlugin.ts +96 -0
- package/src/plugins/entityWatch/EntityWatchPluginTypes.ts +19 -0
- package/src/plugins/serverOperation/ServerOperationPlugin.ts +94 -0
- package/src/plugins/serverOperation/ServerOperationPluginTypes.ts +13 -0
- package/src/plugins/serverOperation/actionHandlers/index.ts +6 -0
- package/src/plugins/serverOperation/actionHandlers/runServerOperation.ts +15 -0
- package/src/server.ts +1 -1
- package/src/types.ts +13 -2
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { RpdEntityCreateEventPayload, RpdServerEventTypes } from "../../types";
|
|
2
|
+
import { IRpdServer, RapidPlugin, RpdConfigurationItemOptions, RpdServerPluginConfigurableTargetOptions, RpdServerPluginExtendingAbilities } from "../../core/server";
|
|
3
|
+
import { EntityWatchPluginInitOptions } from "./EntityWatchPluginTypes";
|
|
4
|
+
declare class EntityWatchPlugin implements RapidPlugin {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(options: EntityWatchPluginInitOptions);
|
|
7
|
+
get code(): string;
|
|
8
|
+
get description(): string;
|
|
9
|
+
get extendingAbilities(): RpdServerPluginExtendingAbilities[];
|
|
10
|
+
get configurableTargets(): RpdServerPluginConfigurableTargetOptions[];
|
|
11
|
+
get configurations(): RpdConfigurationItemOptions[];
|
|
12
|
+
registerEventHandlers(server: IRpdServer): Promise<any>;
|
|
13
|
+
handleEntityEvent(server: IRpdServer, eventName: keyof RpdServerEventTypes, sender: RapidPlugin, payload: RpdEntityCreateEventPayload): void;
|
|
14
|
+
}
|
|
15
|
+
export default EntityWatchPlugin;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { IRpdServer } from "../../core/server";
|
|
2
|
+
import { RpdServerEventTypes } from "../../types";
|
|
3
|
+
export interface EntityWatcher<TEventName extends keyof RpdServerEventTypes> {
|
|
4
|
+
eventName: TEventName;
|
|
5
|
+
modelSingularCode: string;
|
|
6
|
+
handler: EntityWatchHandler<TEventName>;
|
|
7
|
+
}
|
|
8
|
+
export type EntityWatchHandler<TEventName extends keyof RpdServerEventTypes> = (ctx: EntityWatchHandlerContext<TEventName>) => Promise<void>;
|
|
9
|
+
export type EntityWatchHandlerContext<TEventName extends keyof RpdServerEventTypes> = {
|
|
10
|
+
server: IRpdServer;
|
|
11
|
+
payload: RpdServerEventTypes[TEventName][1];
|
|
12
|
+
};
|
|
13
|
+
export interface EntityWatchPluginInitOptions {
|
|
14
|
+
watchers: EntityWatcher<keyof RpdServerEventTypes>[];
|
|
15
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { RpdApplicationConfig } from "../../types";
|
|
2
|
+
import { ServerOperationPluginInitOptions } from "./ServerOperationPluginTypes";
|
|
3
|
+
import { IRpdServer, RapidPlugin, RpdConfigurationItemOptions, RpdServerPluginConfigurableTargetOptions, RpdServerPluginExtendingAbilities } from "../../core/server";
|
|
4
|
+
declare class ServerOperationPlugin implements RapidPlugin {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(options: ServerOperationPluginInitOptions);
|
|
7
|
+
get code(): string;
|
|
8
|
+
get description(): string;
|
|
9
|
+
get extendingAbilities(): RpdServerPluginExtendingAbilities[];
|
|
10
|
+
get configurableTargets(): RpdServerPluginConfigurableTargetOptions[];
|
|
11
|
+
get configurations(): RpdConfigurationItemOptions[];
|
|
12
|
+
initPlugin(server: IRpdServer): Promise<any>;
|
|
13
|
+
registerMiddlewares(server: IRpdServer): Promise<any>;
|
|
14
|
+
registerActionHandlers(server: IRpdServer): Promise<any>;
|
|
15
|
+
registerEventHandlers(server: IRpdServer): Promise<any>;
|
|
16
|
+
registerMessageHandlers(server: IRpdServer): Promise<any>;
|
|
17
|
+
registerTaskProcessors(server: IRpdServer): Promise<any>;
|
|
18
|
+
onLoadingApplication(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
|
|
19
|
+
configureModels(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
|
|
20
|
+
configureModelProperties(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
|
|
21
|
+
configureRoutes(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
|
|
22
|
+
onApplicationLoaded(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
|
|
23
|
+
onApplicationReady(server: IRpdServer, applicationConfig: RpdApplicationConfig): Promise<any>;
|
|
24
|
+
}
|
|
25
|
+
export default ServerOperationPlugin;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ActionHandlerContext } from "../../core/actionHandler";
|
|
2
|
+
import { RpdHttpMethod } from "../../types";
|
|
3
|
+
export interface ServerOperation {
|
|
4
|
+
code: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
method: RpdHttpMethod;
|
|
7
|
+
handler: (ctx: ActionHandlerContext) => Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export interface ServerOperationPluginInitOptions {
|
|
10
|
+
operations: ServerOperation[];
|
|
11
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ActionHandlerContext } from "../../../core/actionHandler";
|
|
2
|
+
import { RapidPlugin } from "../../../core/server";
|
|
3
|
+
export declare const code = "runServerOperation";
|
|
4
|
+
export declare function handler(plugin: RapidPlugin, ctx: ActionHandlerContext, options: {
|
|
5
|
+
operation: (ctx: ActionHandlerContext) => Promise<void>;
|
|
6
|
+
}): Promise<void>;
|
package/dist/types.d.ts
CHANGED
|
@@ -321,9 +321,24 @@ export interface UpdateEntityOptions {
|
|
|
321
321
|
}
|
|
322
322
|
export interface UpdateEntityByIdOptions {
|
|
323
323
|
id: any;
|
|
324
|
-
|
|
325
|
-
changes: any;
|
|
324
|
+
entityToSave: any;
|
|
326
325
|
}
|
|
327
326
|
export interface DeleteEntityOptions {
|
|
328
327
|
filters?: EntityFilterOptions[];
|
|
329
328
|
}
|
|
329
|
+
export interface AddEntityRelationsOptions {
|
|
330
|
+
id: number;
|
|
331
|
+
property: string;
|
|
332
|
+
relations: {
|
|
333
|
+
id?: number;
|
|
334
|
+
[k: string]: any;
|
|
335
|
+
}[];
|
|
336
|
+
}
|
|
337
|
+
export interface RemoveEntityRelationsOptions {
|
|
338
|
+
id: number;
|
|
339
|
+
property: string;
|
|
340
|
+
relations: {
|
|
341
|
+
id?: number;
|
|
342
|
+
[k: string]: any;
|
|
343
|
+
}[];
|
|
344
|
+
}
|
package/package.json
CHANGED
package/src/core/eventManager.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { EventEmitter } from "events";
|
|
2
|
-
import { RpdServerEventTypes as EventTypes } from "~/types";
|
|
3
2
|
|
|
4
|
-
export default class EventManager {
|
|
3
|
+
export default class EventManager<EventTypes extends Record<string, any[]>> {
|
|
5
4
|
#eventEmitter: EventEmitter;
|
|
6
5
|
|
|
7
6
|
constructor() {
|
|
@@ -12,10 +11,10 @@ export default class EventManager {
|
|
|
12
11
|
eventName: K,
|
|
13
12
|
listener: (...args: EventTypes[K]) => void,
|
|
14
13
|
) {
|
|
15
|
-
this.#eventEmitter.on(eventName, listener);
|
|
14
|
+
this.#eventEmitter.on(eventName as string, listener);
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
emit<K extends keyof EventTypes>(eventName: K, ...args: EventTypes[K]) {
|
|
19
|
-
return this.#eventEmitter.emit(eventName, ...args);
|
|
18
|
+
return this.#eventEmitter.emit(eventName as string, ...args);
|
|
20
19
|
}
|
|
21
20
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as _ from "lodash";
|
|
2
2
|
import {
|
|
3
|
+
AddEntityRelationsOptions,
|
|
3
4
|
CountEntityOptions,
|
|
4
5
|
CountEntityResult,
|
|
5
6
|
CreateEntityOptions,
|
|
@@ -8,6 +9,7 @@ import {
|
|
|
8
9
|
FindEntityOptions,
|
|
9
10
|
FindEntityOrderByOptions,
|
|
10
11
|
IRpdDataAccessor,
|
|
12
|
+
RemoveEntityRelationsOptions,
|
|
11
13
|
RpdDataModel,
|
|
12
14
|
RpdDataModelProperty,
|
|
13
15
|
UpdateEntityByIdOptions,
|
|
@@ -16,7 +18,8 @@ import { isNullOrUndefined } from "~/utilities/typeUtility";
|
|
|
16
18
|
import { mapDbRowToEntity, mapEntityToDbRow } from "./entityMapper";
|
|
17
19
|
import { mapPropertyNameToColumnName } from "./propertyMapper";
|
|
18
20
|
import { isRelationProperty } from "~/utilities/rapidUtility";
|
|
19
|
-
import { IRpdServer } from "~/core/server";
|
|
21
|
+
import { IRpdServer, RapidPlugin } from "~/core/server";
|
|
22
|
+
import { getEntityPartChanges } from "~/helpers/entityHelpers";
|
|
20
23
|
|
|
21
24
|
function convertToDataAccessOrderBy(model: RpdDataModel, orderByList?: FindEntityOrderByOptions[]) {
|
|
22
25
|
if (!orderByList) {
|
|
@@ -533,9 +536,23 @@ async function updateEntityById(
|
|
|
533
536
|
server: IRpdServer,
|
|
534
537
|
dataAccessor: IRpdDataAccessor,
|
|
535
538
|
options: UpdateEntityByIdOptions,
|
|
539
|
+
plugin: RapidPlugin
|
|
536
540
|
) {
|
|
537
541
|
const model = dataAccessor.getModel();
|
|
538
|
-
const { id,
|
|
542
|
+
const { id, entityToSave } = options;
|
|
543
|
+
if (!id) {
|
|
544
|
+
throw new Error("Id is required when updating an entity.")
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
const entity = await this.findById(id);
|
|
548
|
+
if (!entity) {
|
|
549
|
+
throw new Error(`${model.namespace}.${model.singularCode} with id "${id}" was not found.`);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
const changes = getEntityPartChanges(entity, entityToSave);
|
|
553
|
+
if (!changes) {
|
|
554
|
+
return entity;
|
|
555
|
+
}
|
|
539
556
|
|
|
540
557
|
const oneRelationPropertiesToUpdate: RpdDataModelProperty[] = [];
|
|
541
558
|
const manyRelationPropertiesToUpdate: RpdDataModelProperty[] = [];
|
|
@@ -648,6 +665,18 @@ async function updateEntityById(
|
|
|
648
665
|
updatedEntity[property.code] = relatedEntities;
|
|
649
666
|
}
|
|
650
667
|
|
|
668
|
+
|
|
669
|
+
server.emitEvent(
|
|
670
|
+
"entity.update",
|
|
671
|
+
plugin,
|
|
672
|
+
{
|
|
673
|
+
namespace: model.namespace,
|
|
674
|
+
modelSingularCode: model.singularCode,
|
|
675
|
+
before: entity,
|
|
676
|
+
after: updatedEntity,
|
|
677
|
+
changes: changes,
|
|
678
|
+
},
|
|
679
|
+
);
|
|
651
680
|
return updatedEntity;
|
|
652
681
|
}
|
|
653
682
|
|
|
@@ -660,6 +689,10 @@ export default class EntityManager<TEntity=any> {
|
|
|
660
689
|
this.#dataAccessor = dataAccessor;
|
|
661
690
|
}
|
|
662
691
|
|
|
692
|
+
getModel(): RpdDataModel {
|
|
693
|
+
return this.#dataAccessor.getModel();
|
|
694
|
+
}
|
|
695
|
+
|
|
663
696
|
async findEntities(options: FindEntityOptions): Promise<TEntity[]> {
|
|
664
697
|
return await findEntities(this.#server, this.#dataAccessor, options);
|
|
665
698
|
}
|
|
@@ -680,23 +713,133 @@ export default class EntityManager<TEntity=any> {
|
|
|
680
713
|
});
|
|
681
714
|
}
|
|
682
715
|
|
|
683
|
-
async createEntity(options: CreateEntityOptions): Promise<TEntity> {
|
|
684
|
-
|
|
716
|
+
async createEntity(options: CreateEntityOptions, plugin: RapidPlugin): Promise<TEntity> {
|
|
717
|
+
const model = this.getModel();
|
|
718
|
+
const newEntity = await createEntity(this.#server, this.#dataAccessor, options);
|
|
719
|
+
|
|
720
|
+
this.#server.emitEvent(
|
|
721
|
+
"entity.create",
|
|
722
|
+
plugin,
|
|
723
|
+
{
|
|
724
|
+
namespace: model.namespace,
|
|
725
|
+
modelSingularCode: model.singularCode,
|
|
726
|
+
after: newEntity,
|
|
727
|
+
},
|
|
728
|
+
);
|
|
729
|
+
|
|
730
|
+
return newEntity;
|
|
685
731
|
}
|
|
686
732
|
|
|
687
|
-
async updateEntityById(options: UpdateEntityByIdOptions): Promise<TEntity> {
|
|
688
|
-
return await updateEntityById(this.#server, this.#dataAccessor, options);
|
|
733
|
+
async updateEntityById(options: UpdateEntityByIdOptions, plugin: RapidPlugin): Promise<TEntity> {
|
|
734
|
+
return await updateEntityById(this.#server, this.#dataAccessor, options, plugin);
|
|
689
735
|
}
|
|
690
736
|
|
|
691
737
|
async count(options: CountEntityOptions): Promise<CountEntityResult> {
|
|
692
738
|
return await this.#dataAccessor.count(options);
|
|
693
739
|
}
|
|
694
740
|
|
|
695
|
-
async deleteById(id: any): Promise<void> {
|
|
696
|
-
|
|
741
|
+
async deleteById(id: any, plugin: RapidPlugin): Promise<void> {
|
|
742
|
+
const model = this.getModel();
|
|
743
|
+
const entity = await this.findById(id);
|
|
744
|
+
if (!entity) {
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
await this.#dataAccessor.deleteById(id);
|
|
749
|
+
this.#server.emitEvent(
|
|
750
|
+
"entity.delete",
|
|
751
|
+
plugin,
|
|
752
|
+
{
|
|
753
|
+
namespace: model.namespace,
|
|
754
|
+
modelSingularCode: model.singularCode,
|
|
755
|
+
before: entity,
|
|
756
|
+
},
|
|
757
|
+
);
|
|
697
758
|
}
|
|
698
759
|
|
|
699
|
-
|
|
700
|
-
|
|
760
|
+
async addRelations(options: AddEntityRelationsOptions, plugin: RapidPlugin): Promise<void> {
|
|
761
|
+
const model = this.getModel();
|
|
762
|
+
const {id, property, relations} = options;
|
|
763
|
+
const entity = await this.findById(id);
|
|
764
|
+
if (!entity) {
|
|
765
|
+
throw new Error(`${model.namespace}.${model.singularCode} with id "${id}" was not found.`);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
const relationProperty = model.properties.find(e => e.code === property);
|
|
769
|
+
if (!relationProperty) {
|
|
770
|
+
throw new Error(`Property '${property}' was not found in ${model.namespace}.${model.singularCode}`);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
if (!(isRelationProperty(relationProperty) && relationProperty.relation === "many")) {
|
|
774
|
+
throw new Error(`Operation 'addRelations' is only supported on property of 'many' relation`);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
const server = this.#server;
|
|
778
|
+
const { queryBuilder } = server;
|
|
779
|
+
if (relationProperty.linkTableName) {
|
|
780
|
+
for (const relation of relations) {
|
|
781
|
+
const command = `INSERT INTO ${queryBuilder.quoteTable({schema:relationProperty.linkSchema, tableName: relationProperty.linkTableName})} (${queryBuilder.quoteObject(relationProperty.selfIdColumnName!)}, ${queryBuilder.quoteObject(relationProperty.targetIdColumnName!)})
|
|
782
|
+
SELECT $1, $2 WHERE NOT EXISTS (
|
|
783
|
+
SELECT ${queryBuilder.quoteObject(relationProperty.selfIdColumnName!)}, ${queryBuilder.quoteObject(relationProperty.targetIdColumnName!)}
|
|
784
|
+
FROM ${queryBuilder.quoteTable({schema:relationProperty.linkSchema, tableName: relationProperty.linkTableName})}
|
|
785
|
+
WHERE ${queryBuilder.quoteObject(relationProperty.selfIdColumnName!)}=$1 AND ${queryBuilder.quoteObject(relationProperty.targetIdColumnName!)}=$2
|
|
786
|
+
)`;
|
|
787
|
+
const params = [id, relation.id];
|
|
788
|
+
await server.queryDatabaseObject(command, params);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
server.emitEvent(
|
|
793
|
+
"entity.addRelations",
|
|
794
|
+
plugin,
|
|
795
|
+
{
|
|
796
|
+
namespace: model.namespace,
|
|
797
|
+
modelSingularCode: model.singularCode,
|
|
798
|
+
entity,
|
|
799
|
+
property,
|
|
800
|
+
relations,
|
|
801
|
+
},
|
|
802
|
+
);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
async removeRelations(options: RemoveEntityRelationsOptions, plugin: RapidPlugin): Promise<void> {
|
|
806
|
+
const model = this.getModel();
|
|
807
|
+
const {id, property, relations} = options;
|
|
808
|
+
const entity = await this.findById(id);
|
|
809
|
+
if (!entity) {
|
|
810
|
+
throw new Error(`${model.namespace}.${model.singularCode} with id "${id}" was not found.`);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
const relationProperty = model.properties.find(e => e.code === property);
|
|
814
|
+
if (!relationProperty) {
|
|
815
|
+
throw new Error(`Property '${property}' was not found in ${model.namespace}.${model.singularCode}`);
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
if (!(isRelationProperty(relationProperty) && relationProperty.relation === "many")) {
|
|
819
|
+
throw new Error(`Operation 'removeRelations' is only supported on property of 'many' relation`);
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
const server = this.#server;
|
|
823
|
+
const { queryBuilder } = server;
|
|
824
|
+
if (relationProperty.linkTableName) {
|
|
825
|
+
for (const relation of relations) {
|
|
826
|
+
const command = `DELETE FROM ${queryBuilder.quoteTable({schema:relationProperty.linkSchema, tableName: relationProperty.linkTableName})}
|
|
827
|
+
WHERE ${queryBuilder.quoteObject(relationProperty.selfIdColumnName!)}=$1 AND ${queryBuilder.quoteObject(relationProperty.targetIdColumnName!)}=$2;`;
|
|
828
|
+
const params = [id, relation.id];
|
|
829
|
+
await server.queryDatabaseObject(command, params);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
server.emitEvent(
|
|
834
|
+
"entity.removeRelations",
|
|
835
|
+
plugin,
|
|
836
|
+
{
|
|
837
|
+
namespace: model.namespace,
|
|
838
|
+
modelSingularCode: model.singularCode,
|
|
839
|
+
entity,
|
|
840
|
+
property,
|
|
841
|
+
relations,
|
|
842
|
+
},
|
|
843
|
+
);
|
|
701
844
|
}
|
|
702
845
|
}
|
package/src/index.ts
CHANGED
|
@@ -19,4 +19,8 @@ export { default as DataManagePlugin } from "./plugins/dataManage/DataManagePlug
|
|
|
19
19
|
export { default as RouteManagePlugin } from "./plugins/routeManage/RouteManagePlugin";
|
|
20
20
|
export { default as WebhooksPlugin } from "./plugins/webhooks/WebhooksPlugin";
|
|
21
21
|
export { default as AuthPlugin } from "./plugins/auth/AuthPlugin";
|
|
22
|
-
export { default as FileManagePlugin } from "./plugins/fileManage/FileManagePlugin";
|
|
22
|
+
export { default as FileManagePlugin } from "./plugins/fileManage/FileManagePlugin";
|
|
23
|
+
export { default as ServerOperationPlugin } from "./plugins/serverOperation/ServerOperationPlugin";
|
|
24
|
+
export * from "./plugins/serverOperation/ServerOperationPluginTypes";
|
|
25
|
+
export { default as EntityWatchPlugin } from "./plugins/entityWatch/EntityWatchPlugin";
|
|
26
|
+
export * from "./plugins/entityWatch/EntityWatchPluginTypes";
|
|
@@ -1,24 +1,16 @@
|
|
|
1
1
|
import { RunEntityActionHandlerOptions } from "~/types";
|
|
2
2
|
import { mergeInput } from "~/helpers/inputHelper";
|
|
3
|
-
import { isRelationProperty } from "~/utilities/rapidUtility";
|
|
4
3
|
import { ActionHandlerContext } from "~/core/actionHandler";
|
|
5
4
|
import { RapidPlugin } from "~/core/server";
|
|
6
5
|
|
|
7
6
|
export const code = "addEntityRelations";
|
|
8
7
|
|
|
9
|
-
interface AddEntityRelationsInput {
|
|
10
|
-
id: number;
|
|
11
|
-
property: string;
|
|
12
|
-
relations: {id?: number, [k: string]: any}[];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
8
|
export async function handler(
|
|
16
9
|
plugin: RapidPlugin,
|
|
17
10
|
ctx: ActionHandlerContext,
|
|
18
11
|
options: RunEntityActionHandlerOptions,
|
|
19
12
|
) {
|
|
20
13
|
const { server, input } = ctx;
|
|
21
|
-
const { queryBuilder } = server;
|
|
22
14
|
const { defaultInput, fixedInput } = options;
|
|
23
15
|
|
|
24
16
|
console.debug(`Running ${code} handler...`);
|
|
@@ -28,48 +20,8 @@ export async function handler(
|
|
|
28
20
|
console.debug(`fixedInput: ${JSON.stringify(fixedInput)}`);
|
|
29
21
|
console.debug(`mergedInput: ${JSON.stringify(mergedInput)}`);
|
|
30
22
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const {id, property, relations} = mergedInput as AddEntityRelationsInput;
|
|
35
|
-
const row = await dataAccessor.findById(id);
|
|
36
|
-
if (!row) {
|
|
37
|
-
throw new Error(`${options.namespace}.${options.singularCode} with id "${id}" was not found.`);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const relationProperty = model.properties.find(e => e.code === property);
|
|
41
|
-
if (!relationProperty) {
|
|
42
|
-
throw new Error(`Property '${property}' was not found in ${options.namespace}.${options.singularCode}`);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (!(isRelationProperty(relationProperty) && relationProperty.relation === "many")) {
|
|
46
|
-
throw new Error(`Operation 'createEntityRelations' is only supported on property of 'many' relation`);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (relationProperty.linkTableName) {
|
|
50
|
-
for (const relation of relations) {
|
|
51
|
-
const command = `INSERT INTO ${queryBuilder.quoteTable({schema:relationProperty.linkSchema, tableName: relationProperty.linkTableName})} (${queryBuilder.quoteObject(relationProperty.selfIdColumnName!)}, ${queryBuilder.quoteObject(relationProperty.targetIdColumnName!)})
|
|
52
|
-
SELECT $1, $2 WHERE NOT EXISTS (
|
|
53
|
-
SELECT ${queryBuilder.quoteObject(relationProperty.selfIdColumnName!)}, ${queryBuilder.quoteObject(relationProperty.targetIdColumnName!)}
|
|
54
|
-
FROM ${queryBuilder.quoteTable({schema:relationProperty.linkSchema, tableName: relationProperty.linkTableName})}
|
|
55
|
-
WHERE ${queryBuilder.quoteObject(relationProperty.selfIdColumnName!)}=$1 AND ${queryBuilder.quoteObject(relationProperty.targetIdColumnName!)}=$2
|
|
56
|
-
)`;
|
|
57
|
-
const params = [id, relation.id];
|
|
58
|
-
await server.queryDatabaseObject(command, params);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
23
|
+
const entityManager = server.getEntityManager(options.singularCode);
|
|
24
|
+
await entityManager.addRelations(mergedInput, plugin);
|
|
61
25
|
|
|
62
26
|
ctx.output = {};
|
|
63
|
-
|
|
64
|
-
server.emitEvent(
|
|
65
|
-
"entity.addRelations",
|
|
66
|
-
plugin,
|
|
67
|
-
{
|
|
68
|
-
namespace: options.namespace,
|
|
69
|
-
modelSingularCode: options.singularCode,
|
|
70
|
-
entity: row,
|
|
71
|
-
property,
|
|
72
|
-
relations: relations,
|
|
73
|
-
},
|
|
74
|
-
);
|
|
75
27
|
}
|
|
@@ -37,21 +37,10 @@ export async function handler(
|
|
|
37
37
|
const entityManager = server.getEntityManager(options.singularCode);
|
|
38
38
|
const newEntity = await entityManager.createEntity({
|
|
39
39
|
entity: mergedEntity,
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
server.emitEvent(
|
|
43
|
-
"entity.create",
|
|
44
|
-
plugin,
|
|
45
|
-
{
|
|
46
|
-
namespace: options.namespace,
|
|
47
|
-
modelSingularCode: options.singularCode,
|
|
48
|
-
after: newEntity,
|
|
49
|
-
},
|
|
50
|
-
);
|
|
40
|
+
}, plugin);
|
|
51
41
|
|
|
52
42
|
output.push(newEntity);
|
|
53
43
|
}
|
|
54
44
|
|
|
55
45
|
ctx.output = output;
|
|
56
|
-
|
|
57
46
|
}
|
|
@@ -28,16 +28,6 @@ export async function handler(
|
|
|
28
28
|
const entityManager = server.getEntityManager(options.singularCode);
|
|
29
29
|
const output = await entityManager.createEntity({
|
|
30
30
|
entity: input,
|
|
31
|
-
});
|
|
31
|
+
}, plugin);
|
|
32
32
|
ctx.output = output;
|
|
33
|
-
|
|
34
|
-
server.emitEvent(
|
|
35
|
-
"entity.create",
|
|
36
|
-
plugin,
|
|
37
|
-
{
|
|
38
|
-
namespace: options.namespace,
|
|
39
|
-
modelSingularCode: options.singularCode,
|
|
40
|
-
after: output,
|
|
41
|
-
},
|
|
42
|
-
);
|
|
43
33
|
}
|
|
@@ -14,26 +14,7 @@ export async function handler(
|
|
|
14
14
|
const { server, input } = ctx;
|
|
15
15
|
|
|
16
16
|
const entityManager = server.getEntityManager(options.singularCode);
|
|
17
|
-
|
|
18
|
-
const row = await entityManager.findById(id);
|
|
19
|
-
if (!row) {
|
|
20
|
-
ctx.status = 200;
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
await entityManager.deleteById(id);
|
|
25
|
-
|
|
26
|
-
const entity = mapDbRowToEntity(entityManager.getModel(), row);
|
|
27
|
-
|
|
28
|
-
server.emitEvent(
|
|
29
|
-
"entity.delete",
|
|
30
|
-
plugin,
|
|
31
|
-
{
|
|
32
|
-
namespace: options.namespace,
|
|
33
|
-
modelSingularCode: options.singularCode,
|
|
34
|
-
before: entity,
|
|
35
|
-
},
|
|
36
|
-
);
|
|
17
|
+
await entityManager.deleteById(input.id, plugin);
|
|
37
18
|
|
|
38
19
|
ctx.status = 200;
|
|
39
20
|
}
|
|
@@ -1,24 +1,16 @@
|
|
|
1
1
|
import { RunEntityActionHandlerOptions } from "~/types";
|
|
2
2
|
import { mergeInput } from "~/helpers/inputHelper";
|
|
3
|
-
import { isRelationProperty } from "~/utilities/rapidUtility";
|
|
4
3
|
import { ActionHandlerContext } from "~/core/actionHandler";
|
|
5
4
|
import { RapidPlugin } from "~/core/server";
|
|
6
5
|
|
|
7
6
|
export const code = "removeEntityRelations";
|
|
8
7
|
|
|
9
|
-
interface RemoveEntityRelationsInput {
|
|
10
|
-
id: number;
|
|
11
|
-
property: string;
|
|
12
|
-
relations: {id?: number, [k: string]: any}[];
|
|
13
|
-
}
|
|
14
|
-
|
|
15
8
|
export async function handler(
|
|
16
9
|
plugin: RapidPlugin,
|
|
17
10
|
ctx: ActionHandlerContext,
|
|
18
11
|
options: RunEntityActionHandlerOptions,
|
|
19
12
|
) {
|
|
20
13
|
const { server, input } = ctx;
|
|
21
|
-
const { queryBuilder } = server;
|
|
22
14
|
const { defaultInput, fixedInput } = options;
|
|
23
15
|
|
|
24
16
|
console.debug(`Running ${code} handler...`);
|
|
@@ -28,46 +20,8 @@ export async function handler(
|
|
|
28
20
|
console.debug(`fixedInput: ${JSON.stringify(fixedInput)}`);
|
|
29
21
|
console.debug(`mergedInput: ${JSON.stringify(mergedInput)}`);
|
|
30
22
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const {id, property, relations} = mergedInput as RemoveEntityRelationsInput;
|
|
35
|
-
const row = await dataAccessor.findById(id);
|
|
36
|
-
if (!row) {
|
|
37
|
-
throw new Error(`${options.namespace}.${options.singularCode} with id "${id}" was not found.`);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
console.log(mergedInput);
|
|
41
|
-
|
|
42
|
-
const relationProperty = model.properties.find(e => e.code === property);
|
|
43
|
-
if (!relationProperty) {
|
|
44
|
-
throw new Error(`Property '${property}' was not found in ${options.namespace}.${options.singularCode}`);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (!(isRelationProperty(relationProperty) && relationProperty.relation === "many")) {
|
|
48
|
-
throw new Error(`Operation 'createEntityRelations' is only supported on property of 'many' relation`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (relationProperty.linkTableName) {
|
|
52
|
-
for (const relation of relations) {
|
|
53
|
-
const command = `DELETE FROM ${queryBuilder.quoteTable({schema:relationProperty.linkSchema, tableName: relationProperty.linkTableName})}
|
|
54
|
-
WHERE ${queryBuilder.quoteObject(relationProperty.selfIdColumnName!)}=$1 AND ${queryBuilder.quoteObject(relationProperty.targetIdColumnName!)}=$2;`;
|
|
55
|
-
const params = [id, relation.id];
|
|
56
|
-
await server.queryDatabaseObject(command, params);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
23
|
+
const entityManager = server.getEntityManager(options.singularCode);
|
|
24
|
+
await entityManager.removeRelations(mergedInput, plugin);
|
|
59
25
|
|
|
60
26
|
ctx.output = {};
|
|
61
|
-
|
|
62
|
-
server.emitEvent(
|
|
63
|
-
"entity.removeRelations",
|
|
64
|
-
plugin,
|
|
65
|
-
{
|
|
66
|
-
namespace: options.namespace,
|
|
67
|
-
modelSingularCode: options.singularCode,
|
|
68
|
-
entity: row,
|
|
69
|
-
property,
|
|
70
|
-
relations: relations,
|
|
71
|
-
},
|
|
72
|
-
);
|
|
73
27
|
}
|
|
@@ -23,31 +23,7 @@ export async function handler(
|
|
|
23
23
|
console.debug(`mergedInput: ${JSON.stringify(mergedInput)}`);
|
|
24
24
|
|
|
25
25
|
const entityManager = server.getEntityManager(options.singularCode);
|
|
26
|
-
const id = mergedInput.id;
|
|
27
|
-
const row = await entityManager.findById(id);
|
|
28
|
-
if (!row) {
|
|
29
|
-
throw new Error(`${options.namespace}.${options.singularCode} with id "${id}" was not found.`);
|
|
30
|
-
}
|
|
31
26
|
|
|
32
|
-
const
|
|
33
|
-
const changes = getEntityPartChanges(entity, mergedInput);
|
|
34
|
-
if (!changes) {
|
|
35
|
-
ctx.output = entity;
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const output = await entityManager.updateEntityById({ id, entity, changes });
|
|
27
|
+
const output = await entityManager.updateEntityById({ id: mergedInput.id, entityToSave: mergedInput }, plugin);
|
|
40
28
|
ctx.output = output;
|
|
41
|
-
|
|
42
|
-
server.emitEvent(
|
|
43
|
-
"entity.update",
|
|
44
|
-
plugin,
|
|
45
|
-
{
|
|
46
|
-
namespace: options.namespace,
|
|
47
|
-
modelSingularCode: options.singularCode,
|
|
48
|
-
before: entity,
|
|
49
|
-
after: output,
|
|
50
|
-
changes: changes,
|
|
51
|
-
},
|
|
52
|
-
);
|
|
53
29
|
}
|