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

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.
@@ -0,0 +1,57 @@
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
+ }
@@ -0,0 +1,143 @@
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
+ }
@@ -0,0 +1,17 @@
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
+ }
@@ -0,0 +1,44 @@
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
+ };
@@ -0,0 +1,14 @@
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
+ }
@@ -0,0 +1,43 @@
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
+ }
@@ -0,0 +1,14 @@
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
+ }
@@ -0,0 +1,18 @@
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
+ }
@@ -0,0 +1,13 @@
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
+ }
@@ -0,0 +1,17 @@
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
+ }
@@ -0,0 +1,13 @@
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
+ }
@@ -0,0 +1,17 @@
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
+ }
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export declare class MelioSDK implements MelioSDK {
7
7
  private environment;
8
8
  private partnerName;
9
9
  private branchOverride;
10
+ private authenticationCode;
10
11
  constructor();
11
12
  /**
12
13
  * Initialize the SDK by creating an authentication flow
package/dist/index.js CHANGED
@@ -1,296 +1,9 @@
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
- /**
23
- * Flow class implementation for handling iframe flows and events
24
- */
25
- class Flow {
26
- constructor(containerId, config, partnerName, environment, branchOverride) {
27
- this.containerId = containerId;
28
- this.config = config;
29
- this.partnerName = partnerName;
30
- this.environment = environment;
31
- this.branchOverride = branchOverride;
32
- this.iframe = null;
33
- this.container = null;
34
- this.eventListeners = new Map();
35
- this.keepAliveInterval = null;
36
- this.setupEventListeners();
37
- }
38
- /**
39
- * Initialize the flow by creating and injecting the iframe
40
- */
41
- async initialize() {
42
- this.container = document.getElementById(this.containerId);
43
- if (!this.container) {
44
- throw new Error(`Container with ID "${this.containerId}" not found`);
45
- }
46
- this.iframe = document.createElement('iframe');
47
- this.iframe.src = this.createFlowUrl();
48
- this.iframe.style.width = '100%';
49
- this.iframe.style.height = '1000px';
50
- this.iframe.style.border = 'none';
51
- this.iframe.style.display = 'block';
52
- this.container.appendChild(this.iframe);
53
- }
54
- /**
55
- * Construct the specific flow URL for onboarding - can be overridden by subclasses
56
- */
57
- constructFlowUrl(baseUrl) {
58
- return `${baseUrl}/${this.partnerName}/auth`;
59
- }
60
- /**
61
- * Create flow URL using partner name and environment
62
- */
63
- createFlowUrl() {
64
- console.log('🔧 Creating flow URL...');
65
- console.log('📝 Config:', this.config);
66
- console.log('🏢 Partner:', this.partnerName);
67
- console.log('🌍 Environment:', this.environment);
68
- console.log('🔝 Branch Override:', this.branchOverride);
69
- const baseUrl = getBaseUrl(this.environment);
70
- let finalUrl = this.constructFlowUrl(baseUrl);
71
- // Add cdn_branch_override parameter for non-production environments
72
- if (this.branchOverride && this.environment !== 'production') {
73
- const separator = finalUrl.includes('?') ? '&' : '?';
74
- finalUrl += `${separator}cdn_branch_override=${this.branchOverride}`;
75
- }
76
- console.log('🌐 Final URL:', finalUrl);
77
- return finalUrl;
78
- }
79
- setupEventListeners() {
80
- // Add post message handlers for internal events - setHeight, scroll etc
81
- // Also need to implement callbacks for flow completed exit etc in the platform-app
82
- window.addEventListener('message', (event) => {
83
- if (!/melio\.com|melioservices\.com/.test(event.origin)) {
84
- return;
85
- }
86
- const { type, ...data } = event.data;
87
- console.log('📬 Received message from iframe:', {
88
- type,
89
- data,
90
- origin: event.origin,
91
- });
92
- switch (type) {
93
- case 'FLOW_COMPLETED':
94
- this.emit('completed', data);
95
- break;
96
- case 'FLOW_EXIT':
97
- this.emit('exit');
98
- break;
99
- case 'NAVIGATED_TO_TARGET':
100
- this.emit('navigated', data);
101
- break;
102
- case 'AUTHENTICATION_SUCCESS':
103
- this.emit('authenticationSucceeded');
104
- break;
105
- case 'AUTHENTICATION_ERROR':
106
- this.emit('authenticationFailed');
107
- break;
108
- case 'ONBOARDING_COMPLETED':
109
- this.emit('completed', { flowName: 'onboarding', ...data });
110
- break;
111
- case 'READY_FOR_INTERACTION':
112
- this.emit('loaded');
113
- break;
114
- case 'MELIO_ERROR':
115
- if (data.code === 'failed_to_sync_bills') {
116
- this.emit('error', { errorCode: 'billsSyncFailed' });
117
- }
118
- break;
119
- case 'HEIGHT_CHANGE':
120
- if (this.iframe) {
121
- this.iframe.style.height = `${data.height}px`;
122
- }
123
- break;
124
- }
125
- });
126
- }
127
- emit(event, data) {
128
- const listeners = this.eventListeners.get(event);
129
- if (listeners) {
130
- listeners.forEach((callback) => {
131
- try {
132
- callback(data);
133
- }
134
- catch (error) {
135
- console.error(`Error in ${event} event listener:`, error);
136
- }
137
- });
138
- }
139
- }
140
- on(event, callback) {
141
- if (!this.eventListeners.has(event)) {
142
- this.eventListeners.set(event, new Set());
143
- }
144
- this.eventListeners.get(event).add(callback);
145
- }
146
- /**
147
- * Remove an event listener
148
- */
149
- off(event, callback) {
150
- const listeners = this.eventListeners.get(event);
151
- if (listeners) {
152
- listeners.delete(callback);
153
- }
154
- }
155
- /**
156
- * Close the flow and clean up resources
157
- */
158
- close() {
159
- if (this.keepAliveInterval) {
160
- clearInterval(this.keepAliveInterval);
161
- this.keepAliveInterval = null;
162
- }
163
- if (this.iframe && this.container) {
164
- this.container.removeChild(this.iframe);
165
- this.iframe = null;
166
- }
167
- this.eventListeners.clear();
168
- }
169
- }
170
- /**
171
- * OnboardingFlow subclass with custom URL construction
172
- */
173
- class OnboardingFlow extends Flow {
174
- constructor(containerId, config, partnerName, environment, branchOverride) {
175
- super(containerId, config, partnerName, environment, branchOverride);
176
- const { userDetails, organizationDetails, enforceOnboarding } = config;
177
- this.preFilledParams = { userDetails, organizationDetails };
178
- this.enforceOnboarding = enforceOnboarding;
179
- }
180
- /**
181
- * Construct the specific flow URL for onboarding
182
- */
183
- constructFlowUrl(baseUrl) {
184
- const params = Object.fromEntries(Object.entries(this.preFilledParams).filter(([_, v]) => v !== undefined));
185
- let preFilledBase64 = '';
186
- if (Object.keys(params).length > 0) {
187
- try {
188
- const json = JSON.stringify(params);
189
- preFilledBase64 = btoa(unescape(encodeURIComponent(json)));
190
- }
191
- catch (e) {
192
- preFilledBase64 = '';
193
- }
194
- }
195
- let url = `${baseUrl}/${this.partnerName}/welcome`;
196
- const queryParams = [];
197
- if (preFilledBase64) {
198
- queryParams.push(`preFilledParams=${encodeURIComponent(preFilledBase64)}`);
199
- }
200
- if (this.enforceOnboarding !== undefined) {
201
- queryParams.push(`enforceOnboarding=${this.enforceOnboarding}`);
202
- }
203
- queryParams.push(`externalOrigin=${this.partnerName}`);
204
- url += `?${queryParams.join('&')}`;
205
- return url;
206
- }
207
- }
208
- /**
209
- * PayFlow subclass with custom URL construction
210
- */
211
- class PayFlow extends Flow {
212
- constructor(containerId, config, partnerName, environment, branchOverride) {
213
- super(containerId, config, partnerName, environment, branchOverride);
214
- this.billIds = config.billIds;
215
- }
216
- /**
217
- * Construct the specific flow URL for bill payment
218
- */
219
- constructFlowUrl(baseUrl) {
220
- return `${baseUrl}/${this.partnerName}/external-entries/payment-flow?billIds=${this.billIds.join(',')}&externalOrigin=${this.partnerName}`;
221
- }
222
- }
223
- /**
224
- * SettingsFlow subclass with custom URL construction
225
- */
226
- class SettingsFlow extends Flow {
227
- constructor(containerId, config, partnerName, environment, branchOverride) {
228
- super(containerId, config, partnerName, environment, branchOverride);
229
- }
230
- /**
231
- * Construct the specific flow URL for settings
232
- */
233
- constructFlowUrl(baseUrl) {
234
- return `${baseUrl}/${this.partnerName}/settings`;
235
- }
236
- }
237
- class PaymentsDashboardFlow extends Flow {
238
- constructor(containerId, config, partnerName, environment, branchOverride) {
239
- super(containerId, config, partnerName, environment, branchOverride);
240
- }
241
- /**
242
- * Construct the specific flow URL for payments dashboard
243
- */
244
- constructFlowUrl(baseUrl) {
245
- return `${baseUrl}/${this.partnerName}/pay-dashboard/payments`;
246
- }
247
- }
248
- const isEmptyString = (str) => {
249
- return !str?.trim();
250
- };
251
- /**
252
- * InitFlow subclass for handling initialization with callbacks
253
- */
254
- class InitFlow extends Flow {
255
- constructor(containerId, config, partnerName, environment, branchOverride) {
256
- super(containerId, config, partnerName, environment, branchOverride);
257
- if (isEmptyString(config.authCode)) {
258
- throw new Error('Authorization code is required for init flow');
259
- }
260
- this.authorizationCode = config.authCode;
261
- }
262
- /**
263
- * Initialize the init flow by creating and injecting a hidden iframe
264
- */
265
- async initialize() {
266
- // For init flow, we create a hidden iframe instead of a visible one
267
- this.iframe = document.createElement('iframe');
268
- this.iframe.src = this.createFlowUrl();
269
- this.iframe.style.width = '1px';
270
- this.iframe.style.height = '1px';
271
- this.iframe.style.position = 'absolute';
272
- this.iframe.style.left = '-9999px';
273
- this.iframe.style.top = '-9999px';
274
- document.body.appendChild(this.iframe);
275
- }
276
- /**
277
- * Construct the specific flow URL for initialization
278
- */
279
- constructFlowUrl(baseUrl) {
280
- const params = new URLSearchParams({
281
- token: this.authorizationCode,
282
- theme: this.partnerName,
283
- });
284
- return `${baseUrl}/${this.partnerName}/start?${params.toString()}`;
285
- }
286
- setupKeepAlive() {
287
- this.keepAliveInterval = window.setInterval(() => {
288
- if (this.iframe && this.iframe.contentWindow) {
289
- this.iframe.contentWindow.postMessage({ type: 'USER_ACTIVE_PING' }, '*');
290
- }
291
- }, 30000); // Send ping every 30 seconds
292
- }
293
- }
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';
294
7
  /**
295
8
  * Main SDK implementation - now partner agnostic
296
9
  */
@@ -300,6 +13,7 @@ export class MelioSDK {
300
13
  this.environment = 'production';
301
14
  this.partnerName = '';
302
15
  this.branchOverride = undefined;
16
+ this.authenticationCode = '';
303
17
  }
304
18
  /**
305
19
  * Initialize the SDK by creating an authentication flow
@@ -308,23 +22,32 @@ export class MelioSDK {
308
22
  this.partnerName = options.partnerName;
309
23
  this.environment = options.environment || 'production';
310
24
  this.branchOverride = options.branchOverride;
25
+ this.authenticationCode = authenticationCode;
311
26
  console.log('starting init flow', {
312
27
  partnerName: this.partnerName,
313
28
  environment: this.environment,
314
29
  });
30
+ const initConfig = {
31
+ authCode: authenticationCode,
32
+ containerId: '',
33
+ };
315
34
  const initFlow = new InitFlow('', // no need container id for init flow as it is created inside the initialization
316
- { authCode: authenticationCode, containerId: '' }, this.partnerName, this.environment, this.branchOverride);
35
+ initConfig, this.partnerName, this.environment, this.branchOverride);
317
36
  initFlow.initialize();
318
- console.log('InitFlow initialized successfully');
319
- if (options.keepAlive)
320
- initFlow.setupKeepAlive();
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();
321
40
  return initFlow;
322
41
  }
323
42
  /**
324
43
  * Launch the onboarding flow
325
44
  */
326
45
  openOnboarding(config) {
327
- const flow = new OnboardingFlow(config.containerId, config, this.partnerName, this.environment, this.branchOverride);
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);
328
51
  flow.initialize();
329
52
  return flow;
330
53
  }
@@ -0,0 +1,6 @@
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";
@@ -0,0 +1,22 @@
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';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@melio-eng/web-sdk",
3
- "version": "1.0.26",
3
+ "version": "1.0.27-pr.53.6e729bc",
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",