react-native-smallcase-gateway 7.0.1 → 7.1.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.
@@ -1,8 +1,4 @@
1
- import {
2
- NativeEventEmitter,
3
- NativeModules,
4
- Platform
5
- } from 'react-native';
1
+ import { NativeEventEmitter, NativeModules } from 'react-native';
6
2
 
7
3
  /**
8
4
  * @typedef {Object} LoansEvent
@@ -16,101 +12,116 @@ import {
16
12
  const nativeModule = NativeModules.SCLoansBridgeEmitter;
17
13
 
18
14
  export const SCLoansEventTypes = {
19
- ANALYTICS_EVENT: 'scloans_analytics_event',
20
- SUPER_PROPERTIES_UPDATED: 'scloans_super_properties_updated',
15
+ ANALYTICS_EVENT: 'scloans_analytics_event',
16
+ SUPER_PROPERTIES_UPDATED: 'scloans_super_properties_updated',
21
17
  };
22
18
 
23
19
  const SCLoansNotificationEvent = 'scloans_notification';
24
20
  class SCLoansEvents {
25
- constructor() {
26
- this.eventEmitter = null;
27
- this.subscriptions = [];
28
- this.initialize();
21
+ constructor() {
22
+ this.eventEmitter = null;
23
+ this.subscriptions = [];
24
+ this.initialize();
25
+ }
26
+
27
+ get isInitialized() {
28
+ return this.eventEmitter !== null;
29
+ }
30
+
31
+ initialize() {
32
+ if (nativeModule) {
33
+ this.eventEmitter = new NativeEventEmitter(nativeModule);
34
+ } else {
35
+ console.warn('[SCLoansEvents] Native module not available');
29
36
  }
30
-
31
- get isInitialized() {
32
- return this.eventEmitter !== null;
37
+ }
38
+
39
+ // ===== LOANS EVENT METHODS =====
40
+ /**
41
+ * Subscribe to Loans Events
42
+ * @param {(event: LoansEvent) => void} callback - Callback function to handle loans events
43
+ * @returns {LoansEventSubscription} subscription - Subscription object with remove() method
44
+ */
45
+ subscribeToLoansEvent(callback) {
46
+ if (!this.isInitialized) {
47
+ console.warn('[SCLoansEvents] Event emitter not initialized');
48
+ return null;
33
49
  }
34
50
 
35
- initialize() {
36
- if (nativeModule) {
37
- this.eventEmitter = new NativeEventEmitter(nativeModule);
38
- } else {
39
- console.warn('[SCLoansEvents] Native module not available');
40
- }
51
+ if (typeof callback !== 'function') {
52
+ console.warn(
53
+ '[SCLoansEvents] Invalid callback provided for subscription'
54
+ );
55
+ return null;
41
56
  }
42
57
 
43
- // ===== LOANS EVENT METHODS =====
44
- /**
45
- * Subscribe to Loans Events
46
- * @param {(event: LoansEvent) => void} callback - Callback function to handle loans events
47
- * @returns {LoansEventSubscription} subscription - Subscription object with remove() method
48
- */
49
- subscribeToLoansEvent(callback) {
50
- if (!this.isInitialized) {
51
- console.warn('[SCLoansEvents] Event emitter not initialized');
52
- return null;
58
+ const subscription = this.eventEmitter.addListener(
59
+ SCLoansNotificationEvent,
60
+ (jsonString) => {
61
+ if (!jsonString) {
62
+ console.warn('[SCLoansEvents] Received null/undefined event data');
63
+ return;
53
64
  }
54
65
 
55
- if (typeof callback !== 'function') {
56
- console.warn('[SCLoansEvents] Invalid callback provided for subscription');
57
- return null;
66
+ let eventData;
67
+ try {
68
+ eventData = JSON.parse(jsonString);
69
+ } catch (error) {
70
+ console.warn(
71
+ '[SCLoansEvents] Failed to parse event JSON:',
72
+ error,
73
+ 'Raw data:',
74
+ jsonString
75
+ );
76
+ return;
58
77
  }
59
78
 
60
- const subscription = this.eventEmitter.addListener(SCLoansNotificationEvent, (jsonString) => {
61
- if (!jsonString) {
62
- console.warn('[SCLoansEvents] Received null/undefined event data');
63
- return;
64
- }
65
-
66
- let eventData;
67
- try {
68
- eventData = JSON.parse(jsonString);
69
- } catch (error) {
70
- console.warn('[SCLoansEvents] Failed to parse event JSON:', error, 'Raw data:', jsonString);
71
- return;
72
- }
73
-
74
- if (!eventData.type) {
75
- console.warn('[SCLoansEvents] Dropping event - missing event type:', eventData);
76
- return;
77
- }
78
-
79
- const normalizedEvent = {
80
- type: eventData.type,
81
- data: eventData.data,
82
- timestamp: eventData.timestamp || Date.now()
83
- };
84
-
85
- callback(normalizedEvent);
86
- });
87
-
88
- this.subscriptions.push(subscription);
89
-
90
- return subscription;
91
- }
92
-
93
- /**
94
- * Unsubscribe from Loans Events
95
- * @param {LoansEventSubscription} subscription - Subscription returned from subscribeToLoansEvents
96
- */
97
- unsubscribeFromLoansEvent(subscription) {
98
- if (subscription && typeof subscription.remove === 'function') {
99
- subscription.remove();
100
- this.subscriptions = this.subscriptions.filter(sub => sub !== subscription);
79
+ if (!eventData.type) {
80
+ console.warn(
81
+ '[SCLoansEvents] Dropping event - missing event type:',
82
+ eventData
83
+ );
84
+ return;
101
85
  }
102
- }
103
86
 
104
- cleanup() {
105
- this.subscriptions.forEach(subscription => {
106
- if (subscription && typeof subscription.remove === 'function') {
107
- subscription.remove();
108
- }
109
- });
110
- this.subscriptions = [];
87
+ const normalizedEvent = {
88
+ type: eventData.type,
89
+ data: eventData.data,
90
+ timestamp: eventData.timestamp || Date.now(),
91
+ };
92
+
93
+ callback(normalizedEvent);
94
+ }
95
+ );
96
+
97
+ this.subscriptions.push(subscription);
98
+
99
+ return subscription;
100
+ }
101
+
102
+ /**
103
+ * Unsubscribe from Loans Events
104
+ * @param {LoansEventSubscription} subscription - Subscription returned from subscribeToLoansEvents
105
+ */
106
+ unsubscribeFromLoansEvent(subscription) {
107
+ if (subscription && typeof subscription.remove === 'function') {
108
+ subscription.remove();
109
+ this.subscriptions = this.subscriptions.filter(
110
+ (sub) => sub !== subscription
111
+ );
111
112
  }
113
+ }
114
+
115
+ cleanup() {
116
+ this.subscriptions.forEach((subscription) => {
117
+ if (subscription && typeof subscription.remove === 'function') {
118
+ subscription.remove();
119
+ }
120
+ });
121
+ this.subscriptions = [];
122
+ }
112
123
  }
113
124
 
114
125
  const scLoansEventManager = new SCLoansEvents();
115
126
 
116
- export default scLoansEventManager;
127
+ export default scLoansEventManager;
package/src/ScLoan.js CHANGED
@@ -31,11 +31,12 @@ const { SmallcaseGateway: SmallcaseGatewayNative } = NativeModules;
31
31
  * @throws {ScLoanError}
32
32
  */
33
33
  const setup = async (config) => {
34
- const safeConfig = safeObject(config);
35
- if(safeConfig.environment === undefined || safeConfig.environment === null) safeConfig.environment = ENV.PROD
34
+ const safeConfig = safeObject(config);
35
+ if (safeConfig.environment === undefined || safeConfig.environment === null)
36
+ safeConfig.environment = ENV.PROD;
36
37
 
37
- return SmallcaseGatewayNative.setupLoans(safeConfig);
38
- };
38
+ return SmallcaseGatewayNative.setupLoans(safeConfig);
39
+ };
39
40
 
40
41
  /**
41
42
  * Triggers the LOS Journey
@@ -46,10 +47,10 @@ const setup = async (config) => {
46
47
  * @deprecated This method is deprecated use triggerInteraction() instead.
47
48
  */
48
49
  const apply = async (loanInfo) => {
49
- const safeLoanInfo = safeObject(loanInfo);
50
+ const safeLoanInfo = safeObject(loanInfo);
50
51
 
51
- return SmallcaseGatewayNative.apply(safeLoanInfo);
52
- };
52
+ return SmallcaseGatewayNative.apply(safeLoanInfo);
53
+ };
53
54
 
54
55
  /**
55
56
  * Triggers the Repayment Journey
@@ -60,10 +61,10 @@ const apply = async (loanInfo) => {
60
61
  * @deprecated This method is deprecated use triggerInteraction() instead.
61
62
  */
62
63
  const pay = async (loanInfo) => {
63
- const safeLoanInfo = safeObject(loanInfo);
64
+ const safeLoanInfo = safeObject(loanInfo);
64
65
 
65
- return SmallcaseGatewayNative.pay(safeLoanInfo);
66
- };
66
+ return SmallcaseGatewayNative.pay(safeLoanInfo);
67
+ };
67
68
 
68
69
  /**
69
70
  * Triggers the Withdraw Journey
@@ -74,10 +75,10 @@ const pay = async (loanInfo) => {
74
75
  * @deprecated This method is deprecated use triggerInteraction() instead.
75
76
  */
76
77
  const withdraw = async (loanInfo) => {
77
- const safeLoanInfo = safeObject(loanInfo);
78
+ const safeLoanInfo = safeObject(loanInfo);
78
79
 
79
- return SmallcaseGatewayNative.withdraw(safeLoanInfo);
80
- };
80
+ return SmallcaseGatewayNative.withdraw(safeLoanInfo);
81
+ };
81
82
 
82
83
  /**
83
84
  * Triggers the Servicing Journey
@@ -88,10 +89,10 @@ const withdraw = async (loanInfo) => {
88
89
  * @deprecated This method is deprecated use triggerInteraction() instead.
89
90
  */
90
91
  const service = async (loanInfo) => {
91
- const safeLoanInfo = safeObject(loanInfo);
92
+ const safeLoanInfo = safeObject(loanInfo);
92
93
 
93
- return SmallcaseGatewayNative.service(safeLoanInfo);
94
- };
94
+ return SmallcaseGatewayNative.service(safeLoanInfo);
95
+ };
95
96
 
96
97
  /**
97
98
  * Triggers the triggerInteraction function
@@ -115,4 +116,4 @@ const ScLoan = {
115
116
  triggerInteraction,
116
117
  };
117
118
 
118
- export default ScLoan;
119
+ export default ScLoan;
@@ -1,6 +1,10 @@
1
- import { NativeModules, Platform } from 'react-native';
1
+ import { NativeModules } from 'react-native';
2
2
  import { ENV } from './constants';
3
- import { safeObject, platformSpecificColorHex } from './util';
3
+ import {
4
+ safeObject,
5
+ platformSpecificColorHex,
6
+ sanitizeBrokerList,
7
+ } from './util';
4
8
  import { version } from '../package.json';
5
9
  const { SmallcaseGateway: SmallcaseGatewayNative } = NativeModules;
6
10
 
@@ -64,7 +68,7 @@ const setConfigEnvironment = async (envConfig) => {
64
68
 
65
69
  const safeIsLeprechaun = Boolean(isLeprechaun);
66
70
  const safeIsAmoEnabled = Boolean(isAmoEnabled);
67
- const safeBrokerList = Array.isArray(brokerList) ? brokerList : [];
71
+ const safeBrokerList = sanitizeBrokerList(brokerList);
68
72
  const safeGatewayName = typeof gatewayName === 'string' ? gatewayName : '';
69
73
  const safeEnvName =
70
74
  typeof environmentName === 'string' ? environmentName : ENV.PROD;
@@ -90,8 +94,9 @@ const setConfigEnvironment = async (envConfig) => {
90
94
  */
91
95
  const init = async (sdkToken, externalMeta) => {
92
96
  const safeToken = typeof sdkToken === 'string' ? sdkToken : '';
93
- const safeExternalMeta = externalMeta && typeof externalMeta === 'object' ? externalMeta : null;
94
-
97
+ const safeExternalMeta =
98
+ externalMeta && typeof externalMeta === 'object' ? externalMeta : null;
99
+
95
100
  return SmallcaseGatewayNative.init(safeToken, safeExternalMeta);
96
101
  };
97
102
 
@@ -107,10 +112,11 @@ const triggerTransaction = async (transactionId, utmParams, brokerList) => {
107
112
  const safeUtm = safeObject(utmParams);
108
113
  const safeId = typeof transactionId === 'string' ? transactionId : '';
109
114
 
110
- const safeBrokerList =
111
- Array.isArray(brokerList) && brokerList.length
112
- ? brokerList
113
- : defaultBrokerList;
115
+ let safeBrokerList = sanitizeBrokerList(brokerList);
116
+
117
+ if (safeBrokerList.length === 0) {
118
+ safeBrokerList = defaultBrokerList;
119
+ }
114
120
 
115
121
  return SmallcaseGatewayNative.triggerTransaction(
116
122
  safeId,
@@ -187,14 +193,14 @@ const launchSmallplugWithBranding = async (
187
193
  const safeBackIconOpacity =
188
194
  typeof backIconOpacity === 'number' ? backIconOpacity : 1;
189
195
 
190
- return SmallcaseGatewayNative.launchSmallplugWithBranding(
191
- safeEndpoint,
192
- safeParams,
193
- safeHeaderColor,
194
- safeHeaderOpacity,
195
- safeBackIconColor,
196
- safeBackIconOpacity
197
- );
196
+ return SmallcaseGatewayNative.launchSmallplugWithBranding(
197
+ safeEndpoint,
198
+ safeParams,
199
+ safeHeaderColor,
200
+ safeHeaderOpacity,
201
+ safeBackIconColor,
202
+ safeBackIconOpacity
203
+ );
198
204
  };
199
205
 
200
206
  /**
@@ -302,4 +308,4 @@ const SmallcaseGateway = {
302
308
  showOrders,
303
309
  };
304
310
 
305
- export default SmallcaseGateway;
311
+ export default SmallcaseGateway;
package/src/constants.js CHANGED
@@ -1,35 +1,35 @@
1
1
  export const ENV = {
2
- STAG: "staging",
3
- DEV: "development",
4
- PROD: "production",
2
+ STAG: 'staging',
3
+ DEV: 'development',
4
+ PROD: 'production',
5
5
  };
6
6
 
7
7
  export const TRANSACTION_TYPE = {
8
- connect: "CONNECT",
9
- sipSetup: "SIP_SETUP",
10
- fetchFunds: "FETCH_FUNDS",
11
- transaction: "TRANSACTION",
12
- holdingsImport: "HOLDINGS_IMPORT",
13
- authorizeHoldings: "AUTHORISE_HOLDINGS",
14
- mfHoldingsImport: "MF_HOLDINGS_IMPORT"
8
+ connect: 'CONNECT',
9
+ sipSetup: 'SIP_SETUP',
10
+ fetchFunds: 'FETCH_FUNDS',
11
+ transaction: 'TRANSACTION',
12
+ holdingsImport: 'HOLDINGS_IMPORT',
13
+ authorizeHoldings: 'AUTHORISE_HOLDINGS',
14
+ mfHoldingsImport: 'MF_HOLDINGS_IMPORT',
15
15
  };
16
16
 
17
17
  export const ERROR_MSG = {
18
- init_sdk: "init_sdk",
19
- no_order: "no_order",
20
- no_broker: "no_broker",
21
- invalid_jwt: "invalid_jwt",
22
- market_closed: "market_closed",
23
- user_mismatch: "user_mismatch",
24
- order_pending: "order_pending",
25
- internal_error: "internal_error",
26
- user_cancelled: "user_cancelled",
27
- consent_denied: "consent_denied",
28
- order_in_queue: "order_in_queue",
29
- invalid_gateway: "invalid_gateway",
30
- transaction_expired: "transaction_expired",
31
- invalid_transactionId: "invalid_transactionId",
32
- insufficient_holdings: "insufficient_holdings",
33
- transaction_in_process: "transaction_in_process",
34
- no_compatible_browser: "no_compatible_browser"
18
+ init_sdk: 'init_sdk',
19
+ no_order: 'no_order',
20
+ no_broker: 'no_broker',
21
+ invalid_jwt: 'invalid_jwt',
22
+ market_closed: 'market_closed',
23
+ user_mismatch: 'user_mismatch',
24
+ order_pending: 'order_pending',
25
+ internal_error: 'internal_error',
26
+ user_cancelled: 'user_cancelled',
27
+ consent_denied: 'consent_denied',
28
+ order_in_queue: 'order_in_queue',
29
+ invalid_gateway: 'invalid_gateway',
30
+ transaction_expired: 'transaction_expired',
31
+ invalid_transactionId: 'invalid_transactionId',
32
+ insufficient_holdings: 'insufficient_holdings',
33
+ transaction_in_process: 'transaction_in_process',
34
+ no_compatible_browser: 'no_compatible_browser',
35
35
  };
package/src/index.js CHANGED
@@ -1,8 +1,16 @@
1
- import SmallcaseGateway from "./SmallcaseGateway";
2
- import ScLoan from "./ScLoan";
3
- import scGatewayEventManager, { SCGatewayEventTypes } from './SCGatewayEventEmitter';
1
+ import SmallcaseGateway from './SmallcaseGateway';
2
+ import ScLoan from './ScLoan';
3
+ import scGatewayEventManager, {
4
+ SCGatewayEventTypes,
5
+ } from './SCGatewayEventEmitter';
4
6
  import scLoansEventManager, { SCLoansEventTypes } from './SCLoansEventEmitter';
5
- import { ENV, TRANSACTION_TYPE, ERROR_MSG } from "./constants";
7
+ import { ENV, TRANSACTION_TYPE, ERROR_MSG } from './constants';
6
8
 
7
- export { ScLoan, scGatewayEventManager as SCGatewayEventManager, scLoansEventManager as SCLoansEventManager, SCGatewayEventTypes, SCLoansEventTypes }
9
+ export {
10
+ ScLoan,
11
+ scGatewayEventManager as SCGatewayEventManager,
12
+ scLoansEventManager as SCLoansEventManager,
13
+ SCGatewayEventTypes,
14
+ SCLoansEventTypes,
15
+ };
8
16
  export default { ...SmallcaseGateway, ENV, ERROR_MSG, TRANSACTION_TYPE };
package/src/util.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { Platform } from 'react-native';
2
+
1
3
  /**
2
4
  * check if value is a valid object.
3
5
  *
@@ -6,13 +8,24 @@
6
8
  * @param {*} obj
7
9
  * @returns {Object} same object if its valid, else returns `{}`
8
10
  */
9
- export const safeObject = (obj) => {
10
- return obj && typeof obj === "object" ? obj : {};
11
+ export const safeObject = (obj) => {
12
+ return obj && typeof obj === 'object' ? obj : {};
11
13
  };
12
14
 
13
15
  export function platformSpecificColorHex(hex) {
14
16
  if (Platform.OS === 'android') {
15
- return `#${hex}`
17
+ return `#${hex}`;
16
18
  }
17
- return hex
19
+ return hex;
20
+ }
21
+
22
+ /** sanitize the input broker array to make sure its an array and only has string values */
23
+ export function sanitizeBrokerList(arr) {
24
+ if (!Array.isArray(arr) || arr.length === 0) {
25
+ return [];
26
+ }
27
+
28
+ return arr.filter((val) => {
29
+ return typeof val === 'string' && val.trim() !== '';
30
+ });
18
31
  }