@memberjunction/server 2.35.0 → 2.36.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/README.md +15 -1
- package/dist/config.d.ts +69 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +11 -1
- package/dist/config.js.map +1 -1
- package/dist/generated/generated.d.ts +15 -12
- package/dist/generated/generated.d.ts.map +1 -1
- package/dist/generated/generated.js +73 -58
- package/dist/generated/generated.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -1
- package/dist/resolvers/AskSkipResolver.d.ts +60 -5
- package/dist/resolvers/AskSkipResolver.d.ts.map +1 -1
- package/dist/resolvers/AskSkipResolver.js +587 -31
- package/dist/resolvers/AskSkipResolver.js.map +1 -1
- package/dist/rest/EntityCRUDHandler.d.ts +29 -0
- package/dist/rest/EntityCRUDHandler.d.ts.map +1 -0
- package/dist/rest/EntityCRUDHandler.js +197 -0
- package/dist/rest/EntityCRUDHandler.js.map +1 -0
- package/dist/rest/RESTEndpointHandler.d.ts +41 -0
- package/dist/rest/RESTEndpointHandler.d.ts.map +1 -0
- package/dist/rest/RESTEndpointHandler.js +537 -0
- package/dist/rest/RESTEndpointHandler.js.map +1 -0
- package/dist/rest/ViewOperationsHandler.d.ts +21 -0
- package/dist/rest/ViewOperationsHandler.d.ts.map +1 -0
- package/dist/rest/ViewOperationsHandler.js +144 -0
- package/dist/rest/ViewOperationsHandler.js.map +1 -0
- package/dist/rest/index.d.ts +5 -0
- package/dist/rest/index.d.ts.map +1 -0
- package/dist/rest/index.js +5 -0
- package/dist/rest/index.js.map +1 -0
- package/dist/rest/setupRESTEndpoints.d.ts +12 -0
- package/dist/rest/setupRESTEndpoints.d.ts.map +1 -0
- package/dist/rest/setupRESTEndpoints.js +27 -0
- package/dist/rest/setupRESTEndpoints.js.map +1 -0
- package/dist/scheduler/LearningCycleScheduler.d.ts +44 -0
- package/dist/scheduler/LearningCycleScheduler.d.ts.map +1 -0
- package/dist/scheduler/LearningCycleScheduler.js +188 -0
- package/dist/scheduler/LearningCycleScheduler.js.map +1 -0
- package/package.json +24 -26
- package/src/config.ts +15 -1
- package/src/generated/generated.ts +53 -44
- package/src/index.ts +56 -1
- package/src/resolvers/AskSkipResolver.ts +787 -51
- package/src/rest/EntityCRUDHandler.ts +279 -0
- package/src/rest/RESTEndpointHandler.ts +834 -0
- package/src/rest/ViewOperationsHandler.ts +207 -0
- package/src/rest/index.ts +4 -0
- package/src/rest/setupRESTEndpoints.ts +89 -0
- package/src/scheduler/LearningCycleScheduler.ts +312 -0
|
@@ -1402,13 +1402,13 @@ export class AIAgentNote_ {
|
|
|
1402
1402
|
@MaxLength(16)
|
|
1403
1403
|
ID: string;
|
|
1404
1404
|
|
|
1405
|
-
@Field(
|
|
1405
|
+
@Field()
|
|
1406
1406
|
@MaxLength(16)
|
|
1407
|
-
AgentID
|
|
1407
|
+
AgentID: string;
|
|
1408
1408
|
|
|
1409
|
-
@Field(
|
|
1409
|
+
@Field()
|
|
1410
1410
|
@MaxLength(16)
|
|
1411
|
-
AgentNoteTypeID
|
|
1411
|
+
AgentNoteTypeID: string;
|
|
1412
1412
|
|
|
1413
1413
|
@Field({nullable: true})
|
|
1414
1414
|
Note?: string;
|
|
@@ -1449,10 +1449,10 @@ export class AIAgentNote_ {
|
|
|
1449
1449
|
@InputType()
|
|
1450
1450
|
export class CreateAIAgentNoteInput {
|
|
1451
1451
|
@Field({ nullable: true })
|
|
1452
|
-
AgentID
|
|
1452
|
+
AgentID?: string;
|
|
1453
1453
|
|
|
1454
1454
|
@Field({ nullable: true })
|
|
1455
|
-
AgentNoteTypeID
|
|
1455
|
+
AgentNoteTypeID?: string;
|
|
1456
1456
|
|
|
1457
1457
|
@Field({ nullable: true })
|
|
1458
1458
|
Note: string | null;
|
|
@@ -1474,10 +1474,10 @@ export class UpdateAIAgentNoteInput {
|
|
|
1474
1474
|
ID: string;
|
|
1475
1475
|
|
|
1476
1476
|
@Field({ nullable: true })
|
|
1477
|
-
AgentID?: string
|
|
1477
|
+
AgentID?: string;
|
|
1478
1478
|
|
|
1479
1479
|
@Field({ nullable: true })
|
|
1480
|
-
AgentNoteTypeID?: string
|
|
1480
|
+
AgentNoteTypeID?: string;
|
|
1481
1481
|
|
|
1482
1482
|
@Field({ nullable: true })
|
|
1483
1483
|
Note?: string | null;
|
|
@@ -6271,9 +6271,6 @@ export class User_ {
|
|
|
6271
6271
|
@Field(() => [UserFavorite_])
|
|
6272
6272
|
UserFavorites_UserIDArray: UserFavorite_[]; // Link to UserFavorites
|
|
6273
6273
|
|
|
6274
|
-
@Field(() => [ResourceLink_])
|
|
6275
|
-
ResourceLinks_UserIDArray: ResourceLink_[]; // Link to ResourceLinks
|
|
6276
|
-
|
|
6277
6274
|
@Field(() => [ListCategory_])
|
|
6278
6275
|
ListCategories_UserIDArray: ListCategory_[]; // Link to ListCategories
|
|
6279
6276
|
|
|
@@ -6283,21 +6280,24 @@ export class User_ {
|
|
|
6283
6280
|
@Field(() => [AIAgentRequest_])
|
|
6284
6281
|
AIAgentRequests_ResponseByUserIDArray: AIAgentRequest_[]; // Link to AIAgentRequests
|
|
6285
6282
|
|
|
6283
|
+
@Field(() => [ResourceLink_])
|
|
6284
|
+
ResourceLinks_UserIDArray: ResourceLink_[]; // Link to ResourceLinks
|
|
6285
|
+
|
|
6286
6286
|
@Field(() => [ReportUserState_])
|
|
6287
6287
|
MJ_ReportUserStates_UserIDArray: ReportUserState_[]; // Link to MJ_ReportUserStates
|
|
6288
6288
|
|
|
6289
6289
|
@Field(() => [AIAgentNote_])
|
|
6290
6290
|
AIAgentNotes_UserIDArray: AIAgentNote_[]; // Link to AIAgentNotes
|
|
6291
6291
|
|
|
6292
|
-
@Field(() => [ResourcePermission_])
|
|
6293
|
-
ResourcePermissions_UserIDArray: ResourcePermission_[]; // Link to ResourcePermissions
|
|
6294
|
-
|
|
6295
6292
|
@Field(() => [AIAgentRequest_])
|
|
6296
6293
|
AIAgentRequests_RequestForUserIDArray: AIAgentRequest_[]; // Link to AIAgentRequests
|
|
6297
6294
|
|
|
6298
6295
|
@Field(() => [ConversationDetail_])
|
|
6299
6296
|
ConversationDetails_UserIDArray: ConversationDetail_[]; // Link to ConversationDetails
|
|
6300
6297
|
|
|
6298
|
+
@Field(() => [ResourcePermission_])
|
|
6299
|
+
ResourcePermissions_UserIDArray: ResourcePermission_[]; // Link to ResourcePermissions
|
|
6300
|
+
|
|
6301
6301
|
}
|
|
6302
6302
|
|
|
6303
6303
|
//****************************************************************************
|
|
@@ -6720,15 +6720,6 @@ export class UserResolverBase extends ResolverBase {
|
|
|
6720
6720
|
return result;
|
|
6721
6721
|
}
|
|
6722
6722
|
|
|
6723
|
-
@FieldResolver(() => [ResourceLink_])
|
|
6724
|
-
async ResourceLinks_UserIDArray(@Root() user_: User_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
6725
|
-
this.CheckUserReadPermissions('Resource Links', userPayload);
|
|
6726
|
-
const dataSource = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
|
|
6727
|
-
const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwResourceLinks] WHERE [UserID]='${user_.ID}' ` + this.getRowLevelSecurityWhereClause('Resource Links', userPayload, EntityPermissionType.Read, 'AND');
|
|
6728
|
-
const result = this.ArrayMapFieldNamesToCodeNames('Resource Links', await dataSource.query(sSQL));
|
|
6729
|
-
return result;
|
|
6730
|
-
}
|
|
6731
|
-
|
|
6732
6723
|
@FieldResolver(() => [ListCategory_])
|
|
6733
6724
|
async ListCategories_UserIDArray(@Root() user_: User_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
6734
6725
|
this.CheckUserReadPermissions('List Categories', userPayload);
|
|
@@ -6756,6 +6747,15 @@ export class UserResolverBase extends ResolverBase {
|
|
|
6756
6747
|
return result;
|
|
6757
6748
|
}
|
|
6758
6749
|
|
|
6750
|
+
@FieldResolver(() => [ResourceLink_])
|
|
6751
|
+
async ResourceLinks_UserIDArray(@Root() user_: User_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
6752
|
+
this.CheckUserReadPermissions('Resource Links', userPayload);
|
|
6753
|
+
const dataSource = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
|
|
6754
|
+
const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwResourceLinks] WHERE [UserID]='${user_.ID}' ` + this.getRowLevelSecurityWhereClause('Resource Links', userPayload, EntityPermissionType.Read, 'AND');
|
|
6755
|
+
const result = this.ArrayMapFieldNamesToCodeNames('Resource Links', await dataSource.query(sSQL));
|
|
6756
|
+
return result;
|
|
6757
|
+
}
|
|
6758
|
+
|
|
6759
6759
|
@FieldResolver(() => [ReportUserState_])
|
|
6760
6760
|
async MJ_ReportUserStates_UserIDArray(@Root() user_: User_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
6761
6761
|
this.CheckUserReadPermissions('MJ: Report User States', userPayload);
|
|
@@ -6774,15 +6774,6 @@ export class UserResolverBase extends ResolverBase {
|
|
|
6774
6774
|
return result;
|
|
6775
6775
|
}
|
|
6776
6776
|
|
|
6777
|
-
@FieldResolver(() => [ResourcePermission_])
|
|
6778
|
-
async ResourcePermissions_UserIDArray(@Root() user_: User_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
6779
|
-
this.CheckUserReadPermissions('Resource Permissions', userPayload);
|
|
6780
|
-
const dataSource = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
|
|
6781
|
-
const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwResourcePermissions] WHERE [UserID]='${user_.ID}' ` + this.getRowLevelSecurityWhereClause('Resource Permissions', userPayload, EntityPermissionType.Read, 'AND');
|
|
6782
|
-
const result = this.ArrayMapFieldNamesToCodeNames('Resource Permissions', await dataSource.query(sSQL));
|
|
6783
|
-
return result;
|
|
6784
|
-
}
|
|
6785
|
-
|
|
6786
6777
|
@FieldResolver(() => [AIAgentRequest_])
|
|
6787
6778
|
async AIAgentRequests_RequestForUserIDArray(@Root() user_: User_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
6788
6779
|
this.CheckUserReadPermissions('AI Agent Requests', userPayload);
|
|
@@ -6801,6 +6792,15 @@ export class UserResolverBase extends ResolverBase {
|
|
|
6801
6792
|
return result;
|
|
6802
6793
|
}
|
|
6803
6794
|
|
|
6795
|
+
@FieldResolver(() => [ResourcePermission_])
|
|
6796
|
+
async ResourcePermissions_UserIDArray(@Root() user_: User_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
6797
|
+
this.CheckUserReadPermissions('Resource Permissions', userPayload);
|
|
6798
|
+
const dataSource = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
|
|
6799
|
+
const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwResourcePermissions] WHERE [UserID]='${user_.ID}' ` + this.getRowLevelSecurityWhereClause('Resource Permissions', userPayload, EntityPermissionType.Read, 'AND');
|
|
6800
|
+
const result = this.ArrayMapFieldNamesToCodeNames('Resource Permissions', await dataSource.query(sSQL));
|
|
6801
|
+
return result;
|
|
6802
|
+
}
|
|
6803
|
+
|
|
6804
6804
|
@Mutation(() => User_)
|
|
6805
6805
|
async CreateUser(
|
|
6806
6806
|
@Arg('input', () => CreateUserInput) input: CreateUserInput,
|
|
@@ -12023,6 +12023,9 @@ export class AIModel_ {
|
|
|
12023
12023
|
@MaxLength(200)
|
|
12024
12024
|
SupportedResponseFormats: string;
|
|
12025
12025
|
|
|
12026
|
+
@Field(() => Boolean, {description: `Specifies if the model supports the concept of an effort level. For example, for a reasoning model, the options often include low, medium, and high.`})
|
|
12027
|
+
SupportsEffortLevel: boolean;
|
|
12028
|
+
|
|
12026
12029
|
@Field()
|
|
12027
12030
|
@MaxLength(100)
|
|
12028
12031
|
AIModelType: string;
|
|
@@ -12039,15 +12042,15 @@ export class AIModel_ {
|
|
|
12039
12042
|
@Field(() => [VectorIndex_])
|
|
12040
12043
|
VectorIndexes_EmbeddingModelIDArray: VectorIndex_[]; // Link to VectorIndexes
|
|
12041
12044
|
|
|
12042
|
-
@Field(() => [ContentType_])
|
|
12043
|
-
ContentTypes_AIModelIDArray: ContentType_[]; // Link to ContentTypes
|
|
12044
|
-
|
|
12045
12045
|
@Field(() => [AIResultCache_])
|
|
12046
12046
|
AIResultCache_AIModelIDArray: AIResultCache_[]; // Link to AIResultCache
|
|
12047
12047
|
|
|
12048
12048
|
@Field(() => [EntityAIAction_])
|
|
12049
12049
|
EntityAIActions_AIModelIDArray: EntityAIAction_[]; // Link to EntityAIActions
|
|
12050
12050
|
|
|
12051
|
+
@Field(() => [ContentType_])
|
|
12052
|
+
ContentTypes_AIModelIDArray: ContentType_[]; // Link to ContentTypes
|
|
12053
|
+
|
|
12051
12054
|
@Field(() => [AIAgentModel_])
|
|
12052
12055
|
AIAgentModels_ModelIDArray: AIAgentModel_[]; // Link to AIAgentModels
|
|
12053
12056
|
|
|
@@ -12102,6 +12105,9 @@ export class CreateAIModelInput {
|
|
|
12102
12105
|
|
|
12103
12106
|
@Field({ nullable: true })
|
|
12104
12107
|
SupportedResponseFormats?: string;
|
|
12108
|
+
|
|
12109
|
+
@Field(() => Boolean, { nullable: true })
|
|
12110
|
+
SupportsEffortLevel?: boolean;
|
|
12105
12111
|
}
|
|
12106
12112
|
|
|
12107
12113
|
|
|
@@ -12155,6 +12161,9 @@ export class UpdateAIModelInput {
|
|
|
12155
12161
|
@Field({ nullable: true })
|
|
12156
12162
|
SupportedResponseFormats?: string;
|
|
12157
12163
|
|
|
12164
|
+
@Field(() => Boolean, { nullable: true })
|
|
12165
|
+
SupportsEffortLevel?: boolean;
|
|
12166
|
+
|
|
12158
12167
|
@Field(() => [KeyValuePairInput], { nullable: true })
|
|
12159
12168
|
OldValues___?: KeyValuePairInput[];
|
|
12160
12169
|
}
|
|
@@ -12260,15 +12269,6 @@ export class AIModelResolver extends ResolverBase {
|
|
|
12260
12269
|
return result;
|
|
12261
12270
|
}
|
|
12262
12271
|
|
|
12263
|
-
@FieldResolver(() => [ContentType_])
|
|
12264
|
-
async ContentTypes_AIModelIDArray(@Root() aimodel_: AIModel_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
12265
|
-
this.CheckUserReadPermissions('Content Types', userPayload);
|
|
12266
|
-
const dataSource = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
|
|
12267
|
-
const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwContentTypes] WHERE [AIModelID]='${aimodel_.ID}' ` + this.getRowLevelSecurityWhereClause('Content Types', userPayload, EntityPermissionType.Read, 'AND');
|
|
12268
|
-
const result = this.ArrayMapFieldNamesToCodeNames('Content Types', await dataSource.query(sSQL));
|
|
12269
|
-
return result;
|
|
12270
|
-
}
|
|
12271
|
-
|
|
12272
12272
|
@FieldResolver(() => [AIResultCache_])
|
|
12273
12273
|
async AIResultCache_AIModelIDArray(@Root() aimodel_: AIModel_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
12274
12274
|
this.CheckUserReadPermissions('AI Result Cache', userPayload);
|
|
@@ -12287,6 +12287,15 @@ export class AIModelResolver extends ResolverBase {
|
|
|
12287
12287
|
return result;
|
|
12288
12288
|
}
|
|
12289
12289
|
|
|
12290
|
+
@FieldResolver(() => [ContentType_])
|
|
12291
|
+
async ContentTypes_AIModelIDArray(@Root() aimodel_: AIModel_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
12292
|
+
this.CheckUserReadPermissions('Content Types', userPayload);
|
|
12293
|
+
const dataSource = GetReadOnlyDataSource(dataSources, { allowFallbackToReadWrite: true });
|
|
12294
|
+
const sSQL = `SELECT * FROM [${Metadata.Provider.ConfigData.MJCoreSchemaName}].[vwContentTypes] WHERE [AIModelID]='${aimodel_.ID}' ` + this.getRowLevelSecurityWhereClause('Content Types', userPayload, EntityPermissionType.Read, 'AND');
|
|
12295
|
+
const result = this.ArrayMapFieldNamesToCodeNames('Content Types', await dataSource.query(sSQL));
|
|
12296
|
+
return result;
|
|
12297
|
+
}
|
|
12298
|
+
|
|
12290
12299
|
@FieldResolver(() => [AIAgentModel_])
|
|
12291
12300
|
async AIAgentModels_ModelIDArray(@Root() aimodel_: AIModel_, @Ctx() { dataSources, userPayload }: AppContext, @PubSub() pubSub: PubSubEngine) {
|
|
12292
12301
|
this.CheckUserReadPermissions('AI Agent Models', userPayload);
|
package/src/index.ts
CHANGED
|
@@ -21,10 +21,11 @@ import { BuildSchemaOptions, buildSchemaSync, GraphQLTimestamp } from 'type-grap
|
|
|
21
21
|
import { DataSource } from 'typeorm';
|
|
22
22
|
import { WebSocketServer } from 'ws';
|
|
23
23
|
import buildApolloServer from './apolloServer/index.js';
|
|
24
|
-
import { configInfo, dbDatabase, dbHost, dbPort, dbUsername, graphqlPort, graphqlRootPath, mj_core_schema, websiteRunFromPackage } from './config.js';
|
|
24
|
+
import { configInfo, dbDatabase, dbHost, dbPort, dbUsername, graphqlPort, graphqlRootPath, mj_core_schema, websiteRunFromPackage, RESTApiOptions } from './config.js';
|
|
25
25
|
import { contextFunction, getUserPayload } from './context.js';
|
|
26
26
|
import { requireSystemUserDirective, publicDirective } from './directives/index.js';
|
|
27
27
|
import orm from './orm.js';
|
|
28
|
+
import { setupRESTEndpoints } from './rest/setupRESTEndpoints.js';
|
|
28
29
|
|
|
29
30
|
import { LoadActionEntityServer } from '@memberjunction/actions';
|
|
30
31
|
LoadActionEntityServer(); // prevent tree shaking for this dynamic module
|
|
@@ -76,6 +77,7 @@ import { DataSourceInfo, raiseEvent } from './types.js';
|
|
|
76
77
|
|
|
77
78
|
export type MJServerOptions = {
|
|
78
79
|
onBeforeServe?: () => void | Promise<void>;
|
|
80
|
+
restApiOptions?: Partial<RESTApiOptions>; // Options for REST API configuration
|
|
79
81
|
};
|
|
80
82
|
|
|
81
83
|
const localPath = (p: string) => {
|
|
@@ -225,6 +227,59 @@ export const serve = async (resolverPaths: Array<string>, app = createApp(), opt
|
|
|
225
227
|
}),
|
|
226
228
|
})
|
|
227
229
|
);
|
|
230
|
+
|
|
231
|
+
// Setup REST API endpoints
|
|
232
|
+
const authMiddleware = async (req, res, next) => {
|
|
233
|
+
try {
|
|
234
|
+
const sessionIdRaw = req.headers['x-session-id'];
|
|
235
|
+
const requestDomain = new URL(req.headers.origin || '').hostname;
|
|
236
|
+
const sessionId = sessionIdRaw ? sessionIdRaw.toString() : '';
|
|
237
|
+
const bearerToken = req.headers.authorization ?? '';
|
|
238
|
+
const apiKey = String(req.headers['x-mj-api-key']);
|
|
239
|
+
|
|
240
|
+
const userPayload = await getUserPayload(bearerToken, sessionId, dataSources, requestDomain, apiKey);
|
|
241
|
+
if (!userPayload) {
|
|
242
|
+
return res.status(401).json({ error: 'Invalid token' });
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
req.user = userPayload;
|
|
246
|
+
next();
|
|
247
|
+
} catch (error) {
|
|
248
|
+
console.error('Auth error:', error);
|
|
249
|
+
return res.status(401).json({ error: 'Authentication failed' });
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
// Get REST API configuration from the config file
|
|
254
|
+
const restApiConfig: RESTApiOptions = {
|
|
255
|
+
enabled: configInfo.restApiOptions?.enabled ?? true,
|
|
256
|
+
includeEntities: configInfo.restApiOptions?.includeEntities,
|
|
257
|
+
excludeEntities: configInfo.restApiOptions?.excludeEntities
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
// Apply options from server options if provided (these override the config file)
|
|
261
|
+
if (options?.restApiOptions) {
|
|
262
|
+
Object.assign(restApiConfig, options.restApiOptions);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Get REST API configuration from environment variables if present (env vars override everything)
|
|
266
|
+
if (process.env.MJ_REST_API_ENABLED !== undefined) {
|
|
267
|
+
restApiConfig.enabled = process.env.MJ_REST_API_ENABLED === 'true';
|
|
268
|
+
if (restApiConfig.enabled) {
|
|
269
|
+
console.log('REST API is enabled via environment variable');
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (process.env.MJ_REST_API_INCLUDE_ENTITIES) {
|
|
274
|
+
restApiConfig.includeEntities = process.env.MJ_REST_API_INCLUDE_ENTITIES.split(',').map(e => e.trim());
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (process.env.MJ_REST_API_EXCLUDE_ENTITIES) {
|
|
278
|
+
restApiConfig.excludeEntities = process.env.MJ_REST_API_EXCLUDE_ENTITIES.split(',').map(e => e.trim());
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Set up REST endpoints with the configured options and auth middleware
|
|
282
|
+
setupRESTEndpoints(app, restApiConfig, authMiddleware);
|
|
228
283
|
|
|
229
284
|
if (options?.onBeforeServe) {
|
|
230
285
|
await Promise.resolve(options.onBeforeServe());
|