@melio-eng/web-sdk 1.0.27-pr.53.6e729bc → 1.0.27-pr.54.5cf8a1f

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -7,10 +7,10 @@ export declare class MelioSDK implements MelioSDK {
7
7
  private environment;
8
8
  private partnerName;
9
9
  private branchOverride;
10
- private authenticationCode;
10
+ private authCode;
11
11
  constructor();
12
12
  /**
13
- * Initialize the SDK by creating an authentication flow
13
+ * Initialize the SDK - triggers auth event without creating iframe
14
14
  */
15
15
  init(authenticationCode: string, options: InitOptions): FlowInstance;
16
16
  /**
package/dist/index.js CHANGED
@@ -1,9 +1,312 @@
1
- // Import flow classes
2
- import { InitFlow } from './flows/InitFlow.js';
3
- import { OnboardingFlow } from './flows/OnboardingFlow.js';
4
- import { PayFlow } from './flows/PayFlow.js';
5
- import { SettingsFlow } from './flows/SettingsFlow.js';
6
- import { PaymentsDashboardFlow } from './flows/PaymentsDashboardFlow.js';
1
+ /**
2
+ * Utility function to get the base URL for a given environment
3
+ */
4
+ function getBaseUrl(environment) {
5
+ switch (environment) {
6
+ case 'production':
7
+ return 'https://partnerships.production.melioservices.com';
8
+ case 'staging01':
9
+ return 'https://partnerships.staging01.melioservices.com';
10
+ case 'public-qa':
11
+ return 'https://partnerships.public-qa.melioservices.com';
12
+ case 'certification':
13
+ return 'https://partnerships.certification.melioservices.com';
14
+ case 'eilat':
15
+ return 'https://partnerships.eilat.melioservices.com';
16
+ case 'localhost':
17
+ return 'http://localhost:3005';
18
+ default:
19
+ return 'https://partnerships.melioservices.com';
20
+ }
21
+ }
22
+ const isEmptyString = (str) => {
23
+ return !str?.trim();
24
+ };
25
+ /**
26
+ * Flow class implementation for handling iframe flows and events
27
+ */
28
+ class Flow {
29
+ constructor(containerId, config, partnerName, environment, branchOverride) {
30
+ this.containerId = containerId;
31
+ this.config = config;
32
+ this.partnerName = partnerName;
33
+ this.environment = environment;
34
+ this.branchOverride = branchOverride;
35
+ this.iframe = null;
36
+ this.container = null;
37
+ this.eventListeners = new Map();
38
+ this.keepAliveInterval = null;
39
+ this.setupEventListeners();
40
+ }
41
+ /**
42
+ * Initialize the flow by creating and injecting the iframe
43
+ */
44
+ async initialize() {
45
+ this.container = document.getElementById(this.containerId);
46
+ if (!this.container) {
47
+ throw new Error(`Container with ID "${this.containerId}" not found`);
48
+ }
49
+ this.iframe = document.createElement('iframe');
50
+ this.iframe.src = this.createFlowUrl();
51
+ this.iframe.style.width = '100%';
52
+ this.iframe.style.height = '1000px';
53
+ this.iframe.style.border = 'none';
54
+ this.iframe.style.display = 'block';
55
+ this.container.appendChild(this.iframe);
56
+ }
57
+ /**
58
+ * Construct the specific flow URL - can be overridden by subclasses
59
+ */
60
+ constructFlowUrl(baseUrl) {
61
+ return `${baseUrl}/${this.partnerName}/auth`;
62
+ }
63
+ /**
64
+ * Create flow URL using partner name and environment
65
+ */
66
+ createFlowUrl() {
67
+ console.log('🔧 Creating flow URL...');
68
+ console.log('📝 Config:', this.config);
69
+ console.log('🏢 Partner:', this.partnerName);
70
+ console.log('🌍 Environment:', this.environment);
71
+ console.log('🔝 Branch Override:', this.branchOverride);
72
+ const baseUrl = getBaseUrl(this.environment);
73
+ let finalUrl = this.constructFlowUrl(baseUrl);
74
+ // Add cdn_branch_override parameter for non-production environments
75
+ if (this.branchOverride && this.environment !== 'production') {
76
+ const separator = finalUrl.includes('?') ? '&' : '?';
77
+ finalUrl += `${separator}cdn_branch_override=${this.branchOverride}`;
78
+ }
79
+ console.log('🌐 Final URL:', finalUrl);
80
+ return finalUrl;
81
+ }
82
+ setupEventListeners() {
83
+ // Add post message handlers for internal events - setHeight, scroll etc
84
+ // Also need to implement callbacks for flow completed exit etc in the platform-app
85
+ window.addEventListener('message', (event) => {
86
+ if (!/melio\.com|melioservices\.com/.test(event.origin)) {
87
+ return;
88
+ }
89
+ const { type, ...data } = event.data;
90
+ console.log('📬 Received message from iframe:', {
91
+ type,
92
+ data,
93
+ origin: event.origin,
94
+ });
95
+ switch (type) {
96
+ case 'FLOW_COMPLETED':
97
+ this.emit('completed', data);
98
+ break;
99
+ case 'FLOW_EXIT':
100
+ this.emit('exit');
101
+ break;
102
+ case 'NAVIGATED_TO_TARGET':
103
+ this.emit('navigated', data);
104
+ break;
105
+ case 'AUTHENTICATION_SUCCESS':
106
+ this.emit('authenticationSucceeded');
107
+ break;
108
+ case 'AUTHENTICATION_ERROR':
109
+ this.emit('authenticationFailed');
110
+ break;
111
+ case 'ONBOARDING_COMPLETED':
112
+ this.emit('completed', { flowName: 'onboarding', ...data });
113
+ break;
114
+ case 'READY_FOR_INTERACTION':
115
+ this.emit('loaded');
116
+ break;
117
+ case 'MELIO_ERROR':
118
+ if (data.code === 'failed_to_sync_bills') {
119
+ this.emit('error', { errorCode: 'billsSyncFailed' });
120
+ }
121
+ break;
122
+ case 'HEIGHT_CHANGE':
123
+ if (this.iframe) {
124
+ this.iframe.style.height = `${data.height}px`;
125
+ }
126
+ break;
127
+ }
128
+ });
129
+ }
130
+ emit(event, data) {
131
+ const listeners = this.eventListeners.get(event);
132
+ if (listeners) {
133
+ listeners.forEach((callback) => {
134
+ try {
135
+ callback(data);
136
+ }
137
+ catch (error) {
138
+ console.error(`Error in ${event} event listener:`, error);
139
+ }
140
+ });
141
+ }
142
+ }
143
+ on(event, callback) {
144
+ if (!this.eventListeners.has(event)) {
145
+ this.eventListeners.set(event, new Set());
146
+ }
147
+ this.eventListeners.get(event).add(callback);
148
+ }
149
+ /**
150
+ * Remove an event listener
151
+ */
152
+ off(event, callback) {
153
+ const listeners = this.eventListeners.get(event);
154
+ if (listeners) {
155
+ listeners.delete(callback);
156
+ }
157
+ }
158
+ /**
159
+ * Close the flow and clean up resources
160
+ */
161
+ close() {
162
+ if (this.keepAliveInterval) {
163
+ clearInterval(this.keepAliveInterval);
164
+ this.keepAliveInterval = null;
165
+ }
166
+ if (this.iframe && this.container) {
167
+ this.container.removeChild(this.iframe);
168
+ this.iframe = null;
169
+ }
170
+ this.eventListeners.clear();
171
+ }
172
+ }
173
+ /**
174
+ * OnboardingFlow subclass with custom URL construction
175
+ */
176
+ class OnboardingFlow extends Flow {
177
+ constructor(containerId, config, partnerName, environment, authCode, branchOverride) {
178
+ super(containerId, config, partnerName, environment, branchOverride);
179
+ const { userDetails, organizationDetails, enforceOnboarding } = config;
180
+ this.preFilledParams = { userDetails, organizationDetails };
181
+ this.enforceOnboarding = enforceOnboarding;
182
+ this.authCode = authCode;
183
+ if (isEmptyString(this.authCode)) {
184
+ throw new Error('Authorization code is required for onboarding flow. Please call init() before opening onboarding flow.');
185
+ }
186
+ }
187
+ /**
188
+ * Construct the specific flow URL for onboarding - now goes through /auth
189
+ */
190
+ constructFlowUrl(baseUrl) {
191
+ const params = Object.fromEntries(Object.entries(this.preFilledParams).filter(([_, v]) => v !== undefined));
192
+ let preFilledBase64 = '';
193
+ if (Object.keys(params).length > 0) {
194
+ try {
195
+ const json = JSON.stringify(params);
196
+ preFilledBase64 = btoa(unescape(encodeURIComponent(json)));
197
+ }
198
+ catch (e) {
199
+ preFilledBase64 = '';
200
+ }
201
+ }
202
+ const targetQueryParams = [];
203
+ if (preFilledBase64) {
204
+ targetQueryParams.push(`preFilledParams=${encodeURIComponent(preFilledBase64)}`);
205
+ }
206
+ if (this.enforceOnboarding !== undefined) {
207
+ targetQueryParams.push(`enforceOnboarding=${this.enforceOnboarding}`);
208
+ }
209
+ targetQueryParams.push(`externalOrigin=${this.partnerName}`);
210
+ const target = `/welcome?${targetQueryParams.join('&')}`;
211
+ const encodedTarget = encodeURIComponent(target);
212
+ return `${baseUrl}/${this.partnerName}/auth?token=${this.authCode}&target=${encodedTarget}`;
213
+ }
214
+ }
215
+ /**
216
+ * PayFlow subclass with custom URL construction
217
+ */
218
+ class PayFlow extends Flow {
219
+ constructor(containerId, config, partnerName, environment, authCode, branchOverride) {
220
+ super(containerId, config, partnerName, environment, branchOverride);
221
+ this.billIds = config.billIds;
222
+ this.authCode = authCode;
223
+ if (isEmptyString(this.authCode)) {
224
+ throw new Error('Authorization code is required for pay flow. Please call init() before opening pay flow.');
225
+ }
226
+ }
227
+ /**
228
+ * Construct the specific flow URL for bill payment - now goes through /auth
229
+ */
230
+ constructFlowUrl(baseUrl) {
231
+ const target = `/external-entries/payment-flow?externalOrigin=${this.partnerName}`;
232
+ // Encode the target and billIds parameters
233
+ const encodedTarget = encodeURIComponent(target);
234
+ const billIdsParam = this.billIds.join(',');
235
+ return `${baseUrl}/${this.partnerName}/auth?token=${this.authCode}&target=${encodedTarget}&targetId=${encodeURIComponent(billIdsParam)}`;
236
+ }
237
+ }
238
+ /**
239
+ * SettingsFlow subclass with custom URL construction
240
+ */
241
+ class SettingsFlow extends Flow {
242
+ constructor(containerId, config, partnerName, environment, authCode, branchOverride) {
243
+ super(containerId, config, partnerName, environment, branchOverride);
244
+ this.authCode = authCode;
245
+ if (isEmptyString(this.authCode)) {
246
+ throw new Error('Authorization code is required for settings flow. Please call init() before opening settings flow.');
247
+ }
248
+ }
249
+ /**
250
+ * Construct the specific flow URL for settings - now goes through /auth
251
+ */
252
+ constructFlowUrl(baseUrl) {
253
+ const target = '/settings';
254
+ const encodedTarget = encodeURIComponent(target);
255
+ return `${baseUrl}/${this.partnerName}/auth?token=${this.authCode}&target=${encodedTarget}`;
256
+ }
257
+ }
258
+ class PaymentsDashboardFlow extends Flow {
259
+ constructor(containerId, config, partnerName, environment, authCode, branchOverride) {
260
+ super(containerId, config, partnerName, environment, branchOverride);
261
+ this.authCode = authCode;
262
+ if (isEmptyString(this.authCode)) {
263
+ throw new Error('Authorization code is required for payments dashboard flow. Please call init() before opening payments dashboard flow.');
264
+ }
265
+ }
266
+ /**
267
+ * Construct the specific flow URL for payments dashboard - now goes through /auth
268
+ */
269
+ constructFlowUrl(baseUrl) {
270
+ const target = '/pay-dashboard/payments';
271
+ const encodedTarget = encodeURIComponent(target);
272
+ return `${baseUrl}/${this.partnerName}/auth?token=${this.authCode}&target=${encodedTarget}`;
273
+ }
274
+ }
275
+ /**
276
+ * InitFlow subclass for handling initialization with callbacks
277
+ */
278
+ class InitFlow extends Flow {
279
+ constructor(containerId, config, partnerName, environment, branchOverride) {
280
+ super(containerId, config, partnerName, environment, branchOverride);
281
+ if (isEmptyString(config.authCode)) {
282
+ throw new Error('Authorization code is required for init flow');
283
+ }
284
+ this.authorizationCode = config.authCode;
285
+ }
286
+ /**
287
+ * Initialize the init flow by creating and injecting a hidden iframe
288
+ */
289
+ async initialize() {
290
+ this.emit('authenticationSucceeded');
291
+ }
292
+ /**
293
+ * Construct the specific flow URL for initialization
294
+ */
295
+ constructFlowUrl(baseUrl) {
296
+ const params = new URLSearchParams({
297
+ token: this.authorizationCode,
298
+ theme: this.partnerName,
299
+ });
300
+ return `${baseUrl}/${this.partnerName}/auth?${params.toString()}`;
301
+ }
302
+ setupKeepAlive() {
303
+ this.keepAliveInterval = window.setInterval(() => {
304
+ if (this.iframe && this.iframe.contentWindow) {
305
+ this.iframe.contentWindow.postMessage({ type: 'USER_ACTIVE_PING' }, '*');
306
+ }
307
+ }, 30000); // Send ping every 30 seconds
308
+ }
309
+ }
7
310
  /**
8
311
  * Main SDK implementation - now partner agnostic
9
312
  */
@@ -13,41 +316,39 @@ export class MelioSDK {
13
316
  this.environment = 'production';
14
317
  this.partnerName = '';
15
318
  this.branchOverride = undefined;
16
- this.authenticationCode = '';
319
+ this.authCode = '';
17
320
  }
18
321
  /**
19
- * Initialize the SDK by creating an authentication flow
322
+ * Initialize the SDK - triggers auth event without creating iframe
20
323
  */
21
324
  init(authenticationCode, options) {
22
325
  this.partnerName = options.partnerName;
23
326
  this.environment = options.environment || 'production';
24
327
  this.branchOverride = options.branchOverride;
25
- this.authenticationCode = authenticationCode;
328
+ this.authCode = authenticationCode;
26
329
  console.log('starting init flow', {
27
330
  partnerName: this.partnerName,
28
331
  environment: this.environment,
29
332
  });
30
- const initConfig = {
31
- authCode: authenticationCode,
32
- containerId: '',
33
- };
34
333
  const initFlow = new InitFlow('', // no need container id for init flow as it is created inside the initialization
35
- initConfig, this.partnerName, this.environment, this.branchOverride);
36
- initFlow.initialize();
37
- // Disabled for quick performance improvement. Will be re-enabled in the future.
38
- // console.log('InitFlow initialized successfully');
39
- // if (options.keepAlive) initFlow.setupKeepAlive();
334
+ { authCode: authenticationCode, containerId: '' }, this.partnerName, this.environment, this.branchOverride);
335
+ // Defer to next tick to prevent race condition
336
+ setTimeout(() => {
337
+ initFlow.initialize();
338
+ console.log('InitFlow initialized successfully');
339
+ if (options.keepAlive)
340
+ initFlow.setupKeepAlive();
341
+ }, 0);
40
342
  return initFlow;
41
343
  }
42
344
  /**
43
345
  * Launch the onboarding flow
44
346
  */
45
347
  openOnboarding(config) {
46
- const configWithAuth = {
47
- ...config,
48
- authCode: config.authCode || this.authenticationCode,
49
- };
50
- const flow = new OnboardingFlow(config.containerId, configWithAuth, this.partnerName, this.environment, this.branchOverride);
348
+ if (isEmptyString(this.authCode)) {
349
+ throw new Error('SDK not initialized. Please call init() before opening onboarding flow.');
350
+ }
351
+ const flow = new OnboardingFlow(config.containerId, config, this.partnerName, this.environment, this.authCode, this.branchOverride);
51
352
  flow.initialize();
52
353
  return flow;
53
354
  }
@@ -55,7 +356,10 @@ export class MelioSDK {
55
356
  * Launch the pay flow
56
357
  */
57
358
  openPayFlow(config) {
58
- const flow = new PayFlow(config.containerId, config, this.partnerName, this.environment, this.branchOverride);
359
+ if (isEmptyString(this.authCode)) {
360
+ throw new Error('SDK not initialized. Please call init() before opening pay flow.');
361
+ }
362
+ const flow = new PayFlow(config.containerId, config, this.partnerName, this.environment, this.authCode, this.branchOverride);
59
363
  flow.initialize();
60
364
  return flow;
61
365
  }
@@ -63,7 +367,10 @@ export class MelioSDK {
63
367
  * Launch the settings flow
64
368
  */
65
369
  openSettings(config) {
66
- const flow = new SettingsFlow(config.containerId, config, this.partnerName, this.environment, this.branchOverride);
370
+ if (isEmptyString(this.authCode)) {
371
+ throw new Error('SDK not initialized. Please call init() before opening settings flow.');
372
+ }
373
+ const flow = new SettingsFlow(config.containerId, config, this.partnerName, this.environment, this.authCode, this.branchOverride);
67
374
  flow.initialize();
68
375
  return flow;
69
376
  }
@@ -71,7 +378,10 @@ export class MelioSDK {
71
378
  * Launch the payments dashboard flow
72
379
  */
73
380
  openPaymentsDashboard(config) {
74
- const flow = new PaymentsDashboardFlow(config.containerId, config, this.partnerName, this.environment, this.branchOverride);
381
+ if (isEmptyString(this.authCode)) {
382
+ throw new Error('SDK not initialized. Please call init() before opening payments dashboard flow.');
383
+ }
384
+ const flow = new PaymentsDashboardFlow(config.containerId, config, this.partnerName, this.environment, this.authCode, this.branchOverride);
75
385
  flow.initialize();
76
386
  return flow;
77
387
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@melio-eng/web-sdk",
3
- "version": "1.0.27-pr.53.6e729bc",
3
+ "version": "1.0.27-pr.54.5cf8a1f",
4
4
  "description": "Melio Web SDK - Embed core Melio workflows directly into partner UI with minimal effort",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -1,57 +0,0 @@
1
- import { FlowInstance, FlowEventType, FlowEventCallback, FlowCompletionData, NavigationData, BaseFlowConfig, Environment, ErrorData } from '../types.js';
2
- /**
3
- * Base Flow class implementation for handling iframe flows and events
4
- */
5
- export declare abstract class BaseFlow implements FlowInstance {
6
- private containerId;
7
- protected config: BaseFlowConfig;
8
- protected partnerName: string;
9
- protected environment: Environment;
10
- protected branchOverride?: string | undefined;
11
- protected iframe: HTMLIFrameElement | null;
12
- private container;
13
- private eventListeners;
14
- protected keepAliveInterval: number | null;
15
- constructor(containerId: string, config: BaseFlowConfig, partnerName: string, environment: Environment, branchOverride?: string | undefined);
16
- /**
17
- * Initialize the flow by creating and injecting the iframe
18
- */
19
- initialize(): Promise<void>;
20
- /**
21
- * Construct the specific flow URL - must be implemented by subclasses
22
- */
23
- protected abstract constructFlowUrl(baseUrl: string): string;
24
- /**
25
- * Create flow URL using partner name and environment
26
- */
27
- protected createFlowUrl(): string;
28
- private setupEventListeners;
29
- /**
30
- * Emit events to registered listeners
31
- */
32
- emit(event: 'completed', data: FlowCompletionData): void;
33
- emit(event: 'loaded'): void;
34
- emit(event: 'exit'): void;
35
- emit(event: 'navigated', data: NavigationData): void;
36
- emit(event: 'authenticationSucceeded'): void;
37
- emit(event: 'authenticationFailed'): void;
38
- emit(event: 'error', data: ErrorData): void;
39
- /**
40
- * Register an event listener
41
- */
42
- on(event: 'completed', callback: (data: FlowCompletionData) => void): void;
43
- on(event: 'exit', callback: () => void): void;
44
- on(event: 'navigated', callback: (payload: NavigationData) => void): void;
45
- on(event: 'authenticationSucceeded', callback: () => void): void;
46
- on(event: 'authenticationFailed', callback: () => void): void;
47
- on(event: 'error', callback: (data: ErrorData) => void): void;
48
- on(event: 'loaded', callback: () => void): void;
49
- /**
50
- * Remove an event listener
51
- */
52
- off(event: FlowEventType, callback: FlowEventCallback): void;
53
- /**
54
- * Close the flow and clean up resources
55
- */
56
- close(): void;
57
- }
@@ -1,143 +0,0 @@
1
- import { getBaseUrl } from '../utils/environment.js';
2
- /**
3
- * Base Flow class implementation for handling iframe flows and events
4
- */
5
- export class BaseFlow {
6
- constructor(containerId, config, partnerName, environment, branchOverride) {
7
- this.containerId = containerId;
8
- this.config = config;
9
- this.partnerName = partnerName;
10
- this.environment = environment;
11
- this.branchOverride = branchOverride;
12
- this.iframe = null;
13
- this.container = null;
14
- this.eventListeners = new Map();
15
- this.keepAliveInterval = null;
16
- this.setupEventListeners();
17
- }
18
- /**
19
- * Initialize the flow by creating and injecting the iframe
20
- */
21
- async initialize() {
22
- this.container = document.getElementById(this.containerId);
23
- if (!this.container) {
24
- throw new Error(`Container with ID "${this.containerId}" not found`);
25
- }
26
- this.iframe = document.createElement('iframe');
27
- this.iframe.src = this.createFlowUrl();
28
- this.iframe.style.width = '100%';
29
- this.iframe.style.height = '1000px';
30
- this.iframe.style.border = 'none';
31
- this.iframe.style.display = 'block';
32
- this.container.appendChild(this.iframe);
33
- }
34
- /**
35
- * Create flow URL using partner name and environment
36
- */
37
- createFlowUrl() {
38
- console.log('🔧 Creating flow URL...');
39
- console.log('📝 Config:', this.config);
40
- console.log('🏢 Partner:', this.partnerName);
41
- console.log('🌍 Environment:', this.environment);
42
- console.log('🔝 Branch Override:', this.branchOverride);
43
- const baseUrl = getBaseUrl(this.environment);
44
- let finalUrl = this.constructFlowUrl(baseUrl);
45
- // Add cdn_branch_override parameter for non-production environments
46
- if (this.branchOverride && this.environment !== 'production') {
47
- const separator = finalUrl.includes('?') ? '&' : '?';
48
- finalUrl += `${separator}cdn_branch_override=${this.branchOverride}`;
49
- }
50
- console.log('🌐 Final URL:', finalUrl);
51
- return finalUrl;
52
- }
53
- setupEventListeners() {
54
- // Add post message handlers for internal events - setHeight, scroll etc
55
- // Also need to implement callbacks for flow completed exit etc in the platform-app
56
- window.addEventListener('message', (event) => {
57
- if (!/melio\.com|melioservices\.com/.test(event.origin)) {
58
- return;
59
- }
60
- const { type, ...data } = event.data;
61
- console.log('📬 Received message from iframe:', {
62
- type,
63
- data,
64
- origin: event.origin,
65
- });
66
- switch (type) {
67
- case 'FLOW_COMPLETED':
68
- this.emit('completed', data);
69
- break;
70
- case 'FLOW_EXIT':
71
- this.emit('exit');
72
- break;
73
- case 'NAVIGATED_TO_TARGET':
74
- this.emit('navigated', data);
75
- break;
76
- case 'AUTHENTICATION_SUCCESS':
77
- this.emit('authenticationSucceeded');
78
- break;
79
- case 'AUTHENTICATION_ERROR':
80
- this.emit('authenticationFailed');
81
- break;
82
- case 'ONBOARDING_COMPLETED':
83
- this.emit('completed', { flowName: 'onboarding', ...data });
84
- break;
85
- case 'READY_FOR_INTERACTION':
86
- this.emit('loaded');
87
- break;
88
- case 'MELIO_ERROR':
89
- if (data.code === 'failed_to_sync_bills') {
90
- this.emit('error', { errorCode: 'billsSyncFailed' });
91
- }
92
- break;
93
- case 'HEIGHT_CHANGE':
94
- if (this.iframe) {
95
- this.iframe.style.height = `${data.height}px`;
96
- }
97
- break;
98
- }
99
- });
100
- }
101
- emit(event, data) {
102
- const listeners = this.eventListeners.get(event);
103
- if (listeners) {
104
- listeners.forEach((callback) => {
105
- try {
106
- callback(data);
107
- }
108
- catch (error) {
109
- console.error(`Error in ${event} event listener:`, error);
110
- }
111
- });
112
- }
113
- }
114
- on(event, callback) {
115
- if (!this.eventListeners.has(event)) {
116
- this.eventListeners.set(event, new Set());
117
- }
118
- this.eventListeners.get(event).add(callback);
119
- }
120
- /**
121
- * Remove an event listener
122
- */
123
- off(event, callback) {
124
- const listeners = this.eventListeners.get(event);
125
- if (listeners) {
126
- listeners.delete(callback);
127
- }
128
- }
129
- /**
130
- * Close the flow and clean up resources
131
- */
132
- close() {
133
- if (this.keepAliveInterval) {
134
- clearInterval(this.keepAliveInterval);
135
- this.keepAliveInterval = null;
136
- }
137
- if (this.iframe && this.container) {
138
- this.container.removeChild(this.iframe);
139
- this.iframe = null;
140
- }
141
- this.eventListeners.clear();
142
- }
143
- }
@@ -1,17 +0,0 @@
1
- import { BaseFlow } from './BaseFlow.js';
2
- import { InitConfig, Environment } from '../types.js';
3
- /**
4
- * InitFlow subclass for handling initialization with callbacks
5
- */
6
- export declare class InitFlow extends BaseFlow {
7
- private authorizationCode;
8
- constructor(containerId: string, config: InitConfig, partnerName: string, environment: Environment, branchOverride?: string);
9
- /**
10
- * Initialize the init flow by creating and injecting a hidden iframe
11
- */
12
- initialize(): Promise<void>;
13
- /**
14
- * Construct the specific flow URL for initialization
15
- */
16
- protected constructFlowUrl(_baseUrl: string): string;
17
- }
@@ -1,44 +0,0 @@
1
- import { BaseFlow } from './BaseFlow.js';
2
- /**
3
- * InitFlow subclass for handling initialization with callbacks
4
- */
5
- export class InitFlow extends BaseFlow {
6
- constructor(containerId, config, partnerName, environment, branchOverride) {
7
- super(containerId, config, partnerName, environment, branchOverride);
8
- if (isEmptyString(config.authCode)) {
9
- throw new Error('Authorization code is required for init flow');
10
- }
11
- this.authorizationCode = config.authCode;
12
- }
13
- /**
14
- * Initialize the init flow by creating and injecting a hidden iframe
15
- */
16
- async initialize() {
17
- this.emit('authenticationSucceeded');
18
- // Disabled for quick performance improvement. Will be re-enabled in the future.
19
- // For init flow, we create a hidden iframe instead of a visible one
20
- // this.iframe = document.createElement('iframe');
21
- // this.iframe.src = this.createFlowUrl();
22
- // this.iframe.style.width = '1px';
23
- // this.iframe.style.height = '1px';
24
- // this.iframe.style.position = 'absolute';
25
- // this.iframe.style.left = '-9999px';
26
- // this.iframe.style.top = '-9999px';
27
- // document.body.appendChild(this.iframe);
28
- }
29
- /**
30
- * Construct the specific flow URL for initialization
31
- */
32
- constructFlowUrl(_baseUrl) {
33
- return '';
34
- // Disabled for quick performance improvement. Will be re-enabled in the future.
35
- // const params = new URLSearchParams({
36
- // token: this.authorizationCode,
37
- // theme: this.partnerName,
38
- // });
39
- // return `${baseUrl}/${this.partnerName}/auth?${params.toString()}`;
40
- }
41
- }
42
- const isEmptyString = (str) => {
43
- return !str?.trim();
44
- };
@@ -1,14 +0,0 @@
1
- import { BaseFlow } from './BaseFlow.js';
2
- import { OnboardingConfig, Environment } from '../types.js';
3
- /**
4
- * OnboardingFlow subclass with custom URL construction
5
- */
6
- export declare class OnboardingFlow extends BaseFlow {
7
- private preFilledParams;
8
- private enforceOnboarding?;
9
- constructor(containerId: string, config: OnboardingConfig, partnerName: string, environment: Environment, branchOverride?: string);
10
- /**
11
- * Construct the specific flow URL for onboarding
12
- */
13
- protected constructFlowUrl(baseUrl: string): string;
14
- }
@@ -1,43 +0,0 @@
1
- import { BaseFlow } from './BaseFlow.js';
2
- import { BASE_ACTION } from '../utils/environment.js';
3
- /**
4
- * OnboardingFlow subclass with custom URL construction
5
- */
6
- export class OnboardingFlow extends BaseFlow {
7
- constructor(containerId, config, partnerName, environment, branchOverride) {
8
- super(containerId, config, partnerName, environment, branchOverride);
9
- const { userDetails, organizationDetails, enforceOnboarding } = config;
10
- this.preFilledParams = { userDetails, organizationDetails };
11
- this.enforceOnboarding = enforceOnboarding;
12
- }
13
- /**
14
- * Construct the specific flow URL for onboarding
15
- */
16
- constructFlowUrl(baseUrl) {
17
- const params = Object.fromEntries(Object.entries(this.preFilledParams).filter(([_, v]) => v !== undefined));
18
- let preFilledBase64 = '';
19
- if (Object.keys(params).length > 0) {
20
- try {
21
- const json = JSON.stringify(params);
22
- preFilledBase64 = btoa(unescape(encodeURIComponent(json)));
23
- }
24
- catch (e) {
25
- preFilledBase64 = '';
26
- }
27
- }
28
- const authCode = this.config.authCode || '';
29
- let url = `${baseUrl}/${this.partnerName}${BASE_ACTION}`;
30
- const queryParams = [];
31
- if (preFilledBase64) {
32
- queryParams.push(`preFilledParams=${encodeURIComponent(preFilledBase64)}`);
33
- }
34
- if (this.enforceOnboarding !== undefined) {
35
- queryParams.push(`enforceOnboarding=${this.enforceOnboarding}`);
36
- }
37
- queryParams.push(`externalOrigin=${this.partnerName}`);
38
- queryParams.push('target=/welcome');
39
- queryParams.push(`token=${authCode}`);
40
- url += `?${queryParams.join('&')}`;
41
- return url;
42
- }
43
- }
@@ -1,14 +0,0 @@
1
- import { BaseFlow } from './BaseFlow.js';
2
- import { PayFlowConfig, Environment } from '../types.js';
3
- /**
4
- * PayFlow subclass with custom URL construction
5
- */
6
- export declare class PayFlow extends BaseFlow {
7
- private billIds;
8
- private authCode;
9
- constructor(containerId: string, config: PayFlowConfig, partnerName: string, environment: Environment, branchOverride?: string);
10
- /**
11
- * Construct the specific flow URL for bill payment
12
- */
13
- protected constructFlowUrl(baseUrl: string): string;
14
- }
@@ -1,18 +0,0 @@
1
- import { BaseFlow } from './BaseFlow.js';
2
- import { BASE_ACTION } from '../utils/environment.js';
3
- /**
4
- * PayFlow subclass with custom URL construction
5
- */
6
- export class PayFlow extends BaseFlow {
7
- constructor(containerId, config, partnerName, environment, branchOverride) {
8
- super(containerId, config, partnerName, environment, branchOverride);
9
- this.billIds = config.billIds;
10
- this.authCode = config.authCode || '';
11
- }
12
- /**
13
- * Construct the specific flow URL for bill payment
14
- */
15
- constructFlowUrl(baseUrl) {
16
- return `${baseUrl}/${this.partnerName}${BASE_ACTION}?token=${this.authCode}&target=/external-entries/payment-flow?billIds=${this.billIds.join(',')}&externalOrigin=${this.partnerName}`;
17
- }
18
- }
@@ -1,13 +0,0 @@
1
- import { BaseFlow } from './BaseFlow.js';
2
- import { PaymentsDashboardConfig, Environment } from '../types.js';
3
- /**
4
- * PaymentsDashboardFlow subclass with custom URL construction
5
- */
6
- export declare class PaymentsDashboardFlow extends BaseFlow {
7
- private authCode;
8
- constructor(containerId: string, config: PaymentsDashboardConfig, partnerName: string, environment: Environment, branchOverride?: string);
9
- /**
10
- * Construct the specific flow URL for payments dashboard
11
- */
12
- protected constructFlowUrl(baseUrl: string): string;
13
- }
@@ -1,17 +0,0 @@
1
- import { BaseFlow } from './BaseFlow.js';
2
- import { BASE_ACTION } from '../utils/environment.js';
3
- /**
4
- * PaymentsDashboardFlow subclass with custom URL construction
5
- */
6
- export class PaymentsDashboardFlow extends BaseFlow {
7
- constructor(containerId, config, partnerName, environment, branchOverride) {
8
- super(containerId, config, partnerName, environment, branchOverride);
9
- this.authCode = config.authCode || '';
10
- }
11
- /**
12
- * Construct the specific flow URL for payments dashboard
13
- */
14
- constructFlowUrl(baseUrl) {
15
- return `${baseUrl}/${this.partnerName}${BASE_ACTION}?token=${this.authCode}&target=/pay-dashboard/payments`;
16
- }
17
- }
@@ -1,13 +0,0 @@
1
- import { BaseFlow } from './BaseFlow.js';
2
- import { SettingsConfig, Environment } from '../types.js';
3
- /**
4
- * SettingsFlow subclass with custom URL construction
5
- */
6
- export declare class SettingsFlow extends BaseFlow {
7
- private authCode;
8
- constructor(containerId: string, config: SettingsConfig, partnerName: string, environment: Environment, branchOverride?: string);
9
- /**
10
- * Construct the specific flow URL for settings
11
- */
12
- protected constructFlowUrl(baseUrl: string): string;
13
- }
@@ -1,17 +0,0 @@
1
- import { BaseFlow } from './BaseFlow.js';
2
- import { BASE_ACTION } from '../utils/environment.js';
3
- /**
4
- * SettingsFlow subclass with custom URL construction
5
- */
6
- export class SettingsFlow extends BaseFlow {
7
- constructor(containerId, config, partnerName, environment, branchOverride) {
8
- super(containerId, config, partnerName, environment, branchOverride);
9
- this.authCode = config.authCode || '';
10
- }
11
- /**
12
- * Construct the specific flow URL for settings
13
- */
14
- constructFlowUrl(baseUrl) {
15
- return `${baseUrl}/${this.partnerName}${BASE_ACTION}?token=${this.authCode}&target=/settings`;
16
- }
17
- }
@@ -1,6 +0,0 @@
1
- import { Environment } from '../types.js';
2
- /**
3
- * Get the base URL for a given environment
4
- */
5
- export declare function getBaseUrl(environment: Environment): string;
6
- export declare const BASE_ACTION = "/auth";
@@ -1,22 +0,0 @@
1
- /**
2
- * Get the base URL for a given environment
3
- */
4
- export function getBaseUrl(environment) {
5
- switch (environment) {
6
- case 'production':
7
- return 'https://partnerships.production.melioservices.com';
8
- case 'staging01':
9
- return 'https://partnerships.staging01.melioservices.com';
10
- case 'public-qa':
11
- return 'https://partnerships.public-qa.melioservices.com';
12
- case 'certification':
13
- return 'https://partnerships.certification.melioservices.com';
14
- case 'eilat':
15
- return 'https://partnerships.eilat.melioservices.com';
16
- case 'localhost':
17
- return 'http://localhost:3005';
18
- default:
19
- return 'https://partnerships.melioservices.com';
20
- }
21
- }
22
- export const BASE_ACTION = '/auth';