@memberjunction/server 5.15.0 → 5.17.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 (91) hide show
  1. package/README.md +66 -3
  2. package/dist/auth/index.d.ts +0 -3
  3. package/dist/auth/index.d.ts.map +1 -1
  4. package/dist/auth/index.js +5 -7
  5. package/dist/auth/index.js.map +1 -1
  6. package/dist/auth/initializeProviders.js +2 -2
  7. package/dist/auth/initializeProviders.js.map +1 -1
  8. package/dist/config.d.ts +51 -0
  9. package/dist/config.d.ts.map +1 -1
  10. package/dist/config.js +7 -0
  11. package/dist/config.js.map +1 -1
  12. package/dist/context.d.ts.map +1 -1
  13. package/dist/context.js +3 -3
  14. package/dist/context.js.map +1 -1
  15. package/dist/generated/generated.d.ts +46 -46
  16. package/dist/generated/generated.d.ts.map +1 -1
  17. package/dist/generated/generated.js +332 -332
  18. package/dist/generated/generated.js.map +1 -1
  19. package/dist/index.d.ts +4 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +327 -2
  22. package/dist/index.js.map +1 -1
  23. package/dist/resolvers/DatasetResolver.d.ts +5 -0
  24. package/dist/resolvers/DatasetResolver.d.ts.map +1 -1
  25. package/dist/resolvers/DatasetResolver.js +35 -0
  26. package/dist/resolvers/DatasetResolver.js.map +1 -1
  27. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts +484 -0
  28. package/dist/resolvers/IntegrationDiscoveryResolver.d.ts.map +1 -1
  29. package/dist/resolvers/IntegrationDiscoveryResolver.js +3867 -328
  30. package/dist/resolvers/IntegrationDiscoveryResolver.js.map +1 -1
  31. package/dist/resolvers/RSUResolver.d.ts +89 -0
  32. package/dist/resolvers/RSUResolver.d.ts.map +1 -0
  33. package/dist/resolvers/RSUResolver.js +424 -0
  34. package/dist/resolvers/RSUResolver.js.map +1 -0
  35. package/package.json +63 -60
  36. package/src/__tests__/unifiedAuth.test.ts +3 -2
  37. package/src/auth/__tests__/backward-compatibility.test.ts +2 -3
  38. package/src/auth/index.ts +5 -8
  39. package/src/auth/initializeProviders.ts +2 -2
  40. package/src/config.ts +9 -0
  41. package/src/context.ts +3 -3
  42. package/src/generated/generated.ts +269 -269
  43. package/src/index.ts +371 -4
  44. package/src/resolvers/DatasetResolver.ts +36 -0
  45. package/src/resolvers/IntegrationDiscoveryResolver.ts +2970 -39
  46. package/src/resolvers/RSUResolver.ts +351 -0
  47. package/dist/auth/AuthProviderFactory.d.ts +0 -68
  48. package/dist/auth/AuthProviderFactory.d.ts.map +0 -1
  49. package/dist/auth/AuthProviderFactory.js +0 -155
  50. package/dist/auth/AuthProviderFactory.js.map +0 -1
  51. package/dist/auth/BaseAuthProvider.d.ts +0 -41
  52. package/dist/auth/BaseAuthProvider.d.ts.map +0 -1
  53. package/dist/auth/BaseAuthProvider.js +0 -102
  54. package/dist/auth/BaseAuthProvider.js.map +0 -1
  55. package/dist/auth/IAuthProvider.d.ts +0 -46
  56. package/dist/auth/IAuthProvider.d.ts.map +0 -1
  57. package/dist/auth/IAuthProvider.js +0 -2
  58. package/dist/auth/IAuthProvider.js.map +0 -1
  59. package/dist/auth/providers/Auth0Provider.d.ts +0 -18
  60. package/dist/auth/providers/Auth0Provider.d.ts.map +0 -1
  61. package/dist/auth/providers/Auth0Provider.js +0 -52
  62. package/dist/auth/providers/Auth0Provider.js.map +0 -1
  63. package/dist/auth/providers/CognitoProvider.d.ts +0 -18
  64. package/dist/auth/providers/CognitoProvider.d.ts.map +0 -1
  65. package/dist/auth/providers/CognitoProvider.js +0 -56
  66. package/dist/auth/providers/CognitoProvider.js.map +0 -1
  67. package/dist/auth/providers/GoogleProvider.d.ts +0 -18
  68. package/dist/auth/providers/GoogleProvider.d.ts.map +0 -1
  69. package/dist/auth/providers/GoogleProvider.js +0 -51
  70. package/dist/auth/providers/GoogleProvider.js.map +0 -1
  71. package/dist/auth/providers/MSALProvider.d.ts +0 -18
  72. package/dist/auth/providers/MSALProvider.d.ts.map +0 -1
  73. package/dist/auth/providers/MSALProvider.js +0 -52
  74. package/dist/auth/providers/MSALProvider.js.map +0 -1
  75. package/dist/auth/providers/OktaProvider.d.ts +0 -18
  76. package/dist/auth/providers/OktaProvider.d.ts.map +0 -1
  77. package/dist/auth/providers/OktaProvider.js +0 -52
  78. package/dist/auth/providers/OktaProvider.js.map +0 -1
  79. package/dist/auth/tokenExpiredError.d.ts +0 -5
  80. package/dist/auth/tokenExpiredError.d.ts.map +0 -1
  81. package/dist/auth/tokenExpiredError.js +0 -12
  82. package/dist/auth/tokenExpiredError.js.map +0 -1
  83. package/src/auth/AuthProviderFactory.ts +0 -182
  84. package/src/auth/BaseAuthProvider.ts +0 -137
  85. package/src/auth/IAuthProvider.ts +0 -54
  86. package/src/auth/providers/Auth0Provider.ts +0 -45
  87. package/src/auth/providers/CognitoProvider.ts +0 -50
  88. package/src/auth/providers/GoogleProvider.ts +0 -45
  89. package/src/auth/providers/MSALProvider.ts +0 -45
  90. package/src/auth/providers/OktaProvider.ts +0 -46
  91. package/src/auth/tokenExpiredError.ts +0 -12
@@ -0,0 +1,351 @@
1
+ /**
2
+ * RSUResolver — GraphQL API for the Runtime Schema Update pipeline.
3
+ *
4
+ * Exposes:
5
+ * - Query: RuntimeSchemaUpdateStatus — current RSU system status
6
+ * - Mutation: RunRuntimeSchemaUpdate — execute the full RSU pipeline
7
+ * - Mutation: PreviewRuntimeSchemaUpdate — dry-run preview
8
+ *
9
+ * All mutations require system user authorization.
10
+ */
11
+ import {
12
+ Arg,
13
+ Ctx,
14
+ Field,
15
+ InputType,
16
+ Mutation,
17
+ ObjectType,
18
+ Query,
19
+ Resolver,
20
+ Int,
21
+ } from 'type-graphql';
22
+ import { AppContext } from '../types.js';
23
+ import { RequireSystemUser } from '../directives/RequireSystemUser.js';
24
+ import {
25
+ RuntimeSchemaManager,
26
+ type RSUPipelineInput,
27
+ } from '@memberjunction/schema-engine';
28
+ import { readFileSync, existsSync } from 'node:fs';
29
+
30
+ // ─── RSU Input Types ─────────────────────────────────────────────────
31
+
32
+ @InputType()
33
+ export class RSUMetadataFileInput {
34
+ @Field(() => String)
35
+ Path: string;
36
+
37
+ @Field(() => String)
38
+ Content: string;
39
+ }
40
+
41
+ @InputType()
42
+ export class RSUPipelineInputGQL {
43
+ @Field(() => String, { description: 'The migration SQL to execute' })
44
+ MigrationSQL: string;
45
+
46
+ @Field(() => String, { description: 'Descriptive name for this schema change' })
47
+ Description: string;
48
+
49
+ @Field(() => [String], { description: 'Tables being created or modified' })
50
+ AffectedTables: string[];
51
+
52
+ @Field(() => String, { nullable: true, description: 'additionalSchemaInfo JSON for soft FKs' })
53
+ AdditionalSchemaInfo?: string;
54
+
55
+ @Field(() => [RSUMetadataFileInput], { nullable: true, description: 'Metadata JSON files for mj-sync' })
56
+ MetadataFiles?: RSUMetadataFileInput[];
57
+
58
+ @Field(() => Boolean, { nullable: true, description: 'Skip git commit/push step' })
59
+ SkipGitCommit?: boolean;
60
+
61
+ @Field(() => Boolean, { nullable: true, description: 'Skip MJAPI restart' })
62
+ SkipRestart?: boolean;
63
+ }
64
+
65
+ // ─── Output Types ────────────────────────────────────────────────────
66
+
67
+ @ObjectType()
68
+ export class RSUPipelineStepGQL {
69
+ @Field(() => String)
70
+ Name: string;
71
+
72
+ @Field(() => String)
73
+ Status: string;
74
+
75
+ @Field(() => Int)
76
+ DurationMs: number;
77
+
78
+ @Field(() => String)
79
+ Message: string;
80
+ }
81
+
82
+ @ObjectType()
83
+ export class RSUPipelineResultGQL {
84
+ @Field(() => Boolean)
85
+ Success: boolean;
86
+
87
+ @Field(() => String, { nullable: true })
88
+ BranchName?: string;
89
+
90
+ @Field(() => String, { nullable: true })
91
+ MigrationFilePath?: string;
92
+
93
+ @Field(() => Int, { nullable: true })
94
+ EntitiesProcessed?: number;
95
+
96
+ @Field(() => Boolean)
97
+ APIRestarted: boolean;
98
+
99
+ @Field(() => Boolean)
100
+ GitCommitSuccess: boolean;
101
+
102
+ @Field(() => [RSUPipelineStepGQL])
103
+ Steps: RSUPipelineStepGQL[];
104
+
105
+ @Field(() => String, { nullable: true })
106
+ ErrorMessage?: string;
107
+
108
+ @Field(() => String, { nullable: true })
109
+ ErrorStep?: string;
110
+ }
111
+
112
+ @ObjectType()
113
+ export class RSUPipelineBatchResultGQL {
114
+ @Field(() => [RSUPipelineResultGQL])
115
+ Results: RSUPipelineResultGQL[];
116
+
117
+ @Field(() => Int)
118
+ SuccessCount: number;
119
+
120
+ @Field(() => Int)
121
+ FailureCount: number;
122
+
123
+ @Field(() => Int)
124
+ TotalCount: number;
125
+ }
126
+
127
+ @ObjectType()
128
+ export class RSUPreviewResultGQL {
129
+ @Field(() => String)
130
+ MigrationSQL: string;
131
+
132
+ @Field(() => [String])
133
+ AffectedTables: string[];
134
+
135
+ @Field(() => [String])
136
+ ValidationErrors: string[];
137
+
138
+ @Field(() => Boolean)
139
+ WouldExecute: boolean;
140
+ }
141
+
142
+ @ObjectType()
143
+ export class RSUStatusGQL {
144
+ @Field(() => Boolean)
145
+ Enabled: boolean;
146
+
147
+ @Field(() => Boolean)
148
+ Running: boolean;
149
+
150
+ @Field(() => Boolean)
151
+ OutOfSync: boolean;
152
+
153
+ @Field(() => Date, { nullable: true })
154
+ OutOfSyncSince?: Date | null;
155
+
156
+ @Field(() => Date, { nullable: true })
157
+ LastRunAt?: Date | null;
158
+
159
+ @Field(() => String, { nullable: true })
160
+ LastRunResult?: string | null;
161
+ }
162
+
163
+ @ObjectType()
164
+ export class RSUQueueStatusGQL {
165
+ @Field(() => Int)
166
+ PendingCount: number;
167
+
168
+ @Field(() => Boolean)
169
+ IsCycleRunning: boolean;
170
+ }
171
+
172
+ // ─── Resolver ────────────────────────────────────────────────────────
173
+
174
+ @Resolver()
175
+ export class RSUResolver {
176
+ /**
177
+ * Query: Get current RSU system status.
178
+ * Available to any authenticated user (status is informational).
179
+ */
180
+ @Query(() => RSUStatusGQL, { description: 'Returns the current Runtime Schema Update status' })
181
+ RuntimeSchemaUpdateStatus(): RSUStatusGQL {
182
+ const rsm = RuntimeSchemaManager.Instance;
183
+ const status = rsm.GetStatus();
184
+ return {
185
+ Enabled: status.Enabled,
186
+ Running: status.Running,
187
+ OutOfSync: status.OutOfSync,
188
+ OutOfSyncSince: status.OutOfSyncSince,
189
+ LastRunAt: status.LastRunAt,
190
+ LastRunResult: status.LastRunResult,
191
+ };
192
+ }
193
+
194
+ /**
195
+ * Query: Tail the RSU pipeline log file. Returns the last N lines.
196
+ */
197
+ @Query(() => [String], { description: 'Returns recent lines from the RSU pipeline log' })
198
+ RuntimeSchemaUpdateLogTail(
199
+ @Arg('lines', () => Int, { defaultValue: 100 }) lines: number
200
+ ): string[] {
201
+ try {
202
+ const logPath = `${process.env.RSU_WORK_DIR || process.cwd()}/rsu-pipeline.log`;
203
+ if (!existsSync(logPath)) return ['(no log file found)'];
204
+ const content = readFileSync(logPath, 'utf-8');
205
+ const allLines = content.split('\n').filter(l => l.trim());
206
+ const maxLines = Math.min(Math.max(lines, 1), 1000);
207
+ return allLines.slice(-maxLines);
208
+ } catch (e) {
209
+ return [`Error reading log: ${(e as Error).message}`];
210
+ }
211
+ }
212
+
213
+ /**
214
+ * Query: Get RSU CodeGen queue status.
215
+ * Shows how many requests are pending and whether a cycle is running.
216
+ */
217
+ @Query(() => RSUQueueStatusGQL, { description: 'Returns the RSU pipeline status' })
218
+ RuntimeSchemaUpdateQueueStatus(): RSUQueueStatusGQL {
219
+ const rsm = RuntimeSchemaManager.Instance;
220
+ return {
221
+ PendingCount: 0, // Batching is explicit via RunPipelineBatch — no implicit queue
222
+ IsCycleRunning: rsm.IsRunning,
223
+ };
224
+ }
225
+
226
+ /**
227
+ * Mutation: Execute the full RSU pipeline.
228
+ * Requires system user authorization.
229
+ */
230
+ @Mutation(() => RSUPipelineResultGQL, {
231
+ description: 'Execute the Runtime Schema Update pipeline. Requires system user.',
232
+ })
233
+ @RequireSystemUser()
234
+ async RunRuntimeSchemaUpdate(
235
+ @Arg('input', () => RSUPipelineInputGQL) input: RSUPipelineInputGQL,
236
+ @Ctx() _ctx: AppContext
237
+ ): Promise<RSUPipelineResultGQL> {
238
+ const rsm = RuntimeSchemaManager.Instance;
239
+
240
+ const pipelineInput: RSUPipelineInput = {
241
+ MigrationSQL: input.MigrationSQL,
242
+ Description: input.Description,
243
+ AffectedTables: input.AffectedTables,
244
+ AdditionalSchemaInfo: input.AdditionalSchemaInfo ?? undefined,
245
+ MetadataFiles: input.MetadataFiles?.map(mf => ({ Path: mf.Path, Content: mf.Content })),
246
+ SkipGitCommit: input.SkipGitCommit ?? undefined,
247
+ SkipRestart: input.SkipRestart ?? undefined,
248
+ };
249
+
250
+ const result = await rsm.RunPipeline(pipelineInput);
251
+
252
+ return {
253
+ Success: result.Success,
254
+ BranchName: result.BranchName,
255
+ MigrationFilePath: result.MigrationFilePath,
256
+ EntitiesProcessed: result.EntitiesProcessed,
257
+ APIRestarted: result.APIRestarted,
258
+ GitCommitSuccess: result.GitCommitSuccess,
259
+ Steps: result.Steps.map(s => ({
260
+ Name: s.Name,
261
+ Status: s.Status,
262
+ DurationMs: s.DurationMs,
263
+ Message: s.Message,
264
+ })),
265
+ ErrorMessage: result.ErrorMessage,
266
+ ErrorStep: result.ErrorStep,
267
+ };
268
+ }
269
+
270
+ /**
271
+ * Mutation: Execute the RSU pipeline for a batch of inputs.
272
+ * All migrations execute under one lock, then one CodeGen/compile/restart/git.
273
+ * Per-item migration results + shared post-migration result.
274
+ */
275
+ @Mutation(() => RSUPipelineBatchResultGQL, {
276
+ description: 'Execute Runtime Schema Update for a batch of inputs. Requires system user.',
277
+ })
278
+ @RequireSystemUser()
279
+ async RunRuntimeSchemaUpdateBatch(
280
+ @Arg('inputs', () => [RSUPipelineInputGQL]) inputs: RSUPipelineInputGQL[],
281
+ @Ctx() _ctx: AppContext
282
+ ): Promise<RSUPipelineBatchResultGQL> {
283
+ const rsm = RuntimeSchemaManager.Instance;
284
+
285
+ const pipelineInputs: RSUPipelineInput[] = inputs.map(input => ({
286
+ MigrationSQL: input.MigrationSQL,
287
+ Description: input.Description,
288
+ AffectedTables: input.AffectedTables,
289
+ AdditionalSchemaInfo: input.AdditionalSchemaInfo ?? undefined,
290
+ MetadataFiles: input.MetadataFiles?.map(mf => ({ Path: mf.Path, Content: mf.Content })),
291
+ SkipGitCommit: input.SkipGitCommit ?? undefined,
292
+ SkipRestart: input.SkipRestart ?? undefined,
293
+ }));
294
+
295
+ const batchResult = await rsm.RunPipelineBatch(pipelineInputs);
296
+
297
+ return {
298
+ Results: batchResult.Results.map(result => ({
299
+ Success: result.Success,
300
+ BranchName: result.BranchName,
301
+ MigrationFilePath: result.MigrationFilePath,
302
+ EntitiesProcessed: result.EntitiesProcessed,
303
+ APIRestarted: result.APIRestarted,
304
+ GitCommitSuccess: result.GitCommitSuccess,
305
+ Steps: result.Steps.map(s => ({
306
+ Name: s.Name,
307
+ Status: s.Status,
308
+ DurationMs: s.DurationMs,
309
+ Message: s.Message,
310
+ })),
311
+ ErrorMessage: result.ErrorMessage,
312
+ ErrorStep: result.ErrorStep,
313
+ })),
314
+ SuccessCount: batchResult.SuccessCount,
315
+ FailureCount: batchResult.FailureCount,
316
+ TotalCount: batchResult.TotalCount,
317
+ };
318
+ }
319
+
320
+ /**
321
+ * Mutation: Preview mode — validate SQL and return what would happen.
322
+ * Requires system user authorization.
323
+ */
324
+ @Mutation(() => RSUPreviewResultGQL, {
325
+ description: 'Preview Runtime Schema Update without executing. Requires system user.',
326
+ })
327
+ @RequireSystemUser()
328
+ PreviewRuntimeSchemaUpdate(
329
+ @Arg('input', () => RSUPipelineInputGQL) input: RSUPipelineInputGQL,
330
+ @Ctx() _ctx: AppContext
331
+ ): RSUPreviewResultGQL {
332
+ const rsm = RuntimeSchemaManager.Instance;
333
+
334
+ const pipelineInput: RSUPipelineInput = {
335
+ MigrationSQL: input.MigrationSQL,
336
+ Description: input.Description,
337
+ AffectedTables: input.AffectedTables,
338
+ };
339
+
340
+ const preview = rsm.Preview(pipelineInput);
341
+
342
+ return {
343
+ MigrationSQL: preview.MigrationSQL,
344
+ AffectedTables: preview.AffectedTables,
345
+ ValidationErrors: preview.ValidationErrors,
346
+ WouldExecute: preview.WouldExecute,
347
+ };
348
+ }
349
+ }
350
+
351
+ export default RSUResolver;
@@ -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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"}
@@ -1,41 +0,0 @@
1
- import { JwtHeader, JwtPayload, SigningKeyCallback } from 'jsonwebtoken';
2
- import jwksClient from 'jwks-rsa';
3
- import { AuthProviderConfig, AuthUserInfo } from '@memberjunction/core';
4
- import { IAuthProvider } from './IAuthProvider.js';
5
- /**
6
- * Base implementation of IAuthProvider with common functionality
7
- * Concrete providers should extend this class and use @RegisterClass decorator
8
- * with BaseAuthProvider as the base class
9
- */
10
- export declare abstract class BaseAuthProvider implements IAuthProvider {
11
- name: string;
12
- issuer: string;
13
- audience: string;
14
- jwksUri: string;
15
- /** OAuth client ID for this provider (used by OAuth proxy for upstream auth) */
16
- clientId?: string;
17
- protected config: AuthProviderConfig;
18
- protected jwksClient: jwksClient.JwksClient;
19
- constructor(config: AuthProviderConfig);
20
- /**
21
- * Validates that required configuration is present
22
- */
23
- validateConfig(): boolean;
24
- /**
25
- * Gets the signing key for token verification with retry logic
26
- */
27
- getSigningKey(header: JwtHeader, callback: SigningKeyCallback): void;
28
- /**
29
- * Retrieves signing key with exponential backoff retry logic
30
- */
31
- private getSigningKeyWithRetry;
32
- /**
33
- * Checks if a given issuer URL belongs to this provider
34
- */
35
- matchesIssuer(issuer: string): boolean;
36
- /**
37
- * Abstract method for extracting user info - must be implemented by each provider
38
- */
39
- abstract extractUserInfo(payload: JwtPayload): AuthUserInfo;
40
- }
41
- //# sourceMappingURL=BaseAuthProvider.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BaseAuthProvider.d.ts","sourceRoot":"","sources":["../../src/auth/BaseAuthProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,UAAU,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAInD;;;;GAIG;AACH,8BAAsB,gBAAiB,YAAW,aAAa;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACrC,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC;gBAEhC,MAAM,EAAE,kBAAkB;IAoCtC;;OAEG;IACH,cAAc,IAAI,OAAO;IAIzB;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,kBAAkB,GAAG,IAAI;IAYpE;;OAEG;YACW,sBAAsB;IAuCpC;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAOtC;;OAEG;IACH,QAAQ,CAAC,eAAe,CAAC,OAAO,EAAE,UAAU,GAAG,YAAY;CAC5D"}