@memberjunction/server 0.9.74 → 0.9.75

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.js CHANGED
@@ -1,102 +1,102 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.contextFunction = exports.getUserPayload = void 0;
27
- const url = __importStar(require("url"));
28
- const jsonwebtoken_1 = require("jsonwebtoken");
29
- require("reflect-metadata");
30
- const rxjs_1 = require("rxjs");
31
- const type_graphql_1 = require("type-graphql");
32
- const auth_1 = require("./auth");
33
- const cache_1 = require("./cache");
34
- const config_1 = require("./config");
35
- const verifyAsync = async (issuer, options, token) => new Promise((resolve, reject) => {
36
- (0, jsonwebtoken_1.verify)(token, (0, auth_1.getSigningKeys)(issuer), options, (err, jwt) => {
37
- if (jwt && typeof jwt !== 'string' && !err) {
38
- const payload = jwt.payload ?? jwt;
39
- console.log(`Valid token: ${payload.name} (${payload.email ? payload.email : payload.preferred_username})`);
40
- resolve(payload);
41
- }
42
- else {
43
- console.warn('Invalid token');
44
- reject(err);
45
- }
46
- });
47
- });
48
- const getUserPayload = async (bearerToken, sessionId = 'default', dataSource, requestDomain) => {
49
- try {
50
- const token = bearerToken.replace('Bearer ', '');
51
- if (!token) {
52
- console.warn('No token to validate');
53
- throw new type_graphql_1.AuthenticationError('Missing token');
54
- }
55
- const payload = (0, jsonwebtoken_1.decode)(token);
56
- if (!payload || typeof payload === 'string') {
57
- throw new type_graphql_1.AuthenticationError('Invalid token payload');
58
- }
59
- if (!cache_1.authCache.has(token)) {
60
- const issuer = payload.iss;
61
- if (!issuer) {
62
- console.warn('No issuer claim on token');
63
- throw new type_graphql_1.AuthenticationError('Missing issuer claim on token');
64
- }
65
- await verifyAsync(issuer, auth_1.validationOptions[issuer], token);
66
- cache_1.authCache.set(token, true);
67
- }
68
- const email = payload?.email
69
- ? config_1.userEmailMap[payload?.email] ?? payload?.email
70
- : payload?.preferred_username;
71
- const fullName = payload?.name;
72
- const firstName = payload?.given_name || fullName?.split(' ')[0];
73
- const lastName = payload?.family_name || fullName?.split(' ')[1] || fullName?.split(' ')[0];
74
- const userRecord = await (0, auth_1.verifyUserRecord)(email, firstName, lastName, requestDomain, dataSource);
75
- if (!userRecord) {
76
- console.error(`User ${email} not found`);
77
- throw new type_graphql_1.AuthorizationError();
78
- }
79
- else if (!userRecord.IsActive) {
80
- console.error(`User ${email} found but inactive`);
81
- throw new type_graphql_1.AuthorizationError();
82
- }
83
- return { userRecord, email, sessionId };
84
- }
85
- catch (e) {
86
- console.error(e);
87
- return {};
88
- }
89
- };
90
- exports.getUserPayload = getUserPayload;
91
- const contextFunction = ({ setupComplete$, dataSource }) => async ({ req }) => {
92
- await (0, rxjs_1.firstValueFrom)(setupComplete$);
93
- const sessionIdRaw = req.headers['x-session-id'];
94
- const requestDomain = url.parse(req.headers.origin || '');
95
- const sessionId = sessionIdRaw ? sessionIdRaw.toString() : '';
96
- const bearerToken = req.headers.authorization ?? '';
97
- const userPayload = await (0, exports.getUserPayload)(bearerToken, sessionId, dataSource, requestDomain?.hostname ? requestDomain.hostname : undefined);
98
- console.log(req.body?.operationName);
99
- return { dataSource, userPayload };
100
- };
101
- exports.contextFunction = contextFunction;
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.contextFunction = exports.getUserPayload = void 0;
27
+ const url = __importStar(require("url"));
28
+ const jsonwebtoken_1 = require("jsonwebtoken");
29
+ require("reflect-metadata");
30
+ const rxjs_1 = require("rxjs");
31
+ const type_graphql_1 = require("type-graphql");
32
+ const auth_1 = require("./auth");
33
+ const cache_1 = require("./cache");
34
+ const config_1 = require("./config");
35
+ const verifyAsync = async (issuer, options, token) => new Promise((resolve, reject) => {
36
+ (0, jsonwebtoken_1.verify)(token, (0, auth_1.getSigningKeys)(issuer), options, (err, jwt) => {
37
+ if (jwt && typeof jwt !== 'string' && !err) {
38
+ const payload = jwt.payload ?? jwt;
39
+ console.log(`Valid token: ${payload.name} (${payload.email ? payload.email : payload.preferred_username})`);
40
+ resolve(payload);
41
+ }
42
+ else {
43
+ console.warn('Invalid token');
44
+ reject(err);
45
+ }
46
+ });
47
+ });
48
+ const getUserPayload = async (bearerToken, sessionId = 'default', dataSource, requestDomain) => {
49
+ try {
50
+ const token = bearerToken.replace('Bearer ', '');
51
+ if (!token) {
52
+ console.warn('No token to validate');
53
+ throw new type_graphql_1.AuthenticationError('Missing token');
54
+ }
55
+ const payload = (0, jsonwebtoken_1.decode)(token);
56
+ if (!payload || typeof payload === 'string') {
57
+ throw new type_graphql_1.AuthenticationError('Invalid token payload');
58
+ }
59
+ if (!cache_1.authCache.has(token)) {
60
+ const issuer = payload.iss;
61
+ if (!issuer) {
62
+ console.warn('No issuer claim on token');
63
+ throw new type_graphql_1.AuthenticationError('Missing issuer claim on token');
64
+ }
65
+ await verifyAsync(issuer, auth_1.validationOptions[issuer], token);
66
+ cache_1.authCache.set(token, true);
67
+ }
68
+ const email = payload?.email
69
+ ? config_1.userEmailMap[payload?.email] ?? payload?.email
70
+ : payload?.preferred_username;
71
+ const fullName = payload?.name;
72
+ const firstName = payload?.given_name || fullName?.split(' ')[0];
73
+ const lastName = payload?.family_name || fullName?.split(' ')[1] || fullName?.split(' ')[0];
74
+ const userRecord = await (0, auth_1.verifyUserRecord)(email, firstName, lastName, requestDomain, dataSource);
75
+ if (!userRecord) {
76
+ console.error(`User ${email} not found`);
77
+ throw new type_graphql_1.AuthorizationError();
78
+ }
79
+ else if (!userRecord.IsActive) {
80
+ console.error(`User ${email} found but inactive`);
81
+ throw new type_graphql_1.AuthorizationError();
82
+ }
83
+ return { userRecord, email, sessionId };
84
+ }
85
+ catch (e) {
86
+ console.error(e);
87
+ return {};
88
+ }
89
+ };
90
+ exports.getUserPayload = getUserPayload;
91
+ const contextFunction = ({ setupComplete$, dataSource }) => async ({ req }) => {
92
+ await (0, rxjs_1.firstValueFrom)(setupComplete$);
93
+ const sessionIdRaw = req.headers['x-session-id'];
94
+ const requestDomain = url.parse(req.headers.origin || '');
95
+ const sessionId = sessionIdRaw ? sessionIdRaw.toString() : '';
96
+ const bearerToken = req.headers.authorization ?? '';
97
+ const userPayload = await (0, exports.getUserPayload)(bearerToken, sessionId, dataSource, requestDomain?.hostname ? requestDomain.hostname : undefined);
98
+ console.log(req.body?.operationName);
99
+ return { dataSource, userPayload };
100
+ };
101
+ exports.contextFunction = contextFunction;
102
102
  //# sourceMappingURL=context.js.map
@@ -1,34 +1,34 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.publicDirective = exports.Public = void 0;
4
- const utils_1 = require("@graphql-tools/utils");
5
- const graphql_1 = require("graphql");
6
- const type_graphql_1 = require("type-graphql");
7
- const DIRECTIVE_NAME = 'Public';
8
- function Public() {
9
- return (targetOrPrototype, propertyKey, descriptor) => (0, type_graphql_1.Directive)(`@${DIRECTIVE_NAME}`)(targetOrPrototype, propertyKey, descriptor);
10
- }
11
- exports.Public = Public;
12
- exports.publicDirective = {
13
- typeDefs: `directive @${DIRECTIVE_NAME} on FIELD_DEFINITION`,
14
- transformer: (schema) => {
15
- const fieldMapper = (fieldConfig) => {
16
- const directive = (0, utils_1.getDirective)(schema, fieldConfig, DIRECTIVE_NAME)?.[0];
17
- if (directive) {
18
- return fieldConfig;
19
- }
20
- else {
21
- const { resolve = graphql_1.defaultFieldResolver } = fieldConfig;
22
- const directiveResolver = async (source, args, context, info) => {
23
- if (!context?.userPayload?.userRecord?.IsActive) {
24
- throw new type_graphql_1.AuthorizationError();
25
- }
26
- return await resolve(source, args, context, info);
27
- };
28
- return { ...fieldConfig, resolve: directiveResolver };
29
- }
30
- };
31
- return (0, utils_1.mapSchema)(schema, { [utils_1.MapperKind.OBJECT_FIELD]: fieldMapper });
32
- },
33
- };
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.publicDirective = exports.Public = void 0;
4
+ const utils_1 = require("@graphql-tools/utils");
5
+ const graphql_1 = require("graphql");
6
+ const type_graphql_1 = require("type-graphql");
7
+ const DIRECTIVE_NAME = 'Public';
8
+ function Public() {
9
+ return (targetOrPrototype, propertyKey, descriptor) => (0, type_graphql_1.Directive)(`@${DIRECTIVE_NAME}`)(targetOrPrototype, propertyKey, descriptor);
10
+ }
11
+ exports.Public = Public;
12
+ exports.publicDirective = {
13
+ typeDefs: `directive @${DIRECTIVE_NAME} on FIELD_DEFINITION`,
14
+ transformer: (schema) => {
15
+ const fieldMapper = (fieldConfig) => {
16
+ const directive = (0, utils_1.getDirective)(schema, fieldConfig, DIRECTIVE_NAME)?.[0];
17
+ if (directive) {
18
+ return fieldConfig;
19
+ }
20
+ else {
21
+ const { resolve = graphql_1.defaultFieldResolver } = fieldConfig;
22
+ const directiveResolver = async (source, args, context, info) => {
23
+ if (!context?.userPayload?.userRecord?.IsActive) {
24
+ throw new type_graphql_1.AuthorizationError();
25
+ }
26
+ return await resolve(source, args, context, info);
27
+ };
28
+ return { ...fieldConfig, resolve: directiveResolver };
29
+ }
30
+ };
31
+ return (0, utils_1.mapSchema)(schema, { [utils_1.MapperKind.OBJECT_FIELD]: fieldMapper });
32
+ },
33
+ };
34
34
  //# sourceMappingURL=Public.js.map
@@ -1,18 +1,18 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./Public"), exports);
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./Public"), exports);
18
18
  //# sourceMappingURL=index.js.map
@@ -1,145 +1,145 @@
1
- "use strict";
2
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
- 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;
6
- return c > 3 && r && Object.defineProperty(target, key, r), r;
7
- };
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.UserViewEntity_Server = void 0;
10
- const global_1 = require("@memberjunction/global");
11
- const core_1 = require("@memberjunction/core");
12
- const core_entities_1 = require("@memberjunction/core-entities");
13
- const ai_1 = require("@memberjunction/ai");
14
- let UserViewEntity_Server = class UserViewEntity_Server extends core_entities_1.UserViewEntityExtended {
15
- get SmartFilterImplemented() {
16
- return true;
17
- }
18
- async GenerateSmartFilterWhereClause(prompt, entityInfo) {
19
- try {
20
- const llm = new ai_1.OpenAILLM();
21
- const chatParams = {
22
- model: 'gpt-4',
23
- systemPrompt: this.GenerateSysPrompt(entityInfo),
24
- userMessage: '',
25
- messages: [
26
- {
27
- role: 'user',
28
- content: `${prompt}`,
29
- },
30
- ],
31
- };
32
- const result = await llm.ChatCompletion(chatParams);
33
- if (result && result.data) {
34
- const llmResponse = result.data.choices[0].message.content;
35
- if (llmResponse) {
36
- try {
37
- const parsed = JSON.parse(llmResponse);
38
- if (parsed.whereClause && parsed.whereClause.length > 0) {
39
- const trimmed = parsed.whereClause.trim();
40
- let ret = '';
41
- if (trimmed.toLowerCase().startsWith('where '))
42
- ret = trimmed.substring(6);
43
- else
44
- ret = parsed.whereClause;
45
- return {
46
- whereClause: ret,
47
- userExplanation: parsed.userExplanationMessage
48
- };
49
- }
50
- else if (parsed.whereClause !== undefined && parsed.whereClause !== null) {
51
- return {
52
- whereClause: '',
53
- userExplanation: parsed.userExplanationMessage
54
- };
55
- }
56
- else {
57
- throw new Error('Invalid response from AI, no whereClause property found in response: ' + llmResponse);
58
- }
59
- }
60
- catch (e) {
61
- (0, core_1.LogError)(e);
62
- throw new Error('Error parsing JSON response from AI: ' + llmResponse);
63
- }
64
- }
65
- else
66
- throw new Error('Null response from AI');
67
- }
68
- else
69
- throw new Error('No result returned from AI');
70
- }
71
- catch (e) {
72
- (0, core_1.LogError)(e);
73
- throw e;
74
- }
75
- }
76
- GenerateSysPrompt(entityInfo) {
77
- const processedViews = [entityInfo.BaseView];
78
- const md = new core_1.Metadata();
79
- const gptSysPrompt = `You are an expert in SQL and Microsoft SQL Server.
80
- You will be provided a user prompt representing how they want to filter the data.
81
- You may *NOT* use JOINS, only sub-queries for related tables.
82
-
83
- I am a bot and can only understand JSON. Your response must be parsable into this type:
84
- const returnType = {
85
- whereClause: string,
86
- orderByClause: string
87
- userExplanationMessage: string
88
- };
89
-
90
- The view that the user is querying is called ${entityInfo.BaseView} and has these fields:
91
- ${entityInfo.Fields.map(f => {
92
- let ret = `${f.Name} (${f.Type})`;
93
- if (f.RelatedEntity) {
94
- ret += ` (fkey to ${f.RelatedEntityBaseView})`;
95
- }
96
- return ret;
97
- }).join(',')}`;
98
- const fkeyFields = entityInfo.Fields.filter(f => f.RelatedEntity && f.RelatedEntity.length > 0);
99
- const fkeyBaseViewsDistinct = fkeyFields.map(f => f.RelatedEntityBaseView).filter((v, i, a) => a.indexOf(v) === i);
100
- const relationships = `
101
- In addition, ${entityInfo.BaseView} has links to other views, as shown here, you can use these views in sub-queries to achieve the request from the user.
102
- If there are multiple filters related to a single related view, attempt to combine them into a single sub-query for efficiency.
103
- ${fkeyBaseViewsDistinct.map(v => {
104
- if (processedViews.indexOf(v) === -1) {
105
- const e = md.Entities.find(e => e.BaseView === v);
106
- if (e) {
107
- processedViews.push(v);
108
- return `* ${e.BaseView}: ${e.Fields.map(ef => {
109
- return ef.Name + ' (' + ef.Type + ')';
110
- }).join(',')}`;
111
- }
112
- else
113
- return '';
114
- }
115
- else
116
- return '';
117
- }).join('\n')}
118
- ${entityInfo.RelatedEntities.map(r => {
119
- const e = md.Entities.find(e => e.Name === r.RelatedEntity);
120
- if (e) {
121
- if (processedViews.indexOf(e.BaseView) === -1) {
122
- processedViews.push(e.BaseView);
123
- return `* ${e.BaseView}: ${e.Fields.map(ef => {
124
- let ret = `${ef.Name} (${ef.Type})`;
125
- if (ef.RelatedEntity) {
126
- ret += ` (fkey to ${ef.RelatedEntityBaseView})`;
127
- }
128
- return ret;
129
- }).join(',')}`;
130
- }
131
- else
132
- return '';
133
- }
134
- else
135
- return '';
136
- }).join('\n')}`;
137
- return gptSysPrompt + (processedViews.length > 1 ? relationships : '') + `
138
- **** REMEMBER **** I am a BOT, do not return anything other than JSON to me or I will choke on your response!`;
139
- }
140
- };
141
- UserViewEntity_Server = __decorate([
142
- (0, global_1.RegisterClass)(core_1.BaseEntity, 'User Views', 3)
143
- ], UserViewEntity_Server);
144
- exports.UserViewEntity_Server = UserViewEntity_Server;
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.UserViewEntity_Server = void 0;
10
+ const global_1 = require("@memberjunction/global");
11
+ const core_1 = require("@memberjunction/core");
12
+ const core_entities_1 = require("@memberjunction/core-entities");
13
+ const ai_1 = require("@memberjunction/ai");
14
+ let UserViewEntity_Server = class UserViewEntity_Server extends core_entities_1.UserViewEntityExtended {
15
+ get SmartFilterImplemented() {
16
+ return true;
17
+ }
18
+ async GenerateSmartFilterWhereClause(prompt, entityInfo) {
19
+ try {
20
+ const llm = new ai_1.OpenAILLM();
21
+ const chatParams = {
22
+ model: 'gpt-4',
23
+ systemPrompt: this.GenerateSysPrompt(entityInfo),
24
+ userMessage: '',
25
+ messages: [
26
+ {
27
+ role: 'user',
28
+ content: `${prompt}`,
29
+ },
30
+ ],
31
+ };
32
+ const result = await llm.ChatCompletion(chatParams);
33
+ if (result && result.data) {
34
+ const llmResponse = result.data.choices[0].message.content;
35
+ if (llmResponse) {
36
+ try {
37
+ const parsed = JSON.parse(llmResponse);
38
+ if (parsed.whereClause && parsed.whereClause.length > 0) {
39
+ const trimmed = parsed.whereClause.trim();
40
+ let ret = '';
41
+ if (trimmed.toLowerCase().startsWith('where '))
42
+ ret = trimmed.substring(6);
43
+ else
44
+ ret = parsed.whereClause;
45
+ return {
46
+ whereClause: ret,
47
+ userExplanation: parsed.userExplanationMessage
48
+ };
49
+ }
50
+ else if (parsed.whereClause !== undefined && parsed.whereClause !== null) {
51
+ return {
52
+ whereClause: '',
53
+ userExplanation: parsed.userExplanationMessage
54
+ };
55
+ }
56
+ else {
57
+ throw new Error('Invalid response from AI, no whereClause property found in response: ' + llmResponse);
58
+ }
59
+ }
60
+ catch (e) {
61
+ (0, core_1.LogError)(e);
62
+ throw new Error('Error parsing JSON response from AI: ' + llmResponse);
63
+ }
64
+ }
65
+ else
66
+ throw new Error('Null response from AI');
67
+ }
68
+ else
69
+ throw new Error('No result returned from AI');
70
+ }
71
+ catch (e) {
72
+ (0, core_1.LogError)(e);
73
+ throw e;
74
+ }
75
+ }
76
+ GenerateSysPrompt(entityInfo) {
77
+ const processedViews = [entityInfo.BaseView];
78
+ const md = new core_1.Metadata();
79
+ const gptSysPrompt = `You are an expert in SQL and Microsoft SQL Server.
80
+ You will be provided a user prompt representing how they want to filter the data.
81
+ You may *NOT* use JOINS, only sub-queries for related tables.
82
+
83
+ I am a bot and can only understand JSON. Your response must be parsable into this type:
84
+ const returnType = {
85
+ whereClause: string,
86
+ orderByClause: string
87
+ userExplanationMessage: string
88
+ };
89
+
90
+ The view that the user is querying is called ${entityInfo.BaseView} and has these fields:
91
+ ${entityInfo.Fields.map(f => {
92
+ let ret = `${f.Name} (${f.Type})`;
93
+ if (f.RelatedEntity) {
94
+ ret += ` (fkey to ${f.RelatedEntityBaseView})`;
95
+ }
96
+ return ret;
97
+ }).join(',')}`;
98
+ const fkeyFields = entityInfo.Fields.filter(f => f.RelatedEntity && f.RelatedEntity.length > 0);
99
+ const fkeyBaseViewsDistinct = fkeyFields.map(f => f.RelatedEntityBaseView).filter((v, i, a) => a.indexOf(v) === i);
100
+ const relationships = `
101
+ In addition, ${entityInfo.BaseView} has links to other views, as shown here, you can use these views in sub-queries to achieve the request from the user.
102
+ If there are multiple filters related to a single related view, attempt to combine them into a single sub-query for efficiency.
103
+ ${fkeyBaseViewsDistinct.map(v => {
104
+ if (processedViews.indexOf(v) === -1) {
105
+ const e = md.Entities.find(e => e.BaseView === v);
106
+ if (e) {
107
+ processedViews.push(v);
108
+ return `* ${e.BaseView}: ${e.Fields.map(ef => {
109
+ return ef.Name + ' (' + ef.Type + ')';
110
+ }).join(',')}`;
111
+ }
112
+ else
113
+ return '';
114
+ }
115
+ else
116
+ return '';
117
+ }).join('\n')}
118
+ ${entityInfo.RelatedEntities.map(r => {
119
+ const e = md.Entities.find(e => e.Name === r.RelatedEntity);
120
+ if (e) {
121
+ if (processedViews.indexOf(e.BaseView) === -1) {
122
+ processedViews.push(e.BaseView);
123
+ return `* ${e.BaseView}: ${e.Fields.map(ef => {
124
+ let ret = `${ef.Name} (${ef.Type})`;
125
+ if (ef.RelatedEntity) {
126
+ ret += ` (fkey to ${ef.RelatedEntityBaseView})`;
127
+ }
128
+ return ret;
129
+ }).join(',')}`;
130
+ }
131
+ else
132
+ return '';
133
+ }
134
+ else
135
+ return '';
136
+ }).join('\n')}`;
137
+ return gptSysPrompt + (processedViews.length > 1 ? relationships : '') + `
138
+ **** REMEMBER **** I am a BOT, do not return anything other than JSON to me or I will choke on your response!`;
139
+ }
140
+ };
141
+ UserViewEntity_Server = __decorate([
142
+ (0, global_1.RegisterClass)(core_1.BaseEntity, 'User Views', 3)
143
+ ], UserViewEntity_Server);
144
+ exports.UserViewEntity_Server = UserViewEntity_Server;
145
145
  //# sourceMappingURL=userViewEntity.server.js.map