@splendidlabz/utils 1.8.1 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cjs/dom/events.cjs +0 -36
  3. package/dist/cjs/dom/index.cjs +90 -36
  4. package/dist/cjs/dom/observers/index.cjs +92 -2
  5. package/dist/cjs/dom/observers/scroll-observer.cjs +170 -0
  6. package/dist/cjs/lib/functions/callback.cjs +31 -0
  7. package/dist/cjs/lib/functions/functional.cjs +20 -0
  8. package/dist/cjs/lib/functions/index.cjs +20 -0
  9. package/dist/cjs/lib/index.cjs +20 -0
  10. package/dist/esm/dom/events.js +0 -35
  11. package/dist/esm/dom/index.js +89 -35
  12. package/dist/esm/dom/observers/index.js +90 -1
  13. package/dist/esm/dom/observers/scroll-observer.js +144 -0
  14. package/dist/esm/lib/functions/callback.js +7 -0
  15. package/dist/esm/lib/functions/functional.js +18 -0
  16. package/dist/esm/lib/functions/index.js +18 -0
  17. package/dist/esm/lib/index.js +18 -0
  18. package/dist/types/dom/events.d.cts +90 -18
  19. package/dist/types/dom/index.d.cts +2 -1
  20. package/dist/types/dom/observers/index.d.cts +1 -0
  21. package/dist/types/dom/observers/scroll-observer.d.cts +27 -0
  22. package/dist/types/lib/functions/callback.d.cts +8 -0
  23. package/dist/types/lib/functions/functional.d.cts +71 -5
  24. package/dist/types/lib/functions/index.d.cts +1 -1
  25. package/dist/types/lib/index.d.cts +1 -1
  26. package/package.json +1 -1
  27. package/src/dom/events.js +44 -50
  28. package/src/dom/observers/index.js +1 -0
  29. package/src/dom/observers/resize-observer.js +5 -5
  30. package/src/dom/observers/scroll-observer.js +132 -0
  31. package/src/lib/functions/callback.js +8 -0
  32. package/src/lib/functions/functional.js +82 -0
  33. package/src/lib/functions/functional.test.js +196 -0
@@ -35,6 +35,7 @@ __export(lib_exports, {
35
35
  RouteManager: () => RouteManager,
36
36
  camelCaseKeys: () => camelCaseKeys,
37
37
  compose: () => compose,
38
+ composeAsync: () => composeAsync,
38
39
  concatMix: () => concatMix,
39
40
  createMix: () => createMix,
40
41
  createSSE: () => createSSE,
@@ -76,6 +77,7 @@ __export(lib_exports, {
76
77
  parseJSON: () => parseJSON,
77
78
  parseSSE: () => parseSSE,
78
79
  pipe: () => pipe,
80
+ pipeAsync: () => pipeAsync,
79
81
  plural: () => plural,
80
82
  pluralize: () => pluralize,
81
83
  reject: () => reject,
@@ -568,11 +570,27 @@ function compose(...fns) {
568
570
  return fns.reduceRight((acc, fn) => fn(acc), value);
569
571
  };
570
572
  }
573
+ function composeAsync(...fns) {
574
+ return async function(value) {
575
+ return fns.reduceRight(async (acc, fn) => {
576
+ const result = await acc;
577
+ return await fn(result);
578
+ }, value);
579
+ };
580
+ }
571
581
  function pipe(...fns) {
572
582
  return function(value) {
573
583
  return fns.reduce((acc, fn) => fn(acc), value);
574
584
  };
575
585
  }
586
+ function pipeAsync(...fns) {
587
+ return async function(value) {
588
+ return fns.reduce(async (acc, fn) => {
589
+ const result = await acc;
590
+ return await fn(result);
591
+ }, value);
592
+ };
593
+ }
576
594
  function times(fn, n) {
577
595
  const result = [];
578
596
  for (let i = 0; i < n; i++) {
@@ -1065,6 +1083,7 @@ function getSymbolValue(object, description) {
1065
1083
  RouteManager,
1066
1084
  camelCaseKeys,
1067
1085
  compose,
1086
+ composeAsync,
1068
1087
  concatMix,
1069
1088
  createMix,
1070
1089
  createSSE,
@@ -1106,6 +1125,7 @@ function getSymbolValue(object, description) {
1106
1125
  parseJSON,
1107
1126
  parseSSE,
1108
1127
  pipe,
1128
+ pipeAsync,
1109
1129
  plural,
1110
1130
  pluralize,
1111
1131
  reject,
@@ -24,43 +24,8 @@ function updateEvent(event, updates) {
24
24
  ...updates
25
25
  });
26
26
  }
27
- function createListeners(listeners) {
28
- listeners = listeners || [];
29
- listeners.forEach((listener) => {
30
- const { node, event, handler } = listener;
31
- node.addEventListener(event, handler);
32
- });
33
- return {
34
- get list() {
35
- return listeners;
36
- },
37
- add({ node, event, handler }) {
38
- listeners.push({ node, event, handler });
39
- node.addEventListener(event, handler);
40
- },
41
- remove({ node, event, handler }) {
42
- const index = listeners.findIndex((listener) => {
43
- if (listener.node === node && listener.event === event && listener.handler === handler) {
44
- return true;
45
- }
46
- return false;
47
- });
48
- if (index !== -1) {
49
- listeners.splice(index, 1);
50
- node.removeEventListener(event, handler);
51
- }
52
- },
53
- clear() {
54
- listeners.forEach(({ node, event, handler }) => {
55
- listeners = [];
56
- node.removeEventListener(event, handler);
57
- });
58
- }
59
- };
60
- }
61
27
  export {
62
28
  addListeners,
63
- createListeners,
64
29
  dispatchEvent,
65
30
  removeListeners,
66
31
  updateEvent
@@ -134,40 +134,6 @@ function updateEvent(event, updates) {
134
134
  ...updates
135
135
  });
136
136
  }
137
- function createListeners(listeners) {
138
- listeners = listeners || [];
139
- listeners.forEach((listener) => {
140
- const { node, event, handler } = listener;
141
- node.addEventListener(event, handler);
142
- });
143
- return {
144
- get list() {
145
- return listeners;
146
- },
147
- add({ node, event, handler }) {
148
- listeners.push({ node, event, handler });
149
- node.addEventListener(event, handler);
150
- },
151
- remove({ node, event, handler }) {
152
- const index = listeners.findIndex((listener) => {
153
- if (listener.node === node && listener.event === event && listener.handler === handler) {
154
- return true;
155
- }
156
- return false;
157
- });
158
- if (index !== -1) {
159
- listeners.splice(index, 1);
160
- node.removeEventListener(event, handler);
161
- }
162
- },
163
- clear() {
164
- listeners.forEach(({ node, event, handler }) => {
165
- listeners = [];
166
- node.removeEventListener(event, handler);
167
- });
168
- }
169
- };
170
- }
171
137
 
172
138
  // src/dom/observers/observer.js
173
139
  function useObserverMethodOnTarget(target, observer, method = "observe", options = void 0) {
@@ -847,6 +813,94 @@ function mutationObserver(target, options) {
847
813
  };
848
814
  }
849
815
 
816
+ // src/dom/observers/scroll-observer.js
817
+ var defaultOptions2 = {
818
+ threshold: 0,
819
+ // Float between 0 to 1.
820
+ tolerance: 0.1,
821
+ // Float between 0 to 1. Tolerance for event firing
822
+ throttle: 16,
823
+ // Throttle interval in ms (default: ~60fps)
824
+ once: false
825
+ // Only fire threshold callback once
826
+ };
827
+ function scrollObserver(node, options = {}) {
828
+ const { callback, onScrollDown, onScrollUp, onEnterThreshold, ...userOpts } = options;
829
+ const opts = { ...defaultOptions2, ...userOpts };
830
+ const { threshold, tolerance, throttle, once } = opts;
831
+ const prevScrollDirection = null;
832
+ let prevScrollTop = 0;
833
+ let prevScrollPercent = 0;
834
+ let lastThrottleTime = 0;
835
+ let thresholdFired = false;
836
+ let rafId = null;
837
+ const isDocumentScroll = node === document || node === window;
838
+ const scrollElement = isDocumentScroll ? document.documentElement : node;
839
+ let cachedScrollHeight = 0;
840
+ let cachedClientHeight = 0;
841
+ updateCache();
842
+ const cacheObserver = resizeObserver(scrollElement, {
843
+ callback: updateCache
844
+ });
845
+ node.addEventListener("scroll", throttledObserve, { passive: true });
846
+ function updateCache() {
847
+ cachedScrollHeight = scrollElement.scrollHeight;
848
+ cachedClientHeight = scrollElement.clientHeight;
849
+ }
850
+ function throttledObserve() {
851
+ const now = Date.now();
852
+ if (now - lastThrottleTime < throttle) return;
853
+ lastThrottleTime = now;
854
+ rafId = requestAnimationFrame(observe);
855
+ }
856
+ function observe() {
857
+ const scrollTop = scrollElement.scrollTop;
858
+ if (Math.abs(scrollTop - prevScrollTop) < 1) return;
859
+ const scrollDirection = scrollTop > prevScrollTop ? "down" : "up";
860
+ const maxScroll = Math.max(1, cachedScrollHeight - cachedClientHeight);
861
+ const scrollPercent = Math.min(1, Math.max(0, scrollTop / maxScroll));
862
+ const thresholdMin = threshold - tolerance / 2;
863
+ const thresholdMax = threshold + tolerance / 2;
864
+ const wasInThreshold = prevScrollPercent >= thresholdMin && prevScrollPercent <= thresholdMax;
865
+ const isInThreshold = scrollPercent >= thresholdMin && scrollPercent <= thresholdMax;
866
+ const hasEnteredThreshold = !wasInThreshold && isInThreshold && (!once || !thresholdFired);
867
+ if (hasEnteredThreshold && once) {
868
+ thresholdFired = true;
869
+ }
870
+ const callbackData = {
871
+ scrollTop,
872
+ scrollDirection,
873
+ scrollPercent,
874
+ directionChanged: scrollDirection !== prevScrollDirection,
875
+ hasEnteredThreshold,
876
+ isInThreshold
877
+ };
878
+ if (typeof callback === "function") {
879
+ callback(callbackData);
880
+ }
881
+ if (scrollDirection !== prevScrollDirection) {
882
+ if (scrollDirection === "down" && typeof onScrollDown === "function") {
883
+ onScrollDown(callbackData);
884
+ }
885
+ if (scrollDirection === "up" && typeof onScrollUp === "function") {
886
+ onScrollUp(callbackData);
887
+ }
888
+ }
889
+ if (hasEnteredThreshold && typeof onEnterThreshold === "function") {
890
+ onEnterThreshold(callbackData);
891
+ }
892
+ prevScrollTop = scrollTop;
893
+ prevScrollPercent = scrollPercent;
894
+ }
895
+ return {
896
+ destroy() {
897
+ node.removeEventListener("scroll", throttledObserve);
898
+ if (rafId) cancelAnimationFrame(rafId);
899
+ cacheObserver.destroy();
900
+ }
901
+ };
902
+ }
903
+
850
904
  // src/dom/random-string.js
851
905
  function randomString(length = 10) {
852
906
  const firstLetter = String.fromCharCode(65 + Math.floor(Math.random() * 26));
@@ -1043,7 +1097,6 @@ export {
1043
1097
  checkForAccessibleName,
1044
1098
  cookies,
1045
1099
  copyRichText,
1046
- createListeners,
1047
1100
  dispatchEvent,
1048
1101
  em,
1049
1102
  findScrollContainer,
@@ -1085,6 +1138,7 @@ export {
1085
1138
  removeListeners,
1086
1139
  resizeObserver,
1087
1140
  sanitize2 as sanitize,
1141
+ scrollObserver,
1088
1142
  scrollToElement,
1089
1143
  sessionStore,
1090
1144
  setCSSValue,
@@ -121,8 +121,97 @@ function resizeObserver(target, options) {
121
121
  destroy: (_) => observer.disconnect()
122
122
  };
123
123
  }
124
+
125
+ // src/dom/observers/scroll-observer.js
126
+ var defaultOptions2 = {
127
+ threshold: 0,
128
+ // Float between 0 to 1.
129
+ tolerance: 0.1,
130
+ // Float between 0 to 1. Tolerance for event firing
131
+ throttle: 16,
132
+ // Throttle interval in ms (default: ~60fps)
133
+ once: false
134
+ // Only fire threshold callback once
135
+ };
136
+ function scrollObserver(node, options = {}) {
137
+ const { callback, onScrollDown, onScrollUp, onEnterThreshold, ...userOpts } = options;
138
+ const opts = { ...defaultOptions2, ...userOpts };
139
+ const { threshold, tolerance, throttle, once } = opts;
140
+ const prevScrollDirection = null;
141
+ let prevScrollTop = 0;
142
+ let prevScrollPercent = 0;
143
+ let lastThrottleTime = 0;
144
+ let thresholdFired = false;
145
+ let rafId = null;
146
+ const isDocumentScroll = node === document || node === window;
147
+ const scrollElement = isDocumentScroll ? document.documentElement : node;
148
+ let cachedScrollHeight = 0;
149
+ let cachedClientHeight = 0;
150
+ updateCache();
151
+ const cacheObserver = resizeObserver(scrollElement, {
152
+ callback: updateCache
153
+ });
154
+ node.addEventListener("scroll", throttledObserve, { passive: true });
155
+ function updateCache() {
156
+ cachedScrollHeight = scrollElement.scrollHeight;
157
+ cachedClientHeight = scrollElement.clientHeight;
158
+ }
159
+ function throttledObserve() {
160
+ const now = Date.now();
161
+ if (now - lastThrottleTime < throttle) return;
162
+ lastThrottleTime = now;
163
+ rafId = requestAnimationFrame(observe);
164
+ }
165
+ function observe() {
166
+ const scrollTop = scrollElement.scrollTop;
167
+ if (Math.abs(scrollTop - prevScrollTop) < 1) return;
168
+ const scrollDirection = scrollTop > prevScrollTop ? "down" : "up";
169
+ const maxScroll = Math.max(1, cachedScrollHeight - cachedClientHeight);
170
+ const scrollPercent = Math.min(1, Math.max(0, scrollTop / maxScroll));
171
+ const thresholdMin = threshold - tolerance / 2;
172
+ const thresholdMax = threshold + tolerance / 2;
173
+ const wasInThreshold = prevScrollPercent >= thresholdMin && prevScrollPercent <= thresholdMax;
174
+ const isInThreshold = scrollPercent >= thresholdMin && scrollPercent <= thresholdMax;
175
+ const hasEnteredThreshold = !wasInThreshold && isInThreshold && (!once || !thresholdFired);
176
+ if (hasEnteredThreshold && once) {
177
+ thresholdFired = true;
178
+ }
179
+ const callbackData = {
180
+ scrollTop,
181
+ scrollDirection,
182
+ scrollPercent,
183
+ directionChanged: scrollDirection !== prevScrollDirection,
184
+ hasEnteredThreshold,
185
+ isInThreshold
186
+ };
187
+ if (typeof callback === "function") {
188
+ callback(callbackData);
189
+ }
190
+ if (scrollDirection !== prevScrollDirection) {
191
+ if (scrollDirection === "down" && typeof onScrollDown === "function") {
192
+ onScrollDown(callbackData);
193
+ }
194
+ if (scrollDirection === "up" && typeof onScrollUp === "function") {
195
+ onScrollUp(callbackData);
196
+ }
197
+ }
198
+ if (hasEnteredThreshold && typeof onEnterThreshold === "function") {
199
+ onEnterThreshold(callbackData);
200
+ }
201
+ prevScrollTop = scrollTop;
202
+ prevScrollPercent = scrollPercent;
203
+ }
204
+ return {
205
+ destroy() {
206
+ node.removeEventListener("scroll", throttledObserve);
207
+ if (rafId) cancelAnimationFrame(rafId);
208
+ cacheObserver.destroy();
209
+ }
210
+ };
211
+ }
124
212
  export {
125
213
  intersectionObserver,
126
214
  mutationObserver,
127
- resizeObserver
215
+ resizeObserver,
216
+ scrollObserver
128
217
  };
@@ -0,0 +1,144 @@
1
+ // src/dom/events.js
2
+ function dispatchEvent(node, eventName, detail, options = {}) {
3
+ node.dispatchEvent(
4
+ new CustomEvent(eventName, {
5
+ ...options,
6
+ detail
7
+ })
8
+ );
9
+ }
10
+
11
+ // src/dom/get-element.js
12
+ function getNodeType(node) {
13
+ if (node instanceof Element) return "element";
14
+ if (node instanceof NodeList) return "nodelist";
15
+ if (Array.isArray(node)) return "array";
16
+ }
17
+
18
+ // src/dom/observers/observer.js
19
+ function useObserverMethodOnTarget(target, observer, method = "observe", options = void 0) {
20
+ const targetType = getNodeType(target);
21
+ if (targetType === "element") observer[method](target, options);
22
+ if (targetType === "nodelist") {
23
+ const elements = Array.from(target);
24
+ elements.forEach((element) => observer[method](element, options));
25
+ }
26
+ if (targetType === "array") {
27
+ target.forEach((element) => observer[method](element, options));
28
+ }
29
+ }
30
+
31
+ // src/dom/observers/resize-observer.js
32
+ function resizeObserver(target, options) {
33
+ const { callback, ...opts } = options;
34
+ const observer = new ResizeObserver(observerFn);
35
+ if (target === window) target = document.body;
36
+ useObserverMethodOnTarget(target, observer, "observe", opts);
37
+ function observerFn(entries) {
38
+ for (const entry of entries) {
39
+ if (callback) callback({ entry, entries, observer });
40
+ else dispatchEvent(target, "resize-obs", { entry, entries, observer });
41
+ }
42
+ }
43
+ return {
44
+ observe(target2) {
45
+ useObserverMethodOnTarget(target2, observer, "observe", options);
46
+ },
47
+ unobserve(target2) {
48
+ useObserverMethodOnTarget(target2, observer, "unobserve");
49
+ },
50
+ disconnect: (_) => observer.disconnect(),
51
+ destroy: (_) => observer.disconnect()
52
+ };
53
+ }
54
+
55
+ // src/dom/observers/scroll-observer.js
56
+ var defaultOptions = {
57
+ threshold: 0,
58
+ // Float between 0 to 1.
59
+ tolerance: 0.1,
60
+ // Float between 0 to 1. Tolerance for event firing
61
+ throttle: 16,
62
+ // Throttle interval in ms (default: ~60fps)
63
+ once: false
64
+ // Only fire threshold callback once
65
+ };
66
+ function scrollObserver(node, options = {}) {
67
+ const { callback, onScrollDown, onScrollUp, onEnterThreshold, ...userOpts } = options;
68
+ const opts = { ...defaultOptions, ...userOpts };
69
+ const { threshold, tolerance, throttle, once } = opts;
70
+ const prevScrollDirection = null;
71
+ let prevScrollTop = 0;
72
+ let prevScrollPercent = 0;
73
+ let lastThrottleTime = 0;
74
+ let thresholdFired = false;
75
+ let rafId = null;
76
+ const isDocumentScroll = node === document || node === window;
77
+ const scrollElement = isDocumentScroll ? document.documentElement : node;
78
+ let cachedScrollHeight = 0;
79
+ let cachedClientHeight = 0;
80
+ updateCache();
81
+ const cacheObserver = resizeObserver(scrollElement, {
82
+ callback: updateCache
83
+ });
84
+ node.addEventListener("scroll", throttledObserve, { passive: true });
85
+ function updateCache() {
86
+ cachedScrollHeight = scrollElement.scrollHeight;
87
+ cachedClientHeight = scrollElement.clientHeight;
88
+ }
89
+ function throttledObserve() {
90
+ const now = Date.now();
91
+ if (now - lastThrottleTime < throttle) return;
92
+ lastThrottleTime = now;
93
+ rafId = requestAnimationFrame(observe);
94
+ }
95
+ function observe() {
96
+ const scrollTop = scrollElement.scrollTop;
97
+ if (Math.abs(scrollTop - prevScrollTop) < 1) return;
98
+ const scrollDirection = scrollTop > prevScrollTop ? "down" : "up";
99
+ const maxScroll = Math.max(1, cachedScrollHeight - cachedClientHeight);
100
+ const scrollPercent = Math.min(1, Math.max(0, scrollTop / maxScroll));
101
+ const thresholdMin = threshold - tolerance / 2;
102
+ const thresholdMax = threshold + tolerance / 2;
103
+ const wasInThreshold = prevScrollPercent >= thresholdMin && prevScrollPercent <= thresholdMax;
104
+ const isInThreshold = scrollPercent >= thresholdMin && scrollPercent <= thresholdMax;
105
+ const hasEnteredThreshold = !wasInThreshold && isInThreshold && (!once || !thresholdFired);
106
+ if (hasEnteredThreshold && once) {
107
+ thresholdFired = true;
108
+ }
109
+ const callbackData = {
110
+ scrollTop,
111
+ scrollDirection,
112
+ scrollPercent,
113
+ directionChanged: scrollDirection !== prevScrollDirection,
114
+ hasEnteredThreshold,
115
+ isInThreshold
116
+ };
117
+ if (typeof callback === "function") {
118
+ callback(callbackData);
119
+ }
120
+ if (scrollDirection !== prevScrollDirection) {
121
+ if (scrollDirection === "down" && typeof onScrollDown === "function") {
122
+ onScrollDown(callbackData);
123
+ }
124
+ if (scrollDirection === "up" && typeof onScrollUp === "function") {
125
+ onScrollUp(callbackData);
126
+ }
127
+ }
128
+ if (hasEnteredThreshold && typeof onEnterThreshold === "function") {
129
+ onEnterThreshold(callbackData);
130
+ }
131
+ prevScrollTop = scrollTop;
132
+ prevScrollPercent = scrollPercent;
133
+ }
134
+ return {
135
+ destroy() {
136
+ node.removeEventListener("scroll", throttledObserve);
137
+ if (rafId) cancelAnimationFrame(rafId);
138
+ cacheObserver.destroy();
139
+ }
140
+ };
141
+ }
142
+ export {
143
+ scrollObserver
144
+ };
@@ -0,0 +1,7 @@
1
+ // src/lib/functions/callback.js
2
+ function runCallback(fn, ...data) {
3
+ if (typeof fn === "function") fn(data);
4
+ }
5
+ export {
6
+ runCallback
7
+ };
@@ -15,11 +15,27 @@ function compose(...fns) {
15
15
  return fns.reduceRight((acc, fn) => fn(acc), value);
16
16
  };
17
17
  }
18
+ function composeAsync(...fns) {
19
+ return async function(value) {
20
+ return fns.reduceRight(async (acc, fn) => {
21
+ const result = await acc;
22
+ return await fn(result);
23
+ }, value);
24
+ };
25
+ }
18
26
  function pipe(...fns) {
19
27
  return function(value) {
20
28
  return fns.reduce((acc, fn) => fn(acc), value);
21
29
  };
22
30
  }
31
+ function pipeAsync(...fns) {
32
+ return async function(value) {
33
+ return fns.reduce(async (acc, fn) => {
34
+ const result = await acc;
35
+ return await fn(result);
36
+ }, value);
37
+ };
38
+ }
23
39
  function times(fn, n) {
24
40
  const result = [];
25
41
  for (let i = 0; i < n; i++) {
@@ -29,7 +45,9 @@ function times(fn, n) {
29
45
  }
30
46
  export {
31
47
  compose,
48
+ composeAsync,
32
49
  curry,
33
50
  pipe,
51
+ pipeAsync,
34
52
  times
35
53
  };
@@ -38,11 +38,27 @@ function compose(...fns) {
38
38
  return fns.reduceRight((acc, fn) => fn(acc), value);
39
39
  };
40
40
  }
41
+ function composeAsync(...fns) {
42
+ return async function(value) {
43
+ return fns.reduceRight(async (acc, fn) => {
44
+ const result = await acc;
45
+ return await fn(result);
46
+ }, value);
47
+ };
48
+ }
41
49
  function pipe(...fns) {
42
50
  return function(value) {
43
51
  return fns.reduce((acc, fn) => fn(acc), value);
44
52
  };
45
53
  }
54
+ function pipeAsync(...fns) {
55
+ return async function(value) {
56
+ return fns.reduce(async (acc, fn) => {
57
+ const result = await acc;
58
+ return await fn(result);
59
+ }, value);
60
+ };
61
+ }
46
62
  function times(fn, n) {
47
63
  const result = [];
48
64
  for (let i = 0; i < n; i++) {
@@ -75,11 +91,13 @@ function wait(ms) {
75
91
  }
76
92
  export {
77
93
  compose,
94
+ composeAsync,
78
95
  curry,
79
96
  debounce,
80
97
  delay,
81
98
  getEnv,
82
99
  pipe,
100
+ pipeAsync,
83
101
  throttle,
84
102
  timeout,
85
103
  times,
@@ -450,11 +450,27 @@ function compose(...fns) {
450
450
  return fns.reduceRight((acc, fn) => fn(acc), value);
451
451
  };
452
452
  }
453
+ function composeAsync(...fns) {
454
+ return async function(value) {
455
+ return fns.reduceRight(async (acc, fn) => {
456
+ const result = await acc;
457
+ return await fn(result);
458
+ }, value);
459
+ };
460
+ }
453
461
  function pipe(...fns) {
454
462
  return function(value) {
455
463
  return fns.reduce((acc, fn) => fn(acc), value);
456
464
  };
457
465
  }
466
+ function pipeAsync(...fns) {
467
+ return async function(value) {
468
+ return fns.reduce(async (acc, fn) => {
469
+ const result = await acc;
470
+ return await fn(result);
471
+ }, value);
472
+ };
473
+ }
458
474
  function times(fn, n) {
459
475
  const result = [];
460
476
  for (let i = 0; i < n; i++) {
@@ -946,6 +962,7 @@ export {
946
962
  RouteManager,
947
963
  camelCaseKeys,
948
964
  compose,
965
+ composeAsync,
949
966
  concatMix,
950
967
  createMix,
951
968
  createSSE,
@@ -987,6 +1004,7 @@ export {
987
1004
  parseJSON,
988
1005
  parseSSE,
989
1006
  pipe,
1007
+ pipeAsync,
990
1008
  plural,
991
1009
  pluralize,
992
1010
  reject,