@cranberry-money/shared-utils 4.9.0 → 4.11.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.
- package/dist/auth.d.ts +90 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +135 -0
- package/dist/filters.d.ts.map +1 -1
- package/dist/filters.js +4 -3
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/instruments.d.ts +118 -0
- package/dist/instruments.d.ts.map +1 -0
- package/dist/instruments.js +135 -0
- package/dist/validation.js +3 -3
- package/package.json +1 -1
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication and token management utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Check if a token has expired based on its expiration timestamp
|
|
6
|
+
* @param expiresAt - The expiration timestamp
|
|
7
|
+
* @returns true if token is expired, false otherwise
|
|
8
|
+
*/
|
|
9
|
+
export declare function isTokenExpired(expiresAt: string): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Check if a token will expire within a specified number of minutes
|
|
12
|
+
* @param expiresAt - The expiration timestamp
|
|
13
|
+
* @param minutesBeforeExpiry - Minutes before expiry to consider as "expiring soon"
|
|
14
|
+
* @returns true if token is expiring soon, false otherwise
|
|
15
|
+
*/
|
|
16
|
+
export declare function isTokenExpiringSoon(expiresAt: string, minutesBeforeExpiry?: number): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Get the remaining time until token expiry in minutes
|
|
19
|
+
* @param expiresAt - The expiration timestamp
|
|
20
|
+
* @returns Number of minutes until expiry
|
|
21
|
+
*/
|
|
22
|
+
export declare function getTimeUntilExpiry(expiresAt: string): number;
|
|
23
|
+
/**
|
|
24
|
+
* Format the time until expiry in a human-readable format
|
|
25
|
+
* @param expiresAt - The expiration timestamp
|
|
26
|
+
* @returns Formatted time string
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatTimeUntilExpiry(expiresAt: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Device info structure
|
|
31
|
+
*/
|
|
32
|
+
export interface DeviceInfo {
|
|
33
|
+
browser: string;
|
|
34
|
+
os: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parse device information from user agent string
|
|
38
|
+
* @param userAgent - The user agent string
|
|
39
|
+
* @returns Parsed device info
|
|
40
|
+
*/
|
|
41
|
+
export declare function parseDeviceInfo(userAgent: string): DeviceInfo;
|
|
42
|
+
/**
|
|
43
|
+
* Token refresh response structure
|
|
44
|
+
*/
|
|
45
|
+
export interface TokenRefreshResponse {
|
|
46
|
+
status?: number;
|
|
47
|
+
data?: {
|
|
48
|
+
access?: string;
|
|
49
|
+
refresh?: string;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Check if token refresh was successful
|
|
54
|
+
* @param response - The refresh response
|
|
55
|
+
* @returns true if refresh was successful, false otherwise
|
|
56
|
+
*/
|
|
57
|
+
export declare function isRefreshSuccess(response: TokenRefreshResponse): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Token refresh error structure
|
|
60
|
+
*/
|
|
61
|
+
export interface TokenRefreshError {
|
|
62
|
+
response?: {
|
|
63
|
+
data?: {
|
|
64
|
+
detail?: string;
|
|
65
|
+
message?: string;
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
message?: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get error message from token refresh error
|
|
72
|
+
* @param error - The refresh error
|
|
73
|
+
* @returns Error message string
|
|
74
|
+
*/
|
|
75
|
+
export declare function getRefreshErrorMessage(error: TokenRefreshError): string;
|
|
76
|
+
/**
|
|
77
|
+
* Auto refresh handler interface
|
|
78
|
+
*/
|
|
79
|
+
export interface AutoRefreshHandler {
|
|
80
|
+
start: () => void;
|
|
81
|
+
stop: () => void;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Create an auto-refresh handler for tokens
|
|
85
|
+
* @param refreshCallback - Callback function to refresh token
|
|
86
|
+
* @param checkInterval - Interval in milliseconds to check for refresh
|
|
87
|
+
* @returns Auto refresh handler with start/stop methods
|
|
88
|
+
*/
|
|
89
|
+
export declare function createAutoRefreshHandler(refreshCallback: () => Promise<void>, checkInterval?: number): AutoRefreshHandler;
|
|
90
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAkBH;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAIzD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,mBAAmB,GAAE,MAA6C,GACjE,OAAO,CAMT;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAU5D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAkB/D;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAwB7D;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE;QACL,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,oBAAoB,GAAG,OAAO,CAExE;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE;QACT,IAAI,CAAC,EAAE;YACL,MAAM,CAAC,EAAE,MAAM,CAAC;YAChB,OAAO,CAAC,EAAE,MAAM,CAAC;SAClB,CAAC;KACH,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAWvE;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EACpC,aAAa,GAAE,MAAc,GAC5B,kBAAkB,CAiBpB"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication and token management utilities
|
|
3
|
+
*/
|
|
4
|
+
import { DEFAULT_TOKEN_REFRESH_BUFFER_MINUTES, MILLISECONDS_PER_MINUTE, MINUTES_PER_HOUR, HOURS_PER_DAY, TIME_LABEL_EXPIRED, TIME_LABEL_MINUTE, TIME_LABEL_MINUTES, TIME_LABEL_HOUR, TIME_LABEL_HOURS, TIME_LABEL_DAY, TIME_LABEL_DAYS, DEFAULT_UNKNOWN_VALUE, DEFAULT_ERROR_MESSAGE, } from '@cranberry-money/shared-constants';
|
|
5
|
+
/**
|
|
6
|
+
* Check if a token has expired based on its expiration timestamp
|
|
7
|
+
* @param expiresAt - The expiration timestamp
|
|
8
|
+
* @returns true if token is expired, false otherwise
|
|
9
|
+
*/
|
|
10
|
+
export function isTokenExpired(expiresAt) {
|
|
11
|
+
const expirationTime = new Date(expiresAt).getTime();
|
|
12
|
+
const currentTime = Date.now();
|
|
13
|
+
return currentTime >= expirationTime;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Check if a token will expire within a specified number of minutes
|
|
17
|
+
* @param expiresAt - The expiration timestamp
|
|
18
|
+
* @param minutesBeforeExpiry - Minutes before expiry to consider as "expiring soon"
|
|
19
|
+
* @returns true if token is expiring soon, false otherwise
|
|
20
|
+
*/
|
|
21
|
+
export function isTokenExpiringSoon(expiresAt, minutesBeforeExpiry = DEFAULT_TOKEN_REFRESH_BUFFER_MINUTES) {
|
|
22
|
+
const expirationTime = new Date(expiresAt).getTime();
|
|
23
|
+
const currentTime = Date.now();
|
|
24
|
+
const bufferTime = minutesBeforeExpiry * MILLISECONDS_PER_MINUTE;
|
|
25
|
+
return currentTime + bufferTime >= expirationTime;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get the remaining time until token expiry in minutes
|
|
29
|
+
* @param expiresAt - The expiration timestamp
|
|
30
|
+
* @returns Number of minutes until expiry
|
|
31
|
+
*/
|
|
32
|
+
export function getTimeUntilExpiry(expiresAt) {
|
|
33
|
+
const expirationTime = new Date(expiresAt).getTime();
|
|
34
|
+
const currentTime = Date.now();
|
|
35
|
+
const remainingTime = expirationTime - currentTime;
|
|
36
|
+
if (remainingTime <= 0) {
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
return Math.floor(remainingTime / MILLISECONDS_PER_MINUTE);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Format the time until expiry in a human-readable format
|
|
43
|
+
* @param expiresAt - The expiration timestamp
|
|
44
|
+
* @returns Formatted time string
|
|
45
|
+
*/
|
|
46
|
+
export function formatTimeUntilExpiry(expiresAt) {
|
|
47
|
+
const minutesRemaining = getTimeUntilExpiry(expiresAt);
|
|
48
|
+
if (minutesRemaining <= 0) {
|
|
49
|
+
return TIME_LABEL_EXPIRED;
|
|
50
|
+
}
|
|
51
|
+
if (minutesRemaining < MINUTES_PER_HOUR) {
|
|
52
|
+
return minutesRemaining === 1 ? `1 ${TIME_LABEL_MINUTE}` : `${minutesRemaining} ${TIME_LABEL_MINUTES}`;
|
|
53
|
+
}
|
|
54
|
+
const hoursRemaining = Math.floor(minutesRemaining / MINUTES_PER_HOUR);
|
|
55
|
+
if (hoursRemaining < HOURS_PER_DAY) {
|
|
56
|
+
return hoursRemaining === 1 ? `1 ${TIME_LABEL_HOUR}` : `${hoursRemaining} ${TIME_LABEL_HOURS}`;
|
|
57
|
+
}
|
|
58
|
+
const daysRemaining = Math.floor(hoursRemaining / HOURS_PER_DAY);
|
|
59
|
+
return daysRemaining === 1 ? `1 ${TIME_LABEL_DAY}` : `${daysRemaining} ${TIME_LABEL_DAYS}`;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Parse device information from user agent string
|
|
63
|
+
* @param userAgent - The user agent string
|
|
64
|
+
* @returns Parsed device info
|
|
65
|
+
*/
|
|
66
|
+
export function parseDeviceInfo(userAgent) {
|
|
67
|
+
const browser = userAgent.includes('Chrome')
|
|
68
|
+
? 'Chrome'
|
|
69
|
+
: userAgent.includes('Firefox')
|
|
70
|
+
? 'Firefox'
|
|
71
|
+
: userAgent.includes('Safari')
|
|
72
|
+
? 'Safari'
|
|
73
|
+
: userAgent.includes('Edge')
|
|
74
|
+
? 'Edge'
|
|
75
|
+
: DEFAULT_UNKNOWN_VALUE;
|
|
76
|
+
const os = userAgent.includes('Windows')
|
|
77
|
+
? 'Windows'
|
|
78
|
+
: userAgent.includes('Mac')
|
|
79
|
+
? 'macOS'
|
|
80
|
+
: userAgent.includes('Linux')
|
|
81
|
+
? 'Linux'
|
|
82
|
+
: userAgent.includes('Android')
|
|
83
|
+
? 'Android'
|
|
84
|
+
: userAgent.includes('iOS')
|
|
85
|
+
? 'iOS'
|
|
86
|
+
: DEFAULT_UNKNOWN_VALUE;
|
|
87
|
+
return { browser, os };
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Check if token refresh was successful
|
|
91
|
+
* @param response - The refresh response
|
|
92
|
+
* @returns true if refresh was successful, false otherwise
|
|
93
|
+
*/
|
|
94
|
+
export function isRefreshSuccess(response) {
|
|
95
|
+
return !!(response?.status === 200 && response?.data?.access && response?.data?.refresh);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Get error message from token refresh error
|
|
99
|
+
* @param error - The refresh error
|
|
100
|
+
* @returns Error message string
|
|
101
|
+
*/
|
|
102
|
+
export function getRefreshErrorMessage(error) {
|
|
103
|
+
if (error.response?.data?.detail) {
|
|
104
|
+
return error.response.data.detail;
|
|
105
|
+
}
|
|
106
|
+
if (error.response?.data?.message) {
|
|
107
|
+
return error.response.data.message;
|
|
108
|
+
}
|
|
109
|
+
if (error.message) {
|
|
110
|
+
return error.message;
|
|
111
|
+
}
|
|
112
|
+
return DEFAULT_ERROR_MESSAGE;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Create an auto-refresh handler for tokens
|
|
116
|
+
* @param refreshCallback - Callback function to refresh token
|
|
117
|
+
* @param checkInterval - Interval in milliseconds to check for refresh
|
|
118
|
+
* @returns Auto refresh handler with start/stop methods
|
|
119
|
+
*/
|
|
120
|
+
export function createAutoRefreshHandler(refreshCallback, checkInterval = 60000 // 1 minute
|
|
121
|
+
) {
|
|
122
|
+
let intervalId = null;
|
|
123
|
+
const start = () => {
|
|
124
|
+
if (intervalId)
|
|
125
|
+
return;
|
|
126
|
+
intervalId = setInterval(refreshCallback, checkInterval);
|
|
127
|
+
};
|
|
128
|
+
const stop = () => {
|
|
129
|
+
if (intervalId) {
|
|
130
|
+
clearInterval(intervalId);
|
|
131
|
+
intervalId = null;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
return { start, stop };
|
|
135
|
+
}
|
package/dist/filters.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filters.d.ts","sourceRoot":"","sources":["../src/filters.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChE,OAAO,EAAE,CAAC,EACV,aAAa,GAAE,CAAC,MAAM,CAAC,CAAC,EAA+B,GACtD,OAAO,CAOT;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,OAAO,EAAE,CAAC,EACV,aAAa,GAAE,CAAC,MAAM,CAAC,CAAC,EAA+B,GACtD,MAAM,CAOR;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/D,OAAO,EAAE,CAAC,EACV,cAAc,GAAE,CAAC,MAAM,CAAC,CAAC,EAAO,GAC/B,OAAO,CAAC,CAAC,CAAC,CAWZ;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAE1G;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAQrD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"filters.d.ts","sourceRoot":"","sources":["../src/filters.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChE,OAAO,EAAE,CAAC,EACV,aAAa,GAAE,CAAC,MAAM,CAAC,CAAC,EAA+B,GACtD,OAAO,CAOT;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,OAAO,EAAE,CAAC,EACV,aAAa,GAAE,CAAC,MAAM,CAAC,CAAC,EAA+B,GACtD,MAAM,CAOR;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/D,OAAO,EAAE,CAAC,EACV,cAAc,GAAE,CAAC,MAAM,CAAC,CAAC,EAAO,GAC/B,OAAO,CAAC,CAAC,CAAC,CAWZ;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAE1G;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAQrD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAW5F;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAE9G;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,OAAO,CAkBpG;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxG,OAAO,EAAE,CAAC,GACT,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAuBtB"}
|
package/dist/filters.js
CHANGED
|
@@ -31,7 +31,7 @@ export function countActiveFilters(filters, excludeFields = ['searchQuery']) {
|
|
|
31
31
|
export function clearAllFilters(filters, preserveFields = []) {
|
|
32
32
|
const clearedFilters = {};
|
|
33
33
|
// Preserve specified fields
|
|
34
|
-
preserveFields.forEach(
|
|
34
|
+
preserveFields.forEach(field => {
|
|
35
35
|
if (field in filters) {
|
|
36
36
|
clearedFilters[field] = filters[field];
|
|
37
37
|
}
|
|
@@ -66,7 +66,8 @@ export function isFilterEmpty(value) {
|
|
|
66
66
|
*/
|
|
67
67
|
export function removeEmptyFilters(filters) {
|
|
68
68
|
const cleanedFilters = {};
|
|
69
|
-
Object.
|
|
69
|
+
Object.keys(filters).forEach(key => {
|
|
70
|
+
const value = filters[key];
|
|
70
71
|
if (!isFilterEmpty(value)) {
|
|
71
72
|
cleanedFilters[key] = value;
|
|
72
73
|
}
|
|
@@ -94,7 +95,7 @@ export function areFiltersEqual(filters1, filters2) {
|
|
|
94
95
|
if (keys1.length !== keys2.length) {
|
|
95
96
|
return false;
|
|
96
97
|
}
|
|
97
|
-
return keys1.every(
|
|
98
|
+
return keys1.every(key => {
|
|
98
99
|
const value1 = filters1[key];
|
|
99
100
|
const value2 = filters2[key];
|
|
100
101
|
if (Array.isArray(value1) && Array.isArray(value2)) {
|
package/dist/index.d.ts
CHANGED
|
@@ -17,4 +17,8 @@ export { formatWithdrawalAmount, formatLiquidationValue, formatSharesQuantity, c
|
|
|
17
17
|
export type { PasswordValidation, EmailConfirmationValidation, ExtendedPasswordValidation } from './validation';
|
|
18
18
|
export { isNumericOnly, validatePassword, isValidTokenFormat, formatVerificationToken, validateEmailConfirmation, isValidEmail, hasUppercase, hasLowercase, hasSpecialCharacter, hasDigit, validatePasswordExtended, isValidPhoneNumber, isValidPhoneFormat, isValidUrl, isValidDate, isEmptyOrWhitespace, meetsMinLength, meetsMaxLength, isInRange, isPositiveNumber, isNonNegativeNumber, isValidFullName, isValidDateOfBirth, formatPhoneNumber, isValidInvestmentAmount, hasMinimumSelection, isSelected, } from './validation';
|
|
19
19
|
export { hasActiveFilters, countActiveFilters, clearAllFilters, updateFilters, isFilterEmpty, removeEmptyFilters, mergeFilters, areFiltersEqual, createFilterPredicate, } from './filters';
|
|
20
|
+
export type { DeviceInfo, TokenRefreshResponse, TokenRefreshError, AutoRefreshHandler } from './auth';
|
|
21
|
+
export { isTokenExpired, isTokenExpiringSoon, getTimeUntilExpiry, formatTimeUntilExpiry, parseDeviceInfo, isRefreshSuccess, getRefreshErrorMessage, createAutoRefreshHandler, } from './auth';
|
|
22
|
+
export type { InstrumentTypeInfo, InstrumentBasicInfo, PriceChangeResult, PriceSnapshot, FormattedPriceChange, TradeableInstrument, MarketDataInfo, } from './instruments';
|
|
23
|
+
export { formatInstrumentPrice, getCurrencySymbol, getInstrumentType, formatInstrumentName, calculatePriceChange, formatPriceChange, isInstrumentTradeable, formatMarketCap, formatVolume, hasMarketData, } from './instruments';
|
|
20
24
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAGjF,OAAO,EACL,8BAA8B,EAC9B,qCAAqC,EACrC,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACrB,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGnE,YAAY,EACV,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGhH,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,4BAA4B,EAC5B,sBAAsB,GACvB,MAAM,cAAc,CAAC;AAGtB,YAAY,EAAE,kBAAkB,EAAE,2BAA2B,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAChH,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,EACvB,yBAAyB,EACzB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,QAAQ,EACR,wBAAwB,EACxB,kBAAkB,EAClB,kBAAkB,EAClB,UAAU,EACV,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,mBAAmB,EACnB,UAAU,GACX,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,qBAAqB,GACtB,MAAM,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAGtC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAGjF,OAAO,EACL,8BAA8B,EAC9B,qCAAqC,EACrC,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,qBAAqB,EACrB,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGnE,YAAY,EACV,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAGhH,YAAY,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,4BAA4B,EAC5B,sBAAsB,GACvB,MAAM,cAAc,CAAC;AAGtB,YAAY,EAAE,kBAAkB,EAAE,2BAA2B,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAChH,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,EACvB,yBAAyB,EACzB,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,QAAQ,EACR,wBAAwB,EACxB,kBAAkB,EAClB,kBAAkB,EAClB,UAAU,EACV,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,uBAAuB,EACvB,mBAAmB,EACnB,UAAU,GACX,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,qBAAqB,GACtB,MAAM,WAAW,CAAC;AAGnB,YAAY,EAAE,UAAU,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AACtG,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,QAAQ,CAAC;AAGhB,YAAY,EACV,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,GACf,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,YAAY,EACZ,aAAa,GACd,MAAM,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -18,3 +18,5 @@ export { formatWithdrawalAmount, formatLiquidationValue, formatSharesQuantity, c
|
|
|
18
18
|
export { isNumericOnly, validatePassword, isValidTokenFormat, formatVerificationToken, validateEmailConfirmation, isValidEmail, hasUppercase, hasLowercase, hasSpecialCharacter, hasDigit, validatePasswordExtended, isValidPhoneNumber, isValidPhoneFormat, isValidUrl, isValidDate, isEmptyOrWhitespace, meetsMinLength, meetsMaxLength, isInRange, isPositiveNumber, isNonNegativeNumber, isValidFullName, isValidDateOfBirth, formatPhoneNumber, isValidInvestmentAmount, hasMinimumSelection, isSelected, } from './validation';
|
|
19
19
|
// Filter utilities
|
|
20
20
|
export { hasActiveFilters, countActiveFilters, clearAllFilters, updateFilters, isFilterEmpty, removeEmptyFilters, mergeFilters, areFiltersEqual, createFilterPredicate, } from './filters';
|
|
21
|
+
export { isTokenExpired, isTokenExpiringSoon, getTimeUntilExpiry, formatTimeUntilExpiry, parseDeviceInfo, isRefreshSuccess, getRefreshErrorMessage, createAutoRefreshHandler, } from './auth';
|
|
22
|
+
export { formatInstrumentPrice, getCurrencySymbol, getInstrumentType, formatInstrumentName, calculatePriceChange, formatPriceChange, isInstrumentTradeable, formatMarketCap, formatVolume, hasMarketData, } from './instruments';
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Instrument and market data formatting utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Format instrument price with currency symbol
|
|
6
|
+
* @param price - The price as string
|
|
7
|
+
* @param currency - The currency code
|
|
8
|
+
* @returns Formatted price with currency symbol
|
|
9
|
+
*/
|
|
10
|
+
export declare function formatInstrumentPrice(price: string, currency?: string | null): string;
|
|
11
|
+
/**
|
|
12
|
+
* Get currency symbol for display
|
|
13
|
+
* @param currency - The currency code
|
|
14
|
+
* @returns Currency symbol
|
|
15
|
+
*/
|
|
16
|
+
export declare function getCurrencySymbol(currency?: string | null): string;
|
|
17
|
+
/**
|
|
18
|
+
* Instrument interface for type determination
|
|
19
|
+
*/
|
|
20
|
+
export interface InstrumentTypeInfo {
|
|
21
|
+
isEtf?: boolean;
|
|
22
|
+
isFund?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Determine instrument type based on flags
|
|
26
|
+
* @param instrument - The instrument with type flags
|
|
27
|
+
* @returns Instrument type string
|
|
28
|
+
*/
|
|
29
|
+
export declare function getInstrumentType(instrument: InstrumentTypeInfo): string;
|
|
30
|
+
/**
|
|
31
|
+
* Basic instrument info for formatting
|
|
32
|
+
*/
|
|
33
|
+
export interface InstrumentBasicInfo {
|
|
34
|
+
symbol: string;
|
|
35
|
+
name: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Format instrument display name with symbol
|
|
39
|
+
* @param instrument - The instrument with symbol and name
|
|
40
|
+
* @returns Formatted display name
|
|
41
|
+
*/
|
|
42
|
+
export declare function formatInstrumentName(instrument: InstrumentBasicInfo): string;
|
|
43
|
+
/**
|
|
44
|
+
* Price change calculation result
|
|
45
|
+
*/
|
|
46
|
+
export interface PriceChangeResult {
|
|
47
|
+
change: number;
|
|
48
|
+
changePercent: number;
|
|
49
|
+
isPositive: boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Snapshot data for price change calculation
|
|
53
|
+
*/
|
|
54
|
+
export interface PriceSnapshot {
|
|
55
|
+
change: string;
|
|
56
|
+
changePercent: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Calculate price change from snapshot
|
|
60
|
+
* @param snapshot - The price snapshot
|
|
61
|
+
* @returns Price change calculation result
|
|
62
|
+
*/
|
|
63
|
+
export declare function calculatePriceChange(snapshot: PriceSnapshot): PriceChangeResult;
|
|
64
|
+
/**
|
|
65
|
+
* Formatted price change result
|
|
66
|
+
*/
|
|
67
|
+
export interface FormattedPriceChange {
|
|
68
|
+
changeText: string;
|
|
69
|
+
changePercentText: string;
|
|
70
|
+
colorClass: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Format price change with appropriate color class
|
|
74
|
+
* @param snapshot - The price snapshot
|
|
75
|
+
* @returns Formatted price change with color class
|
|
76
|
+
*/
|
|
77
|
+
export declare function formatPriceChange(snapshot: PriceSnapshot): FormattedPriceChange;
|
|
78
|
+
/**
|
|
79
|
+
* Tradeable instrument info
|
|
80
|
+
*/
|
|
81
|
+
export interface TradeableInstrument {
|
|
82
|
+
isActive: boolean;
|
|
83
|
+
isActivelyTrading: boolean;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Check if instrument is actively tradeable
|
|
87
|
+
* @param instrument - The instrument with trading flags
|
|
88
|
+
* @returns true if tradeable, false otherwise
|
|
89
|
+
*/
|
|
90
|
+
export declare function isInstrumentTradeable(instrument: TradeableInstrument): boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Format market cap value
|
|
93
|
+
* @param marketCap - The market cap value as string or null
|
|
94
|
+
* @returns Formatted market cap string
|
|
95
|
+
*/
|
|
96
|
+
export declare function formatMarketCap(marketCap: string | null | undefined): string;
|
|
97
|
+
/**
|
|
98
|
+
* Format trading volume
|
|
99
|
+
* @param volume - The volume number
|
|
100
|
+
* @returns Formatted volume string
|
|
101
|
+
*/
|
|
102
|
+
export declare function formatVolume(volume: number): string;
|
|
103
|
+
/**
|
|
104
|
+
* Market data availability info
|
|
105
|
+
*/
|
|
106
|
+
export interface MarketDataInfo {
|
|
107
|
+
openPrice?: string | null;
|
|
108
|
+
dayHigh?: string | null;
|
|
109
|
+
dayLow?: string | null;
|
|
110
|
+
volume?: number | null;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Check if market data is available
|
|
114
|
+
* @param marketData - The market data to check
|
|
115
|
+
* @returns true if market data is available, false otherwise
|
|
116
|
+
*/
|
|
117
|
+
export declare function hasMarketData(marketData: MarketDataInfo): boolean;
|
|
118
|
+
//# sourceMappingURL=instruments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instruments.d.ts","sourceRoot":"","sources":["../src/instruments.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAMrF;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAalE;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,kBAAkB,GAAG,MAAM,CAIxE;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,mBAAmB,GAAG,MAAM,CAE5E;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,aAAa,GAAG,iBAAiB,CAS/E;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,aAAa,GAAG,oBAAoB,CAY/E;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,mBAAmB,GAAG,OAAO,CAE9E;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAU5E;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,cAAc,GAAG,OAAO,CAEjE"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Instrument and market data formatting utilities
|
|
3
|
+
*/
|
|
4
|
+
import { INSTRUMENT_TYPE_ETF, INSTRUMENT_TYPE_FUND, INSTRUMENT_TYPE_STOCK, CURRENCY_USD, CURRENCY_AUD, } from '@cranberry-money/shared-constants';
|
|
5
|
+
/**
|
|
6
|
+
* Format instrument price with currency symbol
|
|
7
|
+
* @param price - The price as string
|
|
8
|
+
* @param currency - The currency code
|
|
9
|
+
* @returns Formatted price with currency symbol
|
|
10
|
+
*/
|
|
11
|
+
export function formatInstrumentPrice(price, currency) {
|
|
12
|
+
const numericPrice = parseFloat(price);
|
|
13
|
+
if (isNaN(numericPrice))
|
|
14
|
+
return price;
|
|
15
|
+
const currencySymbol = getCurrencySymbol(currency);
|
|
16
|
+
return `${currencySymbol}${numericPrice.toFixed(2)}`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Get currency symbol for display
|
|
20
|
+
* @param currency - The currency code
|
|
21
|
+
* @returns Currency symbol
|
|
22
|
+
*/
|
|
23
|
+
export function getCurrencySymbol(currency) {
|
|
24
|
+
switch (currency) {
|
|
25
|
+
case CURRENCY_USD:
|
|
26
|
+
return '$';
|
|
27
|
+
case CURRENCY_AUD:
|
|
28
|
+
return 'A$';
|
|
29
|
+
case 'EUR':
|
|
30
|
+
return '€';
|
|
31
|
+
case 'GBP':
|
|
32
|
+
return '£';
|
|
33
|
+
default:
|
|
34
|
+
return '$'; // Default to USD symbol
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Determine instrument type based on flags
|
|
39
|
+
* @param instrument - The instrument with type flags
|
|
40
|
+
* @returns Instrument type string
|
|
41
|
+
*/
|
|
42
|
+
export function getInstrumentType(instrument) {
|
|
43
|
+
if (instrument.isEtf)
|
|
44
|
+
return INSTRUMENT_TYPE_ETF;
|
|
45
|
+
if (instrument.isFund)
|
|
46
|
+
return INSTRUMENT_TYPE_FUND;
|
|
47
|
+
return INSTRUMENT_TYPE_STOCK;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Format instrument display name with symbol
|
|
51
|
+
* @param instrument - The instrument with symbol and name
|
|
52
|
+
* @returns Formatted display name
|
|
53
|
+
*/
|
|
54
|
+
export function formatInstrumentName(instrument) {
|
|
55
|
+
return `${instrument.symbol} - ${instrument.name}`;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Calculate price change from snapshot
|
|
59
|
+
* @param snapshot - The price snapshot
|
|
60
|
+
* @returns Price change calculation result
|
|
61
|
+
*/
|
|
62
|
+
export function calculatePriceChange(snapshot) {
|
|
63
|
+
const change = parseFloat(snapshot.change);
|
|
64
|
+
const changePercent = parseFloat(snapshot.changePercent);
|
|
65
|
+
return {
|
|
66
|
+
change,
|
|
67
|
+
changePercent,
|
|
68
|
+
isPositive: change >= 0,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Format price change with appropriate color class
|
|
73
|
+
* @param snapshot - The price snapshot
|
|
74
|
+
* @returns Formatted price change with color class
|
|
75
|
+
*/
|
|
76
|
+
export function formatPriceChange(snapshot) {
|
|
77
|
+
const { change, changePercent, isPositive } = calculatePriceChange(snapshot);
|
|
78
|
+
const changeText = `${isPositive ? '+' : ''}${change.toFixed(2)}`;
|
|
79
|
+
const changePercentText = `${isPositive ? '+' : ''}${changePercent.toFixed(2)}%`;
|
|
80
|
+
const colorClass = isPositive ? 'text-positive' : 'text-negative';
|
|
81
|
+
return {
|
|
82
|
+
changeText,
|
|
83
|
+
changePercentText,
|
|
84
|
+
colorClass,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check if instrument is actively tradeable
|
|
89
|
+
* @param instrument - The instrument with trading flags
|
|
90
|
+
* @returns true if tradeable, false otherwise
|
|
91
|
+
*/
|
|
92
|
+
export function isInstrumentTradeable(instrument) {
|
|
93
|
+
return instrument.isActive && instrument.isActivelyTrading;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Format market cap value
|
|
97
|
+
* @param marketCap - The market cap value as string or null
|
|
98
|
+
* @returns Formatted market cap string
|
|
99
|
+
*/
|
|
100
|
+
export function formatMarketCap(marketCap) {
|
|
101
|
+
if (!marketCap)
|
|
102
|
+
return 'N/A';
|
|
103
|
+
const marketCapValue = parseFloat(marketCap);
|
|
104
|
+
if (isNaN(marketCapValue))
|
|
105
|
+
return 'N/A';
|
|
106
|
+
if (marketCapValue >= 1e12)
|
|
107
|
+
return `$${(marketCapValue / 1e12).toFixed(1)}T`;
|
|
108
|
+
if (marketCapValue >= 1e9)
|
|
109
|
+
return `$${(marketCapValue / 1e9).toFixed(1)}B`;
|
|
110
|
+
if (marketCapValue >= 1e6)
|
|
111
|
+
return `$${(marketCapValue / 1e6).toFixed(1)}M`;
|
|
112
|
+
return `$${marketCapValue.toFixed(0)}`;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Format trading volume
|
|
116
|
+
* @param volume - The volume number
|
|
117
|
+
* @returns Formatted volume string
|
|
118
|
+
*/
|
|
119
|
+
export function formatVolume(volume) {
|
|
120
|
+
if (volume >= 1e9)
|
|
121
|
+
return `${(volume / 1e9).toFixed(1)}B`;
|
|
122
|
+
if (volume >= 1e6)
|
|
123
|
+
return `${(volume / 1e6).toFixed(1)}M`;
|
|
124
|
+
if (volume >= 1e3)
|
|
125
|
+
return `${(volume / 1e3).toFixed(1)}K`;
|
|
126
|
+
return volume.toString();
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Check if market data is available
|
|
130
|
+
* @param marketData - The market data to check
|
|
131
|
+
* @returns true if market data is available, false otherwise
|
|
132
|
+
*/
|
|
133
|
+
export function hasMarketData(marketData) {
|
|
134
|
+
return Boolean(marketData.openPrice || marketData.dayHigh || marketData.dayLow || marketData.volume);
|
|
135
|
+
}
|
package/dist/validation.js
CHANGED
|
@@ -85,7 +85,7 @@ export function hasLowercase(str) {
|
|
|
85
85
|
* @returns true if contains special character, false otherwise
|
|
86
86
|
*/
|
|
87
87
|
export function hasSpecialCharacter(str) {
|
|
88
|
-
return /[!@#$%^&*()_
|
|
88
|
+
return /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/.test(str);
|
|
89
89
|
}
|
|
90
90
|
/**
|
|
91
91
|
* Validates if a string contains at least one digit
|
|
@@ -118,7 +118,7 @@ export function validatePasswordExtended(password, minLength = 8) {
|
|
|
118
118
|
*/
|
|
119
119
|
export function isValidPhoneNumber(phoneNumber) {
|
|
120
120
|
// Remove common formatting characters
|
|
121
|
-
const cleaned = phoneNumber.replace(/[\s
|
|
121
|
+
const cleaned = phoneNumber.replace(/[\s\-().]/g, '');
|
|
122
122
|
// Check if it's a valid phone number (digits only, 10-15 digits)
|
|
123
123
|
return /^\+?\d{10,15}$/.test(cleaned);
|
|
124
124
|
}
|
|
@@ -217,7 +217,7 @@ export function isNonNegativeNumber(value) {
|
|
|
217
217
|
export function isValidFullName(fullName, minParts = 2) {
|
|
218
218
|
const trimmedName = fullName.trim();
|
|
219
219
|
const nameParts = trimmedName.split(/\s+/);
|
|
220
|
-
return nameParts.length >= minParts && nameParts.every(
|
|
220
|
+
return nameParts.length >= minParts && nameParts.every(part => part.length > 0);
|
|
221
221
|
}
|
|
222
222
|
/**
|
|
223
223
|
* Validates if a date is a valid date of birth (not in future, reasonable age range)
|