@splendidlabz/utils 1.11.2 → 1.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/dom/accessibility.cjs +2 -0
- package/dist/cjs/dom/actions/index.cjs +392 -7
- package/dist/cjs/dom/actions/masonry.cjs +97 -6
- package/dist/cjs/dom/actions/prefer-horizontal-scroll.cjs +58 -14
- package/dist/cjs/dom/actions/sticky.cjs +126 -6
- package/dist/cjs/dom/bounding-box.cjs +2 -0
- package/dist/cjs/dom/clipboard.cjs +2 -0
- package/dist/cjs/dom/cookie.cjs +3 -1
- package/dist/cjs/dom/css-vars.cjs +13 -3
- package/dist/cjs/dom/events.cjs +2 -0
- package/dist/cjs/dom/focusable.cjs +2 -0
- package/dist/cjs/dom/font-size.cjs +15 -3
- package/dist/cjs/dom/get-element.cjs +3 -1
- package/dist/cjs/dom/hash.cjs +2 -0
- package/dist/cjs/dom/index.cjs +1249 -47
- package/dist/cjs/dom/keyboard.cjs +2 -0
- package/dist/cjs/dom/local-store.cjs +3 -1
- package/dist/cjs/dom/media.cjs +2 -0
- package/dist/cjs/dom/observers/index.cjs +235 -9
- package/dist/cjs/dom/observers/intersection-observer.cjs +38 -6
- package/dist/cjs/dom/observers/mutation-observer.cjs +38 -6
- package/dist/cjs/dom/observers/observer.cjs +12 -2
- package/dist/cjs/dom/observers/resize-observer.cjs +38 -6
- package/dist/cjs/dom/observers/scroll-observer.cjs +62 -3
- package/dist/cjs/dom/pkce.cjs +13 -3
- package/dist/cjs/dom/query-params.cjs +3 -1
- package/dist/cjs/dom/random-string.cjs +2 -0
- package/dist/cjs/dom/sanitize.cjs +27 -3
- package/dist/cjs/dom/session-store.cjs +3 -1
- package/dist/cjs/dom/spam-prevention.cjs +2 -0
- package/dist/cjs/dom/trap-focus.cjs +131 -9
- package/dist/cjs/dom/ui/aria-current.cjs +2 -0
- package/dist/cjs/dom/ui/inconsistent-button-fix.cjs +2 -0
- package/dist/cjs/dom/ui/index.cjs +87 -9
- package/dist/cjs/dom/ui/scroll-container.cjs +2 -0
- package/dist/cjs/dom/ui/traverse-and-scramble.cjs +2 -0
- package/dist/cjs/lib/arrays/index.cjs +121 -13
- package/dist/cjs/lib/arrays/item-position.cjs +2 -0
- package/dist/cjs/lib/arrays/join.cjs +10 -2
- package/dist/cjs/lib/arrays/shuffle.cjs +2 -0
- package/dist/cjs/lib/arrays/sort.cjs +11 -3
- package/dist/cjs/lib/arrays/split-array.cjs +2 -0
- package/dist/cjs/lib/arrays/unique.cjs +2 -0
- package/dist/cjs/lib/auth/index.cjs +35 -3
- package/dist/cjs/lib/auth/route-manager.cjs +2 -0
- package/dist/cjs/lib/checks.cjs +2 -0
- package/dist/cjs/lib/date/days.cjs +3 -1
- package/dist/cjs/lib/date/index.cjs +190 -7
- package/dist/cjs/lib/date/months.cjs +3 -1
- package/dist/cjs/lib/date/time.cjs +14 -2
- package/dist/cjs/lib/form/form-data.cjs +2 -0
- package/dist/cjs/lib/form/index.cjs +104 -5
- package/dist/cjs/lib/form/sanitize.cjs +2 -0
- package/dist/cjs/lib/functions/callback.cjs +2 -0
- package/dist/cjs/lib/functions/debounce.cjs +2 -0
- package/dist/cjs/lib/functions/env.cjs +2 -0
- package/dist/cjs/lib/functions/functional.cjs +2 -0
- package/dist/cjs/lib/functions/index.cjs +124 -11
- package/dist/cjs/lib/functions/throttle.cjs +2 -0
- package/dist/cjs/lib/functions/timeout.cjs +2 -0
- package/dist/cjs/lib/hash.cjs +2 -0
- package/dist/cjs/lib/index.cjs +1160 -29
- package/dist/cjs/lib/numbers/index.cjs +17 -4
- package/dist/cjs/lib/numbers/math.cjs +2 -0
- package/dist/cjs/lib/objects/camelcase-keys.cjs +45 -4
- package/dist/cjs/lib/objects/empty.cjs +2 -0
- package/dist/cjs/lib/objects/equal.cjs +2 -0
- package/dist/cjs/lib/objects/extend.cjs +117 -6
- package/dist/cjs/lib/objects/flatten.cjs +11 -3
- package/dist/cjs/lib/objects/index.cjs +360 -27
- package/dist/cjs/lib/objects/json.cjs +2 -0
- package/dist/cjs/lib/objects/loop.cjs +2 -0
- package/dist/cjs/lib/objects/mix/mix.cjs +5 -3
- package/dist/cjs/lib/objects/nested-property.cjs +2 -0
- package/dist/cjs/lib/objects/normalize-object.cjs +78 -4
- package/dist/cjs/lib/objects/omit-empty.cjs +2 -0
- package/dist/cjs/lib/objects/size.cjs +2 -0
- package/dist/cjs/lib/objects/split.cjs +2 -0
- package/dist/cjs/lib/promises/index.cjs +51 -3
- package/dist/cjs/lib/promises/reject.cjs +19 -2
- package/dist/cjs/lib/sse.cjs +29 -4
- package/dist/cjs/lib/strings/convert-case/convert-case.cjs +2 -0
- package/dist/cjs/lib/strings/index.cjs +179 -11
- package/dist/cjs/lib/strings/markdown.cjs +3 -1
- package/dist/cjs/lib/strings/name.cjs +2 -0
- package/dist/cjs/lib/strings/pluralize.cjs +3 -1
- package/dist/cjs/lib/strings/query-string.cjs +2 -0
- package/dist/cjs/lib/style/index.cjs +31 -2
- package/dist/cjs/lib/symbols/index.cjs +22 -3
- package/dist/cjs/lib/symbols/symbols.cjs +2 -0
- package/dist/cjs/node/context.cjs +0 -0
- package/dist/cjs/node/dirname.cjs +4 -2
- package/dist/cjs/node/file-cache.cjs +45 -3
- package/dist/cjs/node/file.cjs +4 -2
- package/dist/cjs/node/hash.cjs +3 -1
- package/dist/cjs/node/index.cjs +278 -15
- package/dist/cjs/node/pkce.cjs +20 -8
- package/dist/cjs/node/random-string.cjs +3 -1
- package/dist/cjs/node/sanitize.cjs +27 -3
- package/dist/cjs/node/uuid.cjs +2 -0
- package/dist/esm/node/context.js +0 -0
- package/dist/esm/node/file-cache.js +1 -1
- package/dist/esm/node/pkce.js +3 -2
- package/dist/types/node/context.d.cts +2 -0
- package/dist/types/node/index.d.cts +1 -1
- package/dist/types/node/pkce.d.cts +7 -1
- package/package.json +5 -2
- package/CHANGELOG.md +0 -231
- package/eslint.config.js +0 -2
- package/src/dom/accessibility.js +0 -58
- package/src/dom/actions/index.js +0 -3
- package/src/dom/actions/masonry.js +0 -43
- package/src/dom/actions/prefer-horizontal-scroll.js +0 -121
- package/src/dom/actions/sticky.js +0 -85
- package/src/dom/bounding-box.js +0 -82
- package/src/dom/clipboard.js +0 -14
- package/src/dom/cookie.js +0 -32
- package/src/dom/css-vars.js +0 -19
- package/src/dom/events.js +0 -71
- package/src/dom/focusable.js +0 -165
- package/src/dom/font-size.js +0 -40
- package/src/dom/get-element.js +0 -176
- package/src/dom/hash.js +0 -9
- package/src/dom/index.js +0 -23
- package/src/dom/keyboard.js +0 -44
- package/src/dom/local-store.js +0 -66
- package/src/dom/media.js +0 -30
- package/src/dom/observers/index.js +0 -4
- package/src/dom/observers/intersection-observer.js +0 -43
- package/src/dom/observers/mutation-observer.js +0 -51
- package/src/dom/observers/observer.js +0 -18
- package/src/dom/observers/resize-observer.js +0 -66
- package/src/dom/observers/scroll-observer.js +0 -146
- package/src/dom/pkce.js +0 -34
- package/src/dom/query-params.js +0 -14
- package/src/dom/random-string.js +0 -18
- package/src/dom/random-string.test.js +0 -13
- package/src/dom/sanitize.js +0 -16
- package/src/dom/session-store.js +0 -29
- package/src/dom/spam-prevention.js +0 -40
- package/src/dom/trap-focus.js +0 -70
- package/src/dom/ui/aria-current.js +0 -20
- package/src/dom/ui/inconsistent-button-fix.js +0 -20
- package/src/dom/ui/index.js +0 -4
- package/src/dom/ui/scroll-container.js +0 -25
- package/src/dom/ui/traverse-and-scramble.js +0 -61
- package/src/lib/arrays/index.js +0 -6
- package/src/lib/arrays/item-position.js +0 -23
- package/src/lib/arrays/join.js +0 -20
- package/src/lib/arrays/shuffle.js +0 -21
- package/src/lib/arrays/sort.js +0 -88
- package/src/lib/arrays/sort.spec.js +0 -123
- package/src/lib/arrays/split-array.js +0 -15
- package/src/lib/arrays/unique.js +0 -3
- package/src/lib/auth/index.js +0 -1
- package/src/lib/auth/route-manager.js +0 -45
- package/src/lib/checks.js +0 -57
- package/src/lib/date/days.js +0 -9
- package/src/lib/date/index.js +0 -3
- package/src/lib/date/months.js +0 -74
- package/src/lib/date/time.js +0 -83
- package/src/lib/form/form-data.js +0 -73
- package/src/lib/form/index.js +0 -2
- package/src/lib/form/sanitize.js +0 -80
- package/src/lib/form/sanitize.spec.js +0 -126
- package/src/lib/functions/callback.js +0 -8
- package/src/lib/functions/debounce.js +0 -18
- package/src/lib/functions/env.js +0 -5
- package/src/lib/functions/functional.js +0 -113
- package/src/lib/functions/functional.test.js +0 -196
- package/src/lib/functions/index.js +0 -5
- package/src/lib/functions/throttle.js +0 -11
- package/src/lib/functions/timeout.js +0 -15
- package/src/lib/hash.js +0 -18
- package/src/lib/hash.spec.js +0 -163
- package/src/lib/index.js +0 -14
- package/src/lib/numbers/index.js +0 -12
- package/src/lib/numbers/math.js +0 -9
- package/src/lib/numbers/split-unit.test.js +0 -45
- package/src/lib/objects/camelcase-keys.js +0 -17
- package/src/lib/objects/camelcase-keys.test.js +0 -72
- package/src/lib/objects/empty.js +0 -10
- package/src/lib/objects/equal.js +0 -9
- package/src/lib/objects/extend.js +0 -16
- package/src/lib/objects/extend.test.js +0 -35
- package/src/lib/objects/flatten.js +0 -19
- package/src/lib/objects/index.js +0 -13
- package/src/lib/objects/json.js +0 -7
- package/src/lib/objects/loop.js +0 -11
- package/src/lib/objects/loop.test.js +0 -31
- package/src/lib/objects/mix/mix.js +0 -191
- package/src/lib/objects/mix/mix.md +0 -78
- package/src/lib/objects/mix/mix.test.js +0 -445
- package/src/lib/objects/nested-property.js +0 -41
- package/src/lib/objects/normalize-object.js +0 -10
- package/src/lib/objects/omit-empty.js +0 -23
- package/src/lib/objects/omit-empty.test.js +0 -85
- package/src/lib/objects/size.js +0 -41
- package/src/lib/objects/split.js +0 -19
- package/src/lib/promises/index.js +0 -1
- package/src/lib/promises/reject.js +0 -17
- package/src/lib/sse.js +0 -61
- package/src/lib/strings/convert-case/convert-case.js +0 -86
- package/src/lib/strings/convert-case/convert-case.md +0 -44
- package/src/lib/strings/convert-case/convert-case.test.js +0 -50
- package/src/lib/strings/index.js +0 -5
- package/src/lib/strings/markdown.js +0 -71
- package/src/lib/strings/name.js +0 -24
- package/src/lib/strings/name.test.js +0 -67
- package/src/lib/strings/pluralize.js +0 -2
- package/src/lib/strings/query-string.js +0 -18
- package/src/lib/style/index.js +0 -13
- package/src/lib/symbols/index.js +0 -1
- package/src/lib/symbols/symbols.js +0 -9
- package/src/node/dirname.js +0 -17
- package/src/node/file-cache.js +0 -184
- package/src/node/file.js +0 -13
- package/src/node/hash.js +0 -5
- package/src/node/index.js +0 -7
- package/src/node/pkce.js +0 -33
- package/src/node/random-string.js +0 -10
- package/src/node/random-string.test.js +0 -15
- package/src/node/sanitize.js +0 -13
- package/src/node/sanitize.spec.js +0 -142
- package/src/node/uuid.js +0 -5
- package/tsconfig.json +0 -23
- package/tsup.config.js +0 -38
- package/tsup.config.mjs +0 -45
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export function last(array, index) {
|
|
2
|
-
console.warn('last is deprecated. Use isLastItem instead.')
|
|
3
|
-
return index === array.length - 1
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Checks if the given index is the last item in the array
|
|
8
|
-
* @param {Array} array - The array to check
|
|
9
|
-
* @param {number} index - The index to check
|
|
10
|
-
* @returns {boolean} True if the index is the last item, false otherwise
|
|
11
|
-
*/
|
|
12
|
-
export function isLastItem(array, index) {
|
|
13
|
-
return index === array.length - 1
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Returns the last item in the array
|
|
18
|
-
* @param {Array} array - The array to get the last item from
|
|
19
|
-
* @returns {*} The last item in the array
|
|
20
|
-
*/
|
|
21
|
-
export function lastArrayItem(array) {
|
|
22
|
-
return array[array.length - 1]
|
|
23
|
-
}
|
package/src/lib/arrays/join.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { lastArrayItem } from './item-position.js'
|
|
2
|
-
/**
|
|
3
|
-
* Joins an array with a conjunction (and/or)
|
|
4
|
-
* @param {Array<string>} array - Array of strings to join
|
|
5
|
-
* @param {Object} [options] - Options for joining
|
|
6
|
-
* @param {string} [options.conjunction='and'] - Conjunction to use ('and' or 'or')
|
|
7
|
-
* @returns {string} Joined string
|
|
8
|
-
* @example
|
|
9
|
-
* joinWithConjunction(['a', 'b', 'c']) // 'a, b, and c'
|
|
10
|
-
* joinWithConjunction(['a', 'b'], { conjunction: 'or' }) // 'a or b'
|
|
11
|
-
*/
|
|
12
|
-
export function joinWithConjunction(array, { conjunction = 'and' } = {}) {
|
|
13
|
-
if (!array?.length) return ''
|
|
14
|
-
if (array.length === 1) return array[0]
|
|
15
|
-
if (array.length === 2) return `${array[0]} ${conjunction} ${array[1]}`
|
|
16
|
-
|
|
17
|
-
const lastItem = lastArrayItem(array)
|
|
18
|
-
const rest = array.slice(0, -1)
|
|
19
|
-
return `${rest.join(', ')} ${conjunction} ${lastItem}`
|
|
20
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
// Fisher Yates Shuffle without mutating the original array
|
|
2
|
-
export function shuffle(array) {
|
|
3
|
-
const clone = array.slice()
|
|
4
|
-
let currentIndex = array.length
|
|
5
|
-
let temporaryValue
|
|
6
|
-
let randomIndex
|
|
7
|
-
|
|
8
|
-
// While there remain elements to shuffle...
|
|
9
|
-
while (currentIndex !== 0) {
|
|
10
|
-
// Pick a remaining element...
|
|
11
|
-
randomIndex = Math.floor(Math.random() * currentIndex)
|
|
12
|
-
currentIndex -= 1
|
|
13
|
-
|
|
14
|
-
// And swap it with the current element.
|
|
15
|
-
temporaryValue = clone[currentIndex]
|
|
16
|
-
clone[currentIndex] = clone[randomIndex]
|
|
17
|
-
clone[randomIndex] = temporaryValue
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
return clone
|
|
21
|
-
}
|
package/src/lib/arrays/sort.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { getNestedValue } from '../objects/nested-property.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Sorts an array of objects, numbers, or strings without mutating the original array.
|
|
5
|
-
* Supports nested properties, multiple sort keys, and various data types.
|
|
6
|
-
*
|
|
7
|
-
* @template T
|
|
8
|
-
* @param {T[]} array - Array to sort
|
|
9
|
-
* @param {Object} [options] - Sort options
|
|
10
|
-
* @param {string|string[]|null} [options.props=null] - Property or array of properties to sort by. If null, sorts simple arrays
|
|
11
|
-
* @param {boolean} [options.reverse=false] - Whether to sort in reverse order
|
|
12
|
-
* @returns {T[]} New sorted array
|
|
13
|
-
* @example
|
|
14
|
-
* // Sort simple array
|
|
15
|
-
* sort([3, 1, 2]) // [1, 2, 3]
|
|
16
|
-
*
|
|
17
|
-
* // Sort objects by single property
|
|
18
|
-
* sort(users, { props: 'name' })
|
|
19
|
-
*
|
|
20
|
-
* // Sort objects by multiple properties
|
|
21
|
-
* sort(users, { props: ['age', 'name'] })
|
|
22
|
-
*
|
|
23
|
-
* // Sort in reverse order
|
|
24
|
-
* sort(users, { props: 'age', reverse: true })
|
|
25
|
-
*
|
|
26
|
-
* // Sort by nested property
|
|
27
|
-
* sort(users, { props: 'address.city' })
|
|
28
|
-
*/
|
|
29
|
-
export function sort(array, { props = null, reverse = false } = {}) {
|
|
30
|
-
const clone = array.slice()
|
|
31
|
-
|
|
32
|
-
// Handle simple arrays (numbers or strings)
|
|
33
|
-
if (props === null) {
|
|
34
|
-
return clone.sort((a, b) => {
|
|
35
|
-
const comparison = compareValues(a, b)
|
|
36
|
-
return reverse ? -comparison : comparison
|
|
37
|
-
})
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Handle objects in arrays
|
|
41
|
-
const properties = Array.isArray(props) ? props : [props]
|
|
42
|
-
|
|
43
|
-
return clone.sort((a, b) => {
|
|
44
|
-
for (const property of properties) {
|
|
45
|
-
const aValue = getNestedValue(a, property)
|
|
46
|
-
const bValue = getNestedValue(b, property)
|
|
47
|
-
|
|
48
|
-
// Skip if values are equal
|
|
49
|
-
if (aValue === bValue) continue
|
|
50
|
-
|
|
51
|
-
// Push null/undefined values to the end
|
|
52
|
-
if (aValue == null) return 1
|
|
53
|
-
if (bValue == null) return -1
|
|
54
|
-
|
|
55
|
-
// Compare values and handle reverse sort
|
|
56
|
-
const comparison = compareValues(aValue, bValue)
|
|
57
|
-
return reverse ? -comparison : comparison
|
|
58
|
-
}
|
|
59
|
-
return 0
|
|
60
|
-
})
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Compares two values for sorting, handling different data types.
|
|
65
|
-
* Supports numbers, strings, dates, and falls back to string comparison.
|
|
66
|
-
*
|
|
67
|
-
* @param {*} a - First value to compare
|
|
68
|
-
* @param {*} b - Second value to compare
|
|
69
|
-
* @returns {number} -1 if a < b, 0 if a === b, 1 if a > b
|
|
70
|
-
* @private
|
|
71
|
-
*/
|
|
72
|
-
function compareValues(a, b) {
|
|
73
|
-
// Compare numbers
|
|
74
|
-
if (typeof a === 'number' && typeof b === 'number') return a - b
|
|
75
|
-
|
|
76
|
-
// Compare strings
|
|
77
|
-
if (typeof a === 'string' && typeof b === 'string') return a.localeCompare(b)
|
|
78
|
-
|
|
79
|
-
// Compare dates
|
|
80
|
-
const aDate = new Date(a)
|
|
81
|
-
const bDate = new Date(b)
|
|
82
|
-
const aTime = aDate.getTime()
|
|
83
|
-
const bTime = bDate.getTime()
|
|
84
|
-
if (!isNaN(aTime) && !isNaN(bTime)) return aTime - bTime
|
|
85
|
-
|
|
86
|
-
// Convert into strings and compare
|
|
87
|
-
return String(a).localeCompare(String(b))
|
|
88
|
-
}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
|
|
3
|
-
import { sort } from './index.js'
|
|
4
|
-
|
|
5
|
-
describe('Sort by', _ => {
|
|
6
|
-
it('Standard array - numbers', async () => {
|
|
7
|
-
const array = [3, 1, 2]
|
|
8
|
-
const sorted = sort(array)
|
|
9
|
-
const reversed = sort(array, { reverse: true })
|
|
10
|
-
expect(sorted).toEqual([1, 2, 3])
|
|
11
|
-
expect(reversed).toEqual([3, 2, 1])
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
it('Standard array - strings', async () => {
|
|
15
|
-
const array = ['c', 'a', 'b']
|
|
16
|
-
const sorted = sort(array)
|
|
17
|
-
const reversed = sort(array, { reverse: true })
|
|
18
|
-
expect(sorted).toEqual(['a', 'b', 'c'])
|
|
19
|
-
expect(reversed).toEqual(['c', 'b', 'a'])
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
it('Standard array - dates', async () => {
|
|
23
|
-
const array = [
|
|
24
|
-
new Date('2021-05-18'),
|
|
25
|
-
new Date('2022-01-01'),
|
|
26
|
-
new Date('2025-03-09'),
|
|
27
|
-
]
|
|
28
|
-
const sorted = sort(array)
|
|
29
|
-
const reversed = sort(array, { reverse: true })
|
|
30
|
-
expect(sorted).toEqual([
|
|
31
|
-
new Date('2021-05-18'),
|
|
32
|
-
new Date('2022-01-01'),
|
|
33
|
-
new Date('2025-03-09'),
|
|
34
|
-
])
|
|
35
|
-
expect(reversed).toEqual([
|
|
36
|
-
new Date('2025-03-09'),
|
|
37
|
-
new Date('2022-01-01'),
|
|
38
|
-
new Date('2021-05-18'),
|
|
39
|
-
])
|
|
40
|
-
})
|
|
41
|
-
it('Array of objects — simple integer', async () => {
|
|
42
|
-
const array = [
|
|
43
|
-
{ name: 'Ace', age: 30 },
|
|
44
|
-
{ name: 'Betty', age: 25 },
|
|
45
|
-
{ name: 'Candy', age: 35 },
|
|
46
|
-
]
|
|
47
|
-
const sorted = sort(array, { props: 'age' })
|
|
48
|
-
const reversed = sort(array, { props: 'age', reverse: true })
|
|
49
|
-
expect(sorted).toEqual([
|
|
50
|
-
{ name: 'Betty', age: 25 },
|
|
51
|
-
{ name: 'Ace', age: 30 },
|
|
52
|
-
{ name: 'Candy', age: 35 },
|
|
53
|
-
])
|
|
54
|
-
expect(reversed).toEqual([
|
|
55
|
-
{ name: 'Candy', age: 35 },
|
|
56
|
-
{ name: 'Ace', age: 30 },
|
|
57
|
-
{ name: 'Betty', age: 25 },
|
|
58
|
-
])
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
it('Array of objects — simple string', async () => {
|
|
62
|
-
const array = [
|
|
63
|
-
{ name: 'Ace', age: 30 },
|
|
64
|
-
{ name: 'Betty', age: 25 },
|
|
65
|
-
{ name: 'Candy', age: 35 },
|
|
66
|
-
]
|
|
67
|
-
const sorted = sort(array, { props: 'name' })
|
|
68
|
-
const reversed = sort(array, { props: 'name', reverse: true })
|
|
69
|
-
expect(sorted).toEqual([
|
|
70
|
-
{ name: 'Ace', age: 30 },
|
|
71
|
-
{ name: 'Betty', age: 25 },
|
|
72
|
-
{ name: 'Candy', age: 35 },
|
|
73
|
-
])
|
|
74
|
-
expect(reversed).toEqual([
|
|
75
|
-
{ name: 'Candy', age: 35 },
|
|
76
|
-
{ name: 'Betty', age: 25 },
|
|
77
|
-
{ name: 'Ace', age: 30 },
|
|
78
|
-
])
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
it('Double property', async () => {
|
|
82
|
-
const array = [
|
|
83
|
-
{ name: 'Ace', age: 30 },
|
|
84
|
-
{ name: 'Betty', age: 25 },
|
|
85
|
-
{ name: 'Candy', age: 35 },
|
|
86
|
-
{ name: 'Danny', age: 30 },
|
|
87
|
-
]
|
|
88
|
-
const sorted = sort(array, { props: ['age', 'name'] })
|
|
89
|
-
const reversed = sort(array, { props: ['age', 'name'], reverse: true })
|
|
90
|
-
expect(sorted).toEqual([
|
|
91
|
-
{ name: 'Betty', age: 25 },
|
|
92
|
-
{ name: 'Ace', age: 30 },
|
|
93
|
-
{ name: 'Danny', age: 30 },
|
|
94
|
-
{ name: 'Candy', age: 35 },
|
|
95
|
-
])
|
|
96
|
-
expect(reversed).toEqual([
|
|
97
|
-
{ name: 'Candy', age: 35 },
|
|
98
|
-
{ name: 'Danny', age: 30 },
|
|
99
|
-
{ name: 'Ace', age: 30 },
|
|
100
|
-
{ name: 'Betty', age: 25 },
|
|
101
|
-
])
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
it('Nested value', async () => {
|
|
105
|
-
const array = [
|
|
106
|
-
{ data: { value: 1 } },
|
|
107
|
-
{ data: { value: 2 } },
|
|
108
|
-
{ data: { value: 3 } },
|
|
109
|
-
]
|
|
110
|
-
const sorted = sort(array, { props: 'data.value' })
|
|
111
|
-
const reversed = sort(array, { props: 'data.value', reverse: true })
|
|
112
|
-
expect(sorted).toEqual([
|
|
113
|
-
{ data: { value: 1 } },
|
|
114
|
-
{ data: { value: 2 } },
|
|
115
|
-
{ data: { value: 3 } },
|
|
116
|
-
])
|
|
117
|
-
expect(reversed).toEqual([
|
|
118
|
-
{ data: { value: 3 } },
|
|
119
|
-
{ data: { value: 2 } },
|
|
120
|
-
{ data: { value: 1 } },
|
|
121
|
-
])
|
|
122
|
-
})
|
|
123
|
-
})
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export function splitArray(array, predicate) {
|
|
2
|
-
const ret = {
|
|
3
|
-
picked: [],
|
|
4
|
-
omitted: [],
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
array.forEach((item, index, arr) => {
|
|
8
|
-
if (predicate(item, index, arr)) ret.picked.push(item)
|
|
9
|
-
else ret.omitted.push(item)
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
ret.p = ret.picked
|
|
13
|
-
ret.o = ret.omitted
|
|
14
|
-
return ret
|
|
15
|
-
}
|
package/src/lib/arrays/unique.js
DELETED
package/src/lib/auth/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './route-manager.js'
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
// Usage ... Probably should use either protected or bypass, not both.
|
|
3
|
-
// Maybe ... glob would be a better for this
|
|
4
|
-
@example
|
|
5
|
-
const config = {
|
|
6
|
-
routeConfig: {
|
|
7
|
-
startsWith: ['/dashboard']
|
|
8
|
-
}
|
|
9
|
-
bypassRoutes: {
|
|
10
|
-
is: ['/'],
|
|
11
|
-
startsWith: ['/fonts', '/auth', '/favicon', '/images'],
|
|
12
|
-
includes: ['/meh'],
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
const {isProtectedRoute, isBypassRoute} = AuthManager(config)
|
|
16
|
-
if (!isProtectedRoute(context.url.pathname)) return next() // Handle only protected routes
|
|
17
|
-
if (isBypassRoute(context.url.pathname)) return next() // Bypass all non protected routes
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
export function RouteManager(config) {
|
|
21
|
-
const { protectedRoutes, bypassRoutes } = config
|
|
22
|
-
return {
|
|
23
|
-
isProtectedRoute(pathname) {
|
|
24
|
-
return isMatch(protectedRoutes, pathname)
|
|
25
|
-
},
|
|
26
|
-
isBypassRoute(pathname) {
|
|
27
|
-
return isMatch(bypassRoutes, pathname)
|
|
28
|
-
},
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Alias for RouteManager
|
|
33
|
-
export function AuthManager(config) {
|
|
34
|
-
return RouteManager(config)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function isMatch(routeConfig, pathname) {
|
|
38
|
-
const { is, startsWith, includes } = routeConfig
|
|
39
|
-
const isExactMatch = is && is.some(u => pathname === u)
|
|
40
|
-
const startsWithMatch =
|
|
41
|
-
startsWith && startsWith.some(u => pathname.startsWith(u))
|
|
42
|
-
const includesMatch = includes && includes.some(u => pathname.includes(u))
|
|
43
|
-
|
|
44
|
-
return isExactMatch || startsWithMatch || includesMatch
|
|
45
|
-
}
|
package/src/lib/checks.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Checks if a value is a plain object (not an array or null)
|
|
3
|
-
* @param {unknown} x - The value to check
|
|
4
|
-
* @returns {boolean} True if the value is a plain object
|
|
5
|
-
* @example
|
|
6
|
-
* isObject({}) // true
|
|
7
|
-
* isObject([]) // false
|
|
8
|
-
* isObject(null) // false
|
|
9
|
-
*/
|
|
10
|
-
export function isObject(x) {
|
|
11
|
-
return typeof x === 'object' && !Array.isArray(x) && x !== null
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Checks if a value is an array
|
|
16
|
-
* @param {unknown} x - The value to check
|
|
17
|
-
* @returns {boolean} True if the value is an array
|
|
18
|
-
* @example
|
|
19
|
-
* isArray([]) // true
|
|
20
|
-
* isArray({}) // false
|
|
21
|
-
*/
|
|
22
|
-
export function isArray(x) {
|
|
23
|
-
return Array.isArray(x)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Checks if a value is not a plain object
|
|
28
|
-
* @param {unknown} x - The value to check
|
|
29
|
-
* @returns {boolean} True if the value is not a plain object
|
|
30
|
-
* @example
|
|
31
|
-
* notObject([]) // true
|
|
32
|
-
* notObject(null) // true
|
|
33
|
-
* notObject({}) // false
|
|
34
|
-
*/
|
|
35
|
-
export function notObject(x) {
|
|
36
|
-
return !isObject(x)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function getType(x) {
|
|
40
|
-
if (typeof x === 'string') return 'string'
|
|
41
|
-
if (typeof x === 'number') {
|
|
42
|
-
if (Number.isInteger(x)) return 'integer'
|
|
43
|
-
return 'float'
|
|
44
|
-
}
|
|
45
|
-
if (typeof x === 'boolean') return 'boolean'
|
|
46
|
-
if (typeof x === 'function') return 'function'
|
|
47
|
-
if (typeof x === 'undefined') return 'undefined'
|
|
48
|
-
if (typeof x === 'symbol') return 'symbol'
|
|
49
|
-
if (typeof x === 'bigint') return 'bigint'
|
|
50
|
-
if (Array.isArray(x)) return 'array'
|
|
51
|
-
if (typeof x === 'object') return 'object'
|
|
52
|
-
return 'unknown'
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function isFunction(x) {
|
|
56
|
-
return typeof x === 'function'
|
|
57
|
-
}
|
package/src/lib/date/days.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export const DAYS = [
|
|
2
|
-
{ short: 'Sun', long: 'Sunday', numeric: 1 },
|
|
3
|
-
{ short: 'Mon', long: 'Monday', numeric: 2 },
|
|
4
|
-
{ short: 'Tue', long: 'Tuesday', numeric: 3 },
|
|
5
|
-
{ short: 'Wed', long: 'Wednesday', numeric: 4 },
|
|
6
|
-
{ short: 'Thu', long: 'Thursday', numeric: 5 },
|
|
7
|
-
{ short: 'Fri', long: 'Friday', numeric: 6 },
|
|
8
|
-
{ short: 'Sat', long: 'Saturday', numeric: 7 },
|
|
9
|
-
]
|
package/src/lib/date/index.js
DELETED
package/src/lib/date/months.js
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
export const MONTHS = [
|
|
2
|
-
{
|
|
3
|
-
long: 'January',
|
|
4
|
-
short: 'jan',
|
|
5
|
-
numeric: 1,
|
|
6
|
-
lastDay: { default: 31, leapYear: 31 },
|
|
7
|
-
},
|
|
8
|
-
{
|
|
9
|
-
long: 'February',
|
|
10
|
-
short: 'feb',
|
|
11
|
-
numeric: 2,
|
|
12
|
-
lastDay: { default: 28, leapYear: 29 },
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
long: 'March',
|
|
16
|
-
short: 'mar',
|
|
17
|
-
numeric: 3,
|
|
18
|
-
lastDay: { default: 31, leapYear: 31 },
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
long: 'April',
|
|
22
|
-
short: 'apr',
|
|
23
|
-
numeric: 4,
|
|
24
|
-
lastDay: { default: 30, leapYear: 30 },
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
long: 'May',
|
|
28
|
-
short: 'may',
|
|
29
|
-
numeric: 5,
|
|
30
|
-
lastDay: { default: 31, leapYear: 31 },
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
long: 'June',
|
|
34
|
-
short: 'jun',
|
|
35
|
-
numeric: 6,
|
|
36
|
-
lastDay: { default: 30, leapYear: 30 },
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
long: 'July',
|
|
40
|
-
short: 'jul',
|
|
41
|
-
numeric: 7,
|
|
42
|
-
lastDay: { default: 31, leapYear: 31 },
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
long: 'August',
|
|
46
|
-
short: 'aug',
|
|
47
|
-
numeric: 8,
|
|
48
|
-
lastDay: { default: 31, leapYear: 31 },
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
long: 'September',
|
|
52
|
-
short: 'sep',
|
|
53
|
-
numeric: 9,
|
|
54
|
-
lastDay: { default: 30, leapYear: 30 },
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
long: 'October',
|
|
58
|
-
short: 'oct',
|
|
59
|
-
numeric: 10,
|
|
60
|
-
lastDay: { default: 31, leapYear: 31 },
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
long: 'November',
|
|
64
|
-
short: 'nov',
|
|
65
|
-
numeric: 11,
|
|
66
|
-
lastDay: { default: 30, leapYear: 30 },
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
long: 'December',
|
|
70
|
-
short: 'dec',
|
|
71
|
-
numeric: 12,
|
|
72
|
-
lastDay: { default: 31, leapYear: 31 },
|
|
73
|
-
},
|
|
74
|
-
]
|
package/src/lib/date/time.js
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { splitUnit } from '../numbers/index.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Convert a time string to milliseconds
|
|
5
|
-
* @param {string} arg - The time string to convert
|
|
6
|
-
* @returns {number}
|
|
7
|
-
*/
|
|
8
|
-
export function ms(arg) {
|
|
9
|
-
const [value, unit] = splitUnit(arg)
|
|
10
|
-
if (unit === 'd') return getTimeInMs(value, 'days')
|
|
11
|
-
if (unit === 'day') return getTimeInMs(value, 'days')
|
|
12
|
-
if (unit === 'days') return getTimeInMs(value, 'days')
|
|
13
|
-
if (unit === 'h') return getTimeInMs(value, 'hours')
|
|
14
|
-
if (unit === 'hr') return getTimeInMs(value, 'hours')
|
|
15
|
-
if (unit === 'hour') return getTimeInMs(value, 'hours')
|
|
16
|
-
if (unit === 'hours') return getTimeInMs(value, 'hours')
|
|
17
|
-
if (unit === 'm') return getTimeInMs(value, 'minutes')
|
|
18
|
-
if (unit === 'min') return getTimeInMs(value, 'minutes')
|
|
19
|
-
if (unit === 'mins') return getTimeInMs(value, 'minutes')
|
|
20
|
-
if (unit === 'minute') return getTimeInMs(value, 'minutes')
|
|
21
|
-
if (unit === 'minutes') return getTimeInMs(value, 'minutes')
|
|
22
|
-
if (unit === 's') return getTimeInMs(value, 'seconds')
|
|
23
|
-
if (unit === 'sec') return getTimeInMs(value, 'seconds')
|
|
24
|
-
if (unit === 'secs') return getTimeInMs(value, 'seconds')
|
|
25
|
-
if (unit === 'second') return getTimeInMs(value, 'seconds')
|
|
26
|
-
if (unit === 'seconds') return getTimeInMs(value, 'seconds')
|
|
27
|
-
|
|
28
|
-
// The rest are for milliseconds
|
|
29
|
-
return value
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function getTimeInMs(value, unit = 'ms') {
|
|
33
|
-
switch (unit) {
|
|
34
|
-
case 'ms':
|
|
35
|
-
return value
|
|
36
|
-
case 'seconds':
|
|
37
|
-
return value * 1000
|
|
38
|
-
case 'minutes':
|
|
39
|
-
return value * 1000 * 60
|
|
40
|
-
case 'hours':
|
|
41
|
-
return value * 1000 * 60 * 60
|
|
42
|
-
case 'days':
|
|
43
|
-
return value * 1000 * 60 * 60 * 24
|
|
44
|
-
case 'weeks':
|
|
45
|
-
return value * 1000 * 60 * 60 * 24 * 7
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function toWeeks(ms) {
|
|
50
|
-
return ms / 1000 / 60 / 60 / 24 / 7
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function toDays(ms) {
|
|
54
|
-
return ms / 1000 / 60 / 60 / 24
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function toHours(ms) {
|
|
58
|
-
return ms / 1000 / 60 / 60
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export function toMinutes(ms) {
|
|
62
|
-
return ms / 1000 / 60
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function toSeconds(ms) {
|
|
66
|
-
return ms / 1000
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Get the total number of weeks, days, hours, minutes, and seconds
|
|
70
|
-
export function toReadableTime(ms) {
|
|
71
|
-
const weekMs = 1000 * 60 * 60 * 24 * 7
|
|
72
|
-
const dayMs = 1000 * 60 * 60 * 24
|
|
73
|
-
const hourMs = 1000 * 60 * 60
|
|
74
|
-
const minuteMs = 1000 * 60
|
|
75
|
-
|
|
76
|
-
const weeks = Math.floor(ms / weekMs)
|
|
77
|
-
const days = Math.floor((ms % weekMs) / dayMs)
|
|
78
|
-
const hours = Math.floor((ms % dayMs) / hourMs)
|
|
79
|
-
const minutes = Math.floor((ms % hourMs) / minuteMs)
|
|
80
|
-
const seconds = Math.floor((ms % minuteMs) / 1000)
|
|
81
|
-
|
|
82
|
-
return { weeks, days, hours, minutes, seconds }
|
|
83
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Converts Form Data into an object
|
|
3
|
-
* @param {FormData} formData
|
|
4
|
-
* @returns Object
|
|
5
|
-
*/
|
|
6
|
-
export function formDataToObject(formData) {
|
|
7
|
-
const obj = {}
|
|
8
|
-
for (let [key, value] of formData) {
|
|
9
|
-
if (typeof value === 'string') value = value.trim()
|
|
10
|
-
|
|
11
|
-
if (key.includes('[]')) {
|
|
12
|
-
// Handle array fields
|
|
13
|
-
const arrayKey = key.replace('[]', '')
|
|
14
|
-
if (!obj[arrayKey]) obj[arrayKey] = []
|
|
15
|
-
obj[arrayKey].push(value)
|
|
16
|
-
} else {
|
|
17
|
-
// Handle normal string fields
|
|
18
|
-
obj[key] = value
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return obj
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function flattenArrayFields(inputObject) {
|
|
25
|
-
const result = {}
|
|
26
|
-
|
|
27
|
-
for (const [key, value] of Object.entries(inputObject)) {
|
|
28
|
-
// Regex to match keys that follow pattern: arrayName[index][property]
|
|
29
|
-
const match = key.match(/^(\w+)(?:\[(\d+)\])?(?:\[(\w+)\])?$/)
|
|
30
|
-
if (match) {
|
|
31
|
-
const [, baseKey, index, property] = match
|
|
32
|
-
|
|
33
|
-
if (index !== undefined) {
|
|
34
|
-
// Handle array of objects
|
|
35
|
-
if (!result[baseKey]) result[baseKey] = []
|
|
36
|
-
const arrayIndex = parseInt(index)
|
|
37
|
-
if (!result[baseKey][arrayIndex]) result[baseKey][arrayIndex] = {}
|
|
38
|
-
if (property) {
|
|
39
|
-
result[baseKey][arrayIndex][property] = value
|
|
40
|
-
} else {
|
|
41
|
-
result[baseKey][arrayIndex] = value
|
|
42
|
-
}
|
|
43
|
-
} else if (property) {
|
|
44
|
-
// Handle single object
|
|
45
|
-
if (!result[baseKey]) result[baseKey] = {}
|
|
46
|
-
result[baseKey][property] = value
|
|
47
|
-
} else {
|
|
48
|
-
// Handle simple key-value
|
|
49
|
-
result[key] = value
|
|
50
|
-
}
|
|
51
|
-
} else {
|
|
52
|
-
// Copy key-value pair for unmatched keys
|
|
53
|
-
result[key] = value
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Remove empty objects from arrays and convert array-like objects to actual arrays
|
|
58
|
-
for (const key in result) {
|
|
59
|
-
if (typeof result[key] === 'object' && result[key] !== null) {
|
|
60
|
-
if (Object.keys(result[key]).every(k => !isNaN(parseInt(k)))) {
|
|
61
|
-
// Convert to array and filter out empty items
|
|
62
|
-
result[key] = Object.values(result[key]).filter(item => {
|
|
63
|
-
if (typeof item === 'object') {
|
|
64
|
-
return Object.values(item).some(v => v !== '')
|
|
65
|
-
}
|
|
66
|
-
return item !== ''
|
|
67
|
-
})
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return result
|
|
73
|
-
}
|
package/src/lib/form/index.js
DELETED