@cranberry-money/shared-utils 4.8.0 → 4.9.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,65 @@
1
+ /**
2
+ * Shared utility functions for filter operations
3
+ * Generic, reusable filter functions for managing filter states
4
+ */
5
+ /**
6
+ * Checks if any filters are active
7
+ * @param filters - The filter object to check
8
+ * @param excludeFields - Fields to exclude from the active check (default: ['searchQuery'])
9
+ * @returns true if any filters are active, false otherwise
10
+ */
11
+ export declare function hasActiveFilters<T extends Record<string, unknown>>(filters: T, excludeFields?: (keyof T)[]): boolean;
12
+ /**
13
+ * Counts the number of active filters
14
+ * @param filters - The filter object to count
15
+ * @param excludeFields - Fields to exclude from the count (default: ['searchQuery'])
16
+ * @returns The number of active filters
17
+ */
18
+ export declare function countActiveFilters<T extends Record<string, unknown>>(filters: T, excludeFields?: (keyof T)[]): number;
19
+ /**
20
+ * Clears all filters except specified fields
21
+ * @param filters - The filter object to clear
22
+ * @param preserveFields - Fields to preserve when clearing (default: [])
23
+ * @returns A new filter object with cleared values
24
+ */
25
+ export declare function clearAllFilters<T extends Record<string, unknown>>(filters: T, preserveFields?: (keyof T)[]): Partial<T>;
26
+ /**
27
+ * Type-safe filter update helper
28
+ * @param currentFilters - The current filter state
29
+ * @param updates - The updates to apply
30
+ * @returns A new filter object with updates applied
31
+ */
32
+ export declare function updateFilters<T extends Record<string, unknown>>(currentFilters: T, updates: Partial<T>): T;
33
+ /**
34
+ * Checks if a filter value is empty
35
+ * @param value - The value to check
36
+ * @returns true if the value is empty, false otherwise
37
+ */
38
+ export declare function isFilterEmpty(value: unknown): boolean;
39
+ /**
40
+ * Removes empty filter values from an object
41
+ * @param filters - The filter object to clean
42
+ * @returns A new filter object with empty values removed
43
+ */
44
+ export declare function removeEmptyFilters<T extends Record<string, unknown>>(filters: T): Partial<T>;
45
+ /**
46
+ * Merges two filter objects, with the second object taking precedence
47
+ * @param baseFilters - The base filter object
48
+ * @param overrideFilters - The override filter object
49
+ * @returns A new merged filter object
50
+ */
51
+ export declare function mergeFilters<T extends Record<string, unknown>>(baseFilters: T, overrideFilters: Partial<T>): T;
52
+ /**
53
+ * Compares two filter objects for equality
54
+ * @param filters1 - The first filter object
55
+ * @param filters2 - The second filter object
56
+ * @returns true if the filters are equal, false otherwise
57
+ */
58
+ export declare function areFiltersEqual<T extends Record<string, unknown>>(filters1: T, filters2: T): boolean;
59
+ /**
60
+ * Creates a filter predicate function from a filter object
61
+ * @param filters - The filter object to create a predicate from
62
+ * @returns A predicate function that tests if an item matches the filters
63
+ */
64
+ export declare function createFilterPredicate<T extends Record<string, unknown>, U extends Record<string, unknown>>(filters: T): (item: U) => boolean;
65
+ //# sourceMappingURL=filters.d.ts.map
@@ -0,0 +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,CAU5F;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"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Shared utility functions for filter operations
3
+ * Generic, reusable filter functions for managing filter states
4
+ */
5
+ /**
6
+ * Checks if any filters are active
7
+ * @param filters - The filter object to check
8
+ * @param excludeFields - Fields to exclude from the active check (default: ['searchQuery'])
9
+ * @returns true if any filters are active, false otherwise
10
+ */
11
+ export function hasActiveFilters(filters, excludeFields = ['searchQuery']) {
12
+ const relevantEntries = Object.entries(filters).filter(([key]) => !excludeFields.includes(key));
13
+ return relevantEntries.some(([, value]) => value !== undefined && value !== null && value !== '' && !(Array.isArray(value) && value.length === 0));
14
+ }
15
+ /**
16
+ * Counts the number of active filters
17
+ * @param filters - The filter object to count
18
+ * @param excludeFields - Fields to exclude from the count (default: ['searchQuery'])
19
+ * @returns The number of active filters
20
+ */
21
+ export function countActiveFilters(filters, excludeFields = ['searchQuery']) {
22
+ const relevantEntries = Object.entries(filters).filter(([key]) => !excludeFields.includes(key));
23
+ return relevantEntries.filter(([, value]) => value !== undefined && value !== null && value !== '' && !(Array.isArray(value) && value.length === 0)).length;
24
+ }
25
+ /**
26
+ * Clears all filters except specified fields
27
+ * @param filters - The filter object to clear
28
+ * @param preserveFields - Fields to preserve when clearing (default: [])
29
+ * @returns A new filter object with cleared values
30
+ */
31
+ export function clearAllFilters(filters, preserveFields = []) {
32
+ const clearedFilters = {};
33
+ // Preserve specified fields
34
+ preserveFields.forEach((field) => {
35
+ if (field in filters) {
36
+ clearedFilters[field] = filters[field];
37
+ }
38
+ });
39
+ return clearedFilters;
40
+ }
41
+ /**
42
+ * Type-safe filter update helper
43
+ * @param currentFilters - The current filter state
44
+ * @param updates - The updates to apply
45
+ * @returns A new filter object with updates applied
46
+ */
47
+ export function updateFilters(currentFilters, updates) {
48
+ return { ...currentFilters, ...updates };
49
+ }
50
+ /**
51
+ * Checks if a filter value is empty
52
+ * @param value - The value to check
53
+ * @returns true if the value is empty, false otherwise
54
+ */
55
+ export function isFilterEmpty(value) {
56
+ return (value === undefined ||
57
+ value === null ||
58
+ value === '' ||
59
+ (Array.isArray(value) && value.length === 0) ||
60
+ (typeof value === 'object' && value !== null && Object.keys(value).length === 0));
61
+ }
62
+ /**
63
+ * Removes empty filter values from an object
64
+ * @param filters - The filter object to clean
65
+ * @returns A new filter object with empty values removed
66
+ */
67
+ export function removeEmptyFilters(filters) {
68
+ const cleanedFilters = {};
69
+ Object.entries(filters).forEach(([key, value]) => {
70
+ if (!isFilterEmpty(value)) {
71
+ cleanedFilters[key] = value;
72
+ }
73
+ });
74
+ return cleanedFilters;
75
+ }
76
+ /**
77
+ * Merges two filter objects, with the second object taking precedence
78
+ * @param baseFilters - The base filter object
79
+ * @param overrideFilters - The override filter object
80
+ * @returns A new merged filter object
81
+ */
82
+ export function mergeFilters(baseFilters, overrideFilters) {
83
+ return { ...baseFilters, ...overrideFilters };
84
+ }
85
+ /**
86
+ * Compares two filter objects for equality
87
+ * @param filters1 - The first filter object
88
+ * @param filters2 - The second filter object
89
+ * @returns true if the filters are equal, false otherwise
90
+ */
91
+ export function areFiltersEqual(filters1, filters2) {
92
+ const keys1 = Object.keys(filters1);
93
+ const keys2 = Object.keys(filters2);
94
+ if (keys1.length !== keys2.length) {
95
+ return false;
96
+ }
97
+ return keys1.every((key) => {
98
+ const value1 = filters1[key];
99
+ const value2 = filters2[key];
100
+ if (Array.isArray(value1) && Array.isArray(value2)) {
101
+ return value1.length === value2.length && value1.every((v, i) => v === value2[i]);
102
+ }
103
+ return value1 === value2;
104
+ });
105
+ }
106
+ /**
107
+ * Creates a filter predicate function from a filter object
108
+ * @param filters - The filter object to create a predicate from
109
+ * @returns A predicate function that tests if an item matches the filters
110
+ */
111
+ export function createFilterPredicate(filters) {
112
+ const activeFilters = removeEmptyFilters(filters);
113
+ const filterEntries = Object.entries(activeFilters);
114
+ if (filterEntries.length === 0) {
115
+ return () => true;
116
+ }
117
+ return (item) => {
118
+ return filterEntries.every(([key, filterValue]) => {
119
+ const itemValue = item[key];
120
+ if (Array.isArray(filterValue)) {
121
+ return filterValue.includes(itemValue);
122
+ }
123
+ if (typeof filterValue === 'string' && typeof itemValue === 'string') {
124
+ return itemValue.toLowerCase().includes(filterValue.toLowerCase());
125
+ }
126
+ return itemValue === filterValue;
127
+ });
128
+ };
129
+ }
package/dist/index.d.ts CHANGED
@@ -15,5 +15,6 @@ export { formatPortfolioValue, calculateTotalValue, getMarketAllocation, getCash
15
15
  export type { LiquidationProgress } from './withdrawal';
16
16
  export { formatWithdrawalAmount, formatLiquidationValue, formatSharesQuantity, calculateLiquidationProgress, getTotalEstimatedValue, } from './withdrawal';
17
17
  export type { PasswordValidation, EmailConfirmationValidation, ExtendedPasswordValidation } from './validation';
18
- export { isNumericOnly, validatePassword, isValidTokenFormat, formatVerificationToken, validateEmailConfirmation, isValidEmail, hasUppercase, hasLowercase, hasSpecialCharacter, hasDigit, validatePasswordExtended, isValidPhoneNumber, isValidUrl, isValidDate, isEmptyOrWhitespace, meetsMinLength, meetsMaxLength, isInRange, isPositiveNumber, isNonNegativeNumber, } from './validation';
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
+ export { hasActiveFilters, countActiveFilters, clearAllFilters, updateFilters, isFilterEmpty, removeEmptyFilters, mergeFilters, areFiltersEqual, createFilterPredicate, } from './filters';
19
20
  //# sourceMappingURL=index.d.ts.map
@@ -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,UAAU,EACV,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,SAAS,EACT,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,cAAc,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"}
package/dist/index.js CHANGED
@@ -15,4 +15,6 @@ export { getTradeStatusBadge, getWithdrawalStatusBadge, getLiquidationStatusBadg
15
15
  // Portfolio utilities
16
16
  export { formatPortfolioValue, calculateTotalValue, getMarketAllocation, getCashAllocation } from './portfolio';
17
17
  export { formatWithdrawalAmount, formatLiquidationValue, formatSharesQuantity, calculateLiquidationProgress, getTotalEstimatedValue, } from './withdrawal';
18
- export { isNumericOnly, validatePassword, isValidTokenFormat, formatVerificationToken, validateEmailConfirmation, isValidEmail, hasUppercase, hasLowercase, hasSpecialCharacter, hasDigit, validatePasswordExtended, isValidPhoneNumber, isValidUrl, isValidDate, isEmptyOrWhitespace, meetsMinLength, meetsMaxLength, isInRange, isPositiveNumber, isNonNegativeNumber, } from './validation';
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
+ // Filter utilities
20
+ export { hasActiveFilters, countActiveFilters, clearAllFilters, updateFilters, isFilterEmpty, removeEmptyFilters, mergeFilters, areFiltersEqual, createFilterPredicate, } from './filters';
@@ -101,6 +101,13 @@ export declare function validatePasswordExtended(password: string, minLength?: n
101
101
  * @returns true if phone number format is valid, false otherwise
102
102
  */
103
103
  export declare function isValidPhoneNumber(phoneNumber: string): boolean;
104
+ /**
105
+ * Validates if a phone number appears to be in a valid format (less strict)
106
+ * @param phoneNumber - The phone number to validate
107
+ * @param minLength - Minimum length for the phone number (default: 8)
108
+ * @returns true if phone number appears valid, false otherwise
109
+ */
110
+ export declare function isValidPhoneFormat(phoneNumber: string, minLength?: number): boolean;
104
111
  /**
105
112
  * Validates if a URL is in a valid format
106
113
  * @param url - The URL to validate
@@ -153,4 +160,46 @@ export declare function isPositiveNumber(value: number): boolean;
153
160
  * @returns true if value is a non-negative number, false otherwise
154
161
  */
155
162
  export declare function isNonNegativeNumber(value: number): boolean;
163
+ /**
164
+ * Validates if a full name contains at least first and last name
165
+ * @param fullName - The full name to validate
166
+ * @param minParts - Minimum number of name parts required (default: 2)
167
+ * @returns true if appears to contain required name parts, false otherwise
168
+ */
169
+ export declare function isValidFullName(fullName: string, minParts?: number): boolean;
170
+ /**
171
+ * Validates if a date is a valid date of birth (not in future, reasonable age range)
172
+ * @param dateOfBirth - The date string in YYYY-MM-DD format
173
+ * @param minAge - Minimum age requirement (default: 13)
174
+ * @param maxAge - Maximum reasonable age (default: 120)
175
+ * @returns true if valid date of birth, false otherwise
176
+ */
177
+ export declare function isValidDateOfBirth(dateOfBirth: string, minAge?: number, maxAge?: number): boolean;
178
+ /**
179
+ * Formats a phone number by removing extra spaces and standardizing format
180
+ * @param phoneNumber - The phone number to format
181
+ * @returns The formatted phone number
182
+ */
183
+ export declare function formatPhoneNumber(phoneNumber: string): string;
184
+ /**
185
+ * Validates if investment amount is within acceptable range
186
+ * @param amount - The investment amount to validate
187
+ * @param minAmount - Minimum investment amount (default: 100)
188
+ * @param maxAmount - Maximum investment amount (default: 10000000)
189
+ * @returns true if amount is within range, false otherwise
190
+ */
191
+ export declare function isValidInvestmentAmount(amount: number, minAmount?: number, maxAmount?: number): boolean;
192
+ /**
193
+ * Validates if at least minimum number of items are selected
194
+ * @param items - Array of selected items
195
+ * @param minItems - Minimum number of items required (default: 1)
196
+ * @returns true if minimum items are selected, false otherwise
197
+ */
198
+ export declare function hasMinimumSelection<T>(items: T[], minItems?: number): boolean;
199
+ /**
200
+ * Validates if a value is selected (not null, undefined, or empty string)
201
+ * @param value - The value to check
202
+ * @returns true if value is selected, false otherwise
203
+ */
204
+ export declare function isSelected(value: unknown): boolean;
156
205
  //# sourceMappingURL=validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,SAAI,GAAG,kBAAkB,CAKpF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAI,GAAG,OAAO,CAIxE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,SAAI,GAAG,2BAA2B,CAQnG;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAGnD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAE7C;AAED;;GAEG;AACH,MAAM,WAAW,0BAA2B,SAAQ,kBAAkB;IACpE,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,SAAI,GAAG,0BAA0B,CAUpG;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAK/D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO/C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAGvD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAEtE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAEtE;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAE1E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE1D"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../src/validation.ts"],"names":[],"mappings":"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"}
@@ -122,6 +122,17 @@ export function isValidPhoneNumber(phoneNumber) {
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
  }
125
+ /**
126
+ * Validates if a phone number appears to be in a valid format (less strict)
127
+ * @param phoneNumber - The phone number to validate
128
+ * @param minLength - Minimum length for the phone number (default: 8)
129
+ * @returns true if phone number appears valid, false otherwise
130
+ */
131
+ export function isValidPhoneFormat(phoneNumber, minLength = 8) {
132
+ const trimmedPhone = phoneNumber.trim();
133
+ // Basic validation: must contain digits and common phone number characters
134
+ return trimmedPhone.length >= minLength && /^[+\-\s\d()]+$/.test(trimmedPhone);
135
+ }
125
136
  /**
126
137
  * Validates if a URL is in a valid format
127
138
  * @param url - The URL to validate
@@ -197,3 +208,68 @@ export function isPositiveNumber(value) {
197
208
  export function isNonNegativeNumber(value) {
198
209
  return typeof value === 'number' && value >= 0 && isFinite(value);
199
210
  }
211
+ /**
212
+ * Validates if a full name contains at least first and last name
213
+ * @param fullName - The full name to validate
214
+ * @param minParts - Minimum number of name parts required (default: 2)
215
+ * @returns true if appears to contain required name parts, false otherwise
216
+ */
217
+ export function isValidFullName(fullName, minParts = 2) {
218
+ const trimmedName = fullName.trim();
219
+ const nameParts = trimmedName.split(/\s+/);
220
+ return nameParts.length >= minParts && nameParts.every((part) => part.length > 0);
221
+ }
222
+ /**
223
+ * Validates if a date is a valid date of birth (not in future, reasonable age range)
224
+ * @param dateOfBirth - The date string in YYYY-MM-DD format
225
+ * @param minAge - Minimum age requirement (default: 13)
226
+ * @param maxAge - Maximum reasonable age (default: 120)
227
+ * @returns true if valid date of birth, false otherwise
228
+ */
229
+ export function isValidDateOfBirth(dateOfBirth, minAge = 13, maxAge = 120) {
230
+ if (!dateOfBirth)
231
+ return false;
232
+ const birthDate = new Date(dateOfBirth);
233
+ const today = new Date();
234
+ const age = today.getFullYear() - birthDate.getFullYear();
235
+ const monthDiff = today.getMonth() - birthDate.getMonth();
236
+ const dayDiff = today.getDate() - birthDate.getDate();
237
+ // Adjust age if birthday hasn't occurred this year
238
+ const actualAge = monthDiff < 0 || (monthDiff === 0 && dayDiff < 0) ? age - 1 : age;
239
+ return actualAge >= minAge && actualAge <= maxAge && birthDate <= today;
240
+ }
241
+ /**
242
+ * Formats a phone number by removing extra spaces and standardizing format
243
+ * @param phoneNumber - The phone number to format
244
+ * @returns The formatted phone number
245
+ */
246
+ export function formatPhoneNumber(phoneNumber) {
247
+ return phoneNumber.trim();
248
+ }
249
+ /**
250
+ * Validates if investment amount is within acceptable range
251
+ * @param amount - The investment amount to validate
252
+ * @param minAmount - Minimum investment amount (default: 100)
253
+ * @param maxAmount - Maximum investment amount (default: 10000000)
254
+ * @returns true if amount is within range, false otherwise
255
+ */
256
+ export function isValidInvestmentAmount(amount, minAmount = 100, maxAmount = 10000000) {
257
+ return amount >= minAmount && amount <= maxAmount;
258
+ }
259
+ /**
260
+ * Validates if at least minimum number of items are selected
261
+ * @param items - Array of selected items
262
+ * @param minItems - Minimum number of items required (default: 1)
263
+ * @returns true if minimum items are selected, false otherwise
264
+ */
265
+ export function hasMinimumSelection(items, minItems = 1) {
266
+ return items && items.length >= minItems;
267
+ }
268
+ /**
269
+ * Validates if a value is selected (not null, undefined, or empty string)
270
+ * @param value - The value to check
271
+ * @returns true if value is selected, false otherwise
272
+ */
273
+ export function isSelected(value) {
274
+ return value !== null && value !== undefined && value !== '';
275
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cranberry-money/shared-utils",
3
- "version": "4.8.0",
3
+ "version": "4.9.0",
4
4
  "description": "Shared utility functions for MyPortfolio platform",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",