@memberjunction/server 2.95.0 → 2.96.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/context.d.ts.map +1 -1
- package/dist/context.js +4 -0
- package/dist/context.js.map +1 -1
- package/dist/resolvers/ActionResolver.d.ts.map +1 -1
- package/dist/resolvers/ActionResolver.js +5 -4
- package/dist/resolvers/ActionResolver.js.map +1 -1
- package/dist/resolvers/AskSkipResolver.d.ts +4 -4
- package/dist/resolvers/AskSkipResolver.d.ts.map +1 -1
- package/dist/resolvers/AskSkipResolver.js +9 -9
- package/dist/resolvers/AskSkipResolver.js.map +1 -1
- package/dist/resolvers/CreateQueryResolver.d.ts +2 -2
- package/dist/resolvers/CreateQueryResolver.d.ts.map +1 -1
- package/dist/resolvers/CreateQueryResolver.js +25 -17
- package/dist/resolvers/CreateQueryResolver.js.map +1 -1
- package/dist/resolvers/DatasetResolver.d.ts +2 -2
- package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
- package/dist/resolvers/DatasetResolver.js +6 -5
- package/dist/resolvers/DatasetResolver.js.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.d.ts +4 -4
- package/dist/resolvers/EntityRecordNameResolver.d.ts.map +1 -1
- package/dist/resolvers/EntityRecordNameResolver.js +6 -5
- package/dist/resolvers/EntityRecordNameResolver.js.map +1 -1
- package/dist/resolvers/FileCategoryResolver.d.ts.map +1 -1
- package/dist/resolvers/FileCategoryResolver.js +10 -11
- package/dist/resolvers/FileCategoryResolver.js.map +1 -1
- package/dist/resolvers/FileResolver.d.ts.map +1 -1
- package/dist/resolvers/FileResolver.js +5 -6
- package/dist/resolvers/FileResolver.js.map +1 -1
- package/dist/resolvers/GetDataContextDataResolver.js +2 -2
- package/dist/resolvers/GetDataContextDataResolver.js.map +1 -1
- package/dist/resolvers/GetDataResolver.js +3 -3
- 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 +8 -7
- 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 +4 -3
- package/dist/resolvers/PotentialDuplicateRecordResolver.js.map +1 -1
- package/dist/resolvers/QueryResolver.d.ts.map +1 -1
- package/dist/resolvers/QueryResolver.js +19 -14
- package/dist/resolvers/QueryResolver.js.map +1 -1
- package/dist/resolvers/ReportResolver.d.ts +2 -2
- package/dist/resolvers/ReportResolver.d.ts.map +1 -1
- package/dist/resolvers/ReportResolver.js +8 -6
- package/dist/resolvers/ReportResolver.js.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.d.ts +3 -7
- package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIAgentResolver.js +8 -5
- package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.d.ts +3 -7
- package/dist/resolvers/RunAIPromptResolver.d.ts.map +1 -1
- package/dist/resolvers/RunAIPromptResolver.js +10 -8
- package/dist/resolvers/RunAIPromptResolver.js.map +1 -1
- package/dist/resolvers/RunTemplateResolver.d.ts +2 -4
- package/dist/resolvers/RunTemplateResolver.d.ts.map +1 -1
- package/dist/resolvers/RunTemplateResolver.js +5 -4
- package/dist/resolvers/RunTemplateResolver.js.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.d.ts.map +1 -1
- package/dist/resolvers/SqlLoggingConfigResolver.js +7 -7
- package/dist/resolvers/SqlLoggingConfigResolver.js.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.d.ts +3 -4
- package/dist/resolvers/UserFavoriteResolver.d.ts.map +1 -1
- package/dist/resolvers/UserFavoriteResolver.js +10 -68
- package/dist/resolvers/UserFavoriteResolver.js.map +1 -1
- package/dist/resolvers/UserViewResolver.d.ts +1 -1
- package/dist/resolvers/UserViewResolver.d.ts.map +1 -1
- package/dist/resolvers/UserViewResolver.js +3 -4
- package/dist/resolvers/UserViewResolver.js.map +1 -1
- package/package.json +39 -39
- package/src/context.ts +5 -0
- package/src/resolvers/ActionResolver.ts +5 -4
- package/src/resolvers/AskSkipResolver.ts +13 -13
- package/src/resolvers/CreateQueryResolver.ts +28 -17
- package/src/resolvers/DatasetResolver.ts +5 -4
- package/src/resolvers/EntityRecordNameResolver.ts +8 -6
- package/src/resolvers/FileCategoryResolver.ts +9 -10
- package/src/resolvers/FileResolver.ts +6 -7
- package/src/resolvers/GetDataContextDataResolver.ts +2 -2
- package/src/resolvers/GetDataResolver.ts +2 -2
- package/src/resolvers/InfoResolver.ts +1 -1
- package/src/resolvers/MergeRecordsResolver.ts +7 -6
- package/src/resolvers/PotentialDuplicateRecordResolver.ts +3 -2
- package/src/resolvers/QueryResolver.ts +22 -15
- package/src/resolvers/ReportResolver.ts +9 -6
- package/src/resolvers/RunAIAgentResolver.ts +12 -4
- package/src/resolvers/RunAIPromptResolver.ts +12 -8
- package/src/resolvers/RunTemplateResolver.ts +5 -5
- package/src/resolvers/SqlLoggingConfigResolver.ts +7 -6
- package/src/resolvers/UserFavoriteResolver.ts +8 -67
- package/src/resolvers/UserViewResolver.ts +3 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.96.0",
|
|
4
4
|
"description": "MemberJunction: This project provides API access via GraphQL to the common data store.",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -22,44 +22,44 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@apollo/server": "^4.9.1",
|
|
24
24
|
"@graphql-tools/utils": "^10.0.1",
|
|
25
|
-
"@memberjunction/actions": "2.
|
|
26
|
-
"@memberjunction/ai": "2.
|
|
27
|
-
"@memberjunction/ai-core-plus": "2.
|
|
28
|
-
"@memberjunction/ai-agents": "2.
|
|
29
|
-
"@memberjunction/aiengine": "2.
|
|
30
|
-
"@memberjunction/ai-prompts": "2.
|
|
31
|
-
"@memberjunction/ai-agent-manager-actions": "2.
|
|
32
|
-
"@memberjunction/ai-mistral": "2.
|
|
33
|
-
"@memberjunction/ai-openai": "2.
|
|
34
|
-
"@memberjunction/ai-anthropic": "2.
|
|
35
|
-
"@memberjunction/ai-groq": "2.
|
|
36
|
-
"@memberjunction/ai-cerebras": "2.
|
|
37
|
-
"@memberjunction/ai-lmstudio": "2.
|
|
38
|
-
"@memberjunction/ai-openrouter": "2.
|
|
39
|
-
"@memberjunction/ai-ollama": "2.
|
|
40
|
-
"@memberjunction/ai-vectors-pinecone": "2.
|
|
41
|
-
"@memberjunction/ai-local-embeddings": "2.
|
|
42
|
-
"@memberjunction/core": "2.
|
|
43
|
-
"@memberjunction/core-actions": "2.
|
|
44
|
-
"@memberjunction/actions-apollo": "2.
|
|
45
|
-
"@memberjunction/actions-bizapps-accounting": "2.
|
|
46
|
-
"@memberjunction/actions-bizapps-crm": "2.
|
|
47
|
-
"@memberjunction/actions-bizapps-lms": "2.
|
|
48
|
-
"@memberjunction/actions-bizapps-social": "2.
|
|
49
|
-
"@memberjunction/core-entities": "2.
|
|
50
|
-
"@memberjunction/core-entities-server": "2.
|
|
51
|
-
"@memberjunction/data-context": "2.
|
|
52
|
-
"@memberjunction/data-context-server": "2.
|
|
53
|
-
"@memberjunction/doc-utils": "2.
|
|
54
|
-
"@memberjunction/entity-communications-server": "2.
|
|
55
|
-
"@memberjunction/external-change-detection": "2.
|
|
56
|
-
"@memberjunction/global": "2.
|
|
57
|
-
"@memberjunction/graphql-dataprovider": "2.
|
|
58
|
-
"@memberjunction/queue": "2.
|
|
59
|
-
"@memberjunction/skip-types": "2.
|
|
60
|
-
"@memberjunction/sqlserver-dataprovider": "2.
|
|
61
|
-
"@memberjunction/storage": "2.
|
|
62
|
-
"@memberjunction/templates": "2.
|
|
25
|
+
"@memberjunction/actions": "2.96.0",
|
|
26
|
+
"@memberjunction/ai": "2.96.0",
|
|
27
|
+
"@memberjunction/ai-core-plus": "2.96.0",
|
|
28
|
+
"@memberjunction/ai-agents": "2.96.0",
|
|
29
|
+
"@memberjunction/aiengine": "2.96.0",
|
|
30
|
+
"@memberjunction/ai-prompts": "2.96.0",
|
|
31
|
+
"@memberjunction/ai-agent-manager-actions": "2.96.0",
|
|
32
|
+
"@memberjunction/ai-mistral": "2.96.0",
|
|
33
|
+
"@memberjunction/ai-openai": "2.96.0",
|
|
34
|
+
"@memberjunction/ai-anthropic": "2.96.0",
|
|
35
|
+
"@memberjunction/ai-groq": "2.96.0",
|
|
36
|
+
"@memberjunction/ai-cerebras": "2.96.0",
|
|
37
|
+
"@memberjunction/ai-lmstudio": "2.96.0",
|
|
38
|
+
"@memberjunction/ai-openrouter": "2.96.0",
|
|
39
|
+
"@memberjunction/ai-ollama": "2.96.0",
|
|
40
|
+
"@memberjunction/ai-vectors-pinecone": "2.96.0",
|
|
41
|
+
"@memberjunction/ai-local-embeddings": "2.96.0",
|
|
42
|
+
"@memberjunction/core": "2.96.0",
|
|
43
|
+
"@memberjunction/core-actions": "2.96.0",
|
|
44
|
+
"@memberjunction/actions-apollo": "2.96.0",
|
|
45
|
+
"@memberjunction/actions-bizapps-accounting": "2.96.0",
|
|
46
|
+
"@memberjunction/actions-bizapps-crm": "2.96.0",
|
|
47
|
+
"@memberjunction/actions-bizapps-lms": "2.96.0",
|
|
48
|
+
"@memberjunction/actions-bizapps-social": "2.96.0",
|
|
49
|
+
"@memberjunction/core-entities": "2.96.0",
|
|
50
|
+
"@memberjunction/core-entities-server": "2.96.0",
|
|
51
|
+
"@memberjunction/data-context": "2.96.0",
|
|
52
|
+
"@memberjunction/data-context-server": "2.96.0",
|
|
53
|
+
"@memberjunction/doc-utils": "2.96.0",
|
|
54
|
+
"@memberjunction/entity-communications-server": "2.96.0",
|
|
55
|
+
"@memberjunction/external-change-detection": "2.96.0",
|
|
56
|
+
"@memberjunction/global": "2.96.0",
|
|
57
|
+
"@memberjunction/graphql-dataprovider": "2.96.0",
|
|
58
|
+
"@memberjunction/queue": "2.96.0",
|
|
59
|
+
"@memberjunction/skip-types": "2.96.0",
|
|
60
|
+
"@memberjunction/sqlserver-dataprovider": "2.96.0",
|
|
61
|
+
"@memberjunction/storage": "2.96.0",
|
|
62
|
+
"@memberjunction/templates": "2.96.0",
|
|
63
63
|
"@types/compression": "^1.7.5",
|
|
64
64
|
"@types/cors": "^2.8.13",
|
|
65
65
|
"@types/jsonwebtoken": "9.0.6",
|
package/src/context.ts
CHANGED
|
@@ -15,6 +15,7 @@ import e from 'express';
|
|
|
15
15
|
import { DatabaseProviderBase } from '@memberjunction/core';
|
|
16
16
|
import { SQLServerDataProvider, SQLServerProviderConfigData } from '@memberjunction/sqlserver-dataprovider';
|
|
17
17
|
import { AuthProviderFactory } from './auth/AuthProviderFactory.js';
|
|
18
|
+
import { Metadata } from '@memberjunction/core';
|
|
18
19
|
|
|
19
20
|
const verifyAsync = async (issuer: string, token: string): Promise<jwt.JwtPayload> =>
|
|
20
21
|
new Promise((resolve, reject) => {
|
|
@@ -157,6 +158,10 @@ export const contextFunction =
|
|
|
157
158
|
apiKey
|
|
158
159
|
);
|
|
159
160
|
|
|
161
|
+
if (Metadata.Provider.Entities.length === 0 ) {
|
|
162
|
+
console.warn('WARNING: No entities found in global/shared metadata, this can often be due to the use of **global** Metadata/RunView/DB Providers in a multi-user environment. Check your code to make sure you are using the providers passed to you in AppContext by MJServer and not calling new Metadata() new RunView() new RunQuery() and similar patterns as those are unstable at times in multi-user server environments!!!');
|
|
163
|
+
}
|
|
164
|
+
|
|
160
165
|
// now create a new instance of SQLServerDataProvider for each request
|
|
161
166
|
const config = new SQLServerProviderConfigData(dataSource, mj_core_schema, 0, undefined, undefined, false);
|
|
162
167
|
const p = new SQLServerDataProvider();
|
|
@@ -5,8 +5,9 @@ import { Metadata, UserInfo, BaseEntity, CompositeKey, KeyValuePair, LogError }
|
|
|
5
5
|
import { ActionParam, ActionResult } from "@memberjunction/actions-base";
|
|
6
6
|
import { Field, InputType, ObjectType } from "type-graphql";
|
|
7
7
|
import { KeyValuePairInput } from "../generic/KeyValuePairInput.js";
|
|
8
|
-
import { AppContext } from "../types.js";
|
|
8
|
+
import { AppContext, ProviderInfo } from "../types.js";
|
|
9
9
|
import { CopyScalarsAndArrays } from "@memberjunction/global";
|
|
10
|
+
import { GetReadOnlyProvider } from "../util.js";
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Input type for action parameters
|
|
@@ -341,7 +342,7 @@ export class ActionResolver {
|
|
|
341
342
|
|
|
342
343
|
// Add entity object if we have entity information and primary key
|
|
343
344
|
if ((input.EntityID || input.EntityName) && input.PrimaryKey && input.PrimaryKey.KeyValuePairs.length > 0) {
|
|
344
|
-
await this.addEntityObject(params, input, user);
|
|
345
|
+
await this.addEntityObject(ctx.providers, params, input, user);
|
|
345
346
|
}
|
|
346
347
|
|
|
347
348
|
// Add other parameters
|
|
@@ -400,8 +401,8 @@ export class ActionResolver {
|
|
|
400
401
|
* @param user The authenticated user
|
|
401
402
|
* @private
|
|
402
403
|
*/
|
|
403
|
-
private async addEntityObject(params: any, input: EntityActionInput, user: UserInfo): Promise<void> {
|
|
404
|
-
const md =
|
|
404
|
+
private async addEntityObject(providers: Array<ProviderInfo>, params: any, input: EntityActionInput, user: UserInfo): Promise<void> {
|
|
405
|
+
const md = GetReadOnlyProvider(providers);
|
|
405
406
|
|
|
406
407
|
// Find the entity by ID or name
|
|
407
408
|
let entity;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Arg, Ctx, Field, Mutation, ObjectType, PubSub, PubSubEngine, Query, Resolver } from 'type-graphql';
|
|
2
|
-
import { LogError, LogStatus, Metadata, RunView, UserInfo, CompositeKey, EntityFieldInfo, EntityInfo, EntityRelationshipInfo, EntitySaveOptions, EntityDeleteOptions } from '@memberjunction/core';
|
|
2
|
+
import { LogError, LogStatus, Metadata, RunView, UserInfo, CompositeKey, EntityFieldInfo, EntityInfo, EntityRelationshipInfo, EntitySaveOptions, EntityDeleteOptions, IMetadataProvider } from '@memberjunction/core';
|
|
3
3
|
import { AppContext, UserPayload, MJ_SERVER_EVENT_CODE } from '../types.js';
|
|
4
4
|
import { BehaviorSubject } from 'rxjs';
|
|
5
5
|
import { take } from 'rxjs/operators';
|
|
@@ -59,7 +59,7 @@ import mssql from 'mssql';
|
|
|
59
59
|
|
|
60
60
|
import { registerEnumType } from 'type-graphql';
|
|
61
61
|
import { MJGlobal, CopyScalarsAndArrays } from '@memberjunction/global';
|
|
62
|
-
import { sendPostRequest } from '../util.js';
|
|
62
|
+
import { GetReadWriteProvider, sendPostRequest } from '../util.js';
|
|
63
63
|
import { GetAIAPIKey } from '@memberjunction/ai';
|
|
64
64
|
import { CompositeKeyInputType } from '../generic/KeyInputOutputTypes.js';
|
|
65
65
|
import { AIEngine } from '@memberjunction/aiengine';
|
|
@@ -479,7 +479,7 @@ export class AskSkipResolver {
|
|
|
479
479
|
@Arg('ConversationId', () => String) ConversationId: string,
|
|
480
480
|
@Arg('EntityName', () => String) EntityName: string,
|
|
481
481
|
@Arg('CompositeKey', () => CompositeKeyInputType) compositeKey: CompositeKeyInputType,
|
|
482
|
-
@Ctx() { dataSource, userPayload }: AppContext,
|
|
482
|
+
@Ctx() { dataSource, userPayload, providers }: AppContext,
|
|
483
483
|
@PubSub() pubSub: PubSubEngine
|
|
484
484
|
) {
|
|
485
485
|
// In this function we're simply going to call the Skip API and pass along the message from the user
|
|
@@ -498,14 +498,14 @@ export class AskSkipResolver {
|
|
|
498
498
|
);
|
|
499
499
|
}
|
|
500
500
|
|
|
501
|
-
const md =
|
|
501
|
+
const md = GetReadWriteProvider(providers);
|
|
502
502
|
const { convoEntity, dataContextEntity, convoDetailEntity, dataContext } = await this.HandleSkipChatInitialObjectLoading(
|
|
503
503
|
dataSource,
|
|
504
504
|
ConversationId,
|
|
505
505
|
UserQuestion,
|
|
506
506
|
user,
|
|
507
507
|
userPayload,
|
|
508
|
-
md,
|
|
508
|
+
md as unknown as Metadata,
|
|
509
509
|
null
|
|
510
510
|
);
|
|
511
511
|
|
|
@@ -558,7 +558,7 @@ export class AskSkipResolver {
|
|
|
558
558
|
*/
|
|
559
559
|
@Mutation(() => AskSkipResultType)
|
|
560
560
|
async ExecuteAskSkipLearningCycle(
|
|
561
|
-
@Ctx() { dataSource, userPayload }: AppContext,
|
|
561
|
+
@Ctx() { dataSource, userPayload, providers }: AppContext,
|
|
562
562
|
@Arg('ForceEntityRefresh', () => Boolean, { nullable: true }) ForceEntityRefresh?: boolean
|
|
563
563
|
) {
|
|
564
564
|
const skipConfigInfo = configInfo.askSkip;
|
|
@@ -612,7 +612,7 @@ export class AskSkipResolver {
|
|
|
612
612
|
}
|
|
613
613
|
|
|
614
614
|
// Get the Skip agent ID
|
|
615
|
-
const md =
|
|
615
|
+
const md = GetReadWriteProvider(providers);
|
|
616
616
|
const skipAgent = AIEngine.Instance.GetAgentByName('Skip');
|
|
617
617
|
if (!skipAgent) {
|
|
618
618
|
throw new Error("Skip agent not found in AIEngine");
|
|
@@ -1467,11 +1467,11 @@ cycle.`);
|
|
|
1467
1467
|
@Query(() => ReattachConversationResponse)
|
|
1468
1468
|
async ReattachToProcessingConversation(
|
|
1469
1469
|
@Arg('ConversationId', () => String) ConversationId: string,
|
|
1470
|
-
@Ctx() { userPayload }: AppContext,
|
|
1470
|
+
@Ctx() { userPayload, providers }: AppContext,
|
|
1471
1471
|
@PubSub() pubSub: PubSubEngine
|
|
1472
1472
|
): Promise<ReattachConversationResponse | null> {
|
|
1473
1473
|
try {
|
|
1474
|
-
const md =
|
|
1474
|
+
const md = GetReadWriteProvider(providers);
|
|
1475
1475
|
const user = UserCache.Instance.Users.find((u) => u.Email.trim().toLowerCase() === userPayload.email.trim().toLowerCase());
|
|
1476
1476
|
if (!user) {
|
|
1477
1477
|
LogError(`User ${userPayload.email} not found in UserCache`);
|
|
@@ -1581,13 +1581,13 @@ cycle.`);
|
|
|
1581
1581
|
async ExecuteAskSkipAnalysisQuery(
|
|
1582
1582
|
@Arg('UserQuestion', () => String) UserQuestion: string,
|
|
1583
1583
|
@Arg('ConversationId', () => String) ConversationId: string,
|
|
1584
|
-
@Ctx() { dataSource, userPayload }: AppContext,
|
|
1584
|
+
@Ctx() { dataSource, userPayload, providers }: AppContext,
|
|
1585
1585
|
@PubSub() pubSub: PubSubEngine,
|
|
1586
1586
|
@Arg('DataContextId', () => String, { nullable: true }) DataContextId?: string,
|
|
1587
1587
|
@Arg('ForceEntityRefresh', () => Boolean, { nullable: true }) ForceEntityRefresh?: boolean,
|
|
1588
1588
|
@Arg('StartTime', () => Date, { nullable: true }) StartTime?: Date
|
|
1589
1589
|
) {
|
|
1590
|
-
const md =
|
|
1590
|
+
const md = GetReadWriteProvider(providers);
|
|
1591
1591
|
const user = UserCache.Instance.Users.find((u) => u.Email.trim().toLowerCase() === userPayload.email.trim().toLowerCase());
|
|
1592
1592
|
if (!user) throw new Error(`User ${userPayload.email} not found in UserCache`);
|
|
1593
1593
|
|
|
@@ -1600,7 +1600,7 @@ cycle.`);
|
|
|
1600
1600
|
UserQuestion,
|
|
1601
1601
|
user,
|
|
1602
1602
|
userPayload,
|
|
1603
|
-
md,
|
|
1603
|
+
md as unknown as Metadata,
|
|
1604
1604
|
DataContextId
|
|
1605
1605
|
);
|
|
1606
1606
|
|
|
@@ -1625,7 +1625,7 @@ cycle.`);
|
|
|
1625
1625
|
ConversationId,
|
|
1626
1626
|
userPayload,
|
|
1627
1627
|
pubSub,
|
|
1628
|
-
md,
|
|
1628
|
+
md as unknown as Metadata,
|
|
1629
1629
|
convoEntity,
|
|
1630
1630
|
convoDetailEntity,
|
|
1631
1631
|
dataContext,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Arg, Ctx, Field, InputType, Mutation, ObjectType, registerEnumType, Resolver, PubSub, PubSubEngine } from 'type-graphql';
|
|
2
2
|
import { AppContext } from '../types.js';
|
|
3
|
-
import { LogError, Metadata, RunView, UserInfo, CompositeKey } from '@memberjunction/core';
|
|
3
|
+
import { LogError, Metadata, RunView, UserInfo, CompositeKey, DatabaseProviderBase } from '@memberjunction/core';
|
|
4
4
|
import { RequireSystemUser } from '../directives/RequireSystemUser.js';
|
|
5
5
|
import { QueryCategoryEntity, QueryPermissionEntity } from '@memberjunction/core-entities';
|
|
6
6
|
import { QueryResolver } from '../generated/generated.js';
|
|
7
|
-
import { GetReadWriteProvider } from '../util.js';
|
|
7
|
+
import { GetReadOnlyProvider, GetReadWriteProvider } from '../util.js';
|
|
8
8
|
import { DeleteOptionsInput } from '../generic/DeleteOptionsInput.js';
|
|
9
9
|
import { QueryEntityExtended } from '@memberjunction/core-entities-server';
|
|
10
10
|
|
|
@@ -312,8 +312,8 @@ export class QueryResolverExtended extends QueryResolver {
|
|
|
312
312
|
// Handle CategoryPath if provided
|
|
313
313
|
let finalCategoryID = input.CategoryID;
|
|
314
314
|
if (input.CategoryPath) {
|
|
315
|
-
const
|
|
316
|
-
finalCategoryID = await this.findOrCreateCategoryPath(input.CategoryPath,
|
|
315
|
+
const p = GetReadOnlyProvider(context.providers, {allowFallbackToReadWrite: true});
|
|
316
|
+
finalCategoryID = await this.findOrCreateCategoryPath(input.CategoryPath, p, context.userPayload.userRecord);
|
|
317
317
|
}
|
|
318
318
|
|
|
319
319
|
// Use QueryEntityExtended which handles AI processing
|
|
@@ -345,7 +345,7 @@ export class QueryResolverExtended extends QueryResolver {
|
|
|
345
345
|
const queryID = record.ID;
|
|
346
346
|
|
|
347
347
|
if (input.Permissions && input.Permissions.length > 0) {
|
|
348
|
-
await this.createPermissions(input.Permissions, queryID, context.userPayload.userRecord);
|
|
348
|
+
await this.createPermissions(provider, input.Permissions, queryID, context.userPayload.userRecord);
|
|
349
349
|
await record.RefreshRelatedMetadata(true); // force DB update since we just created new permissions
|
|
350
350
|
}
|
|
351
351
|
|
|
@@ -374,13 +374,12 @@ export class QueryResolverExtended extends QueryResolver {
|
|
|
374
374
|
}
|
|
375
375
|
}
|
|
376
376
|
|
|
377
|
-
protected async createPermissions(permissions: QueryPermissionInputType[], queryID: string, contextUser: UserInfo): Promise<QueryPermissionType[]> {
|
|
377
|
+
protected async createPermissions(p: DatabaseProviderBase, permissions: QueryPermissionInputType[], queryID: string, contextUser: UserInfo): Promise<QueryPermissionType[]> {
|
|
378
378
|
// Create permissions if provided
|
|
379
379
|
const createdPermissions: QueryPermissionType[] = [];
|
|
380
380
|
if (permissions && permissions.length > 0) {
|
|
381
|
-
const md = new Metadata();
|
|
382
381
|
for (const perm of permissions) {
|
|
383
|
-
const permissionEntity = await
|
|
382
|
+
const permissionEntity = await p.GetEntityObject<QueryPermissionEntity>('Query Permissions', contextUser);
|
|
384
383
|
if (permissionEntity) {
|
|
385
384
|
permissionEntity.QueryID = queryID;
|
|
386
385
|
permissionEntity.RoleID = perm.RoleID;
|
|
@@ -427,8 +426,20 @@ export class QueryResolverExtended extends QueryResolver {
|
|
|
427
426
|
// Handle CategoryPath if provided
|
|
428
427
|
let finalCategoryID = input.CategoryID;
|
|
429
428
|
if (input.CategoryPath) {
|
|
430
|
-
|
|
431
|
-
|
|
429
|
+
finalCategoryID = await this.findOrCreateCategoryPath(input.CategoryPath, provider, context.userPayload.userRecord);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// now make sure there is NO existing query by the same name in the specified category
|
|
433
|
+
const existingQueryResult = await provider.RunView({
|
|
434
|
+
EntityName: 'Queries',
|
|
435
|
+
ExtraFilter: `Name='${input.Name}' AND CategoryID='${finalCategoryID}'`
|
|
436
|
+
}, context.userPayload.userRecord);
|
|
437
|
+
if (existingQueryResult.Success && existingQueryResult.Results?.length > 0) {
|
|
438
|
+
// we have a match! Let's return an error
|
|
439
|
+
return {
|
|
440
|
+
Success: false,
|
|
441
|
+
ErrorMessage: `Query with name '${input.Name}' already exists in the specified ${input.CategoryID ? 'category' : 'categoryPath'}`
|
|
442
|
+
};
|
|
432
443
|
}
|
|
433
444
|
|
|
434
445
|
// Update fields that were provided
|
|
@@ -481,7 +492,7 @@ export class QueryResolverExtended extends QueryResolver {
|
|
|
481
492
|
}
|
|
482
493
|
|
|
483
494
|
// Create new permissions
|
|
484
|
-
await this.createPermissions(input.Permissions, queryID, context.userPayload.userRecord);
|
|
495
|
+
await this.createPermissions(provider, input.Permissions, queryID, context.userPayload.userRecord);
|
|
485
496
|
|
|
486
497
|
// Refresh the metadata to get updated permissions
|
|
487
498
|
await queryEntity.RefreshRelatedMetadata(true);
|
|
@@ -608,7 +619,7 @@ export class QueryResolverExtended extends QueryResolver {
|
|
|
608
619
|
* @param contextUser - User context for operations
|
|
609
620
|
* @returns The ID of the final category in the path
|
|
610
621
|
*/
|
|
611
|
-
private async findOrCreateCategoryPath(categoryPath: string,
|
|
622
|
+
private async findOrCreateCategoryPath(categoryPath: string, p: DatabaseProviderBase, contextUser: UserInfo): Promise<string> {
|
|
612
623
|
if (!categoryPath || categoryPath.trim() === '') {
|
|
613
624
|
throw new Error('CategoryPath cannot be empty');
|
|
614
625
|
}
|
|
@@ -625,7 +636,7 @@ export class QueryResolverExtended extends QueryResolver {
|
|
|
625
636
|
const categoryName = pathParts[i];
|
|
626
637
|
|
|
627
638
|
// Look for existing category at this level
|
|
628
|
-
const existingCategory = await this.findCategoryByNameAndParent(categoryName, currentParentID, contextUser);
|
|
639
|
+
const existingCategory = await this.findCategoryByNameAndParent(p, categoryName, currentParentID, contextUser);
|
|
629
640
|
|
|
630
641
|
if (existingCategory) {
|
|
631
642
|
currentCategoryID = existingCategory.ID;
|
|
@@ -633,7 +644,7 @@ export class QueryResolverExtended extends QueryResolver {
|
|
|
633
644
|
} else {
|
|
634
645
|
try {
|
|
635
646
|
// Create new category
|
|
636
|
-
const newCategory = await
|
|
647
|
+
const newCategory = await p.GetEntityObject<QueryCategoryEntity>("Query Categories", contextUser);
|
|
637
648
|
if (!newCategory) {
|
|
638
649
|
throw new Error(`Failed to create entity object for Query Categories`);
|
|
639
650
|
}
|
|
@@ -652,7 +663,7 @@ export class QueryResolverExtended extends QueryResolver {
|
|
|
652
663
|
currentParentID = newCategory.ID;
|
|
653
664
|
|
|
654
665
|
// Refresh metadata after each category creation to ensure it's available for subsequent lookups
|
|
655
|
-
await
|
|
666
|
+
await p.Refresh();
|
|
656
667
|
} catch (error) {
|
|
657
668
|
throw new Error(`Failed to create category '${categoryName}': ${error instanceof Error ? error.message : String(error)}`);
|
|
658
669
|
}
|
|
@@ -673,9 +684,9 @@ export class QueryResolverExtended extends QueryResolver {
|
|
|
673
684
|
* @param contextUser - User context for database operations
|
|
674
685
|
* @returns The matching category entity or null if not found
|
|
675
686
|
*/
|
|
676
|
-
private async findCategoryByNameAndParent(categoryName: string, parentID: string | null, contextUser: UserInfo): Promise<QueryCategoryEntity | null> {
|
|
687
|
+
private async findCategoryByNameAndParent(provider: DatabaseProviderBase, categoryName: string, parentID: string | null, contextUser: UserInfo): Promise<QueryCategoryEntity | null> {
|
|
677
688
|
try {
|
|
678
|
-
const rv =
|
|
689
|
+
const rv = provider;
|
|
679
690
|
const parentFilter = parentID ? `ParentID='${parentID}'` : 'ParentID IS NULL';
|
|
680
691
|
const nameFilter = `LOWER(Name) = LOWER('${categoryName.replace(/'/g, "''")}')`; // Escape single quotes
|
|
681
692
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Arg, Ctx, Field, InputType, Int, ObjectType, Query, Resolver } from 'type-graphql';
|
|
2
2
|
import { AppContext } from '../types.js';
|
|
3
3
|
import { LogError, Metadata } from '@memberjunction/core';
|
|
4
|
+
import { GetReadOnlyProvider } from '../util.js';
|
|
4
5
|
|
|
5
6
|
@ObjectType()
|
|
6
7
|
export class DatasetResultType {
|
|
@@ -38,11 +39,11 @@ export class DatasetResolverExtended {
|
|
|
38
39
|
@Query(() => DatasetResultType)
|
|
39
40
|
async GetDatasetByName(
|
|
40
41
|
@Arg('DatasetName', () => String) DatasetName: string,
|
|
41
|
-
@Ctx() {}: AppContext,
|
|
42
|
+
@Ctx() {providers}: AppContext,
|
|
42
43
|
@Arg('ItemFilters', () => [DatasetItemFilterTypeGQL], { nullable: 'itemsAndList' }) ItemFilters?: DatasetItemFilterTypeGQL[]
|
|
43
44
|
) {
|
|
44
45
|
try {
|
|
45
|
-
const md =
|
|
46
|
+
const md = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true});
|
|
46
47
|
const result = await md.GetDatasetByName(DatasetName, ItemFilters);
|
|
47
48
|
if (result) {
|
|
48
49
|
return {
|
|
@@ -89,11 +90,11 @@ export class DatasetStatusResolver {
|
|
|
89
90
|
@Query(() => DatasetStatusResultType)
|
|
90
91
|
async GetDatasetStatusByName(
|
|
91
92
|
@Arg('DatasetName', () => String) DatasetName: string,
|
|
92
|
-
@Ctx() {}: AppContext,
|
|
93
|
+
@Ctx() {providers}: AppContext,
|
|
93
94
|
@Arg('ItemFilters', () => [DatasetItemFilterTypeGQL], { nullable: 'itemsAndList' }) ItemFilters?: DatasetItemFilterTypeGQL[]
|
|
94
95
|
) {
|
|
95
96
|
try {
|
|
96
|
-
const md =
|
|
97
|
+
const md = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true});
|
|
97
98
|
const result = await md.GetDatasetStatusByName(DatasetName, ItemFilters);
|
|
98
99
|
if (result) {
|
|
99
100
|
return {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Metadata, CompositeKey } from '@memberjunction/core';
|
|
1
|
+
import { Metadata, CompositeKey, DatabaseProviderBase } from '@memberjunction/core';
|
|
2
2
|
import { Arg, Ctx, Field, InputType, ObjectType, Query, Resolver } from 'type-graphql';
|
|
3
3
|
import { AppContext } from '../types.js';
|
|
4
4
|
import { CompositeKeyInputType, CompositeKeyOutputType } from '../generic/KeyInputOutputTypes.js';
|
|
5
|
+
import { GetReadOnlyProvider } from '../util.js';
|
|
5
6
|
|
|
6
7
|
@InputType()
|
|
7
8
|
export class EntityRecordNameInput {
|
|
@@ -36,26 +37,27 @@ export class EntityRecordNameResolver {
|
|
|
36
37
|
async GetEntityRecordName(
|
|
37
38
|
@Arg('EntityName', () => String) EntityName: string,
|
|
38
39
|
@Arg('CompositeKey', () => CompositeKeyInputType) primaryKey: CompositeKey,
|
|
39
|
-
@Ctx() { userPayload }: AppContext
|
|
40
|
+
@Ctx() { providers, userPayload }: AppContext
|
|
40
41
|
): Promise<EntityRecordNameResult> {
|
|
41
|
-
const md =
|
|
42
|
+
const md = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true});
|
|
43
|
+
|
|
42
44
|
return await this.InnerGetEntityRecordName(md, EntityName, primaryKey);
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
@Query(() => [EntityRecordNameResult])
|
|
46
48
|
async GetEntityRecordNames(
|
|
47
49
|
@Arg('info', () => [EntityRecordNameInput]) info: EntityRecordNameInput[],
|
|
48
|
-
@Ctx() {}: AppContext
|
|
50
|
+
@Ctx() {providers}: AppContext
|
|
49
51
|
): Promise<EntityRecordNameResult[]> {
|
|
50
52
|
const result: EntityRecordNameResult[] = [];
|
|
51
|
-
const md =
|
|
53
|
+
const md = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true});
|
|
52
54
|
for (const i of info) {
|
|
53
55
|
result.push(await this.InnerGetEntityRecordName(md, i.EntityName, i.CompositeKey));
|
|
54
56
|
}
|
|
55
57
|
return result;
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
async InnerGetEntityRecordName(md:
|
|
60
|
+
async InnerGetEntityRecordName(md: DatabaseProviderBase, EntityName: string, primaryKey: CompositeKeyInputType): Promise<EntityRecordNameResult> {
|
|
59
61
|
const pk = new CompositeKey(primaryKey.KeyValuePairs);
|
|
60
62
|
const e = md.Entities.find((e) => e.Name === EntityName);
|
|
61
63
|
if (e) {
|
|
@@ -16,16 +16,15 @@ export class FileResolver extends FileCategoryResolverBase {
|
|
|
16
16
|
) {
|
|
17
17
|
const key = new CompositeKey();
|
|
18
18
|
key.LoadFromSingleKeyValuePair('ID', ID);
|
|
19
|
-
const
|
|
19
|
+
const p = GetReadWriteProvider(providers);
|
|
20
20
|
|
|
21
|
-
if (!(await this.BeforeDelete(
|
|
21
|
+
if (!(await this.BeforeDelete(p, key))) {
|
|
22
22
|
return null;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
const md = new Metadata();
|
|
26
25
|
const user = this.GetUserFromPayload(userPayload);
|
|
27
|
-
const fileEntity = await
|
|
28
|
-
const fileCategoryEntity = await
|
|
26
|
+
const fileEntity = await p.GetEntityObject<FileEntity>('Files', user);
|
|
27
|
+
const fileCategoryEntity = await p.GetEntityObject<FileCategoryEntity>('File Categories', user);
|
|
29
28
|
|
|
30
29
|
fileEntity.CheckPermissions(EntityPermissionType.Update, true);
|
|
31
30
|
fileCategoryEntity.CheckPermissions(EntityPermissionType.Delete, true);
|
|
@@ -34,7 +33,7 @@ export class FileResolver extends FileCategoryResolverBase {
|
|
|
34
33
|
const returnValue = fileCategoryEntity.GetAll();
|
|
35
34
|
|
|
36
35
|
// Any files using the deleted category fall back to its parent
|
|
37
|
-
await
|
|
36
|
+
await p.BeginTransaction();
|
|
38
37
|
try {
|
|
39
38
|
// SHOULD USE BaseEntity for each of these records to ensure object model
|
|
40
39
|
// is used everywhere - new code below. The below is SLOWER than a single
|
|
@@ -60,20 +59,20 @@ export class FileResolver extends FileCategoryResolverBase {
|
|
|
60
59
|
// iterate through each of the files in filesResult.Results
|
|
61
60
|
// and update the CategoryID to fileCategoryEntity.ParentID
|
|
62
61
|
for (const file of filesResult.Results) {
|
|
63
|
-
const fileEntity = await
|
|
62
|
+
const fileEntity = await p.GetEntityObject<FileEntity>('Files', user);
|
|
64
63
|
await fileEntity.Load(file.ID);
|
|
65
64
|
fileEntity.CategoryID = fileCategoryEntity.ParentID;
|
|
66
65
|
await fileEntity.Save();
|
|
67
66
|
}
|
|
68
67
|
}
|
|
69
68
|
await fileCategoryEntity.Delete(options);
|
|
70
|
-
await
|
|
69
|
+
await p.CommitTransaction();
|
|
71
70
|
} catch (error) {
|
|
72
|
-
await
|
|
71
|
+
await p.RollbackTransaction();
|
|
73
72
|
throw error;
|
|
74
73
|
}
|
|
75
74
|
|
|
76
|
-
await this.AfterDelete(
|
|
75
|
+
await this.AfterDelete(p, key); // fire event
|
|
77
76
|
return returnValue;
|
|
78
77
|
}
|
|
79
78
|
}
|
|
@@ -51,14 +51,13 @@ export class FileResolver extends FileResolverBase {
|
|
|
51
51
|
@Ctx() context: AppContext,
|
|
52
52
|
@PubSub() pubSub: PubSubEngine
|
|
53
53
|
) {
|
|
54
|
-
|
|
54
|
+
// Check to see if there's already an object with that name
|
|
55
|
+
const provider = GetReadOnlyProvider(context.providers, {allowFallbackToReadWrite: true})
|
|
55
56
|
const user = this.GetUserFromPayload(context.userPayload);
|
|
56
|
-
const fileEntity = await
|
|
57
|
-
const providerEntity = await
|
|
57
|
+
const fileEntity = await provider.GetEntityObject<FileEntity>('Files', user);
|
|
58
|
+
const providerEntity = await provider.GetEntityObject<FileStorageProviderEntity>('File Storage Providers', user);
|
|
58
59
|
fileEntity.CheckPermissions(EntityPermissionType.Create, true);
|
|
59
60
|
|
|
60
|
-
// Check to see if there's already an object with that name
|
|
61
|
-
const provider = GetReadOnlyProvider(context.providers, {allowFallbackToReadWrite: true})
|
|
62
61
|
const [sameName] = await this.findBy(
|
|
63
62
|
provider,
|
|
64
63
|
'Files',
|
|
@@ -108,7 +107,7 @@ export class FileResolver extends FileResolverBase {
|
|
|
108
107
|
@PubSub() pubSub: PubSubEngine
|
|
109
108
|
) {
|
|
110
109
|
// if the name is changing, rename the target object as well
|
|
111
|
-
const md =
|
|
110
|
+
const md = GetReadOnlyProvider(context.providers);
|
|
112
111
|
const user = this.GetUserFromPayload(context.userPayload);
|
|
113
112
|
const fileEntity = await md.GetEntityObject<FileEntity>('Files', user);
|
|
114
113
|
fileEntity.CheckPermissions(EntityPermissionType.Update, true);
|
|
@@ -136,7 +135,7 @@ export class FileResolver extends FileResolverBase {
|
|
|
136
135
|
@Ctx() context: AppContext,
|
|
137
136
|
@PubSub() pubSub: PubSubEngine
|
|
138
137
|
) {
|
|
139
|
-
const md =
|
|
138
|
+
const md = GetReadOnlyProvider(context.providers);
|
|
140
139
|
const userInfo = this.GetUserFromPayload(context.userPayload);
|
|
141
140
|
|
|
142
141
|
const fileEntity = await md.GetEntityObject<FileEntity>('Files', userInfo);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Arg, Ctx, Field, ObjectType, Query } from "type-graphql";
|
|
2
2
|
import { AppContext } from "../types.js";
|
|
3
3
|
import { DataContext } from "@memberjunction/data-context";
|
|
4
|
-
import { GetReadOnlyDataSource } from "../util.js";
|
|
4
|
+
import { GetReadOnlyDataSource, GetReadOnlyProvider } from "../util.js";
|
|
5
5
|
import { Metadata } from "@memberjunction/core";
|
|
6
6
|
import { DataContextItemEntity } from "@memberjunction/core-entities";
|
|
7
7
|
|
|
@@ -53,7 +53,7 @@ export class GetDataContextDataResolver {
|
|
|
53
53
|
const ds = GetReadOnlyDataSource(appCtx.dataSources, {
|
|
54
54
|
allowFallbackToReadWrite: true,
|
|
55
55
|
})
|
|
56
|
-
const md =
|
|
56
|
+
const md = GetReadOnlyProvider(appCtx.providers, {allowFallbackToReadWrite: true});
|
|
57
57
|
const dciData = await md.GetEntityObject<DataContextItemEntity>("Data Context Items", appCtx.userPayload.userRecord);
|
|
58
58
|
if (await dciData.Load(DataContextItemID)) {
|
|
59
59
|
const dci = DataContext.CreateDataContextItem(); // use class factory to get whatever lowest level sub-class is registered
|
|
@@ -3,7 +3,7 @@ import { AppContext } from '../types.js';
|
|
|
3
3
|
import { LogError, LogStatus, Metadata } from '@memberjunction/core';
|
|
4
4
|
import { RequireSystemUser } from '../directives/RequireSystemUser.js';
|
|
5
5
|
import { v4 as uuidv4 } from 'uuid';
|
|
6
|
-
import { GetReadOnlyDataSource } from '../util.js';
|
|
6
|
+
import { GetReadOnlyDataSource, GetReadOnlyProvider } from '../util.js';
|
|
7
7
|
import sql from 'mssql';
|
|
8
8
|
|
|
9
9
|
@InputType()
|
|
@@ -169,7 +169,7 @@ export class GetDataResolver {
|
|
|
169
169
|
@Ctx() context: AppContext
|
|
170
170
|
): Promise<SimpleEntityResultType> {
|
|
171
171
|
try {
|
|
172
|
-
const md =
|
|
172
|
+
const md = GetReadOnlyProvider(context.providers);
|
|
173
173
|
const result = md.Entities.map((e) => {
|
|
174
174
|
return {
|
|
175
175
|
ID: e.ID,
|
|
@@ -3,6 +3,7 @@ import { Arg, Ctx, Field, InputType, Int, Mutation, ObjectType, PubSub, PubSubEn
|
|
|
3
3
|
import { AppContext } from '../types.js';
|
|
4
4
|
import { CompositeKeyInputType, CompositeKeyOutputType } from '../generic/KeyInputOutputTypes.js';
|
|
5
5
|
import { z } from 'zod';
|
|
6
|
+
import { GetReadOnlyProvider, GetReadWriteProvider } from '../util.js';
|
|
6
7
|
|
|
7
8
|
@ObjectType()
|
|
8
9
|
export class EntityDependencyResult {
|
|
@@ -21,11 +22,11 @@ export class EntityDependencyResolver {
|
|
|
21
22
|
@Query(() => [EntityDependencyResult])
|
|
22
23
|
async GetEntityDependencies(
|
|
23
24
|
@Arg('entityName', () => String) entityName: string,
|
|
24
|
-
@Ctx() { dataSource, userPayload }: AppContext,
|
|
25
|
+
@Ctx() { dataSource, userPayload, providers }: AppContext,
|
|
25
26
|
@PubSub() pubSub: PubSubEngine
|
|
26
27
|
) {
|
|
27
28
|
try {
|
|
28
|
-
const md =
|
|
29
|
+
const md = GetReadOnlyProvider(providers);
|
|
29
30
|
return md.GetEntityDependencies(entityName);
|
|
30
31
|
} catch (err) {
|
|
31
32
|
LogError(err);
|
|
@@ -57,11 +58,11 @@ export class RecordDependencyResolver {
|
|
|
57
58
|
async GetRecordDependencies(
|
|
58
59
|
@Arg('entityName', () => String) entityName: string,
|
|
59
60
|
@Arg('CompositeKey', () => CompositeKeyInputType) ckInput: CompositeKeyInputType,
|
|
60
|
-
@Ctx() { dataSource, userPayload }: AppContext,
|
|
61
|
+
@Ctx() { dataSource, userPayload, providers }: AppContext,
|
|
61
62
|
@PubSub() pubSub: PubSubEngine
|
|
62
63
|
) {
|
|
63
64
|
try {
|
|
64
|
-
const md =
|
|
65
|
+
const md = GetReadOnlyProvider(providers);
|
|
65
66
|
const ck = new CompositeKey(ckInput.KeyValuePairs);
|
|
66
67
|
const result = await md.GetRecordDependencies(entityName, ck);
|
|
67
68
|
|
|
@@ -165,11 +166,11 @@ export class RecordMergeResolver {
|
|
|
165
166
|
@Mutation(() => RecordMergeResult)
|
|
166
167
|
async MergeRecords(
|
|
167
168
|
@Arg('request', () => RecordMergeRequest) request: RecordMergeRequest,
|
|
168
|
-
@Ctx() { dataSource, userPayload }: AppContext,
|
|
169
|
+
@Ctx() { dataSource, userPayload, providers }: AppContext,
|
|
169
170
|
@PubSub() pubSub: PubSubEngine
|
|
170
171
|
) {
|
|
171
172
|
try {
|
|
172
|
-
const md =
|
|
173
|
+
const md = GetReadWriteProvider(providers);
|
|
173
174
|
const options = {};
|
|
174
175
|
const result = await md.MergeRecords(request, userPayload.userRecord, options);
|
|
175
176
|
return result;
|