@memberjunction/server 5.41.0 → 5.42.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.
Files changed (76) hide show
  1. package/dist/agentSessions/index.d.ts +1 -0
  2. package/dist/agentSessions/index.d.ts.map +1 -1
  3. package/dist/agentSessions/index.js +5 -0
  4. package/dist/agentSessions/index.js.map +1 -1
  5. package/dist/agentSessions/remoteBrowserGoalEngine.d.ts +102 -0
  6. package/dist/agentSessions/remoteBrowserGoalEngine.d.ts.map +1 -0
  7. package/dist/agentSessions/remoteBrowserGoalEngine.js +164 -0
  8. package/dist/agentSessions/remoteBrowserGoalEngine.js.map +1 -0
  9. package/dist/agentSessions/remoteBrowserGoalRegistry.d.ts +66 -0
  10. package/dist/agentSessions/remoteBrowserGoalRegistry.d.ts.map +1 -0
  11. package/dist/agentSessions/remoteBrowserGoalRegistry.js +86 -0
  12. package/dist/agentSessions/remoteBrowserGoalRegistry.js.map +1 -0
  13. package/dist/auth/initializeProviders.d.ts.map +1 -1
  14. package/dist/auth/initializeProviders.js +4 -7
  15. package/dist/auth/initializeProviders.js.map +1 -1
  16. package/dist/config.d.ts +7 -0
  17. package/dist/config.d.ts.map +1 -1
  18. package/dist/config.js +12 -2
  19. package/dist/config.js.map +1 -1
  20. package/dist/generated/generated.d.ts +591 -0
  21. package/dist/generated/generated.d.ts.map +1 -1
  22. package/dist/generated/generated.js +6832 -3610
  23. package/dist/generated/generated.js.map +1 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +33 -16
  26. package/dist/index.js.map +1 -1
  27. package/dist/integration/CustomColumnPromoter.d.ts +108 -0
  28. package/dist/integration/CustomColumnPromoter.d.ts.map +1 -0
  29. package/dist/integration/CustomColumnPromoter.js +508 -0
  30. package/dist/integration/CustomColumnPromoter.js.map +1 -0
  31. package/dist/logging/StartupLogger.d.ts +57 -1
  32. package/dist/logging/StartupLogger.d.ts.map +1 -1
  33. package/dist/logging/StartupLogger.js +115 -6
  34. package/dist/logging/StartupLogger.js.map +1 -1
  35. package/dist/resolvers/ExecuteRemoteOperationResolver.d.ts +27 -0
  36. package/dist/resolvers/ExecuteRemoteOperationResolver.d.ts.map +1 -0
  37. package/dist/resolvers/ExecuteRemoteOperationResolver.js +136 -0
  38. package/dist/resolvers/ExecuteRemoteOperationResolver.js.map +1 -0
  39. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts +101 -1
  40. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
  41. package/dist/resolvers/IntegrationDiscoveryResolver.js +544 -42
  42. package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
  43. package/dist/resolvers/RealtimeBridgeResolver.d.ts +121 -0
  44. package/dist/resolvers/RealtimeBridgeResolver.d.ts.map +1 -0
  45. package/dist/resolvers/RealtimeBridgeResolver.js +533 -0
  46. package/dist/resolvers/RealtimeBridgeResolver.js.map +1 -0
  47. package/dist/resolvers/RemoteBrowserActionResolver.d.ts +78 -5
  48. package/dist/resolvers/RemoteBrowserActionResolver.d.ts.map +1 -1
  49. package/dist/resolvers/RemoteBrowserActionResolver.js +227 -15
  50. package/dist/resolvers/RemoteBrowserActionResolver.js.map +1 -1
  51. package/dist/resolvers/RunAIAgentResolver.d.ts.map +1 -1
  52. package/dist/resolvers/RunAIAgentResolver.js +0 -7
  53. package/dist/resolvers/RunAIAgentResolver.js.map +1 -1
  54. package/dist/rest/setupRESTEndpoints.d.ts.map +1 -1
  55. package/dist/rest/setupRESTEndpoints.js +5 -3
  56. package/dist/rest/setupRESTEndpoints.js.map +1 -1
  57. package/package.json +83 -78
  58. package/src/__tests__/RealtimeBridgeResolver.test.ts +100 -0
  59. package/src/__tests__/RemoteBrowserAudioStream.test.ts +8 -1
  60. package/src/__tests__/RemoteBrowserGoalEngine.test.ts +144 -0
  61. package/src/__tests__/remoteBrowserGoalRegistry.test.ts +81 -0
  62. package/src/agentSessions/index.ts +5 -0
  63. package/src/agentSessions/remoteBrowserGoalEngine.ts +191 -0
  64. package/src/agentSessions/remoteBrowserGoalRegistry.ts +122 -0
  65. package/src/auth/initializeProviders.ts +4 -7
  66. package/src/config.ts +13 -2
  67. package/src/generated/generated.ts +2444 -205
  68. package/src/index.ts +33 -16
  69. package/src/integration/CustomColumnPromoter.ts +597 -0
  70. package/src/logging/StartupLogger.ts +130 -6
  71. package/src/resolvers/ExecuteRemoteOperationResolver.ts +108 -0
  72. package/src/resolvers/IntegrationDiscoveryResolver.ts +396 -37
  73. package/src/resolvers/RealtimeBridgeResolver.ts +450 -0
  74. package/src/resolvers/RemoteBrowserActionResolver.ts +232 -17
  75. package/src/resolvers/RunAIAgentResolver.ts +1 -9
  76. package/src/rest/setupRESTEndpoints.ts +5 -3
package/src/index.ts CHANGED
@@ -9,6 +9,7 @@ import { resolveDbPlatformFromEnv } from '@memberjunction/generic-database-provi
9
9
  import { MJGlobal, MJEventType, UUIDsEqual, ShutdownRegistry } from '@memberjunction/global';
10
10
  import { setupSQLServerClient, SQLServerDataProvider, SQLServerProviderConfigData, UserCache } from '@memberjunction/sqlserver-dataprovider';
11
11
  import { extendConnectionPoolWithQuery } from './util.js';
12
+ import { registerIntegrationCustomColumnPromoter } from './integration/CustomColumnPromoter.js';
12
13
  import { default as BodyParser } from 'body-parser';
13
14
  import compression from 'compression'; // Add compression middleware
14
15
  import cors from 'cors';
@@ -26,7 +27,7 @@ import { PubSub } from 'graphql-subscriptions';
26
27
  import sql from 'mssql';
27
28
  import { WebSocketServer } from 'ws';
28
29
  import buildApolloServer from './apolloServer/index.js';
29
- import { configInfo, dbDatabase, dbHost, dbPort, dbUsername, graphqlPort, graphqlRootPath, mj_core_schema, websiteRunFromPackage, RESTApiOptions } from './config.js';
30
+ import { configInfo, configFilePath, dbDatabase, dbHost, dbPort, dbUsername, graphqlPort, graphqlRootPath, mj_core_schema, websiteRunFromPackage, RESTApiOptions } from './config.js';
30
31
  import { default as jwt } from 'jsonwebtoken';
31
32
  import { contextFunction, createUnifiedAuthMiddleware, getUserPayload } from './context.js';
32
33
  import { UserPayload } from './types.js';
@@ -230,6 +231,8 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
230
231
  // LogStatusEx({ verboseOnly: true }) lines (cache, scheduling, integration, MCP, …) honor the
231
232
  // configured level instead of defaulting to hidden. Without this, "verbose-only" is "always hidden".
232
233
  SetVerboseLogging(startupLog.IsAtLeast('verbose'));
234
+ // Transient boot spinner (standard level + TTY only); cleared by PrintSummary.
235
+ startupLog.StartBoot();
233
236
  const lap = (label: string, since: number) => startupLog.EndPhase(label, since);
234
237
 
235
238
  const localResolverPaths = ['resolvers/**/*Resolver.{js,ts}', 'generic/*Resolver.{js,ts}', 'generated/generated.{js,ts}'].map(localPath);
@@ -250,6 +253,7 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
250
253
 
251
254
  if (dbType === 'postgresql') {
252
255
  // ─── PostgreSQL Path ───────────────────────────────────────────
256
+ startupLog.BeginPhase('Connecting to database');
253
257
  startupLog.LogIf('verbose', 'Database type: PostgreSQL');
254
258
  const pg = await import('pg');
255
259
  const { PostgreSQLDataProvider, PostgreSQLProviderConfigData } = await import('@memberjunction/postgresql-dataprovider');
@@ -372,8 +376,7 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
372
376
 
373
377
  // Set up in-process CodeGen runner for RSU
374
378
  try {
375
- const { RunCodeGenBase } = await import('@memberjunction/codegen-lib');
376
- const { PostgreSQLCodeGenConnection } = await import('@memberjunction/codegen-lib/dist/Database/providers/postgresql/PostgreSQLCodeGenConnection.js');
379
+ const { RunCodeGenBase, PostgreSQLCodeGenConnection } = await import('@memberjunction/codegen-lib');
377
380
 
378
381
  const codegenConnection = new PostgreSQLCodeGenConnection(codegenPgPool);
379
382
  const codegenCurrentUser = UserCache.Instance.Users.find(u => u.Type?.trim().toLowerCase() === 'owner') ?? UserCache.Instance.Users[0];
@@ -422,7 +425,7 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
422
425
  } else {
423
426
  // ─── SQL Server Path (existing behavior) ───────────────────────
424
427
  startupLog.LogIf('verbose', 'Database type: SQL Server');
425
- let tPhase = performance.now();
428
+ let tPhase = startupLog.BeginPhase('Connecting to database');
426
429
  const pool = new sql.ConnectionPool(createMSSQLConfig());
427
430
 
428
431
  // Handle connection-level errors from dead/stale connections in the pool.
@@ -433,7 +436,8 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
433
436
  });
434
437
 
435
438
  await pool.connect();
436
- tPhase = lap('DB Pool Connect', tPhase);
439
+ lap('DB Pool Connect', tPhase);
440
+ tPhase = startupLog.BeginPhase('Loading metadata + providers');
437
441
 
438
442
  dataSources.push(new DataSourceInfo({dataSource: pool, type: 'Read-Write', host: dbHost, port: dbPort, database: dbDatabase, userName: dbUsername}));
439
443
 
@@ -458,7 +462,8 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
458
462
 
459
463
  const config = new SQLServerProviderConfigData(pool, mj_core_schema, cacheRefreshInterval);
460
464
  await setupSQLServerClient(config);
461
- tPhase = lap('Metadata + Provider Setup', tPhase);
465
+ lap('Metadata + Provider Setup', tPhase);
466
+ startupLog.BeginPhase('Initializing data provider');
462
467
  const md = new Metadata(); // global-provider-ok: bootstrap
463
468
  const entityCount = md?.Entities ? md.Entities.length : 0;
464
469
  startupLog.LogIf('verbose', `Data Source has been initialized. ${entityCount} entities loaded.`);
@@ -495,8 +500,7 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
495
500
 
496
501
  // Set up in-process CodeGen runner for RSU
497
502
  try {
498
- const { RunCodeGenBase } = await import('@memberjunction/codegen-lib');
499
- const { SQLServerCodeGenConnection } = await import('@memberjunction/codegen-lib/dist/Database/providers/sqlserver/SQLServerCodeGenConnection.js');
503
+ const { RunCodeGenBase, SQLServerCodeGenConnection } = await import('@memberjunction/codegen-lib');
500
504
 
501
505
  const codegenConnection = new SQLServerCodeGenConnection(codegenPool);
502
506
  const codegenCurrentUser = UserCache.Instance.Users.find(u => u.Type?.trim().toLowerCase() === 'owner') ?? UserCache.Instance.Users[0];
@@ -540,7 +544,15 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
540
544
  }
541
545
  }
542
546
 
543
- let tServe = performance.now();
547
+ // Register the post-sync custom-column promotion hook (gaps.md §2). Safe to call regardless of
548
+ // RSU config: the hook self-gates on captured overflow data and uses RSU only at fire time.
549
+ try {
550
+ registerIntegrationCustomColumnPromoter();
551
+ } catch (err) {
552
+ console.warn(`Custom-column promoter registration failed (post-sync promotion disabled): ${(err as Error).message}`);
553
+ }
554
+
555
+ let tServe = startupLog.BeginPhase('Initializing services');
544
556
 
545
557
  // Store queryDialects config in GlobalObjectStore so MJQueryEntityServer can
546
558
  // read it without a circular dependency on MJServer
@@ -647,7 +659,8 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
647
659
  /******TEST HARNESS FOR CHANGE DETECTION */
648
660
  /******TEST HARNESS FOR CHANGE DETECTION */
649
661
 
650
- tServe = lap('Telemetry + Cache + APIKey Init', tServe);
662
+ lap('Telemetry + Cache + APIKey Init', tServe);
663
+ tServe = startupLog.BeginPhase('Discovering resolvers');
651
664
 
652
665
  const dynamicModules = await Promise.all(
653
666
  paths.map((modulePath) => {
@@ -804,7 +817,8 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
804
817
  }
805
818
  });
806
819
 
807
- tServe = lap('Resolver + Middleware Discovery', tServe);
820
+ lap('Resolver + Middleware Discovery', tServe);
821
+ tServe = startupLog.BeginPhase('Building GraphQL schema');
808
822
 
809
823
  let schema = mergeSchemas({
810
824
  schemas: [
@@ -831,7 +845,8 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
831
845
  schema = transformer(schema);
832
846
  }
833
847
 
834
- tServe = lap('Schema Build', tServe);
848
+ lap('Schema Build', tServe);
849
+ tServe = startupLog.BeginPhase('Starting HTTP server');
835
850
 
836
851
  const httpServer = createServer(app);
837
852
 
@@ -1118,18 +1133,20 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
1118
1133
  await Promise.resolve(options.onBeforeServe());
1119
1134
  }
1120
1135
 
1121
- tServe = lap('Apollo + Express Setup', tServe);
1136
+ lap('Apollo + Express Setup', tServe);
1122
1137
 
1123
1138
  await new Promise<void>((resolve) => httpServer.listen({ port: graphqlPort }, resolve));
1124
- // Total startup measured but not pushed as a phase row — the per-phase rows already
1125
- // sum to the total in the collapsed summary line. Keep the measurement for verbose.
1126
- startupLog.EndPhase('Total Startup', t0);
1139
+ // The summary headline reports TRUE wall-clock since process start (see
1140
+ // StartupLogger.buildStartupLine), so we don't push a synthetic "total" phase row
1141
+ // (that double-counted the headline). Keep a verbose-only line for the serve()-scoped span.
1142
+ startupLog.LogIf('verbose', `serve() startup: ${((performance.now() - t0) / 1000).toFixed(1)}s`);
1127
1143
  startupLog.SetReadyUrl(`http://localhost:${graphqlPort}/`);
1128
1144
  // Populate summary fields that are known only now, then print the one summary block.
1129
1145
  for (const provider of AuthProviderFactory.Instance.getAllProviders()) {
1130
1146
  startupLog.AddAuthProvider(provider.name);
1131
1147
  }
1132
1148
  startupLog.SetVersion(resolveServerVersion());
1149
+ startupLog.SetConfigPath(configFilePath);
1133
1150
  if (scheduledJobsService) {
1134
1151
  startupLog.SetScheduledJobCount(scheduledJobsService.GetStatus().activeJobs);
1135
1152
  }