@cranberry-money/shared-utils 8.6.0 → 8.7.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/index.d.ts CHANGED
@@ -25,4 +25,5 @@ export { processAllocationData, calculateTotals, formatPercentage, formatDashboa
25
25
  export { isValidTemplateSelection, validatePortfolioSelection, type PortfolioSelectionValidation, type PortfolioSelectionState, } from './portfolio-validation';
26
26
  export { getStatusColor, getStatusLabel, getWithdrawalTypeLabel, getReasonLabel, getLiquidationStatusColor, getLiquidationStatusLabel, type WithdrawalStatus, type WithdrawalType, type WithdrawalReason, type LiquidationStatus, } from './withdrawal-status';
27
27
  export { findPrimaryTaxResidency, filterTaxResidenciesByCountry, hasTaxResidencyInCountry, getNonExemptedTaxResidencies, type BaseTaxResidency, } from './tax-residency';
28
+ export { getCountriesFromExchanges, groupExchangesByCountry, findExchangeByShortName, sortExchangesByName, filterExchangesByCountry, type BaseCountry, type BaseStockExchange, type SortDirection, } from './stock-exchange';
28
29
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -50,3 +50,5 @@ export { isValidTemplateSelection, validatePortfolioSelection, } from './portfol
50
50
  export { getStatusColor, getStatusLabel, getWithdrawalTypeLabel, getReasonLabel, getLiquidationStatusColor, getLiquidationStatusLabel, } from './withdrawal-status';
51
51
  // Tax residency utilities
52
52
  export { findPrimaryTaxResidency, filterTaxResidenciesByCountry, hasTaxResidencyInCountry, getNonExemptedTaxResidencies, } from './tax-residency';
53
+ // Stock exchange utilities
54
+ export { getCountriesFromExchanges, groupExchangesByCountry, findExchangeByShortName, sortExchangesByName, filterExchangesByCountry, } from './stock-exchange';
@@ -0,0 +1,89 @@
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[];
89
+ //# sourceMappingURL=stock-exchange.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stock-exchange.d.ts","sourceRoot":"","sources":["../src/stock-exchange.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;CACvC;AAGD,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,CAAC;AAE3C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yBAAyB,GAAI,CAAC,SAAS,iBAAiB,EACnE,WAAW,SAAS,CAAC,EAAE,KACtB,WAAW,EAUb,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,uBAAuB,GAAI,CAAC,SAAS,iBAAiB,EACjE,WAAW,SAAS,CAAC,EAAE,KACtB,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,CAYpB,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,uBAAuB,GAAI,CAAC,SAAS,iBAAiB,EACjE,WAAW,SAAS,CAAC,EAAE,EACvB,WAAW,MAAM,KAChB,CAAC,GAAG,SAEN,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mBAAmB,GAAI,CAAC,SAAS,iBAAiB,EAC7D,WAAW,SAAS,CAAC,EAAE,EACvB,YAAW,aAAqB,KAC/B,CAAC,EAGH,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB,GAAI,CAAC,SAAS,iBAAiB,EAClE,WAAW,SAAS,CAAC,EAAE,EACvB,aAAa,MAAM,KAClB,CAAC,EAEH,CAAC"}
@@ -0,0 +1,101 @@
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
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cranberry-money/shared-utils",
3
- "version": "8.6.0",
3
+ "version": "8.7.0",
4
4
  "description": "Shared utility functions for MyPortfolio platform",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",