@memberjunction/server 2.43.0 → 2.44.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.
@@ -0,0 +1,138 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { Resolver, Mutation, Arg, Ctx, ObjectType, Field } from 'type-graphql';
14
+ import { LogError, LogStatus, Metadata, RunView } from '@memberjunction/core';
15
+ import { TemplateEngineServer } from '@memberjunction/templates';
16
+ import { ResolverBase } from '../generic/ResolverBase.js';
17
+ let TemplateRunResult = class TemplateRunResult {
18
+ success;
19
+ output;
20
+ error;
21
+ executionTimeMs;
22
+ };
23
+ __decorate([
24
+ Field(),
25
+ __metadata("design:type", Boolean)
26
+ ], TemplateRunResult.prototype, "success", void 0);
27
+ __decorate([
28
+ Field({ nullable: true }),
29
+ __metadata("design:type", String)
30
+ ], TemplateRunResult.prototype, "output", void 0);
31
+ __decorate([
32
+ Field({ nullable: true }),
33
+ __metadata("design:type", String)
34
+ ], TemplateRunResult.prototype, "error", void 0);
35
+ __decorate([
36
+ Field({ nullable: true }),
37
+ __metadata("design:type", Number)
38
+ ], TemplateRunResult.prototype, "executionTimeMs", void 0);
39
+ TemplateRunResult = __decorate([
40
+ ObjectType()
41
+ ], TemplateRunResult);
42
+ export { TemplateRunResult };
43
+ let RunTemplateResolver = class RunTemplateResolver extends ResolverBase {
44
+ async RunTemplate(templateId, { userPayload }, contextData) {
45
+ const startTime = Date.now();
46
+ try {
47
+ LogStatus(`=== RUNNING TEMPLATE FOR ID: ${templateId} ===`);
48
+ let data = {};
49
+ if (contextData) {
50
+ try {
51
+ data = JSON.parse(contextData);
52
+ }
53
+ catch (parseError) {
54
+ return {
55
+ success: false,
56
+ error: `Invalid JSON in context data: ${parseError.message}`,
57
+ executionTimeMs: Date.now() - startTime
58
+ };
59
+ }
60
+ }
61
+ const currentUser = this.GetUserFromPayload(userPayload);
62
+ if (!currentUser) {
63
+ return {
64
+ success: false,
65
+ error: 'Unable to determine current user',
66
+ executionTimeMs: Date.now() - startTime
67
+ };
68
+ }
69
+ const md = new Metadata();
70
+ const templateEntity = await md.GetEntityObject('Templates', currentUser);
71
+ await templateEntity.Load(templateId);
72
+ if (!templateEntity.IsSaved) {
73
+ return {
74
+ success: false,
75
+ error: `Template with ID ${templateId} not found`,
76
+ executionTimeMs: Date.now() - startTime
77
+ };
78
+ }
79
+ const rv = new RunView();
80
+ const templateContentResult = await rv.RunView({
81
+ EntityName: 'Template Contents',
82
+ ExtraFilter: `TemplateID = '${templateId}'`,
83
+ OrderBy: 'Priority ASC',
84
+ MaxRows: 1,
85
+ ResultType: 'entity_object'
86
+ }, currentUser);
87
+ if (!templateContentResult.Results || templateContentResult.Results.length === 0) {
88
+ return {
89
+ success: false,
90
+ error: `No template content found for template ${templateEntity.Name}`,
91
+ executionTimeMs: Date.now() - startTime
92
+ };
93
+ }
94
+ await TemplateEngineServer.Instance.Config(true, currentUser);
95
+ const result = await TemplateEngineServer.Instance.RenderTemplate(templateEntity, templateContentResult.Results[0], data, true);
96
+ const executionTime = Date.now() - startTime;
97
+ if (result.Success) {
98
+ LogStatus(`=== TEMPLATE RUN COMPLETED FOR: ${templateEntity.Name} (${executionTime}ms) ===`);
99
+ return {
100
+ success: true,
101
+ output: result.Output,
102
+ executionTimeMs: executionTime
103
+ };
104
+ }
105
+ else {
106
+ LogError(`Template run failed for ${templateEntity.Name}: ${result.Message}`);
107
+ return {
108
+ success: false,
109
+ error: result.Message,
110
+ executionTimeMs: executionTime
111
+ };
112
+ }
113
+ }
114
+ catch (error) {
115
+ const executionTime = Date.now() - startTime;
116
+ LogError(`Template run failed:`, undefined, error);
117
+ return {
118
+ success: false,
119
+ error: error.message || 'Unknown error occurred',
120
+ executionTimeMs: executionTime
121
+ };
122
+ }
123
+ }
124
+ };
125
+ __decorate([
126
+ Mutation(() => TemplateRunResult),
127
+ __param(0, Arg('templateId')),
128
+ __param(1, Ctx()),
129
+ __param(2, Arg('contextData', { nullable: true })),
130
+ __metadata("design:type", Function),
131
+ __metadata("design:paramtypes", [String, Object, String]),
132
+ __metadata("design:returntype", Promise)
133
+ ], RunTemplateResolver.prototype, "RunTemplate", null);
134
+ RunTemplateResolver = __decorate([
135
+ Resolver()
136
+ ], RunTemplateResolver);
137
+ export { RunTemplateResolver };
138
+ //# sourceMappingURL=RunTemplateResolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RunTemplateResolver.js","sourceRoot":"","sources":["../../src/resolvers/RunTemplateResolver.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE/E,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAE9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAGnD,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAE1B,OAAO,CAAU;IAGjB,MAAM,CAAU;IAGhB,KAAK,CAAU;IAGf,eAAe,CAAU;CAC5B,CAAA;AAVG;IADC,KAAK,EAAE;;kDACS;AAGjB;IADC,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;iDACV;AAGhB;IADC,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;gDACX;AAGf;IADC,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;0DACD;AAXhB,iBAAiB;IAD7B,UAAU,EAAE;GACA,iBAAiB,CAY7B;;AAGM,IAAM,mBAAmB,GAAzB,MAAM,mBAAoB,SAAQ,YAAY;IAE3C,AAAN,KAAK,CAAC,WAAW,CACM,UAAkB,EAC9B,EAAE,WAAW,EAAgC,EACZ,WAAoB;QAE5D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,IAAI,CAAC;YACD,SAAS,CAAC,gCAAgC,UAAU,MAAM,CAAC,CAAC;YAG5D,IAAI,IAAI,GAAG,EAAE,CAAC;YACd,IAAI,WAAW,EAAE,CAAC;gBACd,IAAI,CAAC;oBACD,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;gBACnC,CAAC;gBAAC,OAAO,UAAU,EAAE,CAAC;oBAClB,OAAO;wBACH,OAAO,EAAE,KAAK;wBACd,KAAK,EAAE,iCAAkC,UAAoB,CAAC,OAAO,EAAE;wBACvE,eAAe,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;qBAC1C,CAAC;gBACN,CAAC;YACL,CAAC;YAGD,MAAM,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC;YACzD,IAAI,CAAC,WAAW,EAAE,CAAC;gBACf,OAAO;oBACH,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,kCAAkC;oBACzC,eAAe,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;iBAC1C,CAAC;YACN,CAAC;YAED,MAAM,EAAE,GAAG,IAAI,QAAQ,EAAE,CAAC;YAG1B,MAAM,cAAc,GAAG,MAAM,EAAE,CAAC,eAAe,CAAyB,WAAW,EAAE,WAAW,CAAC,CAAC;YAClG,MAAM,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAEtC,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,CAAC;gBAC1B,OAAO;oBACH,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,oBAAoB,UAAU,YAAY;oBACjD,eAAe,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;iBAC1C,CAAC;YACN,CAAC;YAGD,MAAM,EAAE,GAAG,IAAI,OAAO,EAAE,CAAC;YACzB,MAAM,qBAAqB,GAAG,MAAM,EAAE,CAAC,OAAO,CAAwB;gBAClE,UAAU,EAAE,mBAAmB;gBAC/B,WAAW,EAAE,iBAAiB,UAAU,GAAG;gBAC3C,OAAO,EAAE,cAAc;gBACvB,OAAO,EAAE,CAAC;gBACV,UAAU,EAAE,eAAe;aAC9B,EAAE,WAAW,CAAC,CAAC;YAEhB,IAAI,CAAC,qBAAqB,CAAC,OAAO,IAAI,qBAAqB,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC/E,OAAO;oBACH,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,0CAA0C,cAAc,CAAC,IAAI,EAAE;oBACtE,eAAe,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;iBAC1C,CAAC;YACN,CAAC;YAGD,MAAM,oBAAoB,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAA6C,WAAW,CAAC,CAAC;YACzG,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,QAAQ,CAAC,cAAc,CAC7D,cAAc,EACd,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC,EAChC,IAAI,EACJ,IAAI,CACP,CAAC;YAEF,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAE7C,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACjB,SAAS,CAAC,mCAAmC,cAAc,CAAC,IAAI,KAAK,aAAa,SAAS,CAAC,CAAC;gBAC7F,OAAO;oBACH,OAAO,EAAE,IAAI;oBACb,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,eAAe,EAAE,aAAa;iBACjC,CAAC;YACN,CAAC;iBAAM,CAAC;gBACJ,QAAQ,CAAC,2BAA2B,cAAc,CAAC,IAAI,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC9E,OAAO;oBACH,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,MAAM,CAAC,OAAO;oBACrB,eAAe,EAAE,aAAa;iBACjC,CAAC;YACN,CAAC;QAEL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;YAC7C,QAAQ,CAAC,sBAAsB,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;YACnD,OAAO;gBACH,OAAO,EAAE,KAAK;gBACd,KAAK,EAAG,KAAe,CAAC,OAAO,IAAI,wBAAwB;gBAC3D,eAAe,EAAE,aAAa;aACjC,CAAC;QACN,CAAC;IACL,CAAC;CACJ,CAAA;AAvGS;IADL,QAAQ,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC;IAE7B,WAAA,GAAG,CAAC,YAAY,CAAC,CAAA;IACjB,WAAA,GAAG,EAAE,CAAA;IACL,WAAA,GAAG,CAAC,aAAa,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;;;;sDAmG1C;AAxGQ,mBAAmB;IAD/B,QAAQ,EAAE;GACE,mBAAmB,CAyG/B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/server",
3
- "version": "2.43.0",
3
+ "version": "2.44.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,27 +22,28 @@
22
22
  "dependencies": {
23
23
  "@apollo/server": "^4.9.1",
24
24
  "@graphql-tools/utils": "^10.0.1",
25
- "@memberjunction/actions": "2.43.0",
26
- "@memberjunction/ai": "2.43.0",
27
- "@memberjunction/ai-mistral": "2.43.0",
28
- "@memberjunction/ai-openai": "2.43.0",
29
- "@memberjunction/ai-vectors-pinecone": "2.43.0",
30
- "@memberjunction/aiengine": "2.43.0",
31
- "@memberjunction/core": "2.43.0",
32
- "@memberjunction/core-actions": "2.43.0",
33
- "@memberjunction/core-entities": "2.43.0",
34
- "@memberjunction/data-context": "2.43.0",
35
- "@memberjunction/data-context-server": "2.43.0",
36
- "@memberjunction/doc-utils": "2.43.0",
37
- "@memberjunction/entity-communications-server": "2.43.0",
38
- "@memberjunction/external-change-detection": "2.43.0",
39
- "@memberjunction/global": "2.43.0",
40
- "@memberjunction/graphql-dataprovider": "2.43.0",
41
- "@memberjunction/queue": "2.43.0",
42
- "@memberjunction/skip-types": "2.43.0",
43
- "@memberjunction/sqlserver-dataprovider": "2.43.0",
44
- "@memberjunction/storage": "2.43.0",
45
- "@memberjunction/templates": "2.43.0",
25
+ "@memberjunction/actions": "2.44.0",
26
+ "@memberjunction/ai": "2.44.0",
27
+ "@memberjunction/ai-mistral": "2.44.0",
28
+ "@memberjunction/ai-openai": "2.44.0",
29
+ "@memberjunction/ai-vectors-pinecone": "2.44.0",
30
+ "@memberjunction/aiengine": "2.44.0",
31
+ "@memberjunction/ai-prompts": "2.44.0",
32
+ "@memberjunction/core": "2.44.0",
33
+ "@memberjunction/core-actions": "2.44.0",
34
+ "@memberjunction/core-entities": "2.44.0",
35
+ "@memberjunction/data-context": "2.44.0",
36
+ "@memberjunction/data-context-server": "2.44.0",
37
+ "@memberjunction/doc-utils": "2.44.0",
38
+ "@memberjunction/entity-communications-server": "2.44.0",
39
+ "@memberjunction/external-change-detection": "2.44.0",
40
+ "@memberjunction/global": "2.44.0",
41
+ "@memberjunction/graphql-dataprovider": "2.44.0",
42
+ "@memberjunction/queue": "2.44.0",
43
+ "@memberjunction/skip-types": "2.44.0",
44
+ "@memberjunction/sqlserver-dataprovider": "2.44.0",
45
+ "@memberjunction/storage": "2.44.0",
46
+ "@memberjunction/templates": "2.44.0",
46
47
  "@types/compression": "^1.7.5",
47
48
  "@types/cors": "^2.8.13",
48
49
  "@types/jsonwebtoken": "9.0.6",
@@ -7489,15 +7489,15 @@ export class User_ {
7489
7489
  @Field(() => [UserFavorite_])
7490
7490
  UserFavorites_UserIDArray: UserFavorite_[]; // Link to UserFavorites
7491
7491
 
7492
- @Field(() => [ResourceLink_])
7493
- ResourceLinks_UserIDArray: ResourceLink_[]; // Link to ResourceLinks
7494
-
7495
7492
  @Field(() => [ListCategory_])
7496
7493
  ListCategories_UserIDArray: ListCategory_[]; // Link to ListCategories
7497
7494
 
7498
7495
  @Field(() => [ScheduledAction_])
7499
7496
  ScheduledActions_CreatedByUserIDArray: ScheduledAction_[]; // Link to ScheduledActions
7500
7497
 
7498
+ @Field(() => [ResourceLink_])
7499
+ ResourceLinks_UserIDArray: ResourceLink_[]; // Link to ResourceLinks
7500
+
7501
7501
  @Field(() => [AIAgentRequest_])
7502
7502
  AIAgentRequests_ResponseByUserIDArray: AIAgentRequest_[]; // Link to AIAgentRequests
7503
7503
 
@@ -7944,15 +7944,6 @@ export class UserResolverBase extends ResolverBase {
7944
7944
  return result;
7945
7945
  }
7946
7946
 
7947
- @FieldResolver(() => [ResourceLink_])
7948
- async ResourceLinks_UserIDArray(@Root() user_: User_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
7949
- this.CheckUserReadPermissions('Resource Links', userPayload);
7950
- const dataSource = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
7951
- const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwResourceLinks] WHERE [UserID]='${user_.ID}' ` + this.getRowLevelSecurityWhereClause('Resource Links', userPayload, EntityPermissionType.Read, 'AND');
7952
- const result = this.ArrayMapFieldNamesToCodeNames('Resource Links', await dataSource.query(sSQL));
7953
- return result;
7954
- }
7955
-
7956
7947
  @FieldResolver(() => [ListCategory_])
7957
7948
  async ListCategories_UserIDArray(@Root() user_: User_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
7958
7949
  this.CheckUserReadPermissions('List Categories', userPayload);
@@ -7971,6 +7962,15 @@ export class UserResolverBase extends ResolverBase {
7971
7962
  return result;
7972
7963
  }
7973
7964
 
7965
+ @FieldResolver(() => [ResourceLink_])
7966
+ async ResourceLinks_UserIDArray(@Root() user_: User_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
7967
+ this.CheckUserReadPermissions('Resource Links', userPayload);
7968
+ const dataSource = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
7969
+ const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwResourceLinks] WHERE [UserID]='${user_.ID}' ` + this.getRowLevelSecurityWhereClause('Resource Links', userPayload, EntityPermissionType.Read, 'AND');
7970
+ const result = this.ArrayMapFieldNamesToCodeNames('Resource Links', await dataSource.query(sSQL));
7971
+ return result;
7972
+ }
7973
+
7974
7974
  @FieldResolver(() => [AIAgentRequest_])
7975
7975
  async AIAgentRequests_ResponseByUserIDArray(@Root() user_: User_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
7976
7976
  this.CheckUserReadPermissions('AI Agent Requests', userPayload);
@@ -15086,14 +15086,14 @@ export class Dashboard_ {
15086
15086
  @MaxLength(16)
15087
15087
  ApplicationID?: string;
15088
15088
 
15089
- @Field({nullable: true, description: `Used to identify the dashboard for code-base dashboards. Allows reuse of the same DriverClass for multiple dashboards that can be rendered differently.`})
15090
- @MaxLength(510)
15091
- Code?: string;
15092
-
15093
15089
  @Field({nullable: true, description: `Specifies the runtime class that will be used for the Dashboard when Type is set to 'Code'. This class contains the custom logic and implementation for code-based dashboards.`})
15094
15090
  @MaxLength(510)
15095
15091
  DriverClass?: string;
15096
15092
 
15093
+ @Field({nullable: true, description: `Used to identify the dashboard for code-base dashboards. Allows reuse of the same DriverClass for multiple dashboards that can be rendered differently.`})
15094
+ @MaxLength(510)
15095
+ Code?: string;
15096
+
15097
15097
  @Field()
15098
15098
  @MaxLength(200)
15099
15099
  User: string;
@@ -15147,10 +15147,10 @@ export class CreateDashboardInput {
15147
15147
  ApplicationID: string | null;
15148
15148
 
15149
15149
  @Field({ nullable: true })
15150
- Code: string | null;
15150
+ DriverClass: string | null;
15151
15151
 
15152
15152
  @Field({ nullable: true })
15153
- DriverClass: string | null;
15153
+ Code: string | null;
15154
15154
  }
15155
15155
 
15156
15156
 
@@ -15190,10 +15190,10 @@ export class UpdateDashboardInput {
15190
15190
  ApplicationID?: string | null;
15191
15191
 
15192
15192
  @Field({ nullable: true })
15193
- Code?: string | null;
15193
+ DriverClass?: string | null;
15194
15194
 
15195
15195
  @Field({ nullable: true })
15196
- DriverClass?: string | null;
15196
+ Code?: string | null;
15197
15197
 
15198
15198
  @Field(() => [KeyValuePairInput], { nullable: true })
15199
15199
  OldValues___?: KeyValuePairInput[];
@@ -742,6 +742,7 @@ export class ResolverBase {
742
742
  if (await entityObject.Save()) {
743
743
  // save worked, fire afterevent and return all the data
744
744
  await this.AfterUpdate(dataSource, input); // fire event
745
+
745
746
  return this.MapFieldNamesToCodeNames(entityName, entityObject.GetAll());
746
747
  } else {
747
748
  throw new GraphQLError(entityObject.LatestResult?.Message ?? 'Unknown error', {
@@ -753,7 +754,7 @@ export class ResolverBase {
753
754
  extensions: { code: 'SAVE_ENTITY_ERROR', entityName },
754
755
  });
755
756
  }
756
-
757
+
757
758
  /**
758
759
  * This routine compares the OldValues property in the input object to the values in the DB that we just loaded. If there are differences, we need to check to see if the client
759
760
  * is trying to update any of those fields (e.g. overlap). If there is overlap, we throw an error. If there is no overlap, we can proceed with the update even if the DB Values
package/src/index.ts CHANGED
@@ -52,6 +52,8 @@ export { TokenExpiredError, getSystemUser } from './auth/index.js';
52
52
  export * from './generic/PushStatusResolver.js';
53
53
  export * from './generic/ResolverBase.js';
54
54
  export * from './generic/RunViewResolver.js';
55
+ export * from './resolvers/RunTemplateResolver.js';
56
+ export * from './resolvers/RunAIPromptResolver.js';
55
57
  export * from './generic/KeyValuePairInput.js';
56
58
  export * from './generic/KeyInputOutputTypes.js';
57
59
  export * from './generic/DeleteOptionsInput.js';
@@ -414,7 +414,7 @@ export class AskSkipResolver {
414
414
  conversationDetailID: convoDetailEntity.ID,
415
415
  });
416
416
 
417
- return this.handleSimpleSkipChatPostRequest(input, convoEntity.ID, convoDetailEntity.ID, true, user);
417
+ return this.handleSimpleSkipChatPostRequest(input, convoEntity, convoDetailEntity, true, user);
418
418
  }
419
419
 
420
420
  /**
@@ -641,51 +641,69 @@ export class AskSkipResolver {
641
641
  * Sends the chat request and processes the response
642
642
  *
643
643
  * @param input The chat request payload
644
- * @param conversationID ID of the conversation, or empty for a new conversation
645
- * @param UserMessageConversationDetailId ID of the user's message in the conversation
644
+ * @param convoEntity The conversation entity object
645
+ * @param convoDetailEntity The conversation detail entity object
646
646
  * @param createAIMessageConversationDetail Whether to create a conversation detail for the AI response
647
647
  * @param user User context for the request
648
648
  * @returns Result of the Skip interaction
649
649
  */
650
650
  protected async handleSimpleSkipChatPostRequest(
651
651
  input: SkipAPIRequest,
652
- conversationID: string = '',
653
- UserMessageConversationDetailId: string = '',
652
+ convoEntity: ConversationEntity = null,
653
+ convoDetailEntity: ConversationDetailEntity = null,
654
654
  createAIMessageConversationDetail: boolean = false,
655
655
  user: UserInfo = null
656
656
  ): Promise<AskSkipResultType> {
657
657
  const skipConfigInfo = configInfo.askSkip;
658
658
  LogStatus(` >>> HandleSimpleSkipChatPostRequest Sending request to Skip API: ${skipConfigInfo.chatURL}`);
659
659
 
660
- const response = await sendPostRequest(skipConfigInfo.chatURL, input, true, null);
661
-
662
- if (response && response.length > 0) {
663
- // the last object in the response array is the final response from the Skip API
664
- const apiResponse = <SkipAPIResponse>response[response.length - 1].value;
665
- const AIMessageConversationDetailID = createAIMessageConversationDetail
666
- ? await this.CreateAIMessageConversationDetail(apiResponse, conversationID, user)
667
- : '';
668
- // const apiResponse = <SkipAPIResponse>response.data;
669
- LogStatus(` Skip API response: ${apiResponse.responsePhase}`);
670
- return {
671
- Success: true,
672
- Status: 'OK',
673
- ResponsePhase: SkipResponsePhase.AnalysisComplete,
674
- ConversationId: conversationID,
675
- UserMessageConversationDetailId: UserMessageConversationDetailId,
676
- AIMessageConversationDetailId: AIMessageConversationDetailID,
677
- Result: JSON.stringify(apiResponse),
678
- };
679
- } else {
680
- return {
681
- Success: false,
682
- Status: 'Error',
683
- Result: `Request failed`,
684
- ResponsePhase: SkipResponsePhase.AnalysisComplete,
685
- ConversationId: conversationID,
686
- UserMessageConversationDetailId: UserMessageConversationDetailId,
687
- AIMessageConversationDetailId: '',
688
- };
660
+ try {
661
+ const response = await sendPostRequest(skipConfigInfo.chatURL, input, true, null);
662
+
663
+ if (response && response.length > 0) {
664
+ // the last object in the response array is the final response from the Skip API
665
+ const apiResponse = <SkipAPIResponse>response[response.length - 1].value;
666
+ const AIMessageConversationDetailID = createAIMessageConversationDetail && convoEntity
667
+ ? await this.CreateAIMessageConversationDetail(apiResponse, convoEntity.ID, user)
668
+ : '';
669
+ // const apiResponse = <SkipAPIResponse>response.data;
670
+ LogStatus(` Skip API response: ${apiResponse.responsePhase}`);
671
+ return {
672
+ Success: true,
673
+ Status: 'OK',
674
+ ResponsePhase: SkipResponsePhase.AnalysisComplete,
675
+ ConversationId: convoEntity ? convoEntity.ID : '',
676
+ UserMessageConversationDetailId: convoDetailEntity ? convoDetailEntity.ID : '',
677
+ AIMessageConversationDetailId: AIMessageConversationDetailID,
678
+ Result: JSON.stringify(apiResponse),
679
+ };
680
+ } else {
681
+ // Set conversation status to Available on failure so user can try again (if conversation exists)
682
+ if (convoEntity) {
683
+ await this.setConversationStatus(convoEntity, 'Available');
684
+ }
685
+
686
+ return {
687
+ Success: false,
688
+ Status: 'Error',
689
+ Result: `Request failed`,
690
+ ResponsePhase: SkipResponsePhase.AnalysisComplete,
691
+ ConversationId: convoEntity ? convoEntity.ID : '',
692
+ UserMessageConversationDetailId: convoDetailEntity ? convoDetailEntity.ID : '',
693
+ AIMessageConversationDetailId: '',
694
+ };
695
+ }
696
+ } catch (error) {
697
+ // Set conversation status to Available on error so user can try again (if conversation exists)
698
+ if (convoEntity) {
699
+ await this.setConversationStatus(convoEntity, 'Available');
700
+ }
701
+
702
+ // Log the error for debugging
703
+ LogError(`Error in handleSimpleSkipChatPostRequest: ${error}`);
704
+
705
+ // Re-throw the error to propagate it up the stack
706
+ throw error;
689
707
  }
690
708
  }
691
709
 
@@ -1343,7 +1361,7 @@ cycle.`);
1343
1361
  );
1344
1362
 
1345
1363
  // Set the conversation status to 'Processing' when a request is initiated
1346
- this.setConversationStatus(convoEntity, 'Processing');
1364
+ await this.setConversationStatus(convoEntity, 'Processing');
1347
1365
 
1348
1366
  // now load up the messages. We will load up ALL of the messages for this conversation, and then pass them to the Skip API
1349
1367
  const messages: SkipMessage[] = await this.LoadConversationDetailsIntoSkipMessages(
@@ -1941,6 +1959,7 @@ cycle.`);
1941
1959
  const convoDetailEntity = await md.GetEntityObject<ConversationDetailEntity>('Conversation Details', user);
1942
1960
  convoDetailEntity.NewRecord();
1943
1961
  convoDetailEntity.ConversationID = ConversationId;
1962
+ convoDetailEntity.UserID = user.ID;
1944
1963
  convoDetailEntity.Message = UserQuestion;
1945
1964
  convoDetailEntity.Role = 'User';
1946
1965
  convoDetailEntity.HiddenToUser = false;
@@ -2141,38 +2160,61 @@ cycle.`);
2141
2160
  };
2142
2161
  }
2143
2162
 
2144
- const response = await sendPostRequest(
2145
- skipConfigInfo.chatURL,
2146
- input,
2147
- true,
2148
- null,
2149
- (message: {
2150
- type: string;
2151
- value: {
2152
- success: boolean;
2153
- error: string;
2154
- responsePhase: string;
2155
- messages: {
2156
- role: string;
2157
- content: string;
2158
- }[];
2159
- };
2160
- }) => {
2161
- LogStatus(JSON.stringify(message, null, 4));
2162
- if (message.type === 'status_update') {
2163
- pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
2164
- message: JSON.stringify({
2165
- type: 'AskSkip',
2166
- status: 'OK',
2167
- conversationID: ConversationId,
2168
- ResponsePhase: message.value.responsePhase,
2169
- message: message.value.messages[0].content,
2170
- }),
2171
- sessionId: userPayload.sessionId,
2172
- });
2163
+ let response;
2164
+ try {
2165
+ response = await sendPostRequest(
2166
+ skipConfigInfo.chatURL,
2167
+ input,
2168
+ true,
2169
+ null,
2170
+ (message: {
2171
+ type: string;
2172
+ value: {
2173
+ success: boolean;
2174
+ error: string;
2175
+ responsePhase: string;
2176
+ messages: {
2177
+ role: string;
2178
+ content: string;
2179
+ }[];
2180
+ };
2181
+ }) => {
2182
+ LogStatus(JSON.stringify(message, null, 4));
2183
+ if (message.type === 'status_update') {
2184
+ pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
2185
+ message: JSON.stringify({
2186
+ type: 'AskSkip',
2187
+ status: 'OK',
2188
+ conversationID: ConversationId,
2189
+ ResponsePhase: message.value.responsePhase,
2190
+ message: message.value.messages[0].content,
2191
+ }),
2192
+ sessionId: userPayload.sessionId,
2193
+ });
2194
+ }
2173
2195
  }
2174
- }
2175
- );
2196
+ );
2197
+ } catch (error) {
2198
+ // Set conversation status to Available on error so user can try again
2199
+ await this.setConversationStatus(convoEntity, 'Available');
2200
+
2201
+ // Log the error for debugging
2202
+ LogError(`Error in HandleSkipChatRequest sendPostRequest: ${error}`);
2203
+
2204
+ // Publish error status update to user
2205
+ pubSub.publish(PUSH_STATUS_UPDATES_TOPIC, {
2206
+ message: JSON.stringify({
2207
+ type: 'AskSkip',
2208
+ status: 'Error',
2209
+ conversationID: ConversationId,
2210
+ message: 'Request failed. Please try again later and if this continues, contact your support desk.',
2211
+ }),
2212
+ sessionId: userPayload.sessionId,
2213
+ });
2214
+
2215
+ // Re-throw the error to propagate it up the stack
2216
+ throw error;
2217
+ }
2176
2218
 
2177
2219
  if (response && response.length > 0) {
2178
2220
  // response.status === 200) {
@@ -2409,7 +2451,7 @@ cycle.`);
2409
2451
  convoDetailEntityAI.CompletionTime = endTime.getTime() - startTime.getTime();
2410
2452
 
2411
2453
  // Set conversation status back to Available since we need user input for the clarifying question
2412
- this.setConversationStatus(convoEntity, 'Available');
2454
+ await this.setConversationStatus(convoEntity, 'Available');
2413
2455
 
2414
2456
  if (await convoDetailEntityAI.Save()) {
2415
2457
  return {
@@ -2804,12 +2846,12 @@ cycle.`);
2804
2846
 
2805
2847
  private async setConversationStatus(convoEntity: ConversationEntity, status: 'Processing' | 'Available'): Promise<boolean> {
2806
2848
  if (convoEntity.Status !== status) {
2807
- convoEntity.Status = status;
2808
- const convoSaveResult = await convoEntity.Save();
2809
- if (!convoSaveResult) {
2810
- LogError(`Error updating conversation status to '${status}'`, undefined, convoEntity.LatestResult);
2811
- }
2812
- return convoSaveResult;
2849
+ convoEntity.Status = status;
2850
+ const convoSaveResult = await convoEntity.Save();
2851
+ if (!convoSaveResult) {
2852
+ LogError(`Error updating conversation status to '${status}'`, undefined, convoEntity.LatestResult);
2853
+ }
2854
+ return convoSaveResult;
2813
2855
  }
2814
2856
  return true;
2815
2857
  }