@cranberry-money/shared-utils 8.19.0 → 8.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +16 -9
  2. package/package.json +4 -2
  3. package/dist/allocations.d.ts +0 -18
  4. package/dist/allocations.d.ts.map +0 -1
  5. package/dist/allocations.js +0 -20
  6. package/dist/auth.d.ts +0 -54
  7. package/dist/auth.js +0 -135
  8. package/dist/badge-status.d.ts +0 -65
  9. package/dist/badge-status.d.ts.map +0 -1
  10. package/dist/badge-status.js +0 -170
  11. package/dist/badge.d.ts +0 -41
  12. package/dist/badge.d.ts.map +0 -1
  13. package/dist/badge.js +0 -72
  14. package/dist/cash-account.d.ts +0 -43
  15. package/dist/cash-account.d.ts.map +0 -1
  16. package/dist/cash-account.js +0 -52
  17. package/dist/collections.d.ts +0 -80
  18. package/dist/collections.js +0 -127
  19. package/dist/country.d.ts +0 -107
  20. package/dist/country.js +0 -116
  21. package/dist/currency.d.ts +0 -99
  22. package/dist/currency.d.ts.map +0 -1
  23. package/dist/currency.js +0 -128
  24. package/dist/dashboard.d.ts +0 -72
  25. package/dist/dashboard.d.ts.map +0 -1
  26. package/dist/dashboard.js +0 -121
  27. package/dist/date.d.ts +0 -64
  28. package/dist/date.d.ts.map +0 -1
  29. package/dist/date.js +0 -91
  30. package/dist/document.d.ts +0 -37
  31. package/dist/document.js +0 -57
  32. package/dist/downloads.d.ts +0 -12
  33. package/dist/downloads.d.ts.map +0 -1
  34. package/dist/downloads.js +0 -20
  35. package/dist/filters.d.ts +0 -82
  36. package/dist/filters.d.ts.map +0 -1
  37. package/dist/filters.js +0 -109
  38. package/dist/formatting.d.ts +0 -58
  39. package/dist/formatting.js +0 -81
  40. package/dist/holdings.d.ts +0 -16
  41. package/dist/holdings.d.ts.map +0 -1
  42. package/dist/holdings.js +0 -23
  43. package/dist/index.d.ts +0 -26
  44. package/dist/index.d.ts.map +0 -1
  45. package/dist/index.js +0 -46
  46. package/dist/industry.d.ts +0 -127
  47. package/dist/industry.js +0 -152
  48. package/dist/instruments.d.ts +0 -17
  49. package/dist/instruments.d.ts.map +0 -1
  50. package/dist/instruments.js +0 -36
  51. package/dist/investment-preference.d.ts +0 -24
  52. package/dist/investment-preference.js +0 -33
  53. package/dist/numbers.d.ts +0 -16
  54. package/dist/numbers.d.ts.map +0 -1
  55. package/dist/numbers.js +0 -27
  56. package/dist/portfolio-template.d.ts +0 -57
  57. package/dist/portfolio-template.d.ts.map +0 -1
  58. package/dist/portfolio-template.js +0 -61
  59. package/dist/portfolio-validation.d.ts +0 -35
  60. package/dist/portfolio-validation.d.ts.map +0 -1
  61. package/dist/portfolio-validation.js +0 -40
  62. package/dist/portfolio.d.ts +0 -68
  63. package/dist/portfolio.d.ts.map +0 -1
  64. package/dist/portfolio.js +0 -87
  65. package/dist/sector.d.ts +0 -123
  66. package/dist/sector.js +0 -134
  67. package/dist/stock-exchange.d.ts +0 -88
  68. package/dist/stock-exchange.js +0 -101
  69. package/dist/tax-residency.d.ts +0 -66
  70. package/dist/tax-residency.js +0 -70
  71. package/dist/text.d.ts +0 -22
  72. package/dist/text.d.ts.map +0 -1
  73. package/dist/text.js +0 -25
  74. package/dist/validation.d.ts +0 -93
  75. package/dist/validation.d.ts.map +0 -1
  76. package/dist/validation.js +0 -143
  77. package/dist/withdrawal-status.d.ts +0 -68
  78. package/dist/withdrawal-status.d.ts.map +0 -1
  79. package/dist/withdrawal-status.js +0 -127
  80. package/dist/withdrawal.d.ts +0 -48
  81. package/dist/withdrawal.d.ts.map +0 -1
  82. package/dist/withdrawal.js +0 -62
package/dist/portfolio.js DELETED
@@ -1,87 +0,0 @@
1
- /**
2
- * Portfolio calculation and formatting utilities
3
- *
4
- * This module provides pure functions for portfolio value calculations,
5
- * allocations, and formatting. All functions handle string or number inputs
6
- * for flexibility with API responses.
7
- */
8
- import { LOCALE_AUSTRALIA, DEFAULT_NUMERIC_ZERO, DEFAULT_EMPTY_STRING, CURRENCY_AUD, } from '@cranberry-money/shared-constants';
9
- import { NUMBER_FORMAT_OPTIONS_CURRENCY } from './currency';
10
- /**
11
- * Formats a portfolio value as currency with AUD
12
- *
13
- * @param value - Portfolio value as string or number
14
- * @returns Formatted currency string with AUD symbol
15
- *
16
- * @example
17
- * ```typescript
18
- * formatPortfolioValue(12345.67) // 'A$12,345.67'
19
- * formatPortfolioValue('12345.67') // 'A$12,345.67'
20
- * ```
21
- */
22
- export function formatPortfolioValue(value) {
23
- const numValue = typeof value === 'string' ? parseFloat(value) : value;
24
- return new Intl.NumberFormat(LOCALE_AUSTRALIA, {
25
- ...NUMBER_FORMAT_OPTIONS_CURRENCY,
26
- currency: CURRENCY_AUD,
27
- }).format(numValue);
28
- }
29
- /**
30
- * Calculates total portfolio value from market value and cash balance
31
- *
32
- * @param marketValue - Market value of holdings
33
- * @param cashBalance - Cash balance in portfolio
34
- * @returns Total portfolio value as number
35
- *
36
- * @example
37
- * ```typescript
38
- * calculateTotalValue(10000, 5000) // 15000
39
- * calculateTotalValue('10000', '5000') // 15000
40
- * calculateTotalValue('10000.50', 5000.25) // 15000.75
41
- * ```
42
- */
43
- export function calculateTotalValue(marketValue, cashBalance) {
44
- const market = typeof marketValue === 'string' ? parseFloat(marketValue || DEFAULT_EMPTY_STRING) : marketValue;
45
- const cash = typeof cashBalance === 'string' ? parseFloat(cashBalance || DEFAULT_EMPTY_STRING) : cashBalance;
46
- return market + cash;
47
- }
48
- /**
49
- * Calculates market allocation percentage in portfolio
50
- *
51
- * @param marketValue - Market value of holdings
52
- * @param totalValue - Total portfolio value
53
- * @returns Market allocation percentage (0-100)
54
- *
55
- * @example
56
- * ```typescript
57
- * getMarketAllocation(7500, 10000) // 75
58
- * getMarketAllocation('7500', '10000') // 75
59
- * getMarketAllocation(0, 10000) // 0
60
- * getMarketAllocation(100, 0) // 0 (prevents division by zero)
61
- * ```
62
- */
63
- export function getMarketAllocation(marketValue, totalValue) {
64
- const market = typeof marketValue === 'string' ? parseFloat(marketValue || DEFAULT_EMPTY_STRING) : marketValue;
65
- const total = typeof totalValue === 'string' ? parseFloat(totalValue || DEFAULT_EMPTY_STRING) : totalValue;
66
- return total > DEFAULT_NUMERIC_ZERO ? (market / total) * 100 : DEFAULT_NUMERIC_ZERO;
67
- }
68
- /**
69
- * Calculates cash allocation percentage in portfolio
70
- *
71
- * @param cashBalance - Cash balance in portfolio
72
- * @param totalValue - Total portfolio value
73
- * @returns Cash allocation percentage (0-100)
74
- *
75
- * @example
76
- * ```typescript
77
- * getCashAllocation(2500, 10000) // 25
78
- * getCashAllocation('2500', '10000') // 25
79
- * getCashAllocation(0, 10000) // 0
80
- * getCashAllocation(100, 0) // 0 (prevents division by zero)
81
- * ```
82
- */
83
- export function getCashAllocation(cashBalance, totalValue) {
84
- const cash = typeof cashBalance === 'string' ? parseFloat(cashBalance || DEFAULT_EMPTY_STRING) : cashBalance;
85
- const total = typeof totalValue === 'string' ? parseFloat(totalValue || DEFAULT_EMPTY_STRING) : totalValue;
86
- return total > DEFAULT_NUMERIC_ZERO ? (cash / total) * 100 : DEFAULT_NUMERIC_ZERO;
87
- }
package/dist/sector.d.ts DELETED
@@ -1,123 +0,0 @@
1
- export interface BaseSector {
2
- readonly uuid: string;
3
- readonly name: string;
4
- }
5
- export type { SortDirection } from './stock-exchange';
6
- /**
7
- * Sort sectors by name
8
- *
9
- * @param sectors - List of sectors
10
- * @param direction - Sort direction ('asc' or 'desc')
11
- * @returns New sorted array of sectors
12
- *
13
- * @example
14
- * const sectors = [
15
- * { uuid: '1', name: 'Technology' },
16
- * { uuid: '2', name: 'Healthcare' }
17
- * ];
18
- * sortSectorsByName(sectors); // returns [Healthcare, Technology]
19
- * sortSectorsByName(sectors, 'desc'); // returns [Technology, Healthcare]
20
- */
21
- export declare const sortSectorsByName: <T extends BaseSector>(sectors: readonly T[], direction?: "asc" | "desc") => T[];
22
- /**
23
- * Filter sectors by name (case-insensitive search)
24
- *
25
- * @param sectors - List of sectors
26
- * @param searchTerm - Search term to filter by
27
- * @returns Filtered array of sectors
28
- *
29
- * @example
30
- * const sectors = [
31
- * { uuid: '1', name: 'Technology' },
32
- * { uuid: '2', name: 'Healthcare' },
33
- * { uuid: '3', name: 'Financial Services' }
34
- * ];
35
- * filterSectorsByName(sectors, 'tech'); // returns [Technology]
36
- * filterSectorsByName(sectors, 'care'); // returns [Healthcare]
37
- */
38
- export declare const filterSectorsByName: <T extends BaseSector>(sectors: readonly T[], searchTerm: string) => T[];
39
- /**
40
- * Find sector by exact name match
41
- *
42
- * @param sectors - List of sectors
43
- * @param name - Exact name to search for
44
- * @returns The sector if found, undefined otherwise
45
- *
46
- * @example
47
- * const sectors = [
48
- * { uuid: '1', name: 'Technology' },
49
- * { uuid: '2', name: 'Healthcare' }
50
- * ];
51
- * findSectorByName(sectors, 'Technology'); // returns Technology sector
52
- * findSectorByName(sectors, 'Tech'); // returns undefined
53
- */
54
- export declare const findSectorByName: <T extends BaseSector>(sectors: readonly T[], name: string) => T | undefined;
55
- /**
56
- * Get sorted list of sector names
57
- *
58
- * @param sectors - List of sectors
59
- * @returns Sorted array of sector names
60
- *
61
- * @example
62
- * const sectors = [
63
- * { uuid: '1', name: 'Technology' },
64
- * { uuid: '2', name: 'Healthcare' },
65
- * { uuid: '3', name: 'Energy' }
66
- * ];
67
- * getSectorNames(sectors); // returns ['Energy', 'Healthcare', 'Technology']
68
- */
69
- export declare const getSectorNames: <T extends BaseSector>(sectors: readonly T[]) => string[];
70
- /**
71
- * Group sectors alphabetically by first letter
72
- *
73
- * @param sectors - List of sectors
74
- * @returns Object with first letters as keys and sectors as values
75
- *
76
- * @example
77
- * const sectors = [
78
- * { uuid: '1', name: 'Technology' },
79
- * { uuid: '2', name: 'Healthcare' },
80
- * { uuid: '3', name: 'Energy' },
81
- * { uuid: '4', name: 'Telecommunications' }
82
- * ];
83
- * groupSectorsAlphabetically(sectors);
84
- * // returns {
85
- * // 'E': [Energy],
86
- * // 'H': [Healthcare],
87
- * // 'T': [Technology, Telecommunications]
88
- * // }
89
- */
90
- export declare const groupSectorsAlphabetically: <T extends BaseSector>(sectors: readonly T[]) => Record<string, T[]>;
91
- /**
92
- * Check if a sector name exists in the list
93
- *
94
- * @param sectors - List of sectors
95
- * @param sectorName - Name to check for existence
96
- * @returns True if sector exists, false otherwise
97
- *
98
- * @example
99
- * const sectors = [
100
- * { uuid: '1', name: 'Technology' },
101
- * { uuid: '2', name: 'Healthcare' }
102
- * ];
103
- * sectorExists(sectors, 'Technology'); // returns true
104
- * sectorExists(sectors, 'Manufacturing'); // returns false
105
- */
106
- export declare const sectorExists: <T extends BaseSector>(sectors: readonly T[], sectorName: string) => boolean;
107
- /**
108
- * Get sectors by partial name match (fuzzy search)
109
- *
110
- * @param sectors - List of sectors
111
- * @param partialName - Partial name to search for
112
- * @returns Array of matching sectors
113
- *
114
- * @example
115
- * const sectors = [
116
- * { uuid: '1', name: 'Technology' },
117
- * { uuid: '2', name: 'Biotechnology' },
118
- * { uuid: '3', name: 'Healthcare Technology' }
119
- * ];
120
- * findSectorsByPartialName(sectors, 'tech');
121
- * // returns [Technology, Biotechnology, Healthcare Technology]
122
- */
123
- export declare const findSectorsByPartialName: <T extends BaseSector>(sectors: readonly T[], partialName: string) => T[];
package/dist/sector.js DELETED
@@ -1,134 +0,0 @@
1
- import { sortByStringField, filterByTextSearch, findByStringField, extractAndSortField, groupByFirstLetter, } from './collections';
2
- /**
3
- * Sort sectors by name
4
- *
5
- * @param sectors - List of sectors
6
- * @param direction - Sort direction ('asc' or 'desc')
7
- * @returns New sorted array of sectors
8
- *
9
- * @example
10
- * const sectors = [
11
- * { uuid: '1', name: 'Technology' },
12
- * { uuid: '2', name: 'Healthcare' }
13
- * ];
14
- * sortSectorsByName(sectors); // returns [Healthcare, Technology]
15
- * sortSectorsByName(sectors, 'desc'); // returns [Technology, Healthcare]
16
- */
17
- export const sortSectorsByName = (sectors, direction = 'asc') => {
18
- const sorted = sortByStringField([...sectors], 'name');
19
- return direction === 'asc' ? sorted : sorted.reverse();
20
- };
21
- /**
22
- * Filter sectors by name (case-insensitive search)
23
- *
24
- * @param sectors - List of sectors
25
- * @param searchTerm - Search term to filter by
26
- * @returns Filtered array of sectors
27
- *
28
- * @example
29
- * const sectors = [
30
- * { uuid: '1', name: 'Technology' },
31
- * { uuid: '2', name: 'Healthcare' },
32
- * { uuid: '3', name: 'Financial Services' }
33
- * ];
34
- * filterSectorsByName(sectors, 'tech'); // returns [Technology]
35
- * filterSectorsByName(sectors, 'care'); // returns [Healthcare]
36
- */
37
- export const filterSectorsByName = (sectors, searchTerm) => {
38
- return filterByTextSearch([...sectors], 'name', searchTerm);
39
- };
40
- /**
41
- * Find sector by exact name match
42
- *
43
- * @param sectors - List of sectors
44
- * @param name - Exact name to search for
45
- * @returns The sector if found, undefined otherwise
46
- *
47
- * @example
48
- * const sectors = [
49
- * { uuid: '1', name: 'Technology' },
50
- * { uuid: '2', name: 'Healthcare' }
51
- * ];
52
- * findSectorByName(sectors, 'Technology'); // returns Technology sector
53
- * findSectorByName(sectors, 'Tech'); // returns undefined
54
- */
55
- export const findSectorByName = (sectors, name) => {
56
- return findByStringField([...sectors], 'name', name);
57
- };
58
- /**
59
- * Get sorted list of sector names
60
- *
61
- * @param sectors - List of sectors
62
- * @returns Sorted array of sector names
63
- *
64
- * @example
65
- * const sectors = [
66
- * { uuid: '1', name: 'Technology' },
67
- * { uuid: '2', name: 'Healthcare' },
68
- * { uuid: '3', name: 'Energy' }
69
- * ];
70
- * getSectorNames(sectors); // returns ['Energy', 'Healthcare', 'Technology']
71
- */
72
- export const getSectorNames = (sectors) => {
73
- return extractAndSortField([...sectors], 'name');
74
- };
75
- /**
76
- * Group sectors alphabetically by first letter
77
- *
78
- * @param sectors - List of sectors
79
- * @returns Object with first letters as keys and sectors as values
80
- *
81
- * @example
82
- * const sectors = [
83
- * { uuid: '1', name: 'Technology' },
84
- * { uuid: '2', name: 'Healthcare' },
85
- * { uuid: '3', name: 'Energy' },
86
- * { uuid: '4', name: 'Telecommunications' }
87
- * ];
88
- * groupSectorsAlphabetically(sectors);
89
- * // returns {
90
- * // 'E': [Energy],
91
- * // 'H': [Healthcare],
92
- * // 'T': [Technology, Telecommunications]
93
- * // }
94
- */
95
- export const groupSectorsAlphabetically = (sectors) => {
96
- return groupByFirstLetter([...sectors], 'name');
97
- };
98
- /**
99
- * Check if a sector name exists in the list
100
- *
101
- * @param sectors - List of sectors
102
- * @param sectorName - Name to check for existence
103
- * @returns True if sector exists, false otherwise
104
- *
105
- * @example
106
- * const sectors = [
107
- * { uuid: '1', name: 'Technology' },
108
- * { uuid: '2', name: 'Healthcare' }
109
- * ];
110
- * sectorExists(sectors, 'Technology'); // returns true
111
- * sectorExists(sectors, 'Manufacturing'); // returns false
112
- */
113
- export const sectorExists = (sectors, sectorName) => {
114
- return findByStringField([...sectors], 'name', sectorName) !== undefined;
115
- };
116
- /**
117
- * Get sectors by partial name match (fuzzy search)
118
- *
119
- * @param sectors - List of sectors
120
- * @param partialName - Partial name to search for
121
- * @returns Array of matching sectors
122
- *
123
- * @example
124
- * const sectors = [
125
- * { uuid: '1', name: 'Technology' },
126
- * { uuid: '2', name: 'Biotechnology' },
127
- * { uuid: '3', name: 'Healthcare Technology' }
128
- * ];
129
- * findSectorsByPartialName(sectors, 'tech');
130
- * // returns [Technology, Biotechnology, Healthcare Technology]
131
- */
132
- export const findSectorsByPartialName = (sectors, partialName) => {
133
- return filterByTextSearch([...sectors], 'name', partialName);
134
- };
@@ -1,88 +0,0 @@
1
- export interface BaseCountry {
2
- readonly uuid: string;
3
- readonly code: string;
4
- readonly name?: string;
5
- }
6
- export interface BaseStockExchange {
7
- readonly uuid: string;
8
- readonly name: string;
9
- readonly shortName: string;
10
- readonly country?: BaseCountry | null;
11
- }
12
- export type SortDirection = 'asc' | 'desc';
13
- /**
14
- * Extract unique countries from stock exchanges
15
- *
16
- * @param exchanges - List of stock exchanges
17
- * @returns Array of unique countries
18
- *
19
- * @example
20
- * const exchanges = [
21
- * { uuid: '1', name: 'NYSE', shortName: 'NYSE', country: { uuid: 'us', code: 'US' } },
22
- * { uuid: '2', name: 'NASDAQ', shortName: 'NASDAQ', country: { uuid: 'us', code: 'US' } },
23
- * { uuid: '3', name: 'TSX', shortName: 'TSX', country: { uuid: 'ca', code: 'CA' } }
24
- * ];
25
- * getCountriesFromExchanges(exchanges); // returns [{ uuid: 'us', code: 'US' }, { uuid: 'ca', code: 'CA' }]
26
- */
27
- export declare const getCountriesFromExchanges: <T extends BaseStockExchange>(exchanges: readonly T[]) => BaseCountry[];
28
- /**
29
- * Group stock exchanges by country code
30
- *
31
- * @param exchanges - List of stock exchanges
32
- * @returns Object with country codes as keys and exchanges as values
33
- *
34
- * @example
35
- * const exchanges = [
36
- * { uuid: '1', name: 'NYSE', shortName: 'NYSE', country: { uuid: 'us', code: 'US' } },
37
- * { uuid: '2', name: 'TSX', shortName: 'TSX', country: { uuid: 'ca', code: 'CA' } }
38
- * ];
39
- * groupExchangesByCountry(exchanges);
40
- * // returns { 'US': [NYSE exchange], 'CA': [TSX exchange], 'Unknown': [] }
41
- */
42
- export declare const groupExchangesByCountry: <T extends BaseStockExchange>(exchanges: readonly T[]) => Record<string, T[]>;
43
- /**
44
- * Find stock exchange by short name
45
- *
46
- * @param exchanges - List of stock exchanges
47
- * @param shortName - Short name to search for
48
- * @returns The exchange if found, undefined otherwise
49
- *
50
- * @example
51
- * const exchanges = [
52
- * { uuid: '1', name: 'New York Stock Exchange', shortName: 'NYSE' },
53
- * { uuid: '2', name: 'NASDAQ', shortName: 'NASDAQ' }
54
- * ];
55
- * findExchangeByShortName(exchanges, 'NYSE'); // returns NYSE exchange
56
- */
57
- export declare const findExchangeByShortName: <T extends BaseStockExchange>(exchanges: readonly T[], shortName: string) => T | undefined;
58
- /**
59
- * Sort stock exchanges by name
60
- *
61
- * @param exchanges - List of stock exchanges
62
- * @param direction - Sort direction ('asc' or 'desc')
63
- * @returns New sorted array of exchanges
64
- *
65
- * @example
66
- * const exchanges = [
67
- * { uuid: '2', name: 'NASDAQ', shortName: 'NASDAQ' },
68
- * { uuid: '1', name: 'NYSE', shortName: 'NYSE' }
69
- * ];
70
- * sortExchangesByName(exchanges); // returns [NASDAQ, NYSE] (alphabetical)
71
- * sortExchangesByName(exchanges, 'desc'); // returns [NYSE, NASDAQ] (reverse)
72
- */
73
- export declare const sortExchangesByName: <T extends BaseStockExchange>(exchanges: readonly T[], direction?: SortDirection) => T[];
74
- /**
75
- * Filter stock exchanges by country code
76
- *
77
- * @param exchanges - List of stock exchanges
78
- * @param countryCode - Country code to filter by
79
- * @returns Array of exchanges in the specified country
80
- *
81
- * @example
82
- * const exchanges = [
83
- * { uuid: '1', name: 'NYSE', shortName: 'NYSE', country: { uuid: 'us', code: 'US' } },
84
- * { uuid: '2', name: 'TSX', shortName: 'TSX', country: { uuid: 'ca', code: 'CA' } }
85
- * ];
86
- * filterExchangesByCountry(exchanges, 'US'); // returns [NYSE exchange]
87
- */
88
- export declare const filterExchangesByCountry: <T extends BaseStockExchange>(exchanges: readonly T[], countryCode: string) => T[];
@@ -1,101 +0,0 @@
1
- import { sortByStringField, findByStringField } from './collections';
2
- /**
3
- * Extract unique countries from stock exchanges
4
- *
5
- * @param exchanges - List of stock exchanges
6
- * @returns Array of unique countries
7
- *
8
- * @example
9
- * const exchanges = [
10
- * { uuid: '1', name: 'NYSE', shortName: 'NYSE', country: { uuid: 'us', code: 'US' } },
11
- * { uuid: '2', name: 'NASDAQ', shortName: 'NASDAQ', country: { uuid: 'us', code: 'US' } },
12
- * { uuid: '3', name: 'TSX', shortName: 'TSX', country: { uuid: 'ca', code: 'CA' } }
13
- * ];
14
- * getCountriesFromExchanges(exchanges); // returns [{ uuid: 'us', code: 'US' }, { uuid: 'ca', code: 'CA' }]
15
- */
16
- export const getCountriesFromExchanges = (exchanges) => {
17
- const countriesMap = new Map();
18
- exchanges.forEach(exchange => {
19
- if (exchange.country) {
20
- countriesMap.set(exchange.country.uuid, exchange.country);
21
- }
22
- });
23
- return Array.from(countriesMap.values());
24
- };
25
- /**
26
- * Group stock exchanges by country code
27
- *
28
- * @param exchanges - List of stock exchanges
29
- * @returns Object with country codes as keys and exchanges as values
30
- *
31
- * @example
32
- * const exchanges = [
33
- * { uuid: '1', name: 'NYSE', shortName: 'NYSE', country: { uuid: 'us', code: 'US' } },
34
- * { uuid: '2', name: 'TSX', shortName: 'TSX', country: { uuid: 'ca', code: 'CA' } }
35
- * ];
36
- * groupExchangesByCountry(exchanges);
37
- * // returns { 'US': [NYSE exchange], 'CA': [TSX exchange], 'Unknown': [] }
38
- */
39
- export const groupExchangesByCountry = (exchanges) => {
40
- return exchanges.reduce((groups, exchange) => {
41
- const countryCode = exchange.country?.code || 'Unknown';
42
- if (!groups[countryCode]) {
43
- groups[countryCode] = [];
44
- }
45
- groups[countryCode].push(exchange);
46
- return groups;
47
- }, {});
48
- };
49
- /**
50
- * Find stock exchange by short name
51
- *
52
- * @param exchanges - List of stock exchanges
53
- * @param shortName - Short name to search for
54
- * @returns The exchange if found, undefined otherwise
55
- *
56
- * @example
57
- * const exchanges = [
58
- * { uuid: '1', name: 'New York Stock Exchange', shortName: 'NYSE' },
59
- * { uuid: '2', name: 'NASDAQ', shortName: 'NASDAQ' }
60
- * ];
61
- * findExchangeByShortName(exchanges, 'NYSE'); // returns NYSE exchange
62
- */
63
- export const findExchangeByShortName = (exchanges, shortName) => {
64
- return findByStringField([...exchanges], 'shortName', shortName);
65
- };
66
- /**
67
- * Sort stock exchanges by name
68
- *
69
- * @param exchanges - List of stock exchanges
70
- * @param direction - Sort direction ('asc' or 'desc')
71
- * @returns New sorted array of exchanges
72
- *
73
- * @example
74
- * const exchanges = [
75
- * { uuid: '2', name: 'NASDAQ', shortName: 'NASDAQ' },
76
- * { uuid: '1', name: 'NYSE', shortName: 'NYSE' }
77
- * ];
78
- * sortExchangesByName(exchanges); // returns [NASDAQ, NYSE] (alphabetical)
79
- * sortExchangesByName(exchanges, 'desc'); // returns [NYSE, NASDAQ] (reverse)
80
- */
81
- export const sortExchangesByName = (exchanges, direction = 'asc') => {
82
- const sorted = sortByStringField([...exchanges], 'name');
83
- return direction === 'asc' ? sorted : sorted.reverse();
84
- };
85
- /**
86
- * Filter stock exchanges by country code
87
- *
88
- * @param exchanges - List of stock exchanges
89
- * @param countryCode - Country code to filter by
90
- * @returns Array of exchanges in the specified country
91
- *
92
- * @example
93
- * const exchanges = [
94
- * { uuid: '1', name: 'NYSE', shortName: 'NYSE', country: { uuid: 'us', code: 'US' } },
95
- * { uuid: '2', name: 'TSX', shortName: 'TSX', country: { uuid: 'ca', code: 'CA' } }
96
- * ];
97
- * filterExchangesByCountry(exchanges, 'US'); // returns [NYSE exchange]
98
- */
99
- export const filterExchangesByCountry = (exchanges, countryCode) => {
100
- return exchanges.filter(exchange => exchange.country?.code === countryCode);
101
- };
@@ -1,66 +0,0 @@
1
- export interface BaseTaxResidency {
2
- readonly country: string;
3
- readonly isPrimary: boolean;
4
- readonly isExempted: boolean;
5
- }
6
- /**
7
- * Find the primary tax residency from a list
8
- *
9
- * @param taxResidencies - List of tax residencies
10
- * @returns The primary tax residency if found, undefined otherwise
11
- *
12
- * @example
13
- * const residencies = [
14
- * { country: 'US', isPrimary: false, isExempted: false },
15
- * { country: 'CA', isPrimary: true, isExempted: false }
16
- * ];
17
- * findPrimaryTaxResidency(residencies); // returns CA residency
18
- */
19
- export declare const findPrimaryTaxResidency: <T extends BaseTaxResidency>(taxResidencies: readonly T[]) => T | undefined;
20
- /**
21
- * Filter tax residencies by country code
22
- *
23
- * @param taxResidencies - List of tax residencies
24
- * @param countryCode - Country code to filter by
25
- * @returns List of tax residencies for the specified country
26
- *
27
- * @example
28
- * const residencies = [
29
- * { country: 'US', isPrimary: true, isExempted: false },
30
- * { country: 'US', isPrimary: false, isExempted: true },
31
- * { country: 'CA', isPrimary: false, isExempted: false }
32
- * ];
33
- * filterTaxResidenciesByCountry(residencies, 'US'); // returns 2 US residencies
34
- */
35
- export declare const filterTaxResidenciesByCountry: <T extends BaseTaxResidency>(taxResidencies: readonly T[], countryCode: string) => T[];
36
- /**
37
- * Check if user has tax residency in a specific country
38
- *
39
- * @param taxResidencies - List of tax residencies
40
- * @param countryCode - Country code to check
41
- * @returns True if user has residency in the country, false otherwise
42
- *
43
- * @example
44
- * const residencies = [
45
- * { country: 'US', isPrimary: true, isExempted: false },
46
- * { country: 'CA', isPrimary: false, isExempted: false }
47
- * ];
48
- * hasTaxResidencyInCountry(residencies, 'US'); // returns true
49
- * hasTaxResidencyInCountry(residencies, 'UK'); // returns false
50
- */
51
- export declare const hasTaxResidencyInCountry: <T extends BaseTaxResidency>(taxResidencies: readonly T[], countryCode: string) => boolean;
52
- /**
53
- * Get all non-exempted tax residencies
54
- *
55
- * @param taxResidencies - List of tax residencies
56
- * @returns List of non-exempted tax residencies
57
- *
58
- * @example
59
- * const residencies = [
60
- * { country: 'US', isPrimary: true, isExempted: false },
61
- * { country: 'CA', isPrimary: false, isExempted: true },
62
- * { country: 'UK', isPrimary: false, isExempted: false }
63
- * ];
64
- * getNonExemptedTaxResidencies(residencies); // returns US and UK residencies
65
- */
66
- export declare const getNonExemptedTaxResidencies: <T extends BaseTaxResidency>(taxResidencies: readonly T[]) => T[];
@@ -1,70 +0,0 @@
1
- import { findByField, hasItemWithFieldValue, filterByBooleanField } from './collections';
2
- /**
3
- * Find the primary tax residency from a list
4
- *
5
- * @param taxResidencies - List of tax residencies
6
- * @returns The primary tax residency if found, undefined otherwise
7
- *
8
- * @example
9
- * const residencies = [
10
- * { country: 'US', isPrimary: false, isExempted: false },
11
- * { country: 'CA', isPrimary: true, isExempted: false }
12
- * ];
13
- * findPrimaryTaxResidency(residencies); // returns CA residency
14
- */
15
- export const findPrimaryTaxResidency = (taxResidencies) => {
16
- return findByField([...taxResidencies], 'isPrimary', true);
17
- };
18
- /**
19
- * Filter tax residencies by country code
20
- *
21
- * @param taxResidencies - List of tax residencies
22
- * @param countryCode - Country code to filter by
23
- * @returns List of tax residencies for the specified country
24
- *
25
- * @example
26
- * const residencies = [
27
- * { country: 'US', isPrimary: true, isExempted: false },
28
- * { country: 'US', isPrimary: false, isExempted: true },
29
- * { country: 'CA', isPrimary: false, isExempted: false }
30
- * ];
31
- * filterTaxResidenciesByCountry(residencies, 'US'); // returns 2 US residencies
32
- */
33
- export const filterTaxResidenciesByCountry = (taxResidencies, countryCode) => {
34
- return taxResidencies.filter(residency => residency.country === countryCode);
35
- };
36
- /**
37
- * Check if user has tax residency in a specific country
38
- *
39
- * @param taxResidencies - List of tax residencies
40
- * @param countryCode - Country code to check
41
- * @returns True if user has residency in the country, false otherwise
42
- *
43
- * @example
44
- * const residencies = [
45
- * { country: 'US', isPrimary: true, isExempted: false },
46
- * { country: 'CA', isPrimary: false, isExempted: false }
47
- * ];
48
- * hasTaxResidencyInCountry(residencies, 'US'); // returns true
49
- * hasTaxResidencyInCountry(residencies, 'UK'); // returns false
50
- */
51
- export const hasTaxResidencyInCountry = (taxResidencies, countryCode) => {
52
- return hasItemWithFieldValue([...taxResidencies], 'country', countryCode);
53
- };
54
- /**
55
- * Get all non-exempted tax residencies
56
- *
57
- * @param taxResidencies - List of tax residencies
58
- * @returns List of non-exempted tax residencies
59
- *
60
- * @example
61
- * const residencies = [
62
- * { country: 'US', isPrimary: true, isExempted: false },
63
- * { country: 'CA', isPrimary: false, isExempted: true },
64
- * { country: 'UK', isPrimary: false, isExempted: false }
65
- * ];
66
- * getNonExemptedTaxResidencies(residencies); // returns US and UK residencies
67
- */
68
- export const getNonExemptedTaxResidencies = (taxResidencies) => {
69
- return filterByBooleanField([...taxResidencies], 'isExempted', false);
70
- };