@cranberry-money/shared-utils 8.10.0 → 8.12.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.
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Base interface for country objects
3
+ */
4
+ export interface BaseCountry {
5
+ readonly name: string;
6
+ readonly code: string;
7
+ readonly uuid: string;
8
+ readonly isAvailable: boolean;
9
+ readonly dialCode?: string;
10
+ }
11
+ /**
12
+ * Sort countries by name
13
+ *
14
+ * @param countries - Array of countries to sort
15
+ * @returns Sorted array of countries
16
+ *
17
+ * @example
18
+ * const sorted = sortCountriesByName(countries);
19
+ */
20
+ export declare const sortCountriesByName: <T extends BaseCountry>(countries: readonly T[]) => T[];
21
+ /**
22
+ * Filter countries by name (case-insensitive search)
23
+ *
24
+ * @param countries - Array of countries to filter
25
+ * @param searchTerm - Search term to filter by
26
+ * @returns Filtered array of countries
27
+ *
28
+ * @example
29
+ * const filtered = filterCountriesByName(countries, 'united');
30
+ * // Returns countries with 'united' in the name
31
+ */
32
+ export declare const filterCountriesByName: <T extends BaseCountry>(countries: readonly T[], searchTerm: string) => T[];
33
+ /**
34
+ * Filter countries by availability
35
+ *
36
+ * @param countries - Array of countries to filter
37
+ * @returns Array of available countries
38
+ *
39
+ * @example
40
+ * const available = filterAvailableCountries(countries);
41
+ */
42
+ export declare const filterAvailableCountries: <T extends BaseCountry>(countries: readonly T[]) => T[];
43
+ /**
44
+ * Find country by exact name match
45
+ *
46
+ * @param countries - Array of countries to search
47
+ * @param name - Exact name to find
48
+ * @returns Found country or undefined
49
+ *
50
+ * @example
51
+ * const country = findCountryByName(countries, 'United States');
52
+ */
53
+ export declare const findCountryByName: <T extends BaseCountry>(countries: readonly T[], name: string) => T | undefined;
54
+ /**
55
+ * Find country by country code
56
+ *
57
+ * @param countries - Array of countries to search
58
+ * @param code - Country code to find (e.g., 'US', 'CA')
59
+ * @returns Found country or undefined
60
+ *
61
+ * @example
62
+ * const country = findCountryByCode(countries, 'US');
63
+ */
64
+ export declare const findCountryByCode: <T extends BaseCountry>(countries: readonly T[], code: string) => T | undefined;
65
+ /**
66
+ * Get sorted list of country names
67
+ *
68
+ * @param countries - Array of countries
69
+ * @returns Sorted array of country names
70
+ *
71
+ * @example
72
+ * const names = getCountryNames(countries);
73
+ * // ['Australia', 'Canada', 'United States', ...]
74
+ */
75
+ export declare const getCountryNames: <T extends BaseCountry>(countries: readonly T[]) => string[];
76
+ /**
77
+ * Group countries alphabetically by first letter
78
+ *
79
+ * @param countries - Array of countries to group
80
+ * @returns Record of countries grouped by first letter
81
+ *
82
+ * @example
83
+ * const grouped = groupCountriesAlphabetically(countries);
84
+ * // { 'A': [...], 'B': [...], 'C': [...], ... }
85
+ */
86
+ export declare const groupCountriesAlphabetically: <T extends BaseCountry>(countries: readonly T[]) => Record<string, T[]>;
87
+ /**
88
+ * Format country with dial code for display
89
+ *
90
+ * @param country - Country to format
91
+ * @returns Formatted string with country name and dial code
92
+ *
93
+ * @example
94
+ * formatCountryWithDialCode({ name: 'United States', dialCode: '+1', ... });
95
+ * // Returns 'United States (+1)'
96
+ */
97
+ export declare const formatCountryWithDialCode: <T extends BaseCountry>(country: T) => string;
98
+ /**
99
+ * Check if a country is available
100
+ *
101
+ * @param country - Country to check
102
+ * @returns True if country is available
103
+ *
104
+ * @example
105
+ * const available = isCountryAvailable(country);
106
+ */
107
+ export declare const isCountryAvailable: <T extends BaseCountry>(country: T) => boolean;
108
+ //# sourceMappingURL=country.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"country.d.ts","sourceRoot":"","sources":["../src/country.ts"],"names":[],"mappings":"AASA;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,GAAI,CAAC,SAAS,WAAW,EACvD,WAAW,SAAS,CAAC,EAAE,KACtB,CAAC,EAEH,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,qBAAqB,GAAI,CAAC,SAAS,WAAW,EACzD,WAAW,SAAS,CAAC,EAAE,EACvB,YAAY,MAAM,KACjB,CAAC,EAEH,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,GAAI,CAAC,SAAS,WAAW,EAC5D,WAAW,SAAS,CAAC,EAAE,KACtB,CAAC,EAEH,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,WAAW,EACrD,WAAW,SAAS,CAAC,EAAE,EACvB,MAAM,MAAM,KACX,CAAC,GAAG,SAEN,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,WAAW,EACrD,WAAW,SAAS,CAAC,EAAE,EACvB,MAAM,MAAM,KACX,CAAC,GAAG,SAEN,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,WAAW,EACnD,WAAW,SAAS,CAAC,EAAE,KACtB,MAAM,EAER,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,4BAA4B,GAAI,CAAC,SAAS,WAAW,EAChE,WAAW,SAAS,CAAC,EAAE,KACtB,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,CAEpB,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,GAAI,CAAC,SAAS,WAAW,EAC7D,SAAS,CAAC,KACT,MAEF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,GAAI,CAAC,SAAS,WAAW,EACtD,SAAS,CAAC,KACT,OAEF,CAAC"}
@@ -0,0 +1,116 @@
1
+ import { sortByStringField, filterByTextSearch, filterByBooleanField, findByStringField, extractAndSortField, groupByFirstLetter, } from './collections';
2
+ /**
3
+ * Sort countries by name
4
+ *
5
+ * @param countries - Array of countries to sort
6
+ * @returns Sorted array of countries
7
+ *
8
+ * @example
9
+ * const sorted = sortCountriesByName(countries);
10
+ */
11
+ export const sortCountriesByName = (countries) => {
12
+ return sortByStringField([...countries], 'name');
13
+ };
14
+ /**
15
+ * Filter countries by name (case-insensitive search)
16
+ *
17
+ * @param countries - Array of countries to filter
18
+ * @param searchTerm - Search term to filter by
19
+ * @returns Filtered array of countries
20
+ *
21
+ * @example
22
+ * const filtered = filterCountriesByName(countries, 'united');
23
+ * // Returns countries with 'united' in the name
24
+ */
25
+ export const filterCountriesByName = (countries, searchTerm) => {
26
+ return filterByTextSearch([...countries], 'name', searchTerm);
27
+ };
28
+ /**
29
+ * Filter countries by availability
30
+ *
31
+ * @param countries - Array of countries to filter
32
+ * @returns Array of available countries
33
+ *
34
+ * @example
35
+ * const available = filterAvailableCountries(countries);
36
+ */
37
+ export const filterAvailableCountries = (countries) => {
38
+ return filterByBooleanField([...countries], 'isAvailable', true);
39
+ };
40
+ /**
41
+ * Find country by exact name match
42
+ *
43
+ * @param countries - Array of countries to search
44
+ * @param name - Exact name to find
45
+ * @returns Found country or undefined
46
+ *
47
+ * @example
48
+ * const country = findCountryByName(countries, 'United States');
49
+ */
50
+ export const findCountryByName = (countries, name) => {
51
+ return findByStringField([...countries], 'name', name);
52
+ };
53
+ /**
54
+ * Find country by country code
55
+ *
56
+ * @param countries - Array of countries to search
57
+ * @param code - Country code to find (e.g., 'US', 'CA')
58
+ * @returns Found country or undefined
59
+ *
60
+ * @example
61
+ * const country = findCountryByCode(countries, 'US');
62
+ */
63
+ export const findCountryByCode = (countries, code) => {
64
+ return findByStringField([...countries], 'code', code);
65
+ };
66
+ /**
67
+ * Get sorted list of country names
68
+ *
69
+ * @param countries - Array of countries
70
+ * @returns Sorted array of country names
71
+ *
72
+ * @example
73
+ * const names = getCountryNames(countries);
74
+ * // ['Australia', 'Canada', 'United States', ...]
75
+ */
76
+ export const getCountryNames = (countries) => {
77
+ return extractAndSortField([...countries], 'name');
78
+ };
79
+ /**
80
+ * Group countries alphabetically by first letter
81
+ *
82
+ * @param countries - Array of countries to group
83
+ * @returns Record of countries grouped by first letter
84
+ *
85
+ * @example
86
+ * const grouped = groupCountriesAlphabetically(countries);
87
+ * // { 'A': [...], 'B': [...], 'C': [...], ... }
88
+ */
89
+ export const groupCountriesAlphabetically = (countries) => {
90
+ return groupByFirstLetter([...countries], 'name');
91
+ };
92
+ /**
93
+ * Format country with dial code for display
94
+ *
95
+ * @param country - Country to format
96
+ * @returns Formatted string with country name and dial code
97
+ *
98
+ * @example
99
+ * formatCountryWithDialCode({ name: 'United States', dialCode: '+1', ... });
100
+ * // Returns 'United States (+1)'
101
+ */
102
+ export const formatCountryWithDialCode = (country) => {
103
+ return country.dialCode ? `${country.name} (${country.dialCode})` : country.name;
104
+ };
105
+ /**
106
+ * Check if a country is available
107
+ *
108
+ * @param country - Country to check
109
+ * @returns True if country is available
110
+ *
111
+ * @example
112
+ * const available = isCountryAvailable(country);
113
+ */
114
+ export const isCountryAvailable = (country) => {
115
+ return country.isAvailable;
116
+ };
package/dist/index.d.ts CHANGED
@@ -29,4 +29,6 @@ export { getCountriesFromExchanges, groupExchangesByCountry, findExchangeByShort
29
29
  export { sortSectorsByName, filterSectorsByName, findSectorByName, getSectorNames, groupSectorsAlphabetically, sectorExists, findSectorsByPartialName, type BaseSector, } from './sector';
30
30
  export { generateDocumentFilename, formatDocumentType, formatDocumentStatus, } from './document';
31
31
  export { sortIndustriesByName, filterIndustriesByName, filterIndustriesBySector, findIndustryByName, getIndustryNames, groupIndustriesBySector, groupIndustriesAlphabetically, getIndustriesWithoutSector, getIndustriesWithSector, countIndustriesBySector, isIndustryInSector, type BaseIndustry, } from './industry';
32
+ export { sortCountriesByName, filterCountriesByName, filterAvailableCountries, findCountryByName, findCountryByCode, getCountryNames, groupCountriesAlphabetically, formatCountryWithDialCode, isCountryAvailable, type BaseCountry as BaseCountryType, } from './country';
33
+ export { calculateTotalAllocation, validateAllocationPercentages, formatRiskLevelDisplay, type BaseAllocation, } from './portfolio-template';
32
34
  //# 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":"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,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGnE,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,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,4BAA4B,EAC5B,sBAAsB,GACvB,MAAM,cAAc,CAAC;AAGtB,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,EAEV,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,EACf,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,qBAAqB,EAErB,0BAA0B,EAC1B,4BAA4B,EAC5B,qBAAqB,EACrB,uBAAuB,EACvB,2BAA2B,EAC3B,6BAA6B,EAC7B,2BAA2B,EAC3B,6BAA6B,GAC9B,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,kBAAkB,EAClB,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,QAAQ,CAAC;AAGhB,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;AAGvB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,2BAA2B,EAC3B,eAAe,EACf,eAAe,GAChB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,qBAAqB,EACrB,YAAY,EACZ,eAAe,EACf,eAAe,EACf,WAAW,EACX,YAAY,GACb,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,wBAAwB,EACxB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,EACf,WAAW,GACZ,MAAM,WAAW,CAAC;AAGnB,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,EACL,uBAAuB,EACvB,2BAA2B,EAC3B,yBAAyB,EACzB,2BAA2B,EAC3B,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,qBAAqB,EACrB,eAAe,EACf,gBAAgB,EAChB,uBAAuB,EACvB,KAAK,qBAAqB,GAC3B,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,KAAK,4BAA4B,EACjC,KAAK,uBAAuB,GAC7B,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,cAAc,EACd,yBAAyB,EACzB,yBAAyB,EACzB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,GACvB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,uBAAuB,EACvB,6BAA6B,EAC7B,wBAAwB,EACxB,4BAA4B,EAC5B,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,yBAAyB,EACzB,uBAAuB,EACvB,uBAAuB,EACvB,mBAAmB,EACnB,wBAAwB,EACxB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,aAAa,GACnB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,0BAA0B,EAC1B,YAAY,EACZ,wBAAwB,EACxB,KAAK,UAAU,GAChB,MAAM,UAAU,CAAC;AAGlB,OAAO,EACL,wBAAwB,EACxB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,wBAAwB,EACxB,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,6BAA6B,EAC7B,0BAA0B,EAC1B,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,KAAK,YAAY,GAClB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,mBAAmB,EACnB,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,4BAA4B,EAC5B,yBAAyB,EACzB,kBAAkB,EAClB,KAAK,WAAW,IAAI,eAAe,GACpC,MAAM,WAAW,CAAC;AAGnB,OAAO,EACL,wBAAwB,EACxB,6BAA6B,EAC7B,sBAAsB,EACtB,KAAK,cAAc,GACpB,MAAM,sBAAsB,CAAC"}
package/dist/index.js CHANGED
@@ -58,3 +58,7 @@ export { sortSectorsByName, filterSectorsByName, findSectorByName, getSectorName
58
58
  export { generateDocumentFilename, formatDocumentType, formatDocumentStatus, } from './document';
59
59
  // Industry utilities
60
60
  export { sortIndustriesByName, filterIndustriesByName, filterIndustriesBySector, findIndustryByName, getIndustryNames, groupIndustriesBySector, groupIndustriesAlphabetically, getIndustriesWithoutSector, getIndustriesWithSector, countIndustriesBySector, isIndustryInSector, } from './industry';
61
+ // Country utilities
62
+ export { sortCountriesByName, filterCountriesByName, filterAvailableCountries, findCountryByName, findCountryByCode, getCountryNames, groupCountriesAlphabetically, formatCountryWithDialCode, isCountryAvailable, } from './country';
63
+ // Portfolio template utilities
64
+ export { calculateTotalAllocation, validateAllocationPercentages, formatRiskLevelDisplay, } from './portfolio-template';
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Base interface for allocation objects
3
+ */
4
+ export interface BaseAllocation {
5
+ readonly percentage: string;
6
+ }
7
+ /**
8
+ * Calculate total allocation from an array of allocations
9
+ *
10
+ * @param allocations - Array of allocation objects with percentage strings
11
+ * @returns Total allocation as a number
12
+ *
13
+ * @example
14
+ * const total = calculateTotalAllocation([
15
+ * { percentage: '50.5' },
16
+ * { percentage: '30.0' },
17
+ * { percentage: '19.5' }
18
+ * ]);
19
+ * // Returns 100.0
20
+ */
21
+ export declare const calculateTotalAllocation: <T extends BaseAllocation>(allocations: readonly T[]) => number;
22
+ /**
23
+ * Validate that allocation percentages sum to approximately 100%
24
+ *
25
+ * @param allocations - Array of allocation objects with percentage strings
26
+ * @param tolerance - Tolerance for percentage validation (default: 0.01)
27
+ * @returns True if allocations sum to approximately 100%
28
+ *
29
+ * @example
30
+ * const isValid = validateAllocationPercentages([
31
+ * { percentage: '50.0' },
32
+ * { percentage: '30.0' },
33
+ * { percentage: '20.0' }
34
+ * ]);
35
+ * // Returns true
36
+ *
37
+ * @example
38
+ * const isValid = validateAllocationPercentages([
39
+ * { percentage: '50.0' },
40
+ * { percentage: '30.0' },
41
+ * { percentage: '15.0' }
42
+ * ]);
43
+ * // Returns false (sums to 95%)
44
+ */
45
+ export declare const validateAllocationPercentages: <T extends BaseAllocation>(allocations: readonly T[], tolerance?: number) => boolean;
46
+ /**
47
+ * Format risk level for display (re-export from formatting utilities)
48
+ *
49
+ * @param riskLevel - Risk level string to format
50
+ * @returns Formatted risk level string
51
+ *
52
+ * @example
53
+ * formatRiskLevelDisplay('HIGH'); // returns 'High'
54
+ * formatRiskLevelDisplay('moderate'); // returns 'Moderate'
55
+ */
56
+ export declare const formatRiskLevelDisplay: (riskLevel: string) => string;
57
+ //# sourceMappingURL=portfolio-template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portfolio-template.d.ts","sourceRoot":"","sources":["../src/portfolio-template.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB,GAAI,CAAC,SAAS,cAAc,EAC/D,aAAa,SAAS,CAAC,EAAE,KACxB,MAIF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,6BAA6B,GAAI,CAAC,SAAS,cAAc,EACpE,aAAa,SAAS,CAAC,EAAE,EACzB,YAAW,MAAa,KACvB,OAGF,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,GAAI,WAAW,MAAM,KAAG,MAE1D,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { formatRiskLevel } from './formatting';
2
+ /**
3
+ * Calculate total allocation from an array of allocations
4
+ *
5
+ * @param allocations - Array of allocation objects with percentage strings
6
+ * @returns Total allocation as a number
7
+ *
8
+ * @example
9
+ * const total = calculateTotalAllocation([
10
+ * { percentage: '50.5' },
11
+ * { percentage: '30.0' },
12
+ * { percentage: '19.5' }
13
+ * ]);
14
+ * // Returns 100.0
15
+ */
16
+ export const calculateTotalAllocation = (allocations) => {
17
+ return allocations.reduce((total, allocation) => {
18
+ return total + parseFloat(allocation.percentage || '0');
19
+ }, 0);
20
+ };
21
+ /**
22
+ * Validate that allocation percentages sum to approximately 100%
23
+ *
24
+ * @param allocations - Array of allocation objects with percentage strings
25
+ * @param tolerance - Tolerance for percentage validation (default: 0.01)
26
+ * @returns True if allocations sum to approximately 100%
27
+ *
28
+ * @example
29
+ * const isValid = validateAllocationPercentages([
30
+ * { percentage: '50.0' },
31
+ * { percentage: '30.0' },
32
+ * { percentage: '20.0' }
33
+ * ]);
34
+ * // Returns true
35
+ *
36
+ * @example
37
+ * const isValid = validateAllocationPercentages([
38
+ * { percentage: '50.0' },
39
+ * { percentage: '30.0' },
40
+ * { percentage: '15.0' }
41
+ * ]);
42
+ * // Returns false (sums to 95%)
43
+ */
44
+ export const validateAllocationPercentages = (allocations, tolerance = 0.01) => {
45
+ const total = calculateTotalAllocation(allocations);
46
+ return Math.abs(total - 100) <= tolerance;
47
+ };
48
+ /**
49
+ * Format risk level for display (re-export from formatting utilities)
50
+ *
51
+ * @param riskLevel - Risk level string to format
52
+ * @returns Formatted risk level string
53
+ *
54
+ * @example
55
+ * formatRiskLevelDisplay('HIGH'); // returns 'High'
56
+ * formatRiskLevelDisplay('moderate'); // returns 'Moderate'
57
+ */
58
+ export const formatRiskLevelDisplay = (riskLevel) => {
59
+ return formatRiskLevel(riskLevel);
60
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cranberry-money/shared-utils",
3
- "version": "8.10.0",
3
+ "version": "8.12.0",
4
4
  "description": "Shared utility functions for MyPortfolio platform",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",