@akadenia/helpers 1.7.2 → 1.8.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/README.MD CHANGED
@@ -1,537 +1,1008 @@
1
- ## Getting Started
1
+ <div align="center">
2
+ <img src="https://cdn.akadenia.com/images/akadenia-webp/logo/horizontal-logo.svg" alt="Akadenia" width="200" />
2
3
 
4
+ ## @akadenia/helpers
5
+
6
+ <img src="https://cdn.akadenia.com/images/badges/npm-version-helpers.svg" alt="npm version" />
7
+ <img src="https://cdn.akadenia.com/images/badges/license-mit.svg" alt="License: MIT" />
8
+ <img src="https://cdn.akadenia.com/images/badges/typescript.svg" alt="TypeScript" />
9
+
10
+ A comprehensive collection of utility functions for common JavaScript/TypeScript operations including date manipulation, text processing, object handling, map calculations, and more.
11
+
12
+ [Documentation](https://akadenia.com/packages/akadenia-helpers) • [GitHub](https://github.com/akadenia/AkadeniaHelpers) • [Issues](https://github.com/akadenia/AkadeniaHelpers/issues)
13
+ </div>
14
+
15
+ ## Features
16
+
17
+ - **Date Helpers**: Comprehensive date manipulation and formatting utilities
18
+ - **Text Helpers**: String processing, validation, and transformation functions
19
+ - **Object Helpers**: Object manipulation, filtering, and utility functions
20
+ - **Map Helpers**: Geographical calculations and coordinate operations
21
+ - **Generic Helpers**: General utility functions for common operations
22
+ - **File Helpers**: File validation and processing utilities
23
+ - **TypeScript Support**: Full type definitions included
24
+ - **Zero Dependencies**: Lightweight with no external dependencies
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ npm install @akadenia/helpers
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ ```typescript
35
+ import { DateHelpers, TextHelpers, ObjectHelpers, MapHelpers, GenericHelpers, FileHelpers } from '@akadenia/helpers'
36
+ ```
37
+
38
+ ## Table of Contents
39
+
40
+ - [Installation](#installation)
41
+ - [Usage](#usage)
3
42
  - [DateHelpers](#datehelpers)
4
- - [`DateHelpers.getReadableDateTime(datetime)`](#datehelpersgetreadabledatetimedatetime)
5
- - [`DateHelpers.getReadableDate(datetime)`](#datehelpersgetreadabledatedatetime)
6
- - [`DateHelpers.getDateString(date)`](#datehelpersgetdatestringdate)
7
- - [`DateHelpers.parseDate(date)`](#datehelpersparsedatedate)
8
- - [`DateHelpers.getShortOrdinalDate(date)`](#datehelpersgetshortordinaldatedate)
9
- - [MapHelpers](#maphelpers)
10
- - [`MapHelpers.getDistanceBetweenPoints(point1, point2)`](#maphelpersgetdistancebetweenpointspoint1-point2)
11
- - [`MapHelpers.compareLocations(location1, location2, precision)`](#maphelperscomparelocationslocation1-location2-precision)
12
- - [`MapHelpers.getBearingToCoordinate({startCoordinate, endCoordinate})`](#maphelpersgetbearingtocoordinatestartcoordinate-endcoordinate)
13
43
  - [TextHelpers](#texthelpers)
14
- - [`TextHelpers.uuidv4()`](#texthelpersuuidv4)
15
- - [`TextHelpers.formatPosition(position)`](#texthelpersformatpositionposition)
16
- - [`TextHelpers.truncateText(text, characterLimit)`](#texthelperstruncatetexttext-characterlimit)
17
- - [`TextHelpers.fileNameFromPath(path)`](#texthelpersfilenamefrompathpath)
18
- - [`TextHelpers.replaceSpacesWithUnderscore(s)`](#texthelpersreplacespaceswithunderscores)
19
- - [`TextHelpers.replaceUnderscoreWithSpaces(s)`](#texthelpersreplaceunderscorewithspacess)
20
- - [`TextHelpers.pluralizeOnCondition(word, condition)`](#texthelperspluralizeonconditionword-condition)
21
- - [`TextHelpers.convertSnakeToCamelCase(data)`](#texthelpersconvertsnaketocamelcasedata)
22
- - [`TextHelpers.convertCamelToSnakeCase(data)`](#texthelpersconvertcameltosnakecasedata)
23
- - [`TextHelpers.convertCamelToKebabCase(data)`](#texthelpersconvertcameltokebabcasedata)
24
- - [`TextHelpers.convertKebabToCamelCase(data)`](#texthelpersconvertkebabtocamelcasedata)
25
- - [`TextHelpers.generateAcronym(term)`](#texthelpersgenerateacronymterm)
26
- - [`TextHelpers.isAcronym(data)`](#texthelpersisacronymdata)
27
- - [`TextHelpers.acronymToKebabCase(data)`](#texthelpersacronymtokebabcasedata)
28
- - [`TextHelpers.handleNullDisplay(value, defaultValue="N/A")`](#texthelpershandlenulldisplayvalue-defaultvaluena)
29
- - [`TextHelpers.enforceCharacterLimit({text, characterLimit, onCharacterLimit})`](#texthelpersenforcecharacterlimittext-characterlimit-oncharacterlimit)
30
- - [`TextHelpers.isValidEmail(email)`](#texthelpersisvalidemailemail)
31
- - [`TextHelpers.generateIdFromWord(word)`](#texthelpersgenerateidfromwordword)
32
- - [`TextHelpers.generateWordFromId(word)`](#texthelpersgeneratewordfromidword)
33
- - [`TextHelpers.generateSlugFromWords(id, ...words)`](#texthelpersgenerateslugfromwordsid-words)
34
- - [`TextHelpers.extractIDfromSlug(slug)`](#texthelpersextractidfromslugslug)
35
- - [`TextHelpers.abbreviateNumber(number)`](#texthelpersabbreviatenumbernumber)
36
44
  - [ObjectHelpers](#objecthelpers)
37
- - [`ObjectHelpers.isPureObject(any)`](#objecthelpersispureobjectany)
38
- - [`ObjectHelpers.parseCookie(str)`](#objecthelpersparsecookiestr)
39
- - [`ObjectHelpers.filterObjectsByProperty ( array, propertyName, propertyValue)`](#objecthelpersfilterobjectsbyproperty--array-propertyname-propertyvalue)
40
- - [`ObjectHelpers.containsSubObject(mainObject, subObject)`](#objecthelperscontainssubobjectmainobject-subobject)
41
- - [`ObjectHelpers.findObjectBySubObject(array, subObject)`](#objecthelpersfindobjectbysubobjectarray-subobject)
42
- - [`ObjectHelpers.filterObjectsBySubObject(array, subObject)`](#objecthelpersfilterobjectsbysubobjectarray-subobject)
43
- - [`ObjectHelpers.objectPropHasValue({object, key, value)}`](#objecthelpersobjectprophasvalueobject-key-value)
44
- - [`ObjectHelpers.findEntry(array, predicate)`](#objecthelpersfindentryarray-predicate)
45
+ - [MapHelpers](#maphelpers)
45
46
  - [GenericHelpers](#generichelpers)
46
- - [`GenericHelpers.delay(ms)`](#generichelpersdelayms)
47
- - [`GenericHelpers.getPreferredUriScheme(host)`](#generichelpersgetpreferredurischemehost)
48
47
  - [FileHelpers](#filehelpers)
49
- - [`FileHelpers.checkFileExtension(filePath, validExtensions)`](#filehelperscheckfileextensionfilepath-validextensions)
50
- - [Contributing to this package](#contributing-to-this-package)
48
+ - [Contributing](#contributing)
51
49
  - [License](#license)
52
50
 
53
- # DateHelpers
51
+ ## DateHelpers
54
52
 
55
- Import the DateHelpers utility.
53
+ Utility functions for date and time operations.
56
54
 
57
- `import { DateHelpers } from "@akadenia/helpers`
58
-
59
- ## `DateHelpers.getReadableDateTime(datetime)`
55
+ ### `getReadableDateTime(datetime?)`
60
56
 
61
57
  Returns the date in `yyyy-mm-dd hh:mm:ss` format.
62
58
 
63
- Arguments
64
- |Name|Type|Required|Description|
65
- |--|--|--|--|
66
- |`datetime`|`Date`|`false`|The date to convert to readable date time. Default is current datetime. i.e. `new Date()`|
59
+ **Parameters:**
60
+ - `datetime` (optional): `Date` - The date to convert. Defaults to current date.
67
61
 
68
- ## `DateHelpers.getReadableDate(datetime)`
62
+ **Example:**
63
+ ```typescript
64
+ import { DateHelpers } from '@akadenia/helpers'
65
+
66
+ // Using current date
67
+ const now = DateHelpers.getReadableDateTime()
68
+ console.log(now) // "2024-01-15 14:30:25"
69
+
70
+ // Using specific date
71
+ const specificDate = DateHelpers.getReadableDateTime(new Date('2024-01-15T10:30:00Z'))
72
+ console.log(specificDate) // "2024-01-15 10:30:00"
73
+ ```
74
+
75
+ ### `getReadableDate(datetime?)`
69
76
 
70
77
  Returns the date in `yyyy-mm-dd` format.
71
78
 
72
- Arguments
73
- |Name|Type|Required|Description|
74
- |--|--|--|--|
75
- |`datetime`|`Date`|`false`|The date to convert to readable date time. Default is current datetime. i.e. `new Date()`|
79
+ **Parameters:**
80
+ - `datetime` (optional): `Date` - The date to convert. Defaults to current date.
81
+
82
+ **Example:**
83
+ ```typescript
84
+ const date = DateHelpers.getReadableDate()
85
+ console.log(date) // "2024-01-15"
86
+
87
+ const specificDate = DateHelpers.getReadableDate(new Date('2024-01-15T10:30:00Z'))
88
+ console.log(specificDate) // "2024-01-15"
89
+ ```
76
90
 
77
- ## `DateHelpers.getDateString(date)`
91
+ ### `getDateString(date)`
78
92
 
79
93
  Returns a string representing the date in the user's local timezone.
80
94
 
81
- Arguments
82
- |Name|Type|Required|Description|
83
- |--|--|--|--|
84
- |`date`|`string` or `Date`|`true`|The date string to convert to the string in the user's local timezone|
95
+ **Parameters:**
96
+ - `date`: `string | Date` - The date to convert.
85
97
 
86
- ## `DateHelpers.parseDate(date)`
98
+ **Example:**
99
+ ```typescript
100
+ const dateString = DateHelpers.getDateString('2024-01-15')
101
+ console.log(dateString) // "1/15/2024" (format depends on locale)
87
102
 
88
- Returns a date representing the new date object.
103
+ const dateString2 = DateHelpers.getDateString(new Date('2024-01-15T10:30:00Z'))
104
+ console.log(dateString2) // "1/15/2024"
105
+ ```
106
+
107
+ ### `formatDateTime(date, options, localTimezone?)`
108
+
109
+ Returns a formatted date string using Intl.DateTimeFormat options.
110
+
111
+ **Parameters:**
112
+ - `date`: `string | Date` - The date to format.
113
+ - `options`: `Intl.DateTimeFormatOptions` - Formatting options.
114
+ - `localTimezone` (optional): `string | Intl.Locale` - Locale for formatting. Defaults to "en-US".
115
+
116
+ **Example:**
117
+ ```typescript
118
+ const formatted = DateHelpers.formatDateTime(
119
+ new Date('2024-01-15T10:30:00Z'),
120
+ {
121
+ year: 'numeric',
122
+ month: 'long',
123
+ day: 'numeric',
124
+ hour: '2-digit',
125
+ minute: '2-digit'
126
+ },
127
+ 'en-US'
128
+ )
129
+ console.log(formatted) // "January 15, 2024 at 10:30 AM"
130
+ ```
89
131
 
90
- Arguments
91
- |Name|Type|Required|Description|
92
- |--|--|--|--|
93
- |`date`|`string`|`true`|The date string that needs to be returned as a date object|
132
+ ### `parseDate(date)`
133
+
134
+ Returns a Date object from a string or Date input. Throws an error for invalid dates.
135
+
136
+ **Parameters:**
137
+ - `date`: `string | Date` - The date to parse.
138
+
139
+ **Example:**
140
+ ```typescript
141
+ const parsedDate = DateHelpers.parseDate('2024-01-15')
142
+ console.log(parsedDate) // Date object for 2024-01-15
143
+
144
+ const parsedDate2 = DateHelpers.parseDate('invalid-date')
145
+ // Throws: Error: Cannot parse date: "invalid-date"
146
+ ```
94
147
 
95
- ## `DateHelpers.getShortOrdinalDate(date)`
148
+ ### `getShortOrdinalDate(date, appendTime?)`
96
149
 
97
150
  Returns a string representing the date in short ordinal format.
98
151
 
99
- Arguments
100
- |Name|Type|Required|Description|
101
- |--|--|--|--|
102
- |`date`|`string`|`true`|The date string that needs to be formatted|
152
+ **Parameters:**
153
+ - `date`: `string | Date` - The date to format.
154
+ - `appendTime` (optional): `boolean` - Whether to include time. Defaults to false.
155
+
156
+ **Example:**
157
+ ```typescript
158
+ const ordinalDate = DateHelpers.getShortOrdinalDate('2024-01-15')
159
+ console.log(ordinalDate) // "Jan 15th 2024"
160
+
161
+ const ordinalDateTime = DateHelpers.getShortOrdinalDate('2024-01-15T10:30:00Z', true)
162
+ console.log(ordinalDateTime) // "Jan 15th 2024 10:30:00"
163
+ ```
164
+
165
+ ## MapHelpers
166
+
167
+ Utility functions for geographical calculations and map operations.
168
+
169
+ ### `getDistanceBetweenPoints(point1, point2)`
170
+
171
+ Calculates the distance between two geographical points using the Haversine formula.
172
+
173
+ **Parameters:**
174
+ - `point1`: `number[] | undefined` - First point coordinates [longitude, latitude].
175
+ - `point2`: `number[] | undefined` - Second point coordinates [longitude, latitude].
176
+
177
+ **Example:**
178
+ ```typescript
179
+ // Distance between New York and Los Angeles
180
+ const nyc = [-74.006, 40.7128] // [lng, lat]
181
+ const la = [-118.2437, 34.0522] // [lng, lat]
182
+
183
+ const distance = MapHelpers.getDistanceBetweenPoints(nyc, la)
184
+ console.log(distance) // 3944419.5 (meters, approximately 3944 km)
185
+
186
+ // Returns null for invalid points
187
+ const invalid = MapHelpers.getDistanceBetweenPoints(nyc, undefined)
188
+ console.log(invalid) // null
189
+ ```
190
+
191
+ ### `compareLocations(location1, location2, precision?)`
192
+
193
+ Compares two locations to see if they are the same within a specified precision.
194
+
195
+ **Parameters:**
196
+ - `location1`: `number[] | undefined` - First location coordinates [longitude, latitude].
197
+ - `location2`: `number[] | undefined` - Second location coordinates [longitude, latitude].
198
+ - `precision` (optional): `number` - Decimal precision for comparison. Defaults to 6.
199
+
200
+ **Example:**
201
+ ```typescript
202
+ const loc1 = [-74.006, 40.7128]
203
+ const loc2 = [-74.006001, 40.712801] // Very close to loc1
204
+ const loc3 = [-74.01, 40.72] // Further from loc1
205
+
206
+ console.log(MapHelpers.compareLocations(loc1, loc2)) // true (within 6 decimal precision)
207
+ console.log(MapHelpers.compareLocations(loc1, loc3)) // false
208
+ console.log(MapHelpers.compareLocations(loc1, loc2, 3)) // true (within 3 decimal precision)
209
+
210
+ // Throws error for undefined locations
211
+ MapHelpers.compareLocations(loc1, undefined) // Error: location1 and location2 are required
212
+ ```
213
+
214
+ ### `getBearingToCoordinate({startCoordinate, endCoordinate})`
215
+
216
+ Calculates the bearing (direction) from one coordinate to another in degrees.
217
+
218
+ **Parameters:**
219
+ - `startCoordinate`: `number[] | undefined` - Starting point [longitude, latitude].
220
+ - `endCoordinate`: `number[] | undefined` - Ending point [longitude, latitude].
221
+
222
+ **Example:**
223
+ ```typescript
224
+ const start = [-74.006, 40.7128] // New York
225
+ const end = [-118.2437, 34.0522] // Los Angeles
226
+
227
+ const bearing = MapHelpers.getBearingToCoordinate({ startCoordinate: start, endCoordinate: end })
228
+ console.log(bearing) // 277.5 (degrees, approximately west)
229
+
230
+ // Throws error for undefined coordinates
231
+ MapHelpers.getBearingToCoordinate({ startCoordinate: start, endCoordinate: undefined })
232
+ // Error: startCoordinate and endCoordinate are required
233
+ ```
234
+
235
+ ## TextHelpers
236
+
237
+ Utility functions for text manipulation and processing.
238
+
239
+ ### `uuidv4()`
240
+
241
+ Returns a randomly generated UUID v4 string.
242
+
243
+ **Example:**
244
+ ```typescript
245
+ const id = TextHelpers.uuidv4()
246
+ console.log(id) // "f47ac10b-58cc-4372-a567-0e02b2c3d479"
247
+ ```
248
+
249
+ ### `formatPosition(position)`
250
+
251
+ Returns a string position with appropriate suffix (st, nd, rd, th).
252
+
253
+ **Parameters:**
254
+ - `position`: `number` - The position number.
255
+
256
+ **Example:**
257
+ ```typescript
258
+ console.log(TextHelpers.formatPosition(1)) // "1st"
259
+ console.log(TextHelpers.formatPosition(2)) // "2nd"
260
+ console.log(TextHelpers.formatPosition(3)) // "3rd"
261
+ console.log(TextHelpers.formatPosition(4)) // "4th"
262
+ console.log(TextHelpers.formatPosition(21)) // "21st"
263
+ ```
264
+
265
+ ### `truncateText(text, characterLimit)`
266
+
267
+ Returns truncated text with ellipsis if it exceeds the character limit.
268
+
269
+ **Parameters:**
270
+ - `text`: `string` - The text to truncate.
271
+ - `characterLimit`: `number` - Maximum number of characters.
272
+
273
+ **Example:**
274
+ ```typescript
275
+ const short = TextHelpers.truncateText("Hello World", 5)
276
+ console.log(short) // "He..."
277
+
278
+ const long = TextHelpers.truncateText("Hello World", 20)
279
+ console.log(long) // "Hello World"
280
+ ```
281
+
282
+ ### `fileNameFromPath(path)`
283
+
284
+ Extracts the filename from a file path.
285
+
286
+ **Parameters:**
287
+ - `path`: `string` - The file path.
288
+
289
+ **Example:**
290
+ ```typescript
291
+ const filename = TextHelpers.fileNameFromPath('/path/to/file.txt')
292
+ console.log(filename) // "file.txt"
293
+
294
+ const filename2 = TextHelpers.fileNameFromPath('C:\\Users\\file.pdf')
295
+ console.log(filename2) // "file.pdf"
296
+ ```
297
+
298
+ ### `replaceSpacesWithUnderscore(s?)`
299
+
300
+ Replaces spaces with underscores in a string.
301
+
302
+ **Parameters:**
303
+ - `s` (optional): `string` - The string to process.
304
+
305
+ **Example:**
306
+ ```typescript
307
+ const result = TextHelpers.replaceSpacesWithUnderscore("hello world test")
308
+ console.log(result) // "hello_world_test"
309
+
310
+ const result2 = TextHelpers.replaceSpacesWithUnderscore()
311
+ console.log(result2) // ""
312
+ ```
313
+
314
+ ### `replaceUnderscoreWithSpaces(s?)`
103
315
 
104
- # MapHelpers
316
+ Replaces underscores with spaces in a string.
105
317
 
106
- Import the MapHelpers utility.
318
+ **Parameters:**
319
+ - `s` (optional): `string` - The string to process.
107
320
 
108
- `import { MapHelpers } from "@akadenia/helpers`
321
+ **Example:**
322
+ ```typescript
323
+ const result = TextHelpers.replaceUnderscoreWithSpaces("hello_world_test")
324
+ console.log(result) // "hello world test"
325
+ ```
109
326
 
110
- ## `MapHelpers.getDistanceBetweenPoints(point1, point2)`
327
+ ### `pluralizeOnCondition(word, condition)`
111
328
 
112
- Returns the distance between two points in meters. Returns `null` if either point is invalid.
329
+ Returns pluralized version of the word if condition is true.
113
330
 
114
- Arguments
115
- |Name|Type|Required|Description|
116
- |--|--|--|--|
117
- |`point1`|`Array<number>`|false| The coordinates of the first point. i.e. `[lat, lng]` |
118
- |`point2`|`Array<number>`|false|The coordinates of the second point. i.e. `[lat, lng]`|
331
+ **Parameters:**
332
+ - `word`: `string` - The word to pluralize.
333
+ - `condition`: `boolean` - Whether to pluralize.
119
334
 
120
- ## `MapHelpers.compareLocations(location1, location2, precision)`
335
+ **Example:**
336
+ ```typescript
337
+ const plural = TextHelpers.pluralizeOnCondition("item", true)
338
+ console.log(plural) // "items"
121
339
 
122
- Returns a boolean value that indicates whether or not the two locations are the same based on precision provided.
340
+ const plural2 = TextHelpers.pluralizeOnCondition("address", true)
341
+ console.log(plural2) // "addresses"
123
342
 
124
- Arguments
125
- |Name|Type|Required|Description|
126
- |--|--|--|--|
127
- |`location1`|`Array<number>`|false| The coordinates of the first location. i.e. `[lat, lng]` |
128
- |`location2`|`Array<number>`|false|The coordinates of the second location. i.e. `[lat, lng]`|
129
- |`precision`|`number`|false|The precision to compare the locations to. Default is `6`|
343
+ const plural3 = TextHelpers.pluralizeOnCondition("library", true)
344
+ console.log(plural3) // "libraries"
130
345
 
131
- ## `MapHelpers.getBearingToCoordinate({startCoordinate, endCoordinate})`
346
+ const singular = TextHelpers.pluralizeOnCondition("item", false)
347
+ console.log(singular) // "item"
348
+ ```
132
349
 
133
- Returns the bearing to the end coordinate from the start coordinate in degrees.
350
+ ### `convertSnakeToCamelCase(data)`
134
351
 
135
- Arguments
136
- |Name|Type|Required|Description|
137
- |--|--|--|--|
138
- |`coordinates`|`object`|`true`|An object containing the start and end coordinates. i.e. `{startCoordinate: [lat, lng], endCoordinate: [lat, lng]}`|
352
+ Converts snake_case to camelCase for strings, objects, or arrays of objects.
139
353
 
140
- # TextHelpers
354
+ **Parameters:**
355
+ - `data`: `string | Object | Array<Object>` - The data to convert.
141
356
 
142
- Import the TextHelpers utility.
357
+ **Example:**
358
+ ```typescript
359
+ // String conversion
360
+ const camelString = TextHelpers.convertSnakeToCamelCase("hello_world")
361
+ console.log(camelString) // "helloWorld"
362
+
363
+ // Object conversion
364
+ const camelObject = TextHelpers.convertSnakeToCamelCase({
365
+ first_name: "John",
366
+ last_name: "Doe",
367
+ user_info: {
368
+ phone_number: "123-456-7890"
369
+ }
370
+ })
371
+ console.log(camelObject)
372
+ // {
373
+ // firstName: "John",
374
+ // lastName: "Doe",
375
+ // userInfo: {
376
+ // phoneNumber: "123-456-7890"
377
+ // }
378
+ // }
379
+ ```
143
380
 
144
- `import { TextHelpers } from "@akadenia/helpers`
381
+ ### `convertCamelToSnakeCase(data)`
145
382
 
146
- ## `TextHelpers.uuidv4()`
383
+ Converts camelCase to snake_case for strings, objects, or arrays of objects.
147
384
 
148
- Returns a randomly generated string.
385
+ **Parameters:**
386
+ - `data`: `string | Object | Array<Object>` - The data to convert.
149
387
 
150
- Arguments
151
- |Name|Type|Required|Description|
152
- |--|--|--|--|
388
+ **Example:**
389
+ ```typescript
390
+ // String conversion
391
+ const snakeString = TextHelpers.convertCamelToSnakeCase("helloWorld")
392
+ console.log(snakeString) // "hello_world"
393
+
394
+ // Object conversion
395
+ const snakeObject = TextHelpers.convertCamelToSnakeCase({
396
+ firstName: "John",
397
+ lastName: "Doe",
398
+ userInfo: {
399
+ phoneNumber: "123-456-7890"
400
+ }
401
+ })
402
+ console.log(snakeObject)
403
+ // {
404
+ // first_name: "John",
405
+ // last_name: "Doe",
406
+ // user_info: {
407
+ // phone_number: "123-456-7890"
408
+ // }
409
+ // }
410
+ ```
153
411
 
154
- ## `TextHelpers.formatPosition(position)`
412
+ ### `convertCamelToKebabCase(word)`
155
413
 
156
- Returns a string position for a provided number. eg. `"2nd"`, `"3rd"` etc.
414
+ Converts camelCase to kebab-case.
157
415
 
158
- Arguments
159
- |Name|Type|Required|Description|
160
- |--|--|--|--|
161
- |`position`|`number`|`true`|A position number to add the appropriate suffix to|
416
+ **Parameters:**
417
+ - `word`: `string` - The word to convert.
162
418
 
163
- ## `TextHelpers.truncateText(text, characterLimit)`
419
+ **Example:**
420
+ ```typescript
421
+ const kebab = TextHelpers.convertCamelToKebabCase("helloWorld")
422
+ console.log(kebab) // "hello-world"
164
423
 
165
- Returns a string ending in an ellipsis `...` or returns the input string if maximum character limit isn't met.
424
+ const kebab2 = TextHelpers.convertCamelToKebabCase("XMLHttpRequest")
425
+ console.log(kebab2) // "xml-http-request"
426
+ ```
166
427
 
167
- Arguments
168
- |Name|Type|Required|Description|
169
- |--|--|--|--|
170
- |`text`|`string`|`true`|The text to truncate|
171
- |`characterLimit`|`number`|`true`|The target number of characters to truncate text to|
428
+ ### `convertKebabToCamelCase(word)`
172
429
 
173
- ## `TextHelpers.fileNameFromPath(path)`
430
+ Converts kebab-case to camelCase.
174
431
 
175
- Returns a file name.
432
+ **Parameters:**
433
+ - `word`: `string` - The word to convert.
176
434
 
177
- Arguments
178
- |Name|Type|Required|Description|
179
- |--|--|--|--|
180
- |`path`|`string`|`true`|The path to extract the file name from|
435
+ **Example:**
436
+ ```typescript
437
+ const camel = TextHelpers.convertKebabToCamelCase("hello-world")
438
+ console.log(camel) // "HelloWorld"
181
439
 
182
- ## `TextHelpers.replaceSpacesWithUnderscore(s)`
440
+ const camel2 = TextHelpers.convertKebabToCamelCase("xml-http-request")
441
+ console.log(camel2) // "XmlHttpRequest"
442
+ ```
183
443
 
184
- Returns a string where the spaces have been replaced with underscores.
444
+ ### `convertCamelCaseToReadableText(name)`
185
445
 
186
- Arguments
187
- |Name|Type|Required|Description|
188
- |--|--|--|--|
189
- |`s`|`string`|`false`|The text to replace spaces with underscores in|
446
+ Converts camelCase to readable text format with proper capitalization.
190
447
 
191
- ## `TextHelpers.replaceUnderscoreWithSpaces(s)`
448
+ **Parameters:**
192
449
 
193
- Returns a string where the underscores have been replaced with spaces.
450
+ - `name`: `string` - The camelCase string to convert.
194
451
 
195
- Arguments
196
- |Name|Type|Required|Description|
197
- |--|--|--|--|
198
- |`s`|`string`|`false`|The text to replace underscores with spaces in|
452
+ **Example:**
199
453
 
200
- ## `TextHelpers.pluralizeOnCondition(word, condition)`
454
+ ```typescript
455
+ const readable = TextHelpers.convertCamelCaseToReadableText("helloWorld")
456
+ console.log(readable) // "Hello World"
201
457
 
202
- Returns a pluralised version of the input string or returns the same string.
458
+ const readable2 = TextHelpers.convertCamelCaseToReadableText("XMLHttpRequest")
459
+ console.log(readable2) // "XML Http Request"
203
460
 
204
- Arguments
205
- |Name|Type|Required|Description|
206
- |--|--|--|--|
207
- |`word`|`string`|`true`|The word to pluralise|
208
- |`condition`|`boolean`|`true`|The condition that determines whether to plurize the input word|
461
+ const readable3 = TextHelpers.convertCamelCaseToReadableText("userName")
462
+ console.log(readable3) // "User Name"
463
+ ```
209
464
 
210
- ## `TextHelpers.convertSnakeToCamelCase(data)`
465
+ ### `generateAcronym(term)`
211
466
 
212
- Returns the input object or array with all object keys recursively transformed to camelCase. Returns input object if type is invalid.
467
+ Generates an acronym from a term.
213
468
 
214
- Arguments
215
- |Name|Type|Required|Description|
216
- |--|--|--|--|
217
- |`data`|`Object` or `Array<Object>`|`true`|The object whose keys to transform|
469
+ **Parameters:**
470
+ - `term`: `string` - The term to convert to acronym.
218
471
 
219
- ## `TextHelpers.convertCamelToSnakeCase(data)`
472
+ **Example:**
473
+ ```typescript
474
+ const acronym = TextHelpers.generateAcronym("Hyper Text Markup Language")
475
+ console.log(acronym) // "HTML"
220
476
 
221
- Returns the input object or array with all object keys recursively transformed to snake_case. Returns input object if type is invalid.
477
+ const acronym2 = TextHelpers.generateAcronym("JavaScript Object Notation")
478
+ console.log(acronym2) // "JSON"
479
+ ```
222
480
 
223
- Arguments
224
- |Name|Type|Required|Description|
225
- |--|--|--|--|
226
- |`data`|`Object` or `Array<Object>`|`true`|The object whose keys to transform|
481
+ ### `isAcronym(word)`
227
482
 
228
- ## `TextHelpers.convertCamelToKebabCase(data)`
483
+ Validates if a word is an acronym (all uppercase).
229
484
 
230
- Convert camel case to kebab case
231
- The word returned as kebab case
485
+ **Parameters:**
486
+ - `word`: `string` - The word to validate.
232
487
 
233
- Arguments
234
- |Name|Type|Required|Description|
235
- |--|--|--|--|
236
- |`data`|`string`|The word needed to be converted to kebab case from camel case|
488
+ **Example:**
489
+ ```typescript
490
+ console.log(TextHelpers.isAcronym("HTML")) // true
491
+ console.log(TextHelpers.isAcronym("html")) // false
492
+ console.log(TextHelpers.isAcronym("JavaScript")) // false
493
+ ```
237
494
 
238
- ## `TextHelpers.convertKebabToCamelCase(data)`
495
+ ### `acronymToKebabCase(word)`
239
496
 
240
- Convert kebab case to camel case
241
- The word returned as camel case
497
+ Converts an acronym to kebab-case.
242
498
 
243
- Arguments
244
- |Name|Type|Required|Description|
245
- |--|--|--|--|
246
- |`data`|`string`|The word needed to be converted from kebab case to camel case|
499
+ **Parameters:**
500
+ - `word`: `string` - The acronym to convert.
247
501
 
248
- ## `TextHelpers.generateAcronym(term)`
502
+ **Example:**
503
+ ```typescript
504
+ const kebab = TextHelpers.acronymToKebabCase("HTML")
505
+ console.log(kebab) // "h-t-m-l"
249
506
 
250
- Generate an acronym from a term
251
- an acronym generated from the term
507
+ const kebab2 = TextHelpers.acronymToKebabCase("API")
508
+ console.log(kebab2) // "a-p-i"
252
509
 
253
- Arguments
254
- |Name|Type|Required|Description|
255
- |--|--|--|--|
256
- |`term`|`string`|The term to be converted to an acronym|
510
+ // Throws error if not an acronym
511
+ TextHelpers.acronymToKebabCase("html") // Error: The text passed: html is not an acronym.
512
+ ```
257
513
 
258
- ## `TextHelpers.isAcronym(data)`
514
+ ### `handleNullDisplay(value, defaultValue?)`
259
515
 
260
- Validate if a word is acronym
261
- The boolean value when the condition is met
516
+ Returns the value or a default string if the value is null or undefined.
262
517
 
263
- Arguments
264
- |Name|Type|Required|Description|
265
- |--|--|--|--|
266
- |`data`|`string`|The word that is being validated as acronym|
518
+ **Parameters:**
519
+ - `value`: `string | null | undefined` - The value to display.
520
+ - `defaultValue` (optional): `string` - Default value. Defaults to "N/A".
267
521
 
268
- ## `TextHelpers.acronymToKebabCase(data)`
522
+ **Example:**
523
+ ```typescript
524
+ console.log(TextHelpers.handleNullDisplay("Hello")) // "Hello"
525
+ console.log(TextHelpers.handleNullDisplay(null)) // "N/A"
526
+ console.log(TextHelpers.handleNullDisplay(undefined)) // "N/A"
527
+ console.log(TextHelpers.handleNullDisplay(null, "No data")) // "No data"
528
+ ```
269
529
 
270
- Convert acronym to kebab case
271
- The word returned as camel case
530
+ ### `capitalizeText(text?)`
272
531
 
273
- Arguments
274
- |Name|Type|Required|Description|
275
- |--|--|--|--|
276
- |`data`|`string`|The acronym to be converted to kebab case|
532
+ Capitalizes the first letter of a text.
277
533
 
278
- ## `TextHelpers.handleNullDisplay(value, defaultValue="N/A")`
534
+ **Parameters:**
535
+ - `text` (optional): `string` - The text to capitalize.
279
536
 
280
- Returns the input string or the default string if the input value is null or undefined.
281
- Arguments
282
- |Name|Type|Required|Description|
283
- |--|--|--|--|
284
- |`value`|`string`|`true`|The string to display in the ui|
285
- |`defaultValue`|`string`|`false`|The default string to display if the input value is null or undefined defaults to `N/A`|
537
+ **Example:**
538
+ ```typescript
539
+ console.log(TextHelpers.capitalizeText("hello world")) // "Hello world"
540
+ console.log(TextHelpers.capitalizeText("HELLO")) // "Hello"
541
+ console.log(TextHelpers.capitalizeText()) // ""
542
+ ```
286
543
 
287
- ## `TextHelpers.enforceCharacterLimit({text, characterLimit, onCharacterLimit})`
544
+ ### `enforceCharacterLimit({text, characterLimit, onCharacterLimit})`
288
545
 
289
- Returns the input string if the character limit is not exceeded or returns the truncated string when the character limit is exceeded. Calls the `onCharacterLimit` callback when the character limit is exceeded.
290
- Arguments
291
- |Name|Type|Required|Description|
292
- |--|--|--|--|
293
- |`text`|`string`|`true`|The string to truncate|
294
- |`characterLimit`|`number`|`true`|The target number of characters to truncate text to|
295
- |`onCharacterLimit`|`function`|`true`|The callback to call when the character limit is exceeded|
546
+ Enforces a character limit and calls a callback when exceeded.
296
547
 
297
- ## `TextHelpers.isValidEmail(email)`
548
+ **Parameters:**
549
+ - `text`: `string` - The text to limit.
550
+ - `characterLimit`: `number` - Maximum characters allowed.
551
+ - `onCharacterLimit`: `() => void` - Callback when limit is exceeded.
298
552
 
299
- Returns true when the email is a proper email and returns false when the email is not a proper email
300
- Arguments
301
- |Name|Type|Required|Description|
302
- |--|--|--|--|
303
- |`email`|`string`|`true`|The email to be validated|
553
+ **Example:**
554
+ ```typescript
555
+ const result = TextHelpers.enforceCharacterLimit({
556
+ text: "This is a very long text that exceeds the limit",
557
+ characterLimit: 10,
558
+ onCharacterLimit: () => console.log("Character limit exceeded!")
559
+ })
560
+ console.log(result) // "This is a" (truncated)
561
+ // Console: "Character limit exceeded!"
562
+ ```
304
563
 
305
- ## `TextHelpers.generateIdFromWord(word)`
564
+ ### `isValidEmail(email)`
306
565
 
307
- Generate ID from word
308
- Returns the generated ID from the word
566
+ Validates if an email address is properly formatted.
309
567
 
310
- Arguments
311
- |Name|Type|Required|Description|
312
- |--|--|--|--|
313
- |`word`|`string`|`true`|The word needed to generate ID from|
568
+ **Parameters:**
569
+ - `email`: `string` - The email to validate.
314
570
 
315
- ## `TextHelpers.generateWordFromId(word)`
571
+ **Example:**
572
+ ```typescript
573
+ console.log(TextHelpers.isValidEmail("user@example.com")) // true
574
+ console.log(TextHelpers.isValidEmail("invalid-email")) // false
575
+ console.log(TextHelpers.isValidEmail("user@domain.co.uk")) // true
576
+ console.log(TextHelpers.isValidEmail("")) // false
577
+ ```
316
578
 
317
- Get the word from the generated ID
318
- Returns the word that is got from the id
579
+ ### `generateIDFromWord(text)`
319
580
 
320
- Arguments
321
- |Name|Type|Required|Description|
322
- |--|--|--|--|
323
- |`words`|`string`|`true`|The id that is needed to get the word from|
324
- |`customList`|`Record<string, string>`|`false`|The custom lists that has the id with the custom list of words|
581
+ Generates an ID from a word by converting to lowercase and replacing spaces with hyphens.
325
582
 
326
- ## `TextHelpers.generateSlugFromWords(id, ...words)`
583
+ **Parameters:**
584
+ - `text`: `string` - The text to convert to ID.
327
585
 
328
- Get the slug from words
329
- Returns the slug from the words and it will be url path safe
586
+ **Example:**
587
+ ```typescript
588
+ const id = TextHelpers.generateIDFromWord("Hello World Test")
589
+ console.log(id) // "hello-world-test"
330
590
 
331
- Arguments
332
- |Name|Type|Required|Description|
333
- |--|--|--|--|
334
- |`id`|`string`|`true`|The id that is needed to be concatenated with the slug|
335
- |`words`|`string[]`|`true`|The words that will be in the slug|
591
+ const id2 = TextHelpers.generateIDFromWord("My Awesome Feature")
592
+ console.log(id2) // "my-awesome-feature"
593
+ ```
336
594
 
337
- ## `TextHelpers.extractIDfromSlug(slug)`
595
+ ### `generateWordFromId(id, customList?)`
338
596
 
339
- Extracts the id from the slug
340
- Returns the id from the slug
341
- Throws error if the string is empty, null or undefined
597
+ Converts an ID back to a readable word format.
342
598
 
343
- Arguments
344
- |Name|Type|Required|Description|
345
- |--|--|--|--|
346
- |`slug`|`string`|`true`|The slug associated with the id|
599
+ **Parameters:**
600
+ - `id`: `string` - The ID to convert.
601
+ - `customList` (optional): `Record<string, string>` - Custom mapping for specific IDs.
347
602
 
348
- ## `TextHelpers.abbreviateNumber(number)`
603
+ **Example:**
604
+ ```typescript
605
+ const word = TextHelpers.generateWordFromId("hello-world-test")
606
+ console.log(word) // "Hello World Test"
349
607
 
350
- Returns the string representation of the abbreviated number, rounded to two decimal places.
608
+ const customWord = TextHelpers.generateWordFromId("api", { "api": "Application Programming Interface" })
609
+ console.log(customWord) // "Application Programming Interface"
610
+ ```
351
611
 
352
- Arguments
353
- |Name|Type|Required|Description|
354
- |--|--|--|--|
355
- |`number`|`number`|`true`|The number to be abbreviated|
612
+ ### `generateSlugFromWordsWithID(id, ...words)`
356
613
 
357
- Examples
358
- - Numbers below 1,000 are displayed without abbreviation
359
- - Numbers between 1,000 and 1,000,000 are displayed in thousands (e.g. 1.23K)
360
- - Numbers between 1,000,000 and 1,000,000,000 are displayed in millions (e.g. 1.23M)
361
- - Numbers above 1,000,000,000 are displayed in billions (e.g. 1.23B)
614
+ Generates a URL-safe slug from an ID and additional words.
362
615
 
363
- Note: If the input `number` is null or undefined, the function returns null.
616
+ **Parameters:**
617
+ - `id`: `string` - The ID to include in the slug.
618
+ - `...words`: `string[]` - Additional words to include.
364
619
 
365
- # ObjectHelpers
620
+ **Example:**
621
+ ```typescript
622
+ const slug = TextHelpers.generateSlugFromWordsWithID("user", "profile", "settings")
623
+ console.log(slug) // "profile-settings-user"
366
624
 
367
- Import the ObjectHelpers utility.
625
+ const slug2 = TextHelpers.generateSlugFromWordsWithID("123", "hello world", "test")
626
+ console.log(slug2) // "hello%20world-test-123"
627
+ ```
368
628
 
369
- `import { ObjectHelpers } from "@akadenia/helpers`
629
+ ### `extractIDfromSlug(slug)`
370
630
 
371
- ## `ObjectHelpers.isPureObject(any)`
631
+ Extracts the ID from a slug (last part after splitting by hyphens).
372
632
 
373
- Returns a boolean indicating whether or not the input is a pure object.
633
+ **Parameters:**
634
+ - `slug`: `string` - The slug to extract ID from.
374
635
 
375
- Arguments
376
- |Name|Type|Required|Description|
377
- |--|--|--|--|
378
- |`object`|`any`|`true`|The object to test for pureness|
636
+ **Example:**
637
+ ```typescript
638
+ const id = TextHelpers.extractIDfromSlug("hello-world-test-123")
639
+ console.log(id) // "123"
379
640
 
380
- ## `ObjectHelpers.parseCookie(str)`
641
+ const id2 = TextHelpers.extractIDfromSlug("user-profile-abc")
642
+ console.log(id2) // "abc"
381
643
 
382
- Returns an object containing the key-value pairs of the parsed cookies.
644
+ // Throws error for empty slug
645
+ TextHelpers.extractIDfromSlug("") // Error: slug cannot be empty, null or undefined string
646
+ ```
383
647
 
384
- Arguments
385
- |Name|Type|Required|Description|
386
- |--|--|--|--|
387
- |`str`|`string`|`true`|The string of cookies to parse|
648
+ ### `abbreviateNumber(number)`
388
649
 
389
- ## `ObjectHelpers.filterObjectsByProperty ( array, propertyName, propertyValue)`
650
+ Abbreviates large numbers with K, M, B suffixes.
390
651
 
391
- Filter an array of objects based on a specific property and its corresponding value.
392
- Returns an array containing all objects that have the specified property with the given value.
652
+ **Parameters:**
653
+ - `number`: `number | undefined | null` - The number to abbreviate.
393
654
 
394
- Template
655
+ **Example:**
395
656
  ```typescript
396
- T extends Record<string, any>
657
+ console.log(TextHelpers.abbreviateNumber(500)) // "500"
658
+ console.log(TextHelpers.abbreviateNumber(1500)) // "1.5K"
659
+ console.log(TextHelpers.abbreviateNumber(1500000)) // "1.5M"
660
+ console.log(TextHelpers.abbreviateNumber(1500000000)) // "1.5B"
661
+ console.log(TextHelpers.abbreviateNumber(null)) // null
397
662
  ```
398
- Arguments
399
- |Name|Type|Required|Description|
400
- |--|--|--|--|
401
- |`array`|`T[]`|`true`|An array of objects to be searched|
402
- |`propertyName`|`keyof T`|`true`|The name of the property to match against|
403
- |`propertyValue`|`T[keyof T]`|`true`|The value that the property should have to be considered|
404
663
 
405
- ## `ObjectHelpers.containsSubObject(mainObject, subObject)`
664
+ ## ObjectHelpers
665
+
666
+ Utility functions for object manipulation and processing.
406
667
 
407
- It compares the key-value pairs of the sub-object with the corresponding key-value pairs in the main object.
408
- Returns true If all key-value pairs in the sub-object are found in the main object; otherwise, it returns false.
668
+ ### `isPureObject(object)`
409
669
 
410
- Template
670
+ Checks if an object is a pure object (not array, date, or function).
671
+
672
+ **Parameters:**
673
+ - `object`: `any` - The object to check.
674
+
675
+ **Example:**
411
676
  ```typescript
412
- T extends Record<string, any>
677
+ console.log(ObjectHelpers.isPureObject({})) // true
678
+ console.log(ObjectHelpers.isPureObject([])) // false
679
+ console.log(ObjectHelpers.isPureObject(new Date())) // false
680
+ console.log(ObjectHelpers.isPureObject(() => {})) // false
681
+ console.log(ObjectHelpers.isPureObject("string")) // false
413
682
  ```
414
683
 
415
- Arguments
416
- |Name|Type|Required|Description|
417
- |--|--|--|--|
418
- |`mainObject`|`T`|`true`|The main object to be checked|
419
- |`subObject`|`Partial<T>`|`true`|The sub-object to be searched for|
684
+ ### `parseCookie(str)`
420
685
 
421
- ## `ObjectHelpers.findObjectBySubObject(array, subObject)`
686
+ Parses a cookie string into an object.
422
687
 
423
- Searches an array of objects for an object that contains a specific sub-object.
424
- Returns the first object found in the array that contains the sub-object or null
425
- if no match is found.
688
+ **Parameters:**
689
+ - `str`: `string` - The cookie string to parse.
426
690
 
427
- Template
691
+ **Example:**
428
692
  ```typescript
429
- T extends Record<string, any>
693
+ const cookies = ObjectHelpers.parseCookie("name=John; age=30; city=New York")
694
+ console.log(cookies) // { name: "John", age: "30", city: "New York" }
695
+
696
+ const cookies2 = ObjectHelpers.parseCookie("session=abc123; theme=dark")
697
+ console.log(cookies2) // { session: "abc123", theme: "dark" }
430
698
  ```
431
699
 
432
- Arguments
433
- |Name|Type|Required|Description|
434
- |--|--|--|--|
435
- |`array`|`T[]`|`true`|An array of objects to be searched|
436
- |`array`|`Partial<T>`|`true`|The sub-object to be searched for in the array|
700
+ ### `filterObjectsByProperty(array, propertyName, propertyValue)`
437
701
 
438
- ## `ObjectHelpers.filterObjectsBySubObject(array, subObject)`
702
+ Filters an array of objects based on a specific property and value.
439
703
 
440
- Filters an array of objects based on the presence of a specific sub-object within each object.
441
- Returns an array containing all objects from the input array that contain the specified sub-object.
704
+ **Parameters:**
705
+ - `array`: `T[]` - Array of objects to filter.
706
+ - `propertyName`: `keyof T` - Name of the property to filter on.
707
+ - `propertyValue`: `T[keyof T]` - Value to match.
442
708
 
443
- Template
709
+ **Example:**
444
710
  ```typescript
445
- T extends Record<string, any>
711
+ const users = [
712
+ { id: 1, name: "John", age: 30 },
713
+ { id: 2, name: "Jane", age: 25 },
714
+ { id: 3, name: "John", age: 35 }
715
+ ]
716
+
717
+ const johns = ObjectHelpers.filterObjectsByProperty(users, "name", "John")
718
+ console.log(johns) // [{ id: 1, name: "John", age: 30 }, { id: 3, name: "John", age: 35 }]
719
+
720
+ const adults = ObjectHelpers.filterObjectsByProperty(users, "age", 30)
721
+ console.log(adults) // [{ id: 1, name: "John", age: 30 }]
446
722
  ```
447
723
 
448
- Arguments
449
- |Name|Type|Required|Description|
450
- |--|--|--|--|
451
- |`array`|`T[]`|`true`|An array of objects to be filtered|
452
- |`array`|`Partial<T>`|`true`|The sub-object to be searched for in the array|
724
+ ### `containsSubObject(mainObject, subObject)`
453
725
 
454
- ## `ObjectHelpers.objectPropHasValue({object, key, value)}`
726
+ Checks if the main object contains all key-value pairs from the sub-object.
455
727
 
456
- Checks if the object has the key with the value.
728
+ **Parameters:**
729
+ - `mainObject`: `T` - The main object to check.
730
+ - `subObject`: `Partial<T>` - The sub-object to search for.
457
731
 
458
- Arguments
459
- |Name|Type|Required|Description|
460
- |--|--|--|--|
461
- |`object`|`Object`|`true`|The object to check|
462
- |`key`|`string`|`true`|The key to check|
463
- |`value`|`any`|`true`|The value to check|
732
+ **Example:**
733
+ ```typescript
734
+ const mainObj = { id: 1, name: "John", age: 30, city: "New York" }
735
+ const subObj = { name: "John", age: 30 }
464
736
 
465
- ## `ObjectHelpers.findEntry(array, predicate)`
737
+ console.log(ObjectHelpers.containsSubObject(mainObj, subObj)) // true
466
738
 
467
- Finds the first entry in the array that satisfies the predicate.
739
+ const subObj2 = { name: "Jane", age: 30 }
740
+ console.log(ObjectHelpers.containsSubObject(mainObj, subObj2)) // false
741
+ ```
468
742
 
469
- Arguments
470
- |Name|Type|Required|Description|
471
- |--|--|--|--|
472
- |`array`|`Array<any>`|`true`|The array of entries to search|
473
- |`predicate`|`(item: any) => boolean`|`true`|The predicate function to use to search the array|
743
+ ### `findObjectBySubObject(array, subObject)`
474
744
 
475
- # GenericHelpers
745
+ Finds the first object in an array that contains the specified sub-object.
476
746
 
477
- Import the GenericHelpers utility.
747
+ **Parameters:**
748
+ - `array`: `T[]` - Array of objects to search.
749
+ - `subObject`: `Partial<T>` - The sub-object to search for.
478
750
 
479
- `import { GenericHelpers } from "@akadenia/helpers`
751
+ **Example:**
752
+ ```typescript
753
+ const users = [
754
+ { id: 1, name: "John", age: 30, city: "New York" },
755
+ { id: 2, name: "Jane", age: 25, city: "Boston" },
756
+ { id: 3, name: "Bob", age: 30, city: "Chicago" }
757
+ ]
480
758
 
481
- ## `GenericHelpers.delay(ms)`
759
+ const result = ObjectHelpers.findObjectBySubObject(users, { age: 30, city: "New York" })
760
+ console.log(result) // { id: 1, name: "John", age: 30, city: "New York" }
482
761
 
483
- A "modern" sleep statement.
762
+ const result2 = ObjectHelpers.findObjectBySubObject(users, { name: "Alice" })
763
+ console.log(result2) // null
764
+ ```
484
765
 
485
- Arguments
486
- |Name|Type|Required|Description|
487
- |--|--|--|--|
488
- |`ms`|`number`|`true`|The number of milliseconds to wait|
766
+ ### `filterObjectsBySubObject(array, subObject)`
489
767
 
490
- ## `GenericHelpers.getPreferredUriScheme(host)`
768
+ Filters an array of objects based on containing the specified sub-object.
491
769
 
492
- Get the preferred scheme for a host
770
+ **Parameters:**
771
+ - `array`: `T[]` - Array of objects to filter.
772
+ - `subObject`: `Partial<T>` - The sub-object to search for.
493
773
 
494
- Arguments
495
- |Name|Type|Required|Description|
496
- |--|--|--|--|
497
- |`host`|`string`|`true`|An IP address or a domain name|
774
+ **Example:**
775
+ ```typescript
776
+ const users = [
777
+ { id: 1, name: "John", age: 30, city: "New York" },
778
+ { id: 2, name: "Jane", age: 25, city: "Boston" },
779
+ { id: 3, name: "Bob", age: 30, city: "Chicago" }
780
+ ]
781
+
782
+ const results = ObjectHelpers.filterObjectsBySubObject(users, { age: 30 })
783
+ console.log(results) // [{ id: 1, name: "John", age: 30, city: "New York" }, { id: 3, name: "Bob", age: 30, city: "Chicago" }]
784
+ ```
785
+
786
+ ### `objectPropHasValue({object, propName, value})`
787
+
788
+ Checks if an object has a specific property with a specific value.
498
789
 
499
- # FileHelpers
790
+ **Parameters:**
791
+ - `object`: `ObjectType` - The object to check.
792
+ - `propName`: `keyof ObjectType` - The property name.
793
+ - `value`: `ObjectType[keyof ObjectType]` - The expected value.
500
794
 
501
- ## `FileHelpers.checkFileExtension(filePath, validExtensions)`
795
+ **Example:**
796
+ ```typescript
797
+ const user = { id: 1, name: "John", age: 30 }
502
798
 
503
- Check if a file path has a valid extension
799
+ console.log(ObjectHelpers.objectPropHasValue({ object: user, propName: "name", value: "John" })) // true
800
+ console.log(ObjectHelpers.objectPropHasValue({ object: user, propName: "age", value: 25 })) // false
801
+ ```
504
802
 
505
- Arguments
506
- |Name|Type|Required|Description|
507
- |--|--|--|--|
508
- |`filePath`|`string`|`true`|The file path to check|
509
- |`validExtensions`|`string[]`|`true`|The valid extensions|
803
+ ### `findEntry(array, predicate)`
510
804
 
511
- ## Contributing to this package
805
+ Finds the first entry in an array that satisfies a predicate function.
512
806
 
513
- This package follows the commitlint and conventional commits standards. As such the commit messages should follow the following format:
807
+ **Parameters:**
808
+ - `array`: `EntryType[]` - Array to search.
809
+ - `predicate`: `(item: EntryType) => boolean` - Predicate function.
514
810
 
515
- ```text
516
- <type>(optional scope): <description> eg: feat: add new feature OR fix(map-loading): fix rendering on ipad devices
811
+ **Example:**
812
+ ```typescript
813
+ const numbers = [1, 2, 3, 4, 5, 6]
814
+
815
+ const even = ObjectHelpers.findEntry(numbers, (n) => n % 2 === 0)
816
+ console.log(even) // 2
817
+
818
+ const greaterThan5 = ObjectHelpers.findEntry(numbers, (n) => n > 5)
819
+ console.log(greaterThan5) // 6
820
+
821
+ const greaterThan10 = ObjectHelpers.findEntry(numbers, (n) => n > 10)
822
+ console.log(greaterThan10) // null
823
+ ```
824
+
825
+ ### `convertArrayToMap(arrayData, keyProp)`
826
+
827
+ Converts an array of objects to a map using a specified key property.
828
+
829
+ **Parameters:**
830
+ - `arrayData`: `T[]` - Array of objects to convert.
831
+ - `keyProp`: `keyof T` - Property to use as the key.
832
+
833
+ **Example:**
834
+ ```typescript
835
+ const users = [
836
+ { id: 1, name: "John", age: 30 },
837
+ { id: 2, name: "Jane", age: 25 },
838
+ { id: 3, name: "Bob", age: 35 }
839
+ ]
840
+
841
+ const userMap = ObjectHelpers.convertArrayToMap(users, "id")
842
+ console.log(userMap)
843
+ // {
844
+ // "1": { id: 1, name: "John", age: 30 },
845
+ // "2": { id: 2, name: "Jane", age: 25 },
846
+ // "3": { id: 3, name: "Bob", age: 35 }
847
+ // }
848
+ ```
849
+
850
+ Converts object keys from camelCase to kebab-case.
851
+
852
+ **Parameters:**
853
+
854
+ - `obj`: `T | undefined` - The object to convert.
855
+
856
+ **Example:**
857
+
858
+ ```typescript
859
+ const camelCaseObj = { firstName: "John", lastName: "Doe", age: 30 }
860
+ const result = ObjectHelpers.convertObjectKeysToKebabCase(camelCaseObj)
861
+ console.log(result) // { "first-name": "John", "last-name": "Doe", age: 30 }
862
+
863
+ // Handles mixed case keys
864
+ const mixedObj = { firstName: "John", "last-name": "Doe", userName: "johndoe" }
865
+ const result2 = ObjectHelpers.convertObjectKeysToKebabCase(mixedObj)
866
+ console.log(result2) // { "first-name": "John", "last-name": "Doe", "user-name": "johndoe" }
867
+
868
+ // Returns undefined for undefined input
869
+ const result3 = ObjectHelpers.convertObjectKeysToKebabCase(undefined)
870
+ console.log(result3) // undefined
871
+ ```
872
+
873
+ ## GenericHelpers
874
+
875
+ General utility functions for common operations.
876
+
877
+ ### `delay(ms)`
878
+
879
+ Creates a delay (sleep) for the specified number of milliseconds.
880
+
881
+ **Parameters:**
882
+ - `ms`: `number` - Number of milliseconds to wait.
883
+
884
+ **Example:**
885
+ ```typescript
886
+ // Using with async/await
887
+ async function example() {
888
+ console.log("Starting...")
889
+ await GenericHelpers.delay(2000) // Wait 2 seconds
890
+ console.log("Done!")
891
+ }
892
+
893
+ // Using with promises
894
+ GenericHelpers.delay(1000).then(() => {
895
+ console.log("1 second has passed")
896
+ })
897
+ ```
898
+
899
+ ### `getPreferredUriScheme(host)`
900
+
901
+ Determines the preferred URI scheme (http or https) for a given host.
902
+
903
+ **Parameters:**
904
+ - `host`: `string` - IP address or domain name.
905
+
906
+ **Example:**
907
+ ```typescript
908
+ console.log(GenericHelpers.getPreferredUriScheme("example.com")) // "https"
909
+ console.log(GenericHelpers.getPreferredUriScheme("localhost")) // "http"
910
+ console.log(GenericHelpers.getPreferredUriScheme("127.0.0.1")) // "http"
911
+ console.log(GenericHelpers.getPreferredUriScheme("192.168.1.1")) // "http"
912
+ console.log(GenericHelpers.getPreferredUriScheme("10.0.0.1")) // "http"
913
+ ```
914
+
915
+ ## FileHelpers
916
+
917
+ Utility functions for file operations and validation.
918
+
919
+ ### `checkFileExtension(filePath, validExtensions)`
920
+
921
+ Checks if a file path has one of the valid extensions.
922
+
923
+ **Parameters:**
924
+ - `filePath`: `string` - The file path to check.
925
+ - `validExtensions`: `string[]` - Array of valid file extensions.
926
+
927
+ **Example:**
928
+ ```typescript
929
+ console.log(FileHelpers.checkFileExtension("document.pdf", ["pdf", "doc", "docx"])) // true
930
+ console.log(FileHelpers.checkFileExtension("image.jpg", ["png", "gif", "svg"])) // false
931
+ console.log(FileHelpers.checkFileExtension("data.geojson", ["geojson", "json"])) // true
932
+ console.log(FileHelpers.checkFileExtension("script.js", ["js", "ts", "jsx"])) // true
933
+ console.log(FileHelpers.checkFileExtension("file", ["txt", "md"])) // false (no extension)
934
+ ```
935
+
936
+ ## Contributing
937
+
938
+ We welcome contributions! Please feel free to submit a Pull Request.
939
+
940
+ ### Development Setup
941
+
942
+ ```bash
943
+ git clone https://github.com/akadenia/AkadeniaHelpers.git
944
+ cd AkadeniaHelpers
945
+ npm install
946
+ npm run build
947
+ npm test
517
948
  ```
518
949
 
519
- Common types according to [commitlint-config-conventional (based on the Angular convention)](https://github.com/conventional-changelog/commitlint/tree/master/@commitlint/config-conventional#type-enum) can be:
950
+ ### Commit Message Guidelines
520
951
 
521
- - build
522
- - chore
523
- - ci
524
- - docs
525
- - feat
526
- - fix
527
- - perf
528
- - refactor
529
- - revert
530
- - style
531
- - test
952
+ We follow [Conventional Commits](https://www.conventionalcommits.org/) for our semantic release process. **We prefer commit messages to include a scope in parentheses** for better categorization and changelog generation.
532
953
 
533
- if you introduce a breaking change, please add BREAKING CHANGE in the pull request description
954
+ ### Preferred Format
955
+ ```
956
+ type(scope): description
957
+
958
+ [optional body]
959
+
960
+ [optional footer]
961
+ ```
962
+
963
+ ### Examples
964
+ ```bash
965
+ ## ✅ Preferred - with scope
966
+ feat(date): add new date formatting options
967
+ fix(text): resolve string validation issue
968
+ docs(readme): add troubleshooting section
969
+ chore(deps): update dependencies
970
+
971
+ ## ❌ Less preferred - without scope
972
+ feat: add new date formatting options
973
+ fix: resolve string validation issue
974
+ docs: add troubleshooting section
975
+ chore: update dependencies
976
+ ```
977
+
978
+ ### Common Scopes
979
+ - `date` - Date manipulation functions
980
+ - `text` - Text processing functions
981
+ - `object` - Object manipulation functions
982
+ - `map` - Map and geographical functions
983
+ - `generic` - Generic utility functions
984
+ - `file` - File processing functions
985
+ - `docs` - Documentation updates
986
+ - `deps` - Dependency updates
987
+ - `test` - Test-related changes
988
+ - `build` - Build and build tooling
989
+ - `ci` - CI/CD configuration
990
+
991
+ ### Commit Types
992
+ - `feat` - New features
993
+ - `fix` - Bug fixes
994
+ - `docs` - Documentation changes
995
+ - `style` - Code style changes (formatting, etc.)
996
+ - `refactor` - Code refactoring
997
+ - `test` - Adding or updating tests
998
+ - `chore` - Maintenance tasks
999
+
1000
+ If you introduce a breaking change, please add `BREAKING CHANGE` in the pull request description.
534
1001
 
535
1002
  ## License
536
1003
 
537
- MIT
1004
+ [MIT](https://github.com/akadenia/AkadeniaHelpers/blob/main/LICENSE)
1005
+
1006
+ ## Support
1007
+
1008
+ For support, please open an issue on [GitHub](https://github.com/akadenia/AkadeniaHelpers/issues).