@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.
Files changed (228) hide show
  1. package/dist/cjs/dom/accessibility.cjs +2 -0
  2. package/dist/cjs/dom/actions/index.cjs +392 -7
  3. package/dist/cjs/dom/actions/masonry.cjs +97 -6
  4. package/dist/cjs/dom/actions/prefer-horizontal-scroll.cjs +58 -14
  5. package/dist/cjs/dom/actions/sticky.cjs +126 -6
  6. package/dist/cjs/dom/bounding-box.cjs +2 -0
  7. package/dist/cjs/dom/clipboard.cjs +2 -0
  8. package/dist/cjs/dom/cookie.cjs +3 -1
  9. package/dist/cjs/dom/css-vars.cjs +13 -3
  10. package/dist/cjs/dom/events.cjs +2 -0
  11. package/dist/cjs/dom/focusable.cjs +2 -0
  12. package/dist/cjs/dom/font-size.cjs +15 -3
  13. package/dist/cjs/dom/get-element.cjs +3 -1
  14. package/dist/cjs/dom/hash.cjs +2 -0
  15. package/dist/cjs/dom/index.cjs +1249 -47
  16. package/dist/cjs/dom/keyboard.cjs +2 -0
  17. package/dist/cjs/dom/local-store.cjs +3 -1
  18. package/dist/cjs/dom/media.cjs +2 -0
  19. package/dist/cjs/dom/observers/index.cjs +235 -9
  20. package/dist/cjs/dom/observers/intersection-observer.cjs +38 -6
  21. package/dist/cjs/dom/observers/mutation-observer.cjs +38 -6
  22. package/dist/cjs/dom/observers/observer.cjs +12 -2
  23. package/dist/cjs/dom/observers/resize-observer.cjs +38 -6
  24. package/dist/cjs/dom/observers/scroll-observer.cjs +62 -3
  25. package/dist/cjs/dom/pkce.cjs +13 -3
  26. package/dist/cjs/dom/query-params.cjs +3 -1
  27. package/dist/cjs/dom/random-string.cjs +2 -0
  28. package/dist/cjs/dom/sanitize.cjs +27 -3
  29. package/dist/cjs/dom/session-store.cjs +3 -1
  30. package/dist/cjs/dom/spam-prevention.cjs +2 -0
  31. package/dist/cjs/dom/trap-focus.cjs +131 -9
  32. package/dist/cjs/dom/ui/aria-current.cjs +2 -0
  33. package/dist/cjs/dom/ui/inconsistent-button-fix.cjs +2 -0
  34. package/dist/cjs/dom/ui/index.cjs +87 -9
  35. package/dist/cjs/dom/ui/scroll-container.cjs +2 -0
  36. package/dist/cjs/dom/ui/traverse-and-scramble.cjs +2 -0
  37. package/dist/cjs/lib/arrays/index.cjs +121 -13
  38. package/dist/cjs/lib/arrays/item-position.cjs +2 -0
  39. package/dist/cjs/lib/arrays/join.cjs +10 -2
  40. package/dist/cjs/lib/arrays/shuffle.cjs +2 -0
  41. package/dist/cjs/lib/arrays/sort.cjs +11 -3
  42. package/dist/cjs/lib/arrays/split-array.cjs +2 -0
  43. package/dist/cjs/lib/arrays/unique.cjs +2 -0
  44. package/dist/cjs/lib/auth/index.cjs +35 -3
  45. package/dist/cjs/lib/auth/route-manager.cjs +2 -0
  46. package/dist/cjs/lib/checks.cjs +2 -0
  47. package/dist/cjs/lib/date/days.cjs +3 -1
  48. package/dist/cjs/lib/date/index.cjs +190 -7
  49. package/dist/cjs/lib/date/months.cjs +3 -1
  50. package/dist/cjs/lib/date/time.cjs +14 -2
  51. package/dist/cjs/lib/form/form-data.cjs +2 -0
  52. package/dist/cjs/lib/form/index.cjs +104 -5
  53. package/dist/cjs/lib/form/sanitize.cjs +2 -0
  54. package/dist/cjs/lib/functions/callback.cjs +2 -0
  55. package/dist/cjs/lib/functions/debounce.cjs +2 -0
  56. package/dist/cjs/lib/functions/env.cjs +2 -0
  57. package/dist/cjs/lib/functions/functional.cjs +2 -0
  58. package/dist/cjs/lib/functions/index.cjs +124 -11
  59. package/dist/cjs/lib/functions/throttle.cjs +2 -0
  60. package/dist/cjs/lib/functions/timeout.cjs +2 -0
  61. package/dist/cjs/lib/hash.cjs +2 -0
  62. package/dist/cjs/lib/index.cjs +1160 -29
  63. package/dist/cjs/lib/numbers/index.cjs +17 -4
  64. package/dist/cjs/lib/numbers/math.cjs +2 -0
  65. package/dist/cjs/lib/objects/camelcase-keys.cjs +45 -4
  66. package/dist/cjs/lib/objects/empty.cjs +2 -0
  67. package/dist/cjs/lib/objects/equal.cjs +2 -0
  68. package/dist/cjs/lib/objects/extend.cjs +117 -6
  69. package/dist/cjs/lib/objects/flatten.cjs +11 -3
  70. package/dist/cjs/lib/objects/index.cjs +360 -27
  71. package/dist/cjs/lib/objects/json.cjs +2 -0
  72. package/dist/cjs/lib/objects/loop.cjs +2 -0
  73. package/dist/cjs/lib/objects/mix/mix.cjs +5 -3
  74. package/dist/cjs/lib/objects/nested-property.cjs +2 -0
  75. package/dist/cjs/lib/objects/normalize-object.cjs +78 -4
  76. package/dist/cjs/lib/objects/omit-empty.cjs +2 -0
  77. package/dist/cjs/lib/objects/size.cjs +2 -0
  78. package/dist/cjs/lib/objects/split.cjs +2 -0
  79. package/dist/cjs/lib/promises/index.cjs +51 -3
  80. package/dist/cjs/lib/promises/reject.cjs +19 -2
  81. package/dist/cjs/lib/sse.cjs +29 -4
  82. package/dist/cjs/lib/strings/convert-case/convert-case.cjs +2 -0
  83. package/dist/cjs/lib/strings/index.cjs +179 -11
  84. package/dist/cjs/lib/strings/markdown.cjs +3 -1
  85. package/dist/cjs/lib/strings/name.cjs +2 -0
  86. package/dist/cjs/lib/strings/pluralize.cjs +3 -1
  87. package/dist/cjs/lib/strings/query-string.cjs +2 -0
  88. package/dist/cjs/lib/style/index.cjs +31 -2
  89. package/dist/cjs/lib/symbols/index.cjs +22 -3
  90. package/dist/cjs/lib/symbols/symbols.cjs +2 -0
  91. package/dist/cjs/node/context.cjs +0 -0
  92. package/dist/cjs/node/dirname.cjs +4 -2
  93. package/dist/cjs/node/file-cache.cjs +45 -3
  94. package/dist/cjs/node/file.cjs +4 -2
  95. package/dist/cjs/node/hash.cjs +3 -1
  96. package/dist/cjs/node/index.cjs +278 -15
  97. package/dist/cjs/node/pkce.cjs +20 -8
  98. package/dist/cjs/node/random-string.cjs +3 -1
  99. package/dist/cjs/node/sanitize.cjs +27 -3
  100. package/dist/cjs/node/uuid.cjs +2 -0
  101. package/dist/esm/node/context.js +0 -0
  102. package/dist/esm/node/file-cache.js +1 -1
  103. package/dist/esm/node/pkce.js +3 -2
  104. package/dist/types/node/context.d.cts +2 -0
  105. package/dist/types/node/index.d.cts +1 -1
  106. package/dist/types/node/pkce.d.cts +7 -1
  107. package/package.json +5 -2
  108. package/CHANGELOG.md +0 -231
  109. package/eslint.config.js +0 -2
  110. package/src/dom/accessibility.js +0 -58
  111. package/src/dom/actions/index.js +0 -3
  112. package/src/dom/actions/masonry.js +0 -43
  113. package/src/dom/actions/prefer-horizontal-scroll.js +0 -121
  114. package/src/dom/actions/sticky.js +0 -85
  115. package/src/dom/bounding-box.js +0 -82
  116. package/src/dom/clipboard.js +0 -14
  117. package/src/dom/cookie.js +0 -32
  118. package/src/dom/css-vars.js +0 -19
  119. package/src/dom/events.js +0 -71
  120. package/src/dom/focusable.js +0 -165
  121. package/src/dom/font-size.js +0 -40
  122. package/src/dom/get-element.js +0 -176
  123. package/src/dom/hash.js +0 -9
  124. package/src/dom/index.js +0 -23
  125. package/src/dom/keyboard.js +0 -44
  126. package/src/dom/local-store.js +0 -66
  127. package/src/dom/media.js +0 -30
  128. package/src/dom/observers/index.js +0 -4
  129. package/src/dom/observers/intersection-observer.js +0 -43
  130. package/src/dom/observers/mutation-observer.js +0 -51
  131. package/src/dom/observers/observer.js +0 -18
  132. package/src/dom/observers/resize-observer.js +0 -66
  133. package/src/dom/observers/scroll-observer.js +0 -146
  134. package/src/dom/pkce.js +0 -34
  135. package/src/dom/query-params.js +0 -14
  136. package/src/dom/random-string.js +0 -18
  137. package/src/dom/random-string.test.js +0 -13
  138. package/src/dom/sanitize.js +0 -16
  139. package/src/dom/session-store.js +0 -29
  140. package/src/dom/spam-prevention.js +0 -40
  141. package/src/dom/trap-focus.js +0 -70
  142. package/src/dom/ui/aria-current.js +0 -20
  143. package/src/dom/ui/inconsistent-button-fix.js +0 -20
  144. package/src/dom/ui/index.js +0 -4
  145. package/src/dom/ui/scroll-container.js +0 -25
  146. package/src/dom/ui/traverse-and-scramble.js +0 -61
  147. package/src/lib/arrays/index.js +0 -6
  148. package/src/lib/arrays/item-position.js +0 -23
  149. package/src/lib/arrays/join.js +0 -20
  150. package/src/lib/arrays/shuffle.js +0 -21
  151. package/src/lib/arrays/sort.js +0 -88
  152. package/src/lib/arrays/sort.spec.js +0 -123
  153. package/src/lib/arrays/split-array.js +0 -15
  154. package/src/lib/arrays/unique.js +0 -3
  155. package/src/lib/auth/index.js +0 -1
  156. package/src/lib/auth/route-manager.js +0 -45
  157. package/src/lib/checks.js +0 -57
  158. package/src/lib/date/days.js +0 -9
  159. package/src/lib/date/index.js +0 -3
  160. package/src/lib/date/months.js +0 -74
  161. package/src/lib/date/time.js +0 -83
  162. package/src/lib/form/form-data.js +0 -73
  163. package/src/lib/form/index.js +0 -2
  164. package/src/lib/form/sanitize.js +0 -80
  165. package/src/lib/form/sanitize.spec.js +0 -126
  166. package/src/lib/functions/callback.js +0 -8
  167. package/src/lib/functions/debounce.js +0 -18
  168. package/src/lib/functions/env.js +0 -5
  169. package/src/lib/functions/functional.js +0 -113
  170. package/src/lib/functions/functional.test.js +0 -196
  171. package/src/lib/functions/index.js +0 -5
  172. package/src/lib/functions/throttle.js +0 -11
  173. package/src/lib/functions/timeout.js +0 -15
  174. package/src/lib/hash.js +0 -18
  175. package/src/lib/hash.spec.js +0 -163
  176. package/src/lib/index.js +0 -14
  177. package/src/lib/numbers/index.js +0 -12
  178. package/src/lib/numbers/math.js +0 -9
  179. package/src/lib/numbers/split-unit.test.js +0 -45
  180. package/src/lib/objects/camelcase-keys.js +0 -17
  181. package/src/lib/objects/camelcase-keys.test.js +0 -72
  182. package/src/lib/objects/empty.js +0 -10
  183. package/src/lib/objects/equal.js +0 -9
  184. package/src/lib/objects/extend.js +0 -16
  185. package/src/lib/objects/extend.test.js +0 -35
  186. package/src/lib/objects/flatten.js +0 -19
  187. package/src/lib/objects/index.js +0 -13
  188. package/src/lib/objects/json.js +0 -7
  189. package/src/lib/objects/loop.js +0 -11
  190. package/src/lib/objects/loop.test.js +0 -31
  191. package/src/lib/objects/mix/mix.js +0 -191
  192. package/src/lib/objects/mix/mix.md +0 -78
  193. package/src/lib/objects/mix/mix.test.js +0 -445
  194. package/src/lib/objects/nested-property.js +0 -41
  195. package/src/lib/objects/normalize-object.js +0 -10
  196. package/src/lib/objects/omit-empty.js +0 -23
  197. package/src/lib/objects/omit-empty.test.js +0 -85
  198. package/src/lib/objects/size.js +0 -41
  199. package/src/lib/objects/split.js +0 -19
  200. package/src/lib/promises/index.js +0 -1
  201. package/src/lib/promises/reject.js +0 -17
  202. package/src/lib/sse.js +0 -61
  203. package/src/lib/strings/convert-case/convert-case.js +0 -86
  204. package/src/lib/strings/convert-case/convert-case.md +0 -44
  205. package/src/lib/strings/convert-case/convert-case.test.js +0 -50
  206. package/src/lib/strings/index.js +0 -5
  207. package/src/lib/strings/markdown.js +0 -71
  208. package/src/lib/strings/name.js +0 -24
  209. package/src/lib/strings/name.test.js +0 -67
  210. package/src/lib/strings/pluralize.js +0 -2
  211. package/src/lib/strings/query-string.js +0 -18
  212. package/src/lib/style/index.js +0 -13
  213. package/src/lib/symbols/index.js +0 -1
  214. package/src/lib/symbols/symbols.js +0 -9
  215. package/src/node/dirname.js +0 -17
  216. package/src/node/file-cache.js +0 -184
  217. package/src/node/file.js +0 -13
  218. package/src/node/hash.js +0 -5
  219. package/src/node/index.js +0 -7
  220. package/src/node/pkce.js +0 -33
  221. package/src/node/random-string.js +0 -10
  222. package/src/node/random-string.test.js +0 -15
  223. package/src/node/sanitize.js +0 -13
  224. package/src/node/sanitize.spec.js +0 -142
  225. package/src/node/uuid.js +0 -5
  226. package/tsconfig.json +0 -23
  227. package/tsup.config.js +0 -38
  228. package/tsup.config.mjs +0 -45
@@ -1,80 +0,0 @@
1
- /**
2
- * @typedef {Object} SanitizeOptions
3
- * @property {Function} [sanitizer] - Function to sanitize strings
4
- * @property {*} [additional] - Any additional properties are passed through to the sanitizer function
5
- */
6
-
7
- /**
8
- * Core sanitization function that handles different value types.
9
- * Throws if no sanitizer function is provided.
10
- * Any additional properties in options are passed through to the sanitizer function.
11
- *
12
- * @param {*} value - The value to sanitize
13
- * @param {SanitizeOptions} [options={}] - Sanitization options
14
- * @throws {Error} If sanitizer function is not provided
15
- * @returns {*} Sanitized value
16
- * @example
17
- * // Basic sanitization
18
- * sanitize('hello', { sanitizer: str => str.trim() })
19
- *
20
- * // With additional options passed to sanitizer
21
- * sanitize('hello', {
22
- * sanitizer: (str, length, char) => str.padEnd(length, char),
23
- * length: 10,
24
- * char: '-'
25
- * })
26
- */
27
- export function sanitize(value, options = {}) {
28
- const { sanitizer, ...rest } = options
29
- if (!sanitizer) throw new Error('sanitizer function is required')
30
-
31
- if (typeof value === 'string') return sanitizer(value, rest)
32
- if (Array.isArray(value)) return sanitizeArray(value, { sanitizer, ...rest })
33
- if (value && typeof value === 'object') {
34
- return Object.fromEntries(
35
- Object.entries(value).map(([key, val]) => [
36
- key,
37
- sanitize(val, { sanitizer, ...rest }),
38
- ]),
39
- )
40
- }
41
- return value
42
- }
43
- /**
44
- * Sanitizes an array by recursively sanitizing each element.
45
- * Throws if no sanitizer function is provided.
46
- * Any additional properties in options are passed through to the sanitizer function.
47
- *
48
- * @param {Array} arr - Array to sanitize
49
- * @param {SanitizeOptions} options - Sanitization options
50
- * @throws {Error} If sanitizer function is not provided
51
- * @returns {Array} New array with sanitized values
52
- */
53
- function sanitizeArray(arr, { sanitizer, ...rest }) {
54
- if (!sanitizer) throw new Error('sanitizer function is required')
55
- return arr.map(item => sanitize(item, { sanitizer, ...rest }))
56
- }
57
-
58
- /**
59
- * Sanitizes all string values in an object recursively.
60
- * Throws if no sanitizer function is not provided.
61
- * Any additional properties in options are passed through to the sanitizer function.
62
- *
63
- * @param {Object} obj - Object to sanitize
64
- * @param {SanitizeOptions} [options={}] - Sanitization options
65
- * @throws {Error} If sanitizer function is not provided
66
- * @returns {Object} New object with sanitized values
67
- */
68
- function sanitizeObject(obj, { sanitizer, ...options } = {}) {
69
- if (!sanitizer) throw new Error('sanitizer function is required')
70
- if (Array.isArray(obj)) return sanitizeArray(obj, { sanitizer, ...options })
71
-
72
- return Object.fromEntries(
73
- Object.entries(obj).map(([key, value]) => [
74
- key,
75
- sanitize(value, { sanitizer, ...options }),
76
- ]),
77
- )
78
- }
79
-
80
- export { sanitizeArray, sanitizeObject }
@@ -1,126 +0,0 @@
1
- import sanitizeHtml from 'sanitize-html'
2
- import { describe, expect, it } from 'vitest'
3
- import { sanitize } from './sanitize.js'
4
-
5
- // Real sanitizer using sanitize-html
6
- function mockSanitizer(value, options = {}) {
7
- if (typeof value !== 'string') return value
8
- return sanitizeHtml(value, {
9
- allowedTags: ['b', 'i', 'em', 'strong', 'a'],
10
- allowedAttributes: {
11
- a: ['href'],
12
- },
13
- ...options,
14
- })
15
- }
16
-
17
- describe('sanitize', () => {
18
- it('sanitizes HTML in string values', () => {
19
- const input = {
20
- name: '<script>alert("xss")</script>John',
21
- bio: '<p>Hello <b>World</b> <script>alert("xss")</script></p>',
22
- link: '<a href="javascript:alert(1)">Click me</a>',
23
- safeLink: '<a href="https://example.com">Safe link</a>',
24
- }
25
-
26
- const expected = {
27
- name: 'John',
28
- bio: 'Hello <b>World</b> ',
29
- link: '<a>Click me</a>',
30
- safeLink: '<a href="https://example.com">Safe link</a>',
31
- }
32
-
33
- expect(sanitize(input, { sanitizer: mockSanitizer })).toEqual(expected)
34
- })
35
-
36
- it('sanitizes nested objects with HTML', () => {
37
- const input = {
38
- user: {
39
- name: '<script>alert("xss")</script>John',
40
- profile: {
41
- bio: '<p>Hello <b>World</b></p>',
42
- links: [
43
- '<a href="javascript:alert(1)">Bad</a>',
44
- '<a href="https://good.com">Good</a>',
45
- ],
46
- },
47
- },
48
- }
49
-
50
- const expected = {
51
- user: {
52
- name: 'John',
53
- profile: {
54
- bio: 'Hello <b>World</b>',
55
- links: ['<a>Bad</a>', '<a href="https://good.com">Good</a>'],
56
- },
57
- },
58
- }
59
-
60
- expect(sanitize(input, { sanitizer: mockSanitizer })).toEqual(expected)
61
- })
62
-
63
- it('preserves non-string values and sanitizes arrays correctly', () => {
64
- const input = {
65
- name: '<script>alert("xss")</script>John',
66
- age: 25,
67
- active: true,
68
- email: null,
69
- role: undefined,
70
- tags: ['<script>alert(1)</script>admin', 'user'],
71
- numbers: [1, 2, 3],
72
- mixed: ['<b>bold</b>', 42, null, '<script>alert(1)</script>text'],
73
- }
74
-
75
- const expected = {
76
- name: 'John',
77
- age: 25,
78
- active: true,
79
- email: null,
80
- role: undefined,
81
- tags: ['admin', 'user'],
82
- numbers: [1, 2, 3],
83
- mixed: ['<b>bold</b>', 42, null, 'text'],
84
- }
85
-
86
- expect(sanitize(input, { sanitizer: mockSanitizer })).toEqual(expected)
87
- })
88
-
89
- it('throws error when sanitizer is not provided', () => {
90
- const input = { name: '<script>alert(1)</script>John' }
91
- expect(() => sanitize(input)).toThrow('sanitizer function is required')
92
- })
93
-
94
- it('allows custom sanitizer options', () => {
95
- const input = {
96
- content: '<p>Hello <span>World</span> <script>alert(1)</script></p>',
97
- }
98
-
99
- const defaultOptions = {
100
- allowedTags: ['b', 'i', 'em', 'strong', 'a'],
101
- allowedAttributes: {
102
- a: ['href'],
103
- },
104
- }
105
-
106
- // Test with custom allowed tags
107
- const withSpan = sanitize(input, {
108
- sanitizer: v =>
109
- mockSanitizer(v, {
110
- ...defaultOptions,
111
- allowedTags: [...defaultOptions.allowedTags, 'span'],
112
- }),
113
- })
114
- expect(withSpan.content).toBe('Hello <span>World</span> ')
115
-
116
- // Test with no allowed tags
117
- const noTags = sanitize(input, {
118
- sanitizer: v =>
119
- mockSanitizer(v, {
120
- ...defaultOptions,
121
- allowedTags: [],
122
- }),
123
- })
124
- expect(noTags.content).toBe('Hello World ')
125
- })
126
- })
@@ -1,8 +0,0 @@
1
- /**
2
- * Safely executes a callback function if it's a function
3
- * @param {Function|*} fn - The potential callback function
4
- * @param {...*} data - Data arguments to pass to the callback
5
- */
6
- export function runCallback(fn, ...data) {
7
- if (typeof fn === 'function') fn(data)
8
- }
@@ -1,18 +0,0 @@
1
- export function debounce(callback, wait, immediate = false) {
2
- let timeout
3
-
4
- return function () {
5
- const context = this
6
- const args = arguments
7
-
8
- const callNow = immediate && !timeout
9
- clearTimeout(timeout)
10
- timeout = setTimeout(later, wait)
11
- if (callNow) callback.apply(context, args)
12
-
13
- function later() {
14
- timeout = null
15
- if (!immediate) callback.apply(context, args)
16
- }
17
- }
18
- }
@@ -1,5 +0,0 @@
1
- // Checks whether current environment is browser or node
2
- export function getEnv() {
3
- if (typeof window === 'object') return 'browser'
4
- if (typeof global === 'object') return 'node'
5
- }
@@ -1,113 +0,0 @@
1
- /**
2
- * Creates a curried version of a function that can be called with partial arguments
3
- * @param {Function} fn - The function to curry
4
- * @return {Function} The curried function
5
- * @property {any} return - The result of calling the original function when all arguments are provided
6
- * @example
7
- * const add = (a, b, c) => a + b + c
8
- * const curriedAdd = curry(add)
9
- * curriedAdd(1)(2)(3) // 6
10
- * curriedAdd(1, 2)(3) // 6
11
- * curriedAdd(1)(2, 3) // 6
12
- */
13
- export function curry(fn) {
14
- return function curried(...args) {
15
- if (args.length >= fn.length) {
16
- return fn.apply(this, args)
17
- } else {
18
- return function (...moreArgs) {
19
- return curried.apply(this, args.concat(moreArgs))
20
- }
21
- }
22
- }
23
- }
24
-
25
- /**
26
- * Composes functions from right to left (synchronous)
27
- * @param {...Function} fns - Functions to compose
28
- * @return {Function} The composed function
29
- * @property {any} return - The result of applying all functions in sequence
30
- * @example
31
- * const add1 = x => x + 1
32
- * const multiply2 = x => x * 2
33
- * const composed = compose(add1, multiply2)
34
- * composed(3) // 7 (3 * 2 + 1)
35
- */
36
- export function compose(...fns) {
37
- return function (value) {
38
- return fns.reduceRight((acc, fn) => fn(acc), value)
39
- }
40
- }
41
-
42
- /**
43
- * Composes functions from right to left (asynchronous)
44
- * @param {...Function} fns - Functions to compose (can be sync or async)
45
- * @return {Function} The composed async function
46
- * @property {Promise<any>} return - A Promise that resolves to the result of applying all functions
47
- * @example
48
- * const add1 = x => x + 1
49
- * const multiplyAsync = async x => x * 2
50
- * await composeAsync(add1, multiplyAsync)(3) // 7 (3 * 2 + 1)
51
- */
52
- export function composeAsync(...fns) {
53
- return async function (value) {
54
- return fns.reduceRight(async (acc, fn) => {
55
- const result = await acc
56
- return await fn(result)
57
- }, value)
58
- }
59
- }
60
-
61
- /**
62
- * Pipes functions from left to right (synchronous)
63
- * @param {...Function} fns - Functions to pipe
64
- * @return {Function} The piped function
65
- * @property {any} return - The result of applying all functions in sequence
66
- * @example
67
- * const add1 = x => x + 1
68
- * const multiply2 = x => x * 2
69
- * const piped = pipe(add1, multiply2)
70
- * piped(3) // 8 (3 + 1) * 2
71
- */
72
- export function pipe(...fns) {
73
- return function (value) {
74
- return fns.reduce((acc, fn) => fn(acc), value)
75
- }
76
- }
77
-
78
- /**
79
- * Pipes functions from left to right (asynchronous)
80
- * @param {...Function} fns - Functions to pipe (can be sync or async)
81
- * @return {Function} The piped async function
82
- * @property {Promise<any>} return - A Promise that resolves to the result of applying all functions
83
- * @example
84
- * const add1 = x => x + 1
85
- * const multiplyAsync = async x => x * 2
86
- * await pipeAsync(add1, multiplyAsync)(3) // 8 ((3 + 1) * 2)
87
- */
88
- export function pipeAsync(...fns) {
89
- return async function (value) {
90
- return fns.reduce(async (acc, fn) => {
91
- const result = await acc
92
- return await fn(result)
93
- }, value)
94
- }
95
- }
96
-
97
- /**
98
- * Calls a function n times with the current index and returns an array of results
99
- * @param {Function} fn - Function to call (receives index as argument)
100
- * @param {number} n - Number of times to call the function
101
- * @return {any[]} Array of results from calling the function
102
- * @property {any[]} return - Array containing the results of each function call
103
- * @example
104
- * times(i => i * 2, 3) // [0, 2, 4]
105
- * times(() => Math.random(), 2) // [0.123, 0.456] (random values)
106
- */
107
- export function times(fn, n) {
108
- const result = []
109
- for (let i = 0; i < n; i++) {
110
- result.push(fn(i))
111
- }
112
- return result
113
- }
@@ -1,196 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
- import {
3
- compose,
4
- composeAsync,
5
- curry,
6
- pipe,
7
- pipeAsync,
8
- times,
9
- } from './functional.js'
10
-
11
- describe('functional utilities', () => {
12
- describe('curry', () => {
13
- it('should curry a function with multiple arguments', () => {
14
- const add = (a, b, c) => a + b + c
15
- const curriedAdd = curry(add)
16
-
17
- expect(curriedAdd(1)(2)(3)).toBe(6)
18
- expect(curriedAdd(1, 2)(3)).toBe(6)
19
- expect(curriedAdd(1)(2, 3)).toBe(6)
20
- expect(curriedAdd(1, 2, 3)).toBe(6)
21
- })
22
- })
23
-
24
- describe('compose (sync)', () => {
25
- it('should compose functions from right to left', () => {
26
- const add1 = x => x + 1
27
- const multiply2 = x => x * 2
28
- const composed = compose(add1, multiply2)
29
-
30
- expect(composed(3)).toBe(7) // (3 * 2) + 1
31
- })
32
-
33
- it('should work with single function', () => {
34
- const add1 = x => x + 1
35
- const composed = compose(add1)
36
-
37
- expect(composed(5)).toBe(6)
38
- })
39
-
40
- it('should work with multiple functions', () => {
41
- const add1 = x => x + 1
42
- const multiply2 = x => x * 2
43
- const subtract3 = x => x - 3
44
- const composed = compose(subtract3, add1, multiply2)
45
-
46
- expect(composed(5)).toBe(8) // ((5 * 2) + 1) - 3 = 8
47
- })
48
- })
49
-
50
- describe('composeAsync', () => {
51
- it('should compose async functions from right to left', async () => {
52
- const add1 = x => x + 1
53
- const multiplyAsync = async x => x * 2
54
-
55
- const result = await composeAsync(add1, multiplyAsync)(3)
56
- expect(result).toBe(7) // (3 * 2) + 1
57
- })
58
-
59
- it('should work with all sync functions', async () => {
60
- const add1 = x => x + 1
61
- const multiply2 = x => x * 2
62
-
63
- const result = await composeAsync(add1, multiply2)(3)
64
- expect(result).toBe(7) // (3 * 2) + 1
65
- })
66
-
67
- it('should work with all async functions', async () => {
68
- const add1Async = async x => x + 1
69
- const multiply2Async = async x => x * 2
70
-
71
- const result = await composeAsync(add1Async, multiply2Async)(3)
72
- expect(result).toBe(7) // (3 * 2) + 1
73
- })
74
-
75
- it('should work with mixed sync and async functions', async () => {
76
- const add1 = x => x + 1
77
- const multiply2Async = async x => x * 2
78
- const subtract3 = x => x - 3
79
-
80
- const result = await composeAsync(subtract3, add1, multiply2Async)(5)
81
- expect(result).toBe(8) // ((5 * 2) + 1) - 3 = 8
82
- })
83
- })
84
-
85
- describe('pipe (sync)', () => {
86
- it('should pipe functions from left to right', () => {
87
- const add1 = x => x + 1
88
- const multiply2 = x => x * 2
89
- const piped = pipe(add1, multiply2)
90
-
91
- expect(piped(3)).toBe(8) // (3 + 1) * 2
92
- })
93
-
94
- it('should work with single function', () => {
95
- const add1 = x => x + 1
96
- const piped = pipe(add1)
97
-
98
- expect(piped(5)).toBe(6)
99
- })
100
-
101
- it('should work with multiple functions', () => {
102
- const add1 = x => x + 1
103
- const multiply2 = x => x * 2
104
- const subtract3 = x => x - 3
105
- const piped = pipe(add1, multiply2, subtract3)
106
-
107
- expect(piped(5)).toBe(9) // ((5 + 1) * 2) - 3 = 9
108
- })
109
- })
110
-
111
- describe('pipeAsync', () => {
112
- it('should pipe async functions from left to right', async () => {
113
- const add1 = x => x + 1
114
- const multiplyAsync = async x => x * 2
115
-
116
- const result = await pipeAsync(add1, multiplyAsync)(3)
117
- expect(result).toBe(8) // (3 + 1) * 2
118
- })
119
-
120
- it('should work with all sync functions', async () => {
121
- const add1 = x => x + 1
122
- const multiply2 = x => x * 2
123
-
124
- const result = await pipeAsync(add1, multiply2)(3)
125
- expect(result).toBe(8) // (3 + 1) * 2
126
- })
127
-
128
- it('should work with all async functions', async () => {
129
- const add1Async = async x => x + 1
130
- const multiply2Async = async x => x * 2
131
-
132
- const result = await pipeAsync(add1Async, multiply2Async)(3)
133
- expect(result).toBe(8) // (3 + 1) * 2
134
- })
135
-
136
- it('should work with mixed sync and async functions', async () => {
137
- const add1 = x => x + 1
138
- const multiply2Async = async x => x * 2
139
- const subtract3 = x => x - 3
140
-
141
- const result = await pipeAsync(add1, multiply2Async, subtract3)(5)
142
- expect(result).toBe(9) // ((5 + 1) * 2) - 3 = 9
143
- })
144
-
145
- it('should handle promises in the pipeline', async () => {
146
- const asyncAdd = async x => {
147
- await new Promise(resolve => setTimeout(resolve, 1))
148
- return x + 1
149
- }
150
- const multiply2 = x => x * 2
151
-
152
- const result = await pipeAsync(asyncAdd, multiply2)(3)
153
- expect(result).toBe(8) // (3 + 1) * 2
154
- })
155
- })
156
-
157
- describe('times', () => {
158
- it('should call function n times with index', () => {
159
- const result = times(i => i * 2, 3)
160
- expect(result).toEqual([0, 2, 4])
161
- })
162
-
163
- it('should work with zero iterations', () => {
164
- const result = times(i => i, 0)
165
- expect(result).toEqual([])
166
- })
167
-
168
- it('should work with functions that ignore index', () => {
169
- const result = times(() => 'hello', 2)
170
- expect(result).toEqual(['hello', 'hello'])
171
- })
172
- })
173
-
174
- // Edge cases and error handling
175
- describe('edge cases', () => {
176
- it('should handle empty function arrays in compose', () => {
177
- const composed = compose()
178
- expect(composed(5)).toBe(5)
179
- })
180
-
181
- it('should handle empty function arrays in pipe', () => {
182
- const piped = pipe()
183
- expect(piped(5)).toBe(5)
184
- })
185
-
186
- it('should handle empty function arrays in composeAsync', async () => {
187
- const result = await composeAsync()(5)
188
- expect(result).toBe(5)
189
- })
190
-
191
- it('should handle empty function arrays in pipeAsync', async () => {
192
- const result = await pipeAsync()(5)
193
- expect(result).toBe(5)
194
- })
195
- })
196
- })
@@ -1,5 +0,0 @@
1
- export * from './debounce.js'
2
- export * from './env.js'
3
- export * from './functional.js'
4
- export * from './throttle.js'
5
- export * from './timeout.js'
@@ -1,11 +0,0 @@
1
- export function throttle(callback, wait) {
2
- let lastCall = 0
3
-
4
- return function (...args) {
5
- const now = new Date().getTime()
6
- if (now - lastCall >= wait) {
7
- callback(...args)
8
- lastCall = now
9
- }
10
- }
11
- }
@@ -1,15 +0,0 @@
1
- // setTimeout for task ticking
2
- // reverses wait and callback functions of timeouts because it makes more sense when reading the code
3
- export function timeout(wait, callback) {
4
- setTimeout(callback, wait)
5
- }
6
-
7
- // Promise based timeouts for microtask ticking
8
- export function delay(ms) {
9
- return new Promise(resolve => setTimeout(resolve, ms))
10
- }
11
-
12
- // Alias of delay
13
- export function wait(ms) {
14
- return delay(ms)
15
- }
package/src/lib/hash.js DELETED
@@ -1,18 +0,0 @@
1
- export function isHashedValue(value, type = 'sha256') {
2
- if (typeof value !== 'string') return null
3
- value = value.trim()
4
- type = type.toLowerCase()
5
-
6
- if (type === 'sha256') {
7
- return value.length === 64 && /^[a-fA-F0-9]{64}$/.test(value)
8
- }
9
-
10
- if (type === 'sha1') {
11
- return value.length === 40 && /^[a-fA-F0-9]{40}$/.test(value)
12
- }
13
-
14
- if (type === 'md5') {
15
- return value.length === 32 && /^[a-fA-F0-9]{32}$/.test(value)
16
- }
17
- return null
18
- }