@memberjunction/server 2.111.1 → 2.112.0
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/agents/skip-agent.d.ts +4 -4
- package/dist/agents/skip-agent.d.ts.map +1 -1
- package/dist/agents/skip-agent.js +808 -951
- package/dist/agents/skip-agent.js.map +1 -1
- package/dist/agents/skip-sdk.d.ts +1 -1
- package/dist/agents/skip-sdk.d.ts.map +1 -1
- package/dist/agents/skip-sdk.js +53 -43
- package/dist/agents/skip-sdk.js.map +1 -1
- package/dist/apolloServer/index.js +1 -1
- package/dist/auth/AuthProviderFactory.d.ts +1 -1
- package/dist/auth/AuthProviderFactory.d.ts.map +1 -1
- package/dist/auth/AuthProviderFactory.js +1 -3
- package/dist/auth/AuthProviderFactory.js.map +1 -1
- package/dist/auth/BaseAuthProvider.d.ts +1 -1
- package/dist/auth/BaseAuthProvider.d.ts.map +1 -1
- package/dist/auth/BaseAuthProvider.js +3 -2
- package/dist/auth/BaseAuthProvider.js.map +1 -1
- package/dist/auth/IAuthProvider.d.ts +1 -1
- package/dist/auth/IAuthProvider.d.ts.map +1 -1
- package/dist/auth/exampleNewUserSubClass.d.ts.map +1 -1
- package/dist/auth/exampleNewUserSubClass.js +1 -1
- package/dist/auth/exampleNewUserSubClass.js.map +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +6 -6
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/initializeProviders.js +1 -1
- package/dist/auth/initializeProviders.js.map +1 -1
- package/dist/auth/newUsers.d.ts +1 -1
- package/dist/auth/newUsers.d.ts.map +1 -1
- package/dist/auth/newUsers.js +7 -7
- package/dist/auth/newUsers.js.map +1 -1
- package/dist/auth/providers/Auth0Provider.d.ts +1 -1
- package/dist/auth/providers/Auth0Provider.d.ts.map +1 -1
- package/dist/auth/providers/Auth0Provider.js +1 -1
- package/dist/auth/providers/Auth0Provider.js.map +1 -1
- package/dist/auth/providers/CognitoProvider.d.ts +1 -1
- package/dist/auth/providers/CognitoProvider.d.ts.map +1 -1
- package/dist/auth/providers/CognitoProvider.js +3 -6
- package/dist/auth/providers/CognitoProvider.js.map +1 -1
- package/dist/auth/providers/GoogleProvider.d.ts +1 -1
- package/dist/auth/providers/GoogleProvider.d.ts.map +1 -1
- package/dist/auth/providers/GoogleProvider.js +1 -1
- package/dist/auth/providers/GoogleProvider.js.map +1 -1
- package/dist/auth/providers/MSALProvider.d.ts +1 -1
- package/dist/auth/providers/MSALProvider.d.ts.map +1 -1
- package/dist/auth/providers/MSALProvider.js +1 -1
- package/dist/auth/providers/MSALProvider.js.map +1 -1
- package/dist/auth/providers/OktaProvider.d.ts +1 -1
- package/dist/auth/providers/OktaProvider.d.ts.map +1 -1
- package/dist/auth/providers/OktaProvider.js +1 -1
- package/dist/auth/providers/OktaProvider.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +22 -10
- package/dist/config.js.map +1 -1
- package/dist/context.d.ts +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +9 -7
- package/dist/context.js.map +1 -1
- package/dist/entitySubclasses/entityPermissions.server.d.ts +1 -1
- package/dist/entitySubclasses/entityPermissions.server.d.ts.map +1 -1
- package/dist/entitySubclasses/entityPermissions.server.js +1 -1
- package/dist/entitySubclasses/entityPermissions.server.js.map +1 -1
- package/dist/generated/generated.d.ts +648 -648
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +2986 -1133
- package/dist/generated/generated.js.map +1 -1
- package/dist/generic/KeyInputOutputTypes.d.ts +1 -1
- package/dist/generic/KeyInputOutputTypes.d.ts.map +1 -1
- package/dist/generic/KeyInputOutputTypes.js +1 -1
- package/dist/generic/KeyInputOutputTypes.js.map +1 -1
- package/dist/generic/ResolverBase.d.ts +1 -1
- package/dist/generic/ResolverBase.d.ts.map +1 -1
- package/dist/generic/ResolverBase.js +15 -10
- package/dist/generic/ResolverBase.js.map +1 -1
- package/dist/generic/RunViewResolver.d.ts +1 -1
- package/dist/generic/RunViewResolver.d.ts.map +1 -1
- package/dist/generic/RunViewResolver.js +15 -15
- package/dist/generic/RunViewResolver.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -9
- package/dist/index.js.map +1 -1
- package/dist/resolvers/ActionResolver.d.ts +2 -2
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +28 -30
- package/dist/resolvers/ActionResolver.js.map +1 -1
- package/dist/resolvers/AskSkipResolver.d.ts +2 -2
- package/dist/resolvers/AskSkipResolver.d.ts.map +1 -1
- package/dist/resolvers/AskSkipResolver.js +60 -50
- package/dist/resolvers/AskSkipResolver.js.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.d.ts.map +1 -1
- package/dist/resolvers/ComponentRegistryResolver.js +36 -38
- package/dist/resolvers/ComponentRegistryResolver.js.map +1 -1
- package/dist/resolvers/CreateQueryResolver.d.ts +1 -1
- package/dist/resolvers/CreateQueryResolver.d.ts.map +1 -1
- package/dist/resolvers/CreateQueryResolver.js +43 -40
- package/dist/resolvers/CreateQueryResolver.js.map +1 -1
- package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
- package/dist/resolvers/DatasetResolver.js +1 -1
- package/dist/resolvers/DatasetResolver.js.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.d.ts +1 -1
- package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.js +1 -1
- package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
- package/dist/resolvers/EntityResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityResolver.js +1 -1
- package/dist/resolvers/EntityResolver.js.map +1 -1
- package/dist/resolvers/FileCategoryResolver.js +1 -1
- package/dist/resolvers/FileCategoryResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.js +1 -1
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts +1 -1
- package/dist/resolvers/GetDataContextDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.js +5 -5
- package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
- package/dist/resolvers/GetDataResolver.d.ts.map +1 -1
- package/dist/resolvers/GetDataResolver.js +8 -6
- package/dist/resolvers/GetDataResolver.js.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.d.ts +3 -3
- package/dist/resolvers/MergeRecordsResolver.d.ts.map +1 -1
- package/dist/resolvers/MergeRecordsResolver.js +3 -3
- package/dist/resolvers/MergeRecordsResolver.js.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.d.ts +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.d.ts.map +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js +1 -1
- package/dist/resolvers/PotentialDuplicateRecordResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +11 -11
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/ReportResolver.js +1 -1
- package/dist/resolvers/ReportResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +27 -28
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.js +31 -31
- package/dist/resolvers/RunAIPromptResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +9 -9
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +10 -10
- package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
- package/dist/resolvers/SyncDataResolver.d.ts +1 -1
- package/dist/resolvers/SyncDataResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncDataResolver.js +15 -14
- package/dist/resolvers/SyncDataResolver.js.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.d.ts +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.d.ts.map +1 -1
- package/dist/resolvers/SyncRolesUsersResolver.js +48 -44
- package/dist/resolvers/SyncRolesUsersResolver.js.map +1 -1
- package/dist/resolvers/TaskResolver.d.ts.map +1 -1
- package/dist/resolvers/TaskResolver.js +7 -7
- package/dist/resolvers/TaskResolver.js.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts +1 -1
- package/dist/resolvers/TransactionGroupResolver.d.ts.map +1 -1
- package/dist/resolvers/TransactionGroupResolver.js +12 -12
- package/dist/resolvers/TransactionGroupResolver.js.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.d.ts +1 -1
- package/dist/resolvers/UserFavoriteResolver.d.ts.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.js +1 -1
- package/dist/resolvers/UserFavoriteResolver.js.map +1 -1
- package/dist/resolvers/UserViewResolver.d.ts.map +1 -1
- package/dist/resolvers/UserViewResolver.js.map +1 -1
- package/dist/rest/EntityCRUDHandler.d.ts +1 -1
- package/dist/rest/EntityCRUDHandler.d.ts.map +1 -1
- package/dist/rest/EntityCRUDHandler.js +14 -16
- package/dist/rest/EntityCRUDHandler.js.map +1 -1
- package/dist/rest/RESTEndpointHandler.d.ts.map +1 -1
- package/dist/rest/RESTEndpointHandler.js +23 -25
- package/dist/rest/RESTEndpointHandler.js.map +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts +1 -1
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -1
- package/dist/rest/ViewOperationsHandler.js +17 -21
- package/dist/rest/ViewOperationsHandler.js.map +1 -1
- package/dist/scheduler/LearningCycleScheduler.d.ts.map +1 -1
- package/dist/scheduler/LearningCycleScheduler.js.map +1 -1
- package/dist/services/ScheduledJobsService.d.ts.map +1 -1
- package/dist/services/ScheduledJobsService.js +4 -6
- package/dist/services/ScheduledJobsService.js.map +1 -1
- package/dist/services/TaskOrchestrator.d.ts +1 -1
- package/dist/services/TaskOrchestrator.d.ts.map +1 -1
- package/dist/services/TaskOrchestrator.js +30 -30
- package/dist/services/TaskOrchestrator.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -1
- package/dist/types.js.map +1 -1
- package/dist/util.d.ts +1 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +2 -2
- package/dist/util.js.map +1 -1
- package/package.json +36 -37
- package/src/agents/skip-agent.ts +1067 -1200
- package/src/agents/skip-sdk.ts +877 -851
- package/src/apolloServer/index.ts +2 -2
- package/src/auth/AuthProviderFactory.ts +8 -14
- package/src/auth/BaseAuthProvider.ts +5 -4
- package/src/auth/IAuthProvider.ts +2 -2
- package/src/auth/exampleNewUserSubClass.ts +9 -2
- package/src/auth/index.ts +31 -26
- package/src/auth/initializeProviders.ts +3 -3
- package/src/auth/newUsers.ts +166 -134
- package/src/auth/providers/Auth0Provider.ts +5 -5
- package/src/auth/providers/CognitoProvider.ts +7 -10
- package/src/auth/providers/GoogleProvider.ts +4 -5
- package/src/auth/providers/MSALProvider.ts +5 -5
- package/src/auth/providers/OktaProvider.ts +6 -7
- package/src/config.ts +63 -54
- package/src/context.ts +42 -30
- package/src/entitySubclasses/entityPermissions.server.ts +3 -3
- package/src/generated/generated.ts +48130 -39930
- package/src/generic/KeyInputOutputTypes.ts +3 -6
- package/src/generic/ResolverBase.ts +119 -78
- package/src/generic/RunViewResolver.ts +27 -23
- package/src/index.ts +66 -42
- package/src/resolvers/ActionResolver.ts +46 -57
- package/src/resolvers/AskSkipResolver.ts +607 -533
- package/src/resolvers/ComponentRegistryResolver.ts +547 -562
- package/src/resolvers/CreateQueryResolver.ts +683 -655
- package/src/resolvers/DatasetResolver.ts +5 -6
- package/src/resolvers/EntityCommunicationsResolver.ts +1 -1
- package/src/resolvers/EntityRecordNameResolver.ts +9 -5
- package/src/resolvers/EntityResolver.ts +9 -7
- package/src/resolvers/FileCategoryResolver.ts +2 -2
- package/src/resolvers/FileResolver.ts +4 -4
- package/src/resolvers/GetDataContextDataResolver.ts +106 -118
- package/src/resolvers/GetDataResolver.ts +194 -205
- package/src/resolvers/MergeRecordsResolver.ts +5 -5
- package/src/resolvers/PotentialDuplicateRecordResolver.ts +1 -1
- package/src/resolvers/QueryResolver.ts +95 -78
- package/src/resolvers/ReportResolver.ts +2 -2
- package/src/resolvers/RunAIAgentResolver.ts +818 -828
- package/src/resolvers/RunAIPromptResolver.ts +693 -709
- package/src/resolvers/RunTemplateResolver.ts +105 -103
- package/src/resolvers/SqlLoggingConfigResolver.ts +69 -72
- package/src/resolvers/SyncDataResolver.ts +386 -352
- package/src/resolvers/SyncRolesUsersResolver.ts +387 -350
- package/src/resolvers/TaskResolver.ts +110 -115
- package/src/resolvers/TransactionGroupResolver.ts +143 -138
- package/src/resolvers/UserFavoriteResolver.ts +17 -8
- package/src/resolvers/UserViewResolver.ts +17 -12
- package/src/rest/EntityCRUDHandler.ts +291 -268
- package/src/rest/RESTEndpointHandler.ts +782 -776
- package/src/rest/ViewOperationsHandler.ts +191 -195
- package/src/scheduler/LearningCycleScheduler.ts +8 -52
- package/src/services/ScheduledJobsService.ts +129 -132
- package/src/services/TaskOrchestrator.ts +792 -776
- package/src/types.ts +15 -9
- package/src/util.ts +112 -109
|
@@ -1,90 +1,95 @@
|
|
|
1
1
|
import { Arg, Ctx, Field, InputType, Mutation, ObjectType, registerEnumType } from 'type-graphql';
|
|
2
2
|
import { AppContext, UserPayload } from '../types.js';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
BaseEntity,
|
|
5
|
+
CompositeKey,
|
|
6
|
+
EntityDeleteOptions,
|
|
7
|
+
EntitySaveOptions,
|
|
8
|
+
LogError,
|
|
9
|
+
Metadata,
|
|
10
|
+
RunView,
|
|
11
|
+
UserInfo,
|
|
12
|
+
} from '@memberjunction/global';
|
|
4
13
|
import { RequireSystemUser } from '../directives/RequireSystemUser.js';
|
|
5
14
|
import { CompositeKeyInputType, CompositeKeyOutputType } from '../generic/KeyInputOutputTypes.js';
|
|
6
15
|
import { DatasetItemEntity } from '@memberjunction/core-entities';
|
|
7
16
|
|
|
8
|
-
|
|
9
|
-
|
|
10
17
|
/**
|
|
11
18
|
* This type defines the possible list of actions that can be taken in syncing data: Create, Update, CreateOrUpdate, Delete, or DeleteWithFilter
|
|
12
19
|
* DeleteWithFilter is where you specify a valid SQL expression that can be used in a where clause to get a list of records in a given entity to delete
|
|
13
20
|
* this can be used to ensure cleaning out data from a subset of a given table.
|
|
14
21
|
*/
|
|
15
22
|
export enum SyncDataActionType {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
23
|
+
Create = 'Create',
|
|
24
|
+
Update = 'Update',
|
|
25
|
+
CreateOrUpdate = 'CreateOrUpdate',
|
|
26
|
+
Delete = 'Delete',
|
|
27
|
+
DeleteWithFilter = 'DeleteWithFilter',
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
registerEnumType(SyncDataActionType, {
|
|
31
|
+
name: 'SyncDataActionType', // GraphQL Enum Name
|
|
32
|
+
description: 'Specifies the type of action to be taken in syncing, Create, Update, CreateOrUpdate, Delete', // Description,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
@InputType()
|
|
36
|
+
export class ActionItemInputType {
|
|
37
|
+
@Field(() => String)
|
|
38
|
+
EntityName!: string;
|
|
39
|
+
|
|
40
|
+
@Field(() => CompositeKeyInputType, { nullable: true })
|
|
41
|
+
PrimaryKey?: CompositeKeyInputType;
|
|
42
|
+
|
|
43
|
+
@Field(() => CompositeKeyInputType, { nullable: true })
|
|
44
|
+
AlternateKey?: CompositeKeyInputType;
|
|
45
|
+
|
|
46
|
+
@Field(() => SyncDataActionType)
|
|
47
|
+
Type!: SyncDataActionType;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* This field is a JSON representation of the field values of the entity to be created or updated. It is used for all ActionTypes except for
|
|
51
|
+
*/
|
|
52
|
+
@Field(() => String, { nullable: true })
|
|
53
|
+
RecordJSON?: string;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* This field is only provided when the Action Type is DeleteWithFilter. It is a valid SQL expression that can be used in a where clause to get a list of records in a given entity to delete
|
|
57
|
+
*/
|
|
58
|
+
@Field(() => String, { nullable: true })
|
|
59
|
+
DeleteFilter?: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
57
62
|
@ObjectType()
|
|
58
63
|
export class ActionItemOutputType {
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
@Field(() => Boolean)
|
|
65
|
+
Success: boolean;
|
|
61
66
|
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
@Field(() => String)
|
|
68
|
+
ErrorMessage: string;
|
|
64
69
|
|
|
65
|
-
|
|
66
|
-
|
|
70
|
+
@Field(() => String)
|
|
71
|
+
EntityName!: string;
|
|
67
72
|
|
|
68
|
-
|
|
69
|
-
|
|
73
|
+
@Field(() => CompositeKeyOutputType, { nullable: true })
|
|
74
|
+
PrimaryKey?: CompositeKeyOutputType;
|
|
70
75
|
|
|
71
|
-
|
|
72
|
-
|
|
76
|
+
@Field(() => CompositeKeyOutputType, { nullable: true })
|
|
77
|
+
AlternateKey?: CompositeKeyOutputType;
|
|
73
78
|
|
|
74
|
-
|
|
75
|
-
|
|
79
|
+
@Field(() => SyncDataActionType)
|
|
80
|
+
Type!: SyncDataActionType;
|
|
76
81
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
/**
|
|
83
|
+
* This field is a JSON representation of the field values of the entity to be created or updated. It is used for all ActionTypes except for
|
|
84
|
+
*/
|
|
85
|
+
@Field(() => String, { nullable: true })
|
|
86
|
+
RecordJSON?: string;
|
|
82
87
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
/**
|
|
89
|
+
* This field is only provided when the Action Type is DeleteWithFilter. It is a valid SQL expression that can be used in a where clause to get a list of records in a given entity to delete
|
|
90
|
+
*/
|
|
91
|
+
@Field(() => String, { nullable: true })
|
|
92
|
+
DeleteFilter?: string;
|
|
88
93
|
}
|
|
89
94
|
|
|
90
95
|
@ObjectType()
|
|
@@ -96,318 +101,347 @@ export class SyncDataResultType {
|
|
|
96
101
|
Results: ActionItemOutputType[] = [];
|
|
97
102
|
}
|
|
98
103
|
|
|
99
|
-
|
|
100
104
|
const __metadata_DatasetItems: string[] = [];
|
|
101
105
|
|
|
102
106
|
export class SyncDataResolver {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
for (const item of items) {
|
|
118
|
-
results.push(await this.SyncSingleItem(item, context, md, context.userPayload));
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (await this.DoSyncItemsAffectMetadata(context.userPayload.userRecord, items)) {
|
|
122
|
-
await md.Refresh(); // force refesh the metadata which will cause a reload from the DB
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const overallSuccess = !results.some((r) => !r.Success); // if any element in the array of results has a Success value of false, then the overall success is false
|
|
126
|
-
return { Success: overallSuccess, Results: results };
|
|
127
|
-
}
|
|
128
|
-
catch (err) {
|
|
129
|
-
LogError(err);
|
|
130
|
-
throw new Error('SyncDataResolver::SyncData --- Error Syncing Data\n\n' + err);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
107
|
+
/**
|
|
108
|
+
* This mutation will sync the specified items with the existing system. Items will be processed in order and the results of each operation will be returned in the Results array within the return value.
|
|
109
|
+
* @param items - an array of ActionItemInputType objects that specify the action to be taken on the specified entity with the specified primary key and the JSON representation of the field values.
|
|
110
|
+
*/
|
|
111
|
+
@RequireSystemUser()
|
|
112
|
+
@Mutation(() => SyncDataResultType)
|
|
113
|
+
async SyncData(@Arg('items', () => [ActionItemInputType]) items: ActionItemInputType[], @Ctx() context: AppContext) {
|
|
114
|
+
try {
|
|
115
|
+
// iterate through the items
|
|
116
|
+
const md = new Metadata();
|
|
117
|
+
const results: ActionItemOutputType[] = [];
|
|
118
|
+
for (const item of items) {
|
|
119
|
+
results.push(await this.SyncSingleItem(item, context, md, context.userPayload));
|
|
120
|
+
}
|
|
133
121
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const result = await rv.RunView<DatasetItemEntity>({
|
|
138
|
-
EntityName: "Dataset Items",
|
|
139
|
-
ExtraFilter: "Dataset = 'MJ_Metadata'",
|
|
140
|
-
}, user)
|
|
141
|
-
if (result && result.Success) {
|
|
142
|
-
__metadata_DatasetItems.length = 0;
|
|
143
|
-
__metadata_DatasetItems.push(...result.Results.map((r) => {
|
|
144
|
-
return r.Entity.trim().toLowerCase();
|
|
145
|
-
}));
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
// now return the list of entities
|
|
149
|
-
return __metadata_DatasetItems;
|
|
150
|
-
}
|
|
122
|
+
if (await this.DoSyncItemsAffectMetadata(context.userPayload.userRecord, items)) {
|
|
123
|
+
await md.Refresh(); // force refesh the metadata which will cause a reload from the DB
|
|
124
|
+
}
|
|
151
125
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return true;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return false; // didn't find any
|
|
126
|
+
const overallSuccess = !results.some((r) => !r.Success); // if any element in the array of results has a Success value of false, then the overall success is false
|
|
127
|
+
return { Success: overallSuccess, Results: results };
|
|
128
|
+
} catch (err) {
|
|
129
|
+
LogError(err);
|
|
130
|
+
throw new Error('SyncDataResolver::SyncData --- Error Syncing Data\n\n' + err);
|
|
161
131
|
}
|
|
132
|
+
}
|
|
162
133
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
case SyncDataActionType.Create:
|
|
182
|
-
await this.SyncSingleItemCreate(entityObject, fieldValues, result, userPayload);
|
|
183
|
-
break;
|
|
184
|
-
case SyncDataActionType.Update:
|
|
185
|
-
await this.SyncSingleItemUpdate(entityObject, pk, ak, fieldValues, result, userPayload);
|
|
186
|
-
break;
|
|
187
|
-
case SyncDataActionType.CreateOrUpdate:
|
|
188
|
-
// in this case we attempt to load the item first, if it is not possible to load the item, then we create it
|
|
189
|
-
await this.SyncSingleItemCreateOrUpdate(entityObject, pk, ak, fieldValues, result, userPayload);
|
|
190
|
-
break;
|
|
191
|
-
case SyncDataActionType.Delete:
|
|
192
|
-
await this.SyncSingleItemDelete(entityObject, pk, ak, result, userPayload);
|
|
193
|
-
break;
|
|
194
|
-
case SyncDataActionType.DeleteWithFilter:
|
|
195
|
-
await this.SyncSingleItemDeleteWithFilter(item.EntityName, item.DeleteFilter, result, context.userPayload.userRecord, userPayload);
|
|
196
|
-
break;
|
|
197
|
-
default:
|
|
198
|
-
throw new Error('Invalid SyncDataActionType');
|
|
199
|
-
}
|
|
200
|
-
} else {
|
|
201
|
-
throw new Error('Entity not found');
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
catch (err) {
|
|
205
|
-
result.ErrorMessage = typeof err === 'string' ? err : (err as any).message;
|
|
206
|
-
LogError(err);
|
|
207
|
-
}
|
|
208
|
-
finally {
|
|
209
|
-
return result;
|
|
210
|
-
}
|
|
134
|
+
protected async GetLowercaseMetadataEntitiesList(user: UserInfo, forceRefresh: boolean = false): Promise<string[]> {
|
|
135
|
+
if (forceRefresh || __metadata_DatasetItems.length === 0) {
|
|
136
|
+
const rv = new RunView(); // cache this, veyr simple - should use an engine for this stuff later
|
|
137
|
+
const result = await rv.RunView<DatasetItemEntity>(
|
|
138
|
+
{
|
|
139
|
+
EntityName: 'Dataset Items',
|
|
140
|
+
ExtraFilter: "Dataset = 'MJ_Metadata'",
|
|
141
|
+
},
|
|
142
|
+
user
|
|
143
|
+
);
|
|
144
|
+
if (result && result.Success) {
|
|
145
|
+
__metadata_DatasetItems.length = 0;
|
|
146
|
+
__metadata_DatasetItems.push(
|
|
147
|
+
...result.Results.map((r) => {
|
|
148
|
+
return r.Entity.trim().toLowerCase();
|
|
149
|
+
})
|
|
150
|
+
);
|
|
151
|
+
}
|
|
211
152
|
}
|
|
153
|
+
// now return the list of entities
|
|
154
|
+
return __metadata_DatasetItems;
|
|
155
|
+
}
|
|
212
156
|
|
|
157
|
+
protected async DoSyncItemsAffectMetadata(user: UserInfo, items: ActionItemInputType[]): Promise<boolean> {
|
|
158
|
+
// check to see if any of the items affect any of these entities:
|
|
159
|
+
const entitiesToCheck = await this.GetLowercaseMetadataEntitiesList(user, false);
|
|
160
|
+
for (const item of items) {
|
|
161
|
+
if (entitiesToCheck.find((e) => e === item.EntityName.trim().toLowerCase())) {
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return false; // didn't find any
|
|
166
|
+
}
|
|
213
167
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
168
|
+
protected async SyncSingleItem(
|
|
169
|
+
item: ActionItemInputType,
|
|
170
|
+
context: AppContext,
|
|
171
|
+
md: Metadata,
|
|
172
|
+
userPayload: UserPayload
|
|
173
|
+
): Promise<ActionItemOutputType> {
|
|
174
|
+
const result = new ActionItemOutputType();
|
|
175
|
+
result.AlternateKey = item.AlternateKey;
|
|
176
|
+
result.PrimaryKey = item.PrimaryKey;
|
|
177
|
+
result.DeleteFilter = item.DeleteFilter;
|
|
178
|
+
result.EntityName = item.EntityName;
|
|
179
|
+
result.RecordJSON = item.RecordJSON;
|
|
180
|
+
result.Type = item.Type;
|
|
181
|
+
result.Success = false;
|
|
182
|
+
result.ErrorMessage = '';
|
|
183
|
+
try {
|
|
184
|
+
const e = md.Entities.find((e) => e.Name === item.EntityName);
|
|
185
|
+
if (e) {
|
|
186
|
+
const pk = item.PrimaryKey ? new CompositeKey(item.PrimaryKey.KeyValuePairs) : null;
|
|
187
|
+
const ak = item.AlternateKey ? new CompositeKey(item.AlternateKey.KeyValuePairs) : null;
|
|
188
|
+
const entityObject =
|
|
189
|
+
item.Type === SyncDataActionType.DeleteWithFilter ? null : await md.GetEntityObject(e.Name, context.userPayload.userRecord);
|
|
190
|
+
const fieldValues = item.RecordJSON ? JSON.parse(item.RecordJSON) : {};
|
|
191
|
+
switch (item.Type) {
|
|
192
|
+
case SyncDataActionType.Create:
|
|
193
|
+
await this.SyncSingleItemCreate(entityObject, fieldValues, result, userPayload);
|
|
194
|
+
break;
|
|
195
|
+
case SyncDataActionType.Update:
|
|
196
|
+
await this.SyncSingleItemUpdate(entityObject, pk, ak, fieldValues, result, userPayload);
|
|
197
|
+
break;
|
|
198
|
+
case SyncDataActionType.CreateOrUpdate:
|
|
199
|
+
// in this case we attempt to load the item first, if it is not possible to load the item, then we create it
|
|
200
|
+
await this.SyncSingleItemCreateOrUpdate(entityObject, pk, ak, fieldValues, result, userPayload);
|
|
201
|
+
break;
|
|
202
|
+
case SyncDataActionType.Delete:
|
|
203
|
+
await this.SyncSingleItemDelete(entityObject, pk, ak, result, userPayload);
|
|
204
|
+
break;
|
|
205
|
+
case SyncDataActionType.DeleteWithFilter:
|
|
206
|
+
await this.SyncSingleItemDeleteWithFilter(
|
|
207
|
+
item.EntityName,
|
|
208
|
+
item.DeleteFilter,
|
|
209
|
+
result,
|
|
210
|
+
context.userPayload.userRecord,
|
|
211
|
+
userPayload
|
|
212
|
+
);
|
|
213
|
+
break;
|
|
214
|
+
default:
|
|
215
|
+
throw new Error('Invalid SyncDataActionType');
|
|
244
216
|
}
|
|
217
|
+
} else {
|
|
218
|
+
throw new Error('Entity not found');
|
|
219
|
+
}
|
|
220
|
+
} catch (err) {
|
|
221
|
+
result.ErrorMessage = typeof err === 'string' ? err : (err as any).message;
|
|
222
|
+
LogError(err);
|
|
223
|
+
} finally {
|
|
224
|
+
return result;
|
|
245
225
|
}
|
|
226
|
+
}
|
|
246
227
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
228
|
+
protected async SyncSingleItemDeleteWithFilter(
|
|
229
|
+
entityName: string,
|
|
230
|
+
filter: string,
|
|
231
|
+
result: ActionItemOutputType,
|
|
232
|
+
user: UserInfo,
|
|
233
|
+
userPayload: UserPayload
|
|
234
|
+
) {
|
|
235
|
+
try {
|
|
236
|
+
// here we will iterate through the result of a RunView on the entityname/filter and delete each matching record
|
|
237
|
+
let overallSuccess: boolean = true;
|
|
238
|
+
let combinedErrorMessage: string = '';
|
|
239
|
+
const rv = new RunView();
|
|
240
|
+
const data = await rv.RunView<BaseEntity>(
|
|
241
|
+
{
|
|
242
|
+
EntityName: entityName,
|
|
243
|
+
ExtraFilter: filter,
|
|
244
|
+
ResultType: 'entity_object',
|
|
245
|
+
},
|
|
246
|
+
user
|
|
247
|
+
);
|
|
248
|
+
if (data && data.Success) {
|
|
249
|
+
for (const entityObject of data.Results) {
|
|
250
|
+
if (!(await entityObject.Delete())) {
|
|
251
|
+
overallSuccess = false;
|
|
252
|
+
combinedErrorMessage += 'Failed to delete the item :' + entityObject.LatestResult.Message + '\n';
|
|
253
|
+
}
|
|
269
254
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
255
|
+
result.Success = overallSuccess;
|
|
256
|
+
if (!overallSuccess) {
|
|
257
|
+
result.ErrorMessage = combinedErrorMessage;
|
|
273
258
|
}
|
|
259
|
+
} else {
|
|
260
|
+
result.Success = false;
|
|
261
|
+
result.ErrorMessage =
|
|
262
|
+
'Failed to run the view to get the list of items to delete for entity: ' + entityName + ' with filter: ' + filter + '\n';
|
|
263
|
+
}
|
|
264
|
+
} catch (e) {
|
|
265
|
+
result.ErrorMessage = typeof e === 'string' ? e : (e as any).message;
|
|
274
266
|
}
|
|
267
|
+
}
|
|
275
268
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
269
|
+
protected async LoadFromAlternateKey(entityName: string, alternateKey: CompositeKey, user: UserInfo): Promise<BaseEntity> {
|
|
270
|
+
try {
|
|
271
|
+
// no primary key provided, attempt to look up the primary key based on the
|
|
272
|
+
const rv = new RunView();
|
|
273
|
+
const md = new Metadata();
|
|
274
|
+
const entity = md.EntityByName(entityName);
|
|
275
|
+
const r = await rv.RunView<BaseEntity>(
|
|
276
|
+
{
|
|
277
|
+
EntityName: entityName,
|
|
278
|
+
ExtraFilter: alternateKey.KeyValuePairs.map((kvp) => {
|
|
279
|
+
const fieldInfo = entity.Fields.find((f) => f.Name === kvp.FieldName);
|
|
280
|
+
const quotes = fieldInfo.NeedsQuotes ? "'" : '';
|
|
281
|
+
return `${kvp.FieldName} = ${quotes}${kvp.Value}${quotes}`;
|
|
282
|
+
}).join(' AND '),
|
|
283
|
+
ResultType: 'entity_object',
|
|
284
|
+
},
|
|
285
|
+
user
|
|
286
|
+
);
|
|
287
|
+
if (r && r.Success && r.Results.length === 1) {
|
|
288
|
+
return r.Results[0];
|
|
289
|
+
} else {
|
|
290
|
+
//LogError (`Failed to load the item with alternate key: ${alternateKey.KeyValuePairs.map((kvp) => `${kvp.FieldName} = ${kvp.Value}`).join(' AND ')}. Result: ${r.Success} and ${r.Results?.length} items returned`);
|
|
291
|
+
return null;
|
|
292
|
+
}
|
|
293
|
+
} catch (e) {
|
|
294
|
+
LogError(e);
|
|
295
|
+
return null;
|
|
297
296
|
}
|
|
297
|
+
}
|
|
298
298
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
else if (await entityObject.InnerLoad(pk)) {
|
|
324
|
-
// pass back the full record as it was JUST BEFORE the delete, often quite useful on the other end
|
|
325
|
-
result.RecordJSON = await entityObject.GetDataObjectJSON({
|
|
326
|
-
includeRelatedEntityData: false,
|
|
327
|
-
excludeFields: [],
|
|
328
|
-
omitEmptyStrings: false,
|
|
329
|
-
relatedEntityList: [],
|
|
330
|
-
omitNullValues: false,
|
|
331
|
-
oldValues: false
|
|
332
|
-
});
|
|
333
|
-
if (await entityObject.Delete()) {
|
|
334
|
-
result.Success = true;
|
|
335
|
-
}
|
|
336
|
-
else {
|
|
337
|
-
result.ErrorMessage = 'Failed to delete the item :' + entityObject.LatestResult.Message;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
else {
|
|
341
|
-
result.ErrorMessage = 'Failed to load the item, it is possible the record with the specified primary key does not exist';
|
|
342
|
-
}
|
|
299
|
+
protected async SyncSingleItemCreateOrUpdate(
|
|
300
|
+
entityObject: BaseEntity,
|
|
301
|
+
pk: CompositeKey,
|
|
302
|
+
ak: CompositeKey,
|
|
303
|
+
fieldValues: any,
|
|
304
|
+
result: ActionItemOutputType,
|
|
305
|
+
userPayload: UserPayload
|
|
306
|
+
) {
|
|
307
|
+
if (!pk || pk.KeyValuePairs.length === 0) {
|
|
308
|
+
// no primary key try to load from alt key
|
|
309
|
+
const altKeyResult = await this.LoadFromAlternateKey(entityObject.EntityInfo.Name, ak, entityObject.ContextCurrentUser);
|
|
310
|
+
if (!altKeyResult) {
|
|
311
|
+
// no record found, create a new one
|
|
312
|
+
await this.SyncSingleItemCreate(entityObject, fieldValues, result, userPayload);
|
|
313
|
+
} else {
|
|
314
|
+
await this.InnerSyncSingleItemUpdate(altKeyResult, fieldValues, result, userPayload);
|
|
315
|
+
}
|
|
316
|
+
} else {
|
|
317
|
+
// have a primary key do the usual load
|
|
318
|
+
if (await entityObject.InnerLoad(pk)) {
|
|
319
|
+
await this.InnerSyncSingleItemUpdate(entityObject, fieldValues, result, userPayload);
|
|
320
|
+
} else {
|
|
321
|
+
await this.SyncSingleItemCreate(entityObject, fieldValues, result, userPayload);
|
|
322
|
+
}
|
|
343
323
|
}
|
|
324
|
+
}
|
|
344
325
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
326
|
+
protected async SyncSingleItemDelete(
|
|
327
|
+
entityObject: BaseEntity,
|
|
328
|
+
pk: CompositeKey,
|
|
329
|
+
ak: CompositeKey,
|
|
330
|
+
result: ActionItemOutputType,
|
|
331
|
+
userPayload: UserPayload
|
|
332
|
+
) {
|
|
333
|
+
if (!pk || pk.KeyValuePairs.length === 0) {
|
|
334
|
+
const altKeyResult = await this.LoadFromAlternateKey(entityObject.EntityInfo.Name, ak, entityObject.ContextCurrentUser);
|
|
335
|
+
if (!altKeyResult) {
|
|
336
|
+
result.ErrorMessage = 'Failed to load the item, it is possible the record with the specified primary key does not exist';
|
|
337
|
+
} else {
|
|
338
|
+
// pass back the full record as it was JUST BEFORE the delete, often quite useful on the other end
|
|
339
|
+
result.RecordJSON = await altKeyResult.GetDataObjectJSON({
|
|
340
|
+
includeRelatedEntityData: false,
|
|
341
|
+
excludeFields: [],
|
|
342
|
+
omitEmptyStrings: false,
|
|
343
|
+
relatedEntityList: [],
|
|
344
|
+
omitNullValues: false,
|
|
345
|
+
oldValues: false,
|
|
350
346
|
});
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
// pass back the full record AFTER the sync, that's often quite useful on the other end
|
|
356
|
-
result.RecordJSON = await entityObject.GetDataObjectJSON({
|
|
357
|
-
includeRelatedEntityData: false,
|
|
358
|
-
excludeFields: [],
|
|
359
|
-
omitEmptyStrings: false,
|
|
360
|
-
relatedEntityList: [],
|
|
361
|
-
omitNullValues: false,
|
|
362
|
-
oldValues: false
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
else {
|
|
366
|
-
result.ErrorMessage = 'Failed to create the item :' + entityObject.LatestResult.Message;
|
|
347
|
+
if (await altKeyResult.Delete()) {
|
|
348
|
+
result.Success = true;
|
|
349
|
+
} else {
|
|
350
|
+
result.ErrorMessage = 'Failed to delete the item :' + entityObject.LatestResult.Message;
|
|
367
351
|
}
|
|
352
|
+
}
|
|
353
|
+
} else if (await entityObject.InnerLoad(pk)) {
|
|
354
|
+
// pass back the full record as it was JUST BEFORE the delete, often quite useful on the other end
|
|
355
|
+
result.RecordJSON = await entityObject.GetDataObjectJSON({
|
|
356
|
+
includeRelatedEntityData: false,
|
|
357
|
+
excludeFields: [],
|
|
358
|
+
omitEmptyStrings: false,
|
|
359
|
+
relatedEntityList: [],
|
|
360
|
+
omitNullValues: false,
|
|
361
|
+
oldValues: false,
|
|
362
|
+
});
|
|
363
|
+
if (await entityObject.Delete()) {
|
|
364
|
+
result.Success = true;
|
|
365
|
+
} else {
|
|
366
|
+
result.ErrorMessage = 'Failed to delete the item :' + entityObject.LatestResult.Message;
|
|
367
|
+
}
|
|
368
|
+
} else {
|
|
369
|
+
result.ErrorMessage = 'Failed to load the item, it is possible the record with the specified primary key does not exist';
|
|
368
370
|
}
|
|
371
|
+
}
|
|
369
372
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
373
|
+
protected async SyncSingleItemCreate(entityObject: BaseEntity, fieldValues: any, result: ActionItemOutputType, userPayload: UserPayload) {
|
|
374
|
+
// make sure we strip out the primary key from fieldValues before we pass it in because otherwise it will appear to be an existing record to the BaseEntity
|
|
375
|
+
const noPKValues = { ...fieldValues };
|
|
376
|
+
entityObject.EntityInfo.PrimaryKeys.forEach((pk) => {
|
|
377
|
+
delete noPKValues[pk.Name];
|
|
378
|
+
});
|
|
379
|
+
entityObject.SetMany(noPKValues);
|
|
380
|
+
if (await entityObject.Save()) {
|
|
381
|
+
result.Success = true;
|
|
382
|
+
result.PrimaryKey = new CompositeKey(entityObject.PrimaryKeys.map((pk) => ({ FieldName: pk.Name, Value: pk.Value })));
|
|
383
|
+
// pass back the full record AFTER the sync, that's often quite useful on the other end
|
|
384
|
+
result.RecordJSON = await entityObject.GetDataObjectJSON({
|
|
385
|
+
includeRelatedEntityData: false,
|
|
386
|
+
excludeFields: [],
|
|
387
|
+
omitEmptyStrings: false,
|
|
388
|
+
relatedEntityList: [],
|
|
389
|
+
omitNullValues: false,
|
|
390
|
+
oldValues: false,
|
|
391
|
+
});
|
|
392
|
+
} else {
|
|
393
|
+
result.ErrorMessage = 'Failed to create the item :' + entityObject.LatestResult.Message;
|
|
389
394
|
}
|
|
395
|
+
}
|
|
390
396
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
397
|
+
protected async SyncSingleItemUpdate(
|
|
398
|
+
entityObject: BaseEntity,
|
|
399
|
+
pk: CompositeKey,
|
|
400
|
+
ak: CompositeKey,
|
|
401
|
+
fieldValues: any,
|
|
402
|
+
result: ActionItemOutputType,
|
|
403
|
+
userPayload: UserPayload
|
|
404
|
+
) {
|
|
405
|
+
if (!pk || pk.KeyValuePairs.length === 0) {
|
|
406
|
+
// no pk, attempt to load by alt key
|
|
407
|
+
const altKeyResult = await this.LoadFromAlternateKey(entityObject.EntityInfo.Name, ak, entityObject.ContextCurrentUser);
|
|
408
|
+
if (!altKeyResult) {
|
|
409
|
+
// no record found, create a new one
|
|
410
|
+
result.ErrorMessage = 'Failed to load the item, it is possible the record with the specified alternate key does not exist';
|
|
411
|
+
} else {
|
|
412
|
+
await this.InnerSyncSingleItemUpdate(altKeyResult, fieldValues, result, userPayload);
|
|
413
|
+
}
|
|
414
|
+
} else if (await entityObject.InnerLoad(pk)) {
|
|
415
|
+
await this.InnerSyncSingleItemUpdate(entityObject, fieldValues, result, userPayload);
|
|
416
|
+
} else {
|
|
417
|
+
// failed to load the item
|
|
418
|
+
result.ErrorMessage = 'Failed to load the item, it is possible the record with the specified primary key does not exist';
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
protected async InnerSyncSingleItemUpdate(
|
|
423
|
+
entityObject: BaseEntity,
|
|
424
|
+
fieldValues: any,
|
|
425
|
+
result: ActionItemOutputType,
|
|
426
|
+
userPayload: UserPayload
|
|
427
|
+
) {
|
|
428
|
+
entityObject.SetMany(fieldValues);
|
|
429
|
+
if (await entityObject.Save()) {
|
|
430
|
+
result.Success = true;
|
|
431
|
+
if (!result.PrimaryKey || result.PrimaryKey.KeyValuePairs.length === 0) {
|
|
432
|
+
result.PrimaryKey = new CompositeKey(entityObject.PrimaryKeys.map((pk) => ({ FieldName: pk.Name, Value: pk.Value })));
|
|
433
|
+
}
|
|
434
|
+
// pass back the full record AFTER the sync, that's often quite useful on the other end
|
|
435
|
+
result.RecordJSON = await entityObject.GetDataObjectJSON({
|
|
436
|
+
includeRelatedEntityData: false,
|
|
437
|
+
excludeFields: [],
|
|
438
|
+
omitEmptyStrings: false,
|
|
439
|
+
relatedEntityList: [],
|
|
440
|
+
omitNullValues: false,
|
|
441
|
+
oldValues: false,
|
|
442
|
+
});
|
|
443
|
+
} else {
|
|
444
|
+
result.ErrorMessage = 'Failed to update the item :' + entityObject.LatestResult.Message;
|
|
411
445
|
}
|
|
446
|
+
}
|
|
412
447
|
}
|
|
413
|
-
|