@memberjunction/server 5.15.0 → 5.16.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 (70) hide show
  1. package/dist/auth/index.d.ts +0 -3
  2. package/dist/auth/index.d.ts.map +1 -1
  3. package/dist/auth/index.js +5 -7
  4. package/dist/auth/index.js.map +1 -1
  5. package/dist/auth/initializeProviders.js +2 -2
  6. package/dist/auth/initializeProviders.js.map +1 -1
  7. package/dist/context.d.ts.map +1 -1
  8. package/dist/context.js +3 -3
  9. package/dist/context.js.map +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +16 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/resolvers/DatasetResolver.d.ts +5 -0
  15. package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
  16. package/dist/resolvers/DatasetResolver.js +35 -0
  17. package/dist/resolvers/DatasetResolver.js.map +1 -1
  18. package/package.json +60 -59
  19. package/src/__tests__/unifiedAuth.test.ts +3 -2
  20. package/src/auth/__tests__/backward-compatibility.test.ts +2 -3
  21. package/src/auth/index.ts +5 -8
  22. package/src/auth/initializeProviders.ts +2 -2
  23. package/src/context.ts +3 -3
  24. package/src/index.ts +21 -3
  25. package/src/resolvers/DatasetResolver.ts +36 -0
  26. package/dist/auth/AuthProviderFactory.d.ts +0 -68
  27. package/dist/auth/AuthProviderFactory.d.ts.map +0 -1
  28. package/dist/auth/AuthProviderFactory.js +0 -155
  29. package/dist/auth/AuthProviderFactory.js.map +0 -1
  30. package/dist/auth/BaseAuthProvider.d.ts +0 -41
  31. package/dist/auth/BaseAuthProvider.d.ts.map +0 -1
  32. package/dist/auth/BaseAuthProvider.js +0 -102
  33. package/dist/auth/BaseAuthProvider.js.map +0 -1
  34. package/dist/auth/IAuthProvider.d.ts +0 -46
  35. package/dist/auth/IAuthProvider.d.ts.map +0 -1
  36. package/dist/auth/IAuthProvider.js +0 -2
  37. package/dist/auth/IAuthProvider.js.map +0 -1
  38. package/dist/auth/providers/Auth0Provider.d.ts +0 -18
  39. package/dist/auth/providers/Auth0Provider.d.ts.map +0 -1
  40. package/dist/auth/providers/Auth0Provider.js +0 -52
  41. package/dist/auth/providers/Auth0Provider.js.map +0 -1
  42. package/dist/auth/providers/CognitoProvider.d.ts +0 -18
  43. package/dist/auth/providers/CognitoProvider.d.ts.map +0 -1
  44. package/dist/auth/providers/CognitoProvider.js +0 -56
  45. package/dist/auth/providers/CognitoProvider.js.map +0 -1
  46. package/dist/auth/providers/GoogleProvider.d.ts +0 -18
  47. package/dist/auth/providers/GoogleProvider.d.ts.map +0 -1
  48. package/dist/auth/providers/GoogleProvider.js +0 -51
  49. package/dist/auth/providers/GoogleProvider.js.map +0 -1
  50. package/dist/auth/providers/MSALProvider.d.ts +0 -18
  51. package/dist/auth/providers/MSALProvider.d.ts.map +0 -1
  52. package/dist/auth/providers/MSALProvider.js +0 -52
  53. package/dist/auth/providers/MSALProvider.js.map +0 -1
  54. package/dist/auth/providers/OktaProvider.d.ts +0 -18
  55. package/dist/auth/providers/OktaProvider.d.ts.map +0 -1
  56. package/dist/auth/providers/OktaProvider.js +0 -52
  57. package/dist/auth/providers/OktaProvider.js.map +0 -1
  58. package/dist/auth/tokenExpiredError.d.ts +0 -5
  59. package/dist/auth/tokenExpiredError.d.ts.map +0 -1
  60. package/dist/auth/tokenExpiredError.js +0 -12
  61. package/dist/auth/tokenExpiredError.js.map +0 -1
  62. package/src/auth/AuthProviderFactory.ts +0 -182
  63. package/src/auth/BaseAuthProvider.ts +0 -137
  64. package/src/auth/IAuthProvider.ts +0 -54
  65. package/src/auth/providers/Auth0Provider.ts +0 -45
  66. package/src/auth/providers/CognitoProvider.ts +0 -50
  67. package/src/auth/providers/GoogleProvider.ts +0 -45
  68. package/src/auth/providers/MSALProvider.ts +0 -45
  69. package/src/auth/providers/OktaProvider.ts +0 -46
  70. package/src/auth/tokenExpiredError.ts +0 -12
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memberjunction/server",
3
- "version": "5.15.0",
3
+ "version": "5.16.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",
@@ -27,62 +27,63 @@
27
27
  "@as-integrations/express5": "^1.0.0",
28
28
  "@graphql-tools/schema": "latest",
29
29
  "@graphql-tools/utils": "^11.0.0",
30
- "@memberjunction/actions": "5.15.0",
31
- "@memberjunction/actions-base": "5.15.0",
32
- "@memberjunction/actions-apollo": "5.15.0",
33
- "@memberjunction/actions-bizapps-accounting": "5.15.0",
34
- "@memberjunction/actions-bizapps-crm": "5.15.0",
35
- "@memberjunction/actions-bizapps-formbuilders": "5.15.0",
36
- "@memberjunction/actions-bizapps-lms": "5.15.0",
37
- "@memberjunction/actions-bizapps-social": "5.15.0",
38
- "@memberjunction/ai": "5.15.0",
39
- "@memberjunction/ai-mcp-client": "5.15.0",
40
- "@memberjunction/ai-agent-manager": "5.15.0",
41
- "@memberjunction/ai-agent-manager-actions": "5.15.0",
42
- "@memberjunction/ai-agents": "5.15.0",
43
- "@memberjunction/ai-core-plus": "5.15.0",
44
- "@memberjunction/ai-prompts": "5.15.0",
45
- "@memberjunction/ai-provider-bundle": "5.15.0",
46
- "@memberjunction/ai-vectors-pinecone": "5.15.0",
47
- "@memberjunction/aiengine": "5.15.0",
48
- "@memberjunction/communication-ms-graph": "5.15.0",
49
- "@memberjunction/communication-sendgrid": "5.15.0",
50
- "@memberjunction/communication-types": "5.15.0",
51
- "@memberjunction/component-registry-client-sdk": "5.15.0",
52
- "@memberjunction/config": "5.15.0",
53
- "@memberjunction/core": "5.15.0",
54
- "@memberjunction/core-actions": "5.15.0",
55
- "@memberjunction/core-entities": "5.15.0",
56
- "@memberjunction/core-entities-server": "5.15.0",
57
- "@memberjunction/data-context": "5.15.0",
58
- "@memberjunction/data-context-server": "5.15.0",
59
- "@memberjunction/doc-utils": "5.15.0",
60
- "@memberjunction/api-keys": "5.15.0",
61
- "@memberjunction/encryption": "5.15.0",
62
- "@memberjunction/entity-communications-base": "5.15.0",
63
- "@memberjunction/entity-communications-server": "5.15.0",
64
- "@memberjunction/external-change-detection": "5.15.0",
65
- "@memberjunction/generic-database-provider": "5.15.0",
66
- "@memberjunction/global": "5.15.0",
67
- "@memberjunction/graphql-dataprovider": "5.15.0",
68
- "@memberjunction/integration-engine": "5.15.0",
69
- "@memberjunction/integration-schema-builder": "5.15.0",
70
- "@memberjunction/interactive-component-types": "5.15.0",
71
- "@memberjunction/computer-use-engine": "5.15.0",
72
- "@memberjunction/notifications": "5.15.0",
73
- "@memberjunction/queue": "5.15.0",
74
- "@memberjunction/redis-provider": "5.15.0",
75
- "@memberjunction/scheduling-actions": "5.15.0",
76
- "@memberjunction/scheduling-base-types": "5.15.0",
77
- "@memberjunction/scheduling-engine": "5.15.0",
78
- "@memberjunction/scheduling-engine-base": "5.15.0",
79
- "@memberjunction/skip-types": "5.15.0",
80
- "@memberjunction/sqlserver-dataprovider": "5.15.0",
81
- "@memberjunction/storage": "5.15.0",
82
- "@memberjunction/templates": "5.15.0",
83
- "@memberjunction/testing-engine": "5.15.0",
84
- "@memberjunction/testing-engine-base": "5.15.0",
85
- "@memberjunction/version-history": "5.15.0",
30
+ "@memberjunction/actions": "5.16.0",
31
+ "@memberjunction/actions-base": "5.16.0",
32
+ "@memberjunction/actions-apollo": "5.16.0",
33
+ "@memberjunction/actions-bizapps-accounting": "5.16.0",
34
+ "@memberjunction/actions-bizapps-crm": "5.16.0",
35
+ "@memberjunction/actions-bizapps-formbuilders": "5.16.0",
36
+ "@memberjunction/actions-bizapps-lms": "5.16.0",
37
+ "@memberjunction/actions-bizapps-social": "5.16.0",
38
+ "@memberjunction/ai": "5.16.0",
39
+ "@memberjunction/ai-mcp-client": "5.16.0",
40
+ "@memberjunction/ai-agent-manager": "5.16.0",
41
+ "@memberjunction/ai-agent-manager-actions": "5.16.0",
42
+ "@memberjunction/ai-agents": "5.16.0",
43
+ "@memberjunction/ai-core-plus": "5.16.0",
44
+ "@memberjunction/ai-prompts": "5.16.0",
45
+ "@memberjunction/ai-provider-bundle": "5.16.0",
46
+ "@memberjunction/ai-vectors-pinecone": "5.16.0",
47
+ "@memberjunction/aiengine": "5.16.0",
48
+ "@memberjunction/auth-providers": "5.16.0",
49
+ "@memberjunction/communication-ms-graph": "5.16.0",
50
+ "@memberjunction/communication-sendgrid": "5.16.0",
51
+ "@memberjunction/communication-types": "5.16.0",
52
+ "@memberjunction/component-registry-client-sdk": "5.16.0",
53
+ "@memberjunction/config": "5.16.0",
54
+ "@memberjunction/core": "5.16.0",
55
+ "@memberjunction/core-actions": "5.16.0",
56
+ "@memberjunction/core-entities": "5.16.0",
57
+ "@memberjunction/core-entities-server": "5.16.0",
58
+ "@memberjunction/data-context": "5.16.0",
59
+ "@memberjunction/data-context-server": "5.16.0",
60
+ "@memberjunction/doc-utils": "5.16.0",
61
+ "@memberjunction/api-keys": "5.16.0",
62
+ "@memberjunction/encryption": "5.16.0",
63
+ "@memberjunction/entity-communications-base": "5.16.0",
64
+ "@memberjunction/entity-communications-server": "5.16.0",
65
+ "@memberjunction/external-change-detection": "5.16.0",
66
+ "@memberjunction/generic-database-provider": "5.16.0",
67
+ "@memberjunction/global": "5.16.0",
68
+ "@memberjunction/graphql-dataprovider": "5.16.0",
69
+ "@memberjunction/integration-engine": "5.16.0",
70
+ "@memberjunction/integration-schema-builder": "5.16.0",
71
+ "@memberjunction/interactive-component-types": "5.16.0",
72
+ "@memberjunction/computer-use-engine": "5.16.0",
73
+ "@memberjunction/notifications": "5.16.0",
74
+ "@memberjunction/queue": "5.16.0",
75
+ "@memberjunction/redis-provider": "5.16.0",
76
+ "@memberjunction/scheduling-actions": "5.16.0",
77
+ "@memberjunction/scheduling-base-types": "5.16.0",
78
+ "@memberjunction/scheduling-engine": "5.16.0",
79
+ "@memberjunction/scheduling-engine-base": "5.16.0",
80
+ "@memberjunction/skip-types": "5.16.0",
81
+ "@memberjunction/sqlserver-dataprovider": "5.16.0",
82
+ "@memberjunction/storage": "5.16.0",
83
+ "@memberjunction/templates": "5.16.0",
84
+ "@memberjunction/testing-engine": "5.16.0",
85
+ "@memberjunction/testing-engine-base": "5.16.0",
86
+ "@memberjunction/version-history": "5.16.0",
86
87
  "@types/compression": "^1.8.1",
87
88
  "@types/cors": "^2.8.19",
88
89
  "@types/jsonwebtoken": "9.0.10",
@@ -107,8 +108,8 @@
107
108
  "jwks-rsa": "^3.2.2",
108
109
  "lru-cache": "^11.2.5",
109
110
  "mssql": "^12.2.0",
110
- "@memberjunction/postgresql-dataprovider": "5.15.0",
111
- "@memberjunction/sql-dialect": "5.15.0",
111
+ "@memberjunction/postgresql-dataprovider": "5.16.0",
112
+ "@memberjunction/sql-dialect": "5.16.0",
112
113
  "pg": "^8.13.3",
113
114
  "@types/pg": "^8.11.11",
114
115
  "reflect-metadata": "0.2.2",
@@ -64,7 +64,6 @@ vi.mock('../auth/index.js', () => ({
64
64
  getValidationOptions: mockGetValidationOptions,
65
65
  verifyUserRecord: mockVerifyUserRecord,
66
66
  extractUserInfoFromPayload: mockExtractUserInfo,
67
- TokenExpiredError: MockTokenExpiredError,
68
67
  }));
69
68
 
70
69
  vi.mock('../cache.js', () => {
@@ -84,9 +83,11 @@ vi.mock('../config.js', () => ({
84
83
  mj_core_schema: '__mj',
85
84
  }));
86
85
 
87
- vi.mock('../auth/AuthProviderFactory.js', () => ({
86
+ vi.mock('@memberjunction/auth-providers', () => ({
87
+ TokenExpiredError: MockTokenExpiredError,
88
88
  AuthProviderFactory: {
89
89
  getInstance: () => ({ getByIssuer: mockGetByIssuer }),
90
+ get Instance() { return { getByIssuer: mockGetByIssuer }; },
90
91
  },
91
92
  }));
92
93
 
@@ -11,8 +11,7 @@ vi.mock('../../config', () => ({
11
11
  },
12
12
  }));
13
13
 
14
- import { AuthProviderFactory } from '../AuthProviderFactory';
15
- import { IAuthProvider } from '../IAuthProvider';
14
+ import { AuthProviderFactory, IAuthProvider } from '@memberjunction/auth-providers';
16
15
  import { initializeAuthProviders } from '../initializeProviders';
17
16
 
18
17
  /**
@@ -22,7 +21,7 @@ describe('Authentication Provider Backward Compatibility', () => {
22
21
  let factory: AuthProviderFactory;
23
22
 
24
23
  beforeEach(() => {
25
- factory = AuthProviderFactory.getInstance();
24
+ factory = AuthProviderFactory.Instance;
26
25
  factory.clear();
27
26
  });
28
27
 
package/src/auth/index.ts CHANGED
@@ -6,12 +6,9 @@ import { Metadata, RoleInfo, UserInfo } from '@memberjunction/core';
6
6
  import { NewUserBase } from './newUsers.js';
7
7
  import { MJGlobal } from '@memberjunction/global';
8
8
  import { MJUserEntity, MJUserEntityType } from '@memberjunction/core-entities';
9
- import { AuthProviderFactory } from './AuthProviderFactory.js';
9
+ import { AuthProviderFactory } from '@memberjunction/auth-providers';
10
10
  import { initializeAuthProviders } from './initializeProviders.js';
11
11
 
12
- export { TokenExpiredError } from './tokenExpiredError.js';
13
- export { IAuthProvider } from './IAuthProvider.js';
14
- export { AuthProviderFactory } from './AuthProviderFactory.js';
15
12
  export * from './APIKeyScopeAuth.js';
16
13
 
17
14
  // This is a hard-coded forever constant due to internal migrations
@@ -53,7 +50,7 @@ const refreshUserCache = async (dataSource?: sql.ConnectionPool) => {
53
50
  * are aggregated into an array. jwt.verify() natively accepts string | string[].
54
51
  */
55
52
  export const getValidationOptions = (issuer: string): { audience: string | string[]; jwksUri: string } | undefined => {
56
- const factory = AuthProviderFactory.getInstance();
53
+ const factory = AuthProviderFactory.Instance;
57
54
  const providers = factory.getAllByIssuer(issuer);
58
55
 
59
56
  if (providers.length === 0) {
@@ -81,7 +78,7 @@ export const validationOptions: Record<string, { audience: string | string[]; jw
81
78
  return getValidationOptions(prop) !== undefined;
82
79
  },
83
80
  ownKeys: () => {
84
- const factory = AuthProviderFactory.getInstance();
81
+ const factory = AuthProviderFactory.Instance;
85
82
  return factory.getAllProviders().map(p => p.issuer);
86
83
  }
87
84
  });
@@ -112,7 +109,7 @@ export class UserPayload {
112
109
  * Gets signing keys for JWT validation
113
110
  */
114
111
  export const getSigningKeys = (issuer: string) => (header: JwtHeader, cb: SigningKeyCallback) => {
115
- const factory = AuthProviderFactory.getInstance();
112
+ const factory = AuthProviderFactory.Instance;
116
113
 
117
114
  // Initialize providers if not already done
118
115
  if (!factory.hasProviders()) {
@@ -142,7 +139,7 @@ export const extractUserInfoFromPayload = (payload: JwtPayload): {
142
139
  fullName?: string;
143
140
  preferredUsername?: string;
144
141
  } => {
145
- const factory = AuthProviderFactory.getInstance();
142
+ const factory = AuthProviderFactory.Instance;
146
143
  const issuer = payload.iss;
147
144
 
148
145
  if (!issuer) {
@@ -1,12 +1,12 @@
1
1
  import { configInfo } from '../config.js';
2
2
  import { AuthProviderConfig, LogError, LogStatus } from '@memberjunction/core';
3
- import { AuthProviderFactory } from './AuthProviderFactory.js';
3
+ import { AuthProviderFactory } from '@memberjunction/auth-providers';
4
4
 
5
5
  /**
6
6
  * Initialize authentication providers from configuration
7
7
  */
8
8
  export function initializeAuthProviders(): void {
9
- const factory = AuthProviderFactory.getInstance();
9
+ const factory = AuthProviderFactory.Instance;
10
10
 
11
11
  // Clear any existing providers
12
12
  factory.clear();
package/src/context.ts CHANGED
@@ -5,7 +5,8 @@ import 'reflect-metadata';
5
5
  import { Subject, firstValueFrom } from 'rxjs';
6
6
  import { AuthenticationError, AuthorizationError } from 'type-graphql';
7
7
  import sql from 'mssql';
8
- import { getSigningKeys, getSystemUser, getValidationOptions, verifyUserRecord, extractUserInfoFromPayload, TokenExpiredError } from './auth/index.js';
8
+ import { getSigningKeys, getSystemUser, getValidationOptions, verifyUserRecord, extractUserInfoFromPayload } from './auth/index.js';
9
+ import { TokenExpiredError, AuthProviderFactory } from '@memberjunction/auth-providers';
9
10
  import { authCache } from './cache.js';
10
11
  import { userEmailMap, apiKey, mj_core_schema } from './config.js';
11
12
  import { DataSourceInfo, UserPayload } from './types.js';
@@ -15,7 +16,6 @@ import e from 'express';
15
16
  import type { RequestHandler, Request, Response, NextFunction } from 'express';
16
17
  import { DatabaseProviderBase } from '@memberjunction/core';
17
18
  import { SQLServerDataProvider, SQLServerProviderConfigData, UserCache } from '@memberjunction/sqlserver-dataprovider';
18
- import { AuthProviderFactory } from './auth/AuthProviderFactory.js';
19
19
  import { Metadata } from '@memberjunction/core';
20
20
  import { UUIDsEqual } from '@memberjunction/global';
21
21
  import { GetAPIKeyEngine } from '@memberjunction/api-keys';
@@ -167,7 +167,7 @@ export const getUserPayload = async (
167
167
  }
168
168
 
169
169
  // Verify issuer is supported
170
- const factory = AuthProviderFactory.getInstance();
170
+ const factory = AuthProviderFactory.Instance;
171
171
  if (!factory.getByIssuer(issuer)) {
172
172
  console.warn(`Unsupported issuer: ${issuer}`);
173
173
  throw new AuthenticationError(`Unsupported authentication provider: ${issuer}`);
package/src/index.ts CHANGED
@@ -66,13 +66,10 @@ export * from './directives/index.js';
66
66
  export * from './entitySubclasses/MJEntityPermissionEntityServer.server.js';
67
67
  export * from './types.js';
68
68
  export {
69
- TokenExpiredError,
70
69
  getSystemUser,
71
70
  getSigningKeys,
72
71
  extractUserInfoFromPayload,
73
72
  verifyUserRecord,
74
- AuthProviderFactory,
75
- IAuthProvider,
76
73
  } from './auth/index.js';
77
74
  export * from './auth/APIKeyScopeAuth.js';
78
75
 
@@ -152,6 +149,13 @@ const localPath = (p: string) => {
152
149
  export const createApp = (): Application => express();
153
150
 
154
151
  export const serve = async (resolverPaths: Array<string>, app: Application = createApp(), options?: MJServerOptions): Promise<void> => {
152
+ const t0 = performance.now();
153
+ const lap = (label: string, since: number) => {
154
+ const ms = performance.now() - since;
155
+ console.log(`⏱️ [Startup] ${label}: ${ms.toFixed(0)}ms`);
156
+ return performance.now();
157
+ };
158
+
155
159
  const localResolverPaths = ['resolvers/**/*Resolver.{js,ts}', 'generic/*Resolver.{js,ts}', 'generated/generated.{js,ts}'].map(localPath);
156
160
 
157
161
  const combinedResolverPaths = [...resolverPaths, ...localResolverPaths];
@@ -260,6 +264,7 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
260
264
  } else {
261
265
  // ─── SQL Server Path (existing behavior) ───────────────────────
262
266
  console.log('Database type: SQL Server');
267
+ let tPhase = performance.now();
263
268
  const pool = new sql.ConnectionPool(createMSSQLConfig());
264
269
 
265
270
  // Handle connection-level errors from dead/stale connections in the pool.
@@ -270,6 +275,7 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
270
275
  });
271
276
 
272
277
  await pool.connect();
278
+ tPhase = lap('DB Pool Connect', tPhase);
273
279
 
274
280
  dataSources.push(new DataSourceInfo({dataSource: pool, type: 'Read-Write', host: dbHost, port: dbPort, database: dbDatabase, userName: dbUsername}));
275
281
 
@@ -294,10 +300,13 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
294
300
 
295
301
  const config = new SQLServerProviderConfigData(pool, mj_core_schema, cacheRefreshInterval);
296
302
  await setupSQLServerClient(config);
303
+ tPhase = lap('Metadata + Provider Setup', tPhase);
297
304
  const md = new Metadata();
298
305
  console.log(`Data Source has been initialized. ${md?.Entities ? md.Entities.length : 0} entities loaded.`);
299
306
  }
300
307
 
308
+ let tServe = performance.now();
309
+
301
310
  // Store queryDialects config in GlobalObjectStore so MJQueryEntityServer can
302
311
  // read it without a circular dependency on MJServer
303
312
  if (configInfo.queryDialects) {
@@ -387,6 +396,8 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
387
396
  /******TEST HARNESS FOR CHANGE DETECTION */
388
397
  /******TEST HARNESS FOR CHANGE DETECTION */
389
398
 
399
+ tServe = lap('Telemetry + Cache + APIKey Init', tServe);
400
+
390
401
  const dynamicModules = await Promise.all(
391
402
  paths.map((modulePath) => {
392
403
  try {
@@ -518,6 +529,8 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
518
529
  }
519
530
  });
520
531
 
532
+ tServe = lap('Resolver + Middleware Discovery', tServe);
533
+
521
534
  let schema = mergeSchemas({
522
535
  schemas: [
523
536
  buildSchemaSync({
@@ -538,6 +551,8 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
538
551
  schema = transformer(schema);
539
552
  }
540
553
 
554
+ tServe = lap('Schema Build', tServe);
555
+
541
556
  const httpServer = createServer(app);
542
557
 
543
558
  const webSocketServer = new WebSocketServer({ server: httpServer, path: graphqlRootPath });
@@ -723,7 +738,10 @@ export const serve = async (resolverPaths: Array<string>, app: Application = cre
723
738
  await Promise.resolve(options.onBeforeServe());
724
739
  }
725
740
 
741
+ tServe = lap('Apollo + Express Setup', tServe);
742
+
726
743
  await new Promise<void>((resolve) => httpServer.listen({ port: graphqlPort }, resolve));
744
+ lap('Total Startup', t0);
727
745
  console.log(`📦 Connected to database: ${dbHost}:${dbPort}/${dbDatabase}`);
728
746
  console.log(`🚀 Server ready at http://localhost:${graphqlPort}/`);
729
747
 
@@ -120,4 +120,40 @@ export class DatasetStatusResolver extends ResolverBase {
120
120
  throw new Error('Error retrieving Dataset Status: ' + DatasetName + '\n\n' + err);
121
121
  }
122
122
  }
123
+
124
+ /**
125
+ * Batch version: fetch status for multiple datasets in a single round-trip.
126
+ * Reduces N separate GetDatasetStatusByName calls to 1 network request.
127
+ */
128
+ @Query(() => [DatasetStatusResultType])
129
+ async GetMultipleDatasetStatusByName(
130
+ @Arg('DatasetNames', () => [String]) DatasetNames: string[],
131
+ @Ctx() { providers, userPayload }: AppContext,
132
+ ): Promise<DatasetStatusResultType[]> {
133
+ const md = GetReadOnlyProvider(providers, {allowFallbackToReadWrite: true});
134
+ const results: DatasetStatusResultType[] = [];
135
+
136
+ // Execute all status checks in parallel
137
+ const statusPromises = DatasetNames.map(async (name) => {
138
+ await this.CheckAPIKeyScopeAuthorization('dataset:read', name, userPayload);
139
+ return md.GetDatasetStatusByName(name);
140
+ });
141
+
142
+ const statuses = await Promise.all(statusPromises);
143
+
144
+ for (const result of statuses) {
145
+ if (result) {
146
+ results.push({
147
+ DatasetID: result.DatasetID,
148
+ DatasetName: result.DatasetName,
149
+ Success: result.Success,
150
+ Status: result.Status,
151
+ LatestUpdateDate: result.LatestUpdateDate,
152
+ EntityUpdateDates: JSON.stringify(result.EntityUpdateDates),
153
+ } as DatasetStatusResultType);
154
+ }
155
+ }
156
+
157
+ return results;
158
+ }
123
159
  }
@@ -1,68 +0,0 @@
1
- import { AuthProviderConfig } from '@memberjunction/core';
2
- import { IAuthProvider } from './IAuthProvider.js';
3
- import './providers/Auth0Provider.js';
4
- import './providers/MSALProvider.js';
5
- import './providers/OktaProvider.js';
6
- import './providers/CognitoProvider.js';
7
- import './providers/GoogleProvider.js';
8
- /**
9
- * Factory and registry for managing authentication providers
10
- * Combines provider creation and lifecycle management in a single class
11
- */
12
- export declare class AuthProviderFactory {
13
- private static instance;
14
- private providers;
15
- private issuerCache;
16
- private issuerMultiCache;
17
- private constructor();
18
- /**
19
- * Gets the singleton instance of the factory
20
- */
21
- static getInstance(): AuthProviderFactory;
22
- /**
23
- * Creates an authentication provider instance based on configuration
24
- * Uses MJGlobal ClassFactory to instantiate the correct provider class
25
- */
26
- static createProvider(config: AuthProviderConfig): IAuthProvider;
27
- /**
28
- * Registers a new authentication provider
29
- */
30
- register(provider: IAuthProvider): void;
31
- /**
32
- * Gets a provider by its issuer URL
33
- */
34
- getByIssuer(issuer: string): IAuthProvider | undefined;
35
- /**
36
- * Gets all providers matching an issuer URL.
37
- * Unlike getByIssuer() which returns only the first match, this returns
38
- * all providers for a given issuer. This is needed when multiple apps
39
- * (e.g. MJExplorer + MJCentral) share the same Auth0 domain but have
40
- * different audiences (client IDs).
41
- */
42
- getAllByIssuer(issuer: string): IAuthProvider[];
43
- /**
44
- * Gets a provider by its name
45
- */
46
- getByName(name: string): IAuthProvider | undefined;
47
- /**
48
- * Gets all registered providers
49
- */
50
- getAllProviders(): IAuthProvider[];
51
- /**
52
- * Checks if any providers are registered
53
- */
54
- hasProviders(): boolean;
55
- /**
56
- * Clears all registered providers (useful for testing)
57
- */
58
- clear(): void;
59
- /**
60
- * Gets all registered provider types from the ClassFactory
61
- */
62
- static getRegisteredProviderTypes(): string[];
63
- /**
64
- * Checks if a provider type is registered
65
- */
66
- static isProviderTypeRegistered(type: string): boolean;
67
- }
68
- //# sourceMappingURL=AuthProviderFactory.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AuthProviderFactory.d.ts","sourceRoot":"","sources":["../../src/auth/AuthProviderFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKnD,OAAO,8BAA8B,CAAC;AACtC,OAAO,6BAA6B,CAAC;AACrC,OAAO,6BAA6B,CAAC;AACrC,OAAO,gCAAgC,CAAC;AACxC,OAAO,+BAA+B,CAAC;AAEvC;;;GAGG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAsB;IAC7C,OAAO,CAAC,SAAS,CAAyC;IAC1D,OAAO,CAAC,WAAW,CAAyC;IAC5D,OAAO,CAAC,gBAAgB,CAA2C;IAEnE,OAAO;IAEP;;OAEG;IACH,MAAM,CAAC,WAAW,IAAI,mBAAmB;IAOzC;;;OAGG;IACH,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,kBAAkB,GAAG,aAAa;IAsBhE;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI;IAcvC;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAkBtD;;;;;;OAMG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE;IAoB/C;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAIlD;;OAEG;IACH,eAAe,IAAI,aAAa,EAAE;IAIlC;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb;;OAEG;IACH,MAAM,CAAC,0BAA0B,IAAI,MAAM,EAAE;IAW7C;;OAEG;IACH,MAAM,CAAC,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;CASvD"}
@@ -1,155 +0,0 @@
1
- import { BaseAuthProvider } from './BaseAuthProvider.js';
2
- import { MJGlobal } from '@memberjunction/global';
3
- // Import providers to ensure they're registered
4
- import './providers/Auth0Provider.js';
5
- import './providers/MSALProvider.js';
6
- import './providers/OktaProvider.js';
7
- import './providers/CognitoProvider.js';
8
- import './providers/GoogleProvider.js';
9
- /**
10
- * Factory and registry for managing authentication providers
11
- * Combines provider creation and lifecycle management in a single class
12
- */
13
- export class AuthProviderFactory {
14
- constructor() {
15
- this.providers = new Map();
16
- this.issuerCache = new Map();
17
- this.issuerMultiCache = new Map();
18
- }
19
- /**
20
- * Gets the singleton instance of the factory
21
- */
22
- static getInstance() {
23
- if (!AuthProviderFactory.instance) {
24
- AuthProviderFactory.instance = new AuthProviderFactory();
25
- }
26
- return AuthProviderFactory.instance;
27
- }
28
- /**
29
- * Creates an authentication provider instance based on configuration
30
- * Uses MJGlobal ClassFactory to instantiate the correct provider class
31
- */
32
- static createProvider(config) {
33
- try {
34
- // Use MJGlobal ClassFactory to create the provider instance
35
- // The provider type in config should match the key used in @RegisterClass
36
- // The config is passed as a constructor parameter via the spread operator
37
- const provider = MJGlobal.Instance.ClassFactory.CreateInstance(BaseAuthProvider, config.type.toLowerCase(), config);
38
- if (!provider) {
39
- throw new Error(`No provider registered for type: ${config.type}`);
40
- }
41
- return provider;
42
- }
43
- catch (error) {
44
- const message = error instanceof Error ? error.message : String(error);
45
- throw new Error(`Failed to create authentication provider for type '${config.type}': ${message}`);
46
- }
47
- }
48
- /**
49
- * Registers a new authentication provider
50
- */
51
- register(provider) {
52
- if (!provider.validateConfig()) {
53
- throw new Error(`Invalid configuration for provider: ${provider.name}`);
54
- }
55
- this.providers.set(provider.name, provider);
56
- // Clear issuer caches when registering new provider
57
- this.issuerCache.clear();
58
- this.issuerMultiCache.clear();
59
- console.log(`Registered auth provider: ${provider.name} with issuer: ${provider.issuer}`);
60
- }
61
- /**
62
- * Gets a provider by its issuer URL
63
- */
64
- getByIssuer(issuer) {
65
- // Check cache first
66
- if (this.issuerCache.has(issuer)) {
67
- return this.issuerCache.get(issuer);
68
- }
69
- // Search through providers
70
- for (const provider of this.providers.values()) {
71
- if (provider.matchesIssuer(issuer)) {
72
- // Cache for future lookups
73
- this.issuerCache.set(issuer, provider);
74
- return provider;
75
- }
76
- }
77
- return undefined;
78
- }
79
- /**
80
- * Gets all providers matching an issuer URL.
81
- * Unlike getByIssuer() which returns only the first match, this returns
82
- * all providers for a given issuer. This is needed when multiple apps
83
- * (e.g. MJExplorer + MJCentral) share the same Auth0 domain but have
84
- * different audiences (client IDs).
85
- */
86
- getAllByIssuer(issuer) {
87
- // Check multi-provider cache first
88
- if (this.issuerMultiCache.has(issuer)) {
89
- return this.issuerMultiCache.get(issuer);
90
- }
91
- const matches = [];
92
- for (const provider of this.providers.values()) {
93
- if (provider.matchesIssuer(issuer)) {
94
- matches.push(provider);
95
- }
96
- }
97
- if (matches.length > 0) {
98
- this.issuerMultiCache.set(issuer, matches);
99
- }
100
- return matches;
101
- }
102
- /**
103
- * Gets a provider by its name
104
- */
105
- getByName(name) {
106
- return this.providers.get(name);
107
- }
108
- /**
109
- * Gets all registered providers
110
- */
111
- getAllProviders() {
112
- return Array.from(this.providers.values());
113
- }
114
- /**
115
- * Checks if any providers are registered
116
- */
117
- hasProviders() {
118
- return this.providers.size > 0;
119
- }
120
- /**
121
- * Clears all registered providers (useful for testing)
122
- */
123
- clear() {
124
- this.providers.clear();
125
- this.issuerCache.clear();
126
- this.issuerMultiCache.clear();
127
- }
128
- /**
129
- * Gets all registered provider types from the ClassFactory
130
- */
131
- static getRegisteredProviderTypes() {
132
- // Get all registrations for BaseAuthProvider from ClassFactory
133
- const registrations = MJGlobal.Instance.ClassFactory.GetAllRegistrations(BaseAuthProvider);
134
- // Extract unique keys (provider types) from registrations
135
- const providerTypes = registrations
136
- .map(reg => reg.Key)
137
- .filter((key) => key !== null && key !== undefined);
138
- // Return unique provider types
139
- return Array.from(new Set(providerTypes));
140
- }
141
- /**
142
- * Checks if a provider type is registered
143
- */
144
- static isProviderTypeRegistered(type) {
145
- try {
146
- // Try to get the registration for this specific type
147
- const registration = MJGlobal.Instance.ClassFactory.GetRegistration(BaseAuthProvider, type.toLowerCase());
148
- return registration !== null && registration !== undefined;
149
- }
150
- catch {
151
- return false;
152
- }
153
- }
154
- }
155
- //# sourceMappingURL=AuthProviderFactory.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AuthProviderFactory.js","sourceRoot":"","sources":["../../src/auth/AuthProviderFactory.ts"],"names":[],"mappings":"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"}