@splendidlabz/utils 1.11.3 → 1.11.5

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 (408) hide show
  1. package/dist/cjs/dom/accessibility.cjs +53 -0
  2. package/dist/cjs/dom/actions/index.cjs +410 -0
  3. package/dist/cjs/dom/actions/masonry.cjs +152 -0
  4. package/dist/cjs/dom/actions/prefer-horizontal-scroll.cjs +157 -0
  5. package/dist/cjs/dom/actions/sticky.cjs +213 -0
  6. package/dist/cjs/dom/bounding-box.cjs +70 -0
  7. package/dist/cjs/dom/clipboard.cjs +37 -0
  8. package/dist/cjs/dom/cookie.cjs +57 -0
  9. package/dist/cjs/dom/css-vars.cjs +57 -0
  10. package/dist/cjs/dom/events.cjs +59 -0
  11. package/{src/dom/focusable.js → dist/cjs/dom/focusable.cjs} +51 -73
  12. package/dist/cjs/dom/font-size.cjs +80 -0
  13. package/dist/cjs/dom/get-element.cjs +98 -0
  14. package/dist/cjs/dom/hash.cjs +35 -0
  15. package/dist/cjs/dom/index.cjs +1267 -0
  16. package/dist/cjs/dom/keyboard.cjs +51 -0
  17. package/dist/cjs/dom/local-store.cjs +79 -0
  18. package/dist/cjs/dom/media.cjs +59 -0
  19. package/dist/cjs/dom/observers/index.cjs +253 -0
  20. package/dist/cjs/dom/observers/intersection-observer.cjs +91 -0
  21. package/dist/cjs/dom/observers/mutation-observer.cjs +95 -0
  22. package/dist/cjs/dom/observers/observer.cjs +48 -0
  23. package/dist/cjs/dom/observers/resize-observer.cjs +84 -0
  24. package/dist/cjs/dom/observers/scroll-observer.cjs +177 -0
  25. package/dist/cjs/dom/pkce.cjs +53 -0
  26. package/dist/cjs/dom/query-params.cjs +38 -0
  27. package/dist/cjs/dom/random-string.cjs +38 -0
  28. package/dist/cjs/dom/sanitize.cjs +65 -0
  29. package/dist/cjs/dom/session-store.cjs +49 -0
  30. package/dist/cjs/dom/spam-prevention.cjs +50 -0
  31. package/dist/cjs/dom/trap-focus.cjs +197 -0
  32. package/dist/cjs/dom/ui/aria-current.cjs +43 -0
  33. package/dist/cjs/dom/ui/inconsistent-button-fix.cjs +35 -0
  34. package/dist/cjs/dom/ui/index.cjs +105 -0
  35. package/dist/cjs/dom/ui/scroll-container.cjs +47 -0
  36. package/dist/cjs/dom/ui/traverse-and-scramble.cjs +50 -0
  37. package/dist/cjs/lib/arrays/index.cjs +139 -0
  38. package/dist/cjs/lib/arrays/item-position.cjs +42 -0
  39. package/dist/cjs/lib/arrays/join.cjs +43 -0
  40. package/dist/cjs/lib/arrays/shuffle.cjs +42 -0
  41. package/dist/cjs/lib/arrays/sort.cjs +67 -0
  42. package/dist/cjs/lib/arrays/split-array.cjs +41 -0
  43. package/dist/cjs/lib/arrays/unique.cjs +31 -0
  44. package/dist/cjs/lib/auth/index.cjs +53 -0
  45. package/dist/cjs/lib/auth/route-manager.cjs +51 -0
  46. package/dist/cjs/lib/checks.cjs +63 -0
  47. package/dist/cjs/lib/date/days.cjs +37 -0
  48. package/dist/cjs/lib/date/index.cjs +208 -0
  49. package/dist/cjs/lib/date/months.cjs +102 -0
  50. package/dist/cjs/lib/date/time.cjs +117 -0
  51. package/dist/cjs/lib/form/form-data.cjs +83 -0
  52. package/dist/cjs/lib/form/index.cjs +122 -0
  53. package/dist/cjs/lib/form/sanitize.cjs +61 -0
  54. package/dist/cjs/lib/functions/callback.cjs +31 -0
  55. package/dist/cjs/lib/functions/debounce.cjs +43 -0
  56. package/dist/cjs/lib/functions/env.cjs +32 -0
  57. package/dist/cjs/lib/functions/functional.cjs +82 -0
  58. package/dist/cjs/lib/functions/index.cjs +142 -0
  59. package/dist/cjs/lib/functions/throttle.cjs +38 -0
  60. package/dist/cjs/lib/functions/timeout.cjs +41 -0
  61. package/dist/cjs/lib/hash.cjs +43 -0
  62. package/dist/cjs/lib/index.cjs +1178 -0
  63. package/dist/cjs/lib/numbers/index.cjs +49 -0
  64. package/dist/cjs/lib/numbers/math.cjs +36 -0
  65. package/dist/cjs/lib/objects/camelcase-keys.cjs +80 -0
  66. package/dist/cjs/lib/objects/empty.cjs +39 -0
  67. package/dist/cjs/lib/objects/equal.cjs +47 -0
  68. package/dist/cjs/lib/objects/extend.cjs +147 -0
  69. package/dist/cjs/lib/objects/flatten.cjs +48 -0
  70. package/dist/cjs/lib/objects/index.cjs +378 -0
  71. package/dist/cjs/lib/objects/json.cjs +35 -0
  72. package/dist/cjs/lib/objects/loop.cjs +40 -0
  73. package/dist/cjs/lib/objects/mix/mix.cjs +115 -0
  74. package/dist/cjs/lib/objects/nested-property.cjs +45 -0
  75. package/dist/cjs/lib/objects/normalize-object.cjs +106 -0
  76. package/dist/cjs/lib/objects/omit-empty.cjs +40 -0
  77. package/dist/cjs/lib/objects/size.cjs +63 -0
  78. package/dist/cjs/lib/objects/split.cjs +39 -0
  79. package/dist/cjs/lib/promises/index.cjs +69 -0
  80. package/dist/cjs/lib/promises/reject.cjs +67 -0
  81. package/dist/cjs/lib/sse.cjs +99 -0
  82. package/dist/cjs/lib/strings/convert-case/convert-case.cjs +96 -0
  83. package/dist/cjs/lib/strings/index.cjs +197 -0
  84. package/dist/cjs/lib/strings/markdown.cjs +76 -0
  85. package/dist/cjs/lib/strings/name.cjs +46 -0
  86. package/dist/cjs/lib/strings/pluralize.cjs +40 -0
  87. package/dist/cjs/lib/strings/query-string.cjs +43 -0
  88. package/dist/cjs/lib/style/index.cjs +64 -0
  89. package/dist/cjs/lib/symbols/index.cjs +40 -0
  90. package/dist/cjs/lib/symbols/symbols.cjs +38 -0
  91. package/dist/cjs/node/dirname.cjs +49 -0
  92. package/dist/cjs/node/file-cache.cjs +200 -0
  93. package/dist/cjs/node/file.cjs +50 -0
  94. package/dist/cjs/node/hash.cjs +42 -0
  95. package/dist/cjs/node/index.cjs +296 -0
  96. package/dist/cjs/node/pkce.cjs +64 -0
  97. package/dist/cjs/node/random-string.cjs +43 -0
  98. package/dist/cjs/node/sanitize.cjs +65 -0
  99. package/dist/cjs/node/uuid.cjs +42 -0
  100. package/dist/esm/dom/accessibility.js +26 -0
  101. package/dist/esm/dom/actions/index.js +3 -0
  102. package/dist/esm/dom/actions/masonry.js +38 -0
  103. package/dist/esm/dom/actions/prefer-horizontal-scroll.js +90 -0
  104. package/dist/esm/dom/actions/sticky.js +70 -0
  105. package/dist/esm/dom/bounding-box.js +44 -0
  106. package/dist/esm/dom/clipboard.js +12 -0
  107. package/dist/esm/dom/cookie.js +31 -0
  108. package/dist/esm/dom/css-vars.js +21 -0
  109. package/dist/esm/dom/events.js +31 -0
  110. package/dist/esm/dom/focusable.js +117 -0
  111. package/dist/esm/dom/font-size.js +40 -0
  112. package/dist/esm/dom/get-element.js +66 -0
  113. package/dist/esm/dom/hash.js +10 -0
  114. package/dist/esm/dom/index.js +23 -0
  115. package/dist/esm/dom/keyboard.js +22 -0
  116. package/{src → dist/esm}/dom/local-store.js +16 -28
  117. package/dist/esm/dom/media.js +32 -0
  118. package/dist/esm/dom/observers/index.js +4 -0
  119. package/dist/esm/dom/observers/intersection-observer.js +36 -0
  120. package/dist/esm/dom/observers/mutation-observer.js +40 -0
  121. package/dist/esm/dom/observers/observer.js +15 -0
  122. package/dist/esm/dom/observers/resize-observer.js +29 -0
  123. package/dist/esm/dom/observers/scroll-observer.js +95 -0
  124. package/dist/esm/dom/pkce.js +20 -0
  125. package/dist/esm/dom/query-params.js +13 -0
  126. package/dist/esm/dom/random-string.js +12 -0
  127. package/dist/esm/dom/sanitize.js +8 -0
  128. package/dist/esm/dom/session-store.js +24 -0
  129. package/dist/esm/dom/spam-prevention.js +25 -0
  130. package/dist/esm/dom/trap-focus.js +51 -0
  131. package/dist/esm/dom/ui/aria-current.js +17 -0
  132. package/dist/esm/dom/ui/inconsistent-button-fix.js +10 -0
  133. package/dist/esm/dom/ui/index.js +4 -0
  134. package/dist/esm/dom/ui/scroll-container.js +22 -0
  135. package/dist/esm/dom/ui/traverse-and-scramble.js +25 -0
  136. package/dist/esm/lib/arrays/index.js +6 -0
  137. package/dist/esm/lib/arrays/item-position.js +15 -0
  138. package/dist/esm/lib/arrays/join.js +12 -0
  139. package/dist/esm/lib/arrays/shuffle.js +17 -0
  140. package/dist/esm/lib/arrays/sort.js +36 -0
  141. package/dist/esm/lib/arrays/split-array.js +16 -0
  142. package/dist/esm/lib/arrays/unique.js +6 -0
  143. package/dist/esm/lib/auth/index.js +1 -0
  144. package/dist/esm/lib/auth/route-manager.js +25 -0
  145. package/dist/esm/lib/checks.js +34 -0
  146. package/dist/esm/lib/date/days.js +12 -0
  147. package/dist/esm/lib/date/index.js +3 -0
  148. package/dist/esm/lib/date/months.js +77 -0
  149. package/dist/esm/lib/date/time.js +75 -0
  150. package/dist/esm/lib/form/form-data.js +57 -0
  151. package/dist/esm/lib/form/index.js +2 -0
  152. package/dist/esm/lib/form/sanitize.js +34 -0
  153. package/dist/esm/lib/functions/callback.js +6 -0
  154. package/dist/esm/lib/functions/debounce.js +18 -0
  155. package/dist/esm/lib/functions/env.js +7 -0
  156. package/dist/esm/lib/functions/functional.js +52 -0
  157. package/dist/esm/lib/functions/index.js +5 -0
  158. package/dist/esm/lib/functions/throttle.js +13 -0
  159. package/dist/esm/lib/functions/timeout.js +14 -0
  160. package/dist/esm/lib/hash.js +18 -0
  161. package/dist/esm/lib/index.js +14 -0
  162. package/dist/esm/lib/numbers/index.js +11 -0
  163. package/dist/esm/lib/numbers/math.js +10 -0
  164. package/dist/esm/lib/objects/camelcase-keys.js +16 -0
  165. package/dist/esm/lib/objects/empty.js +13 -0
  166. package/dist/esm/lib/objects/equal.js +11 -0
  167. package/dist/esm/lib/objects/extend.js +13 -0
  168. package/dist/esm/lib/objects/flatten.js +17 -0
  169. package/dist/esm/lib/objects/index.js +13 -0
  170. package/dist/esm/lib/objects/json.js +10 -0
  171. package/dist/esm/lib/objects/loop.js +14 -0
  172. package/dist/esm/lib/objects/mix/mix.js +88 -0
  173. package/dist/esm/lib/objects/nested-property.js +18 -0
  174. package/dist/esm/lib/objects/normalize-object.js +9 -0
  175. package/dist/esm/lib/objects/omit-empty.js +15 -0
  176. package/dist/esm/lib/objects/size.js +38 -0
  177. package/dist/esm/lib/objects/split.js +14 -0
  178. package/dist/esm/lib/promises/index.js +1 -0
  179. package/dist/esm/lib/promises/reject.js +17 -0
  180. package/dist/esm/lib/sse.js +50 -0
  181. package/dist/esm/lib/strings/convert-case/convert-case.js +64 -0
  182. package/dist/esm/lib/strings/index.js +5 -0
  183. package/dist/esm/lib/strings/markdown.js +40 -0
  184. package/dist/esm/lib/strings/name.js +21 -0
  185. package/dist/esm/lib/strings/pluralize.js +5 -0
  186. package/dist/esm/lib/strings/query-string.js +16 -0
  187. package/dist/esm/lib/style/index.js +12 -0
  188. package/dist/esm/lib/symbols/index.js +1 -0
  189. package/dist/esm/lib/symbols/symbols.js +12 -0
  190. package/dist/esm/node/context.js +0 -0
  191. package/dist/esm/node/dirname.js +13 -0
  192. package/dist/esm/node/file-cache.js +121 -0
  193. package/dist/esm/node/file.js +14 -0
  194. package/dist/esm/node/hash.js +7 -0
  195. package/dist/esm/node/index.js +7 -0
  196. package/dist/esm/node/pkce.js +20 -0
  197. package/dist/esm/node/random-string.js +8 -0
  198. package/dist/esm/node/sanitize.js +8 -0
  199. package/dist/esm/node/uuid.js +7 -0
  200. package/dist/types/dom/accessibility.d.cts +30 -0
  201. package/dist/types/dom/actions/index.d.cts +3 -0
  202. package/dist/types/dom/actions/masonry.d.cts +5 -0
  203. package/dist/types/dom/actions/prefer-horizontal-scroll.d.cts +5 -0
  204. package/dist/types/dom/actions/sticky.d.cts +5 -0
  205. package/{src/dom/bounding-box.js → dist/types/dom/bounding-box.d.cts} +8 -49
  206. package/dist/types/dom/clipboard.d.cts +7 -0
  207. package/dist/types/dom/cookie.d.cts +7 -0
  208. package/dist/types/dom/css-vars.d.cts +6 -0
  209. package/{src/dom/events.js → dist/types/dom/events.d.cts} +52 -31
  210. package/dist/types/dom/focusable.d.cts +78 -0
  211. package/dist/types/dom/font-size.d.cts +8 -0
  212. package/{src/dom/get-element.js → dist/types/dom/get-element.d.cts} +25 -99
  213. package/dist/types/dom/hash.d.cts +3 -0
  214. package/dist/types/dom/index.d.cts +31 -0
  215. package/{src/dom/keyboard.js → dist/types/dom/keyboard.d.cts} +7 -19
  216. package/dist/types/dom/local-store.d.cts +31 -0
  217. package/dist/types/dom/media.d.cts +5 -0
  218. package/dist/types/dom/observers/index.d.cts +4 -0
  219. package/dist/types/dom/observers/intersection-observer.d.cts +10 -0
  220. package/dist/types/dom/observers/mutation-observer.d.cts +9 -0
  221. package/dist/types/dom/observers/observer.d.cts +3 -0
  222. package/{src/dom/observers/resize-observer.js → dist/types/dom/observers/resize-observer.d.cts} +6 -32
  223. package/dist/types/dom/observers/scroll-observer.d.cts +40 -0
  224. package/dist/types/dom/pkce.d.cts +8 -0
  225. package/dist/types/dom/query-params.d.cts +6 -0
  226. package/dist/types/dom/random-string.d.cts +9 -0
  227. package/dist/types/dom/sanitize.d.cts +10 -0
  228. package/dist/types/dom/session-store.d.cts +7 -0
  229. package/dist/types/dom/spam-prevention.d.cts +14 -0
  230. package/dist/types/dom/trap-focus.d.cts +32 -0
  231. package/dist/types/dom/ui/aria-current.d.cts +7 -0
  232. package/{src/dom/ui/inconsistent-button-fix.js → dist/types/dom/ui/inconsistent-button-fix.d.cts} +5 -11
  233. package/dist/types/dom/ui/index.d.cts +4 -0
  234. package/dist/types/dom/ui/scroll-container.d.cts +3 -0
  235. package/dist/types/dom/ui/traverse-and-scramble.d.cts +21 -0
  236. package/dist/types/lib/arrays/index.d.cts +6 -0
  237. package/{src/lib/arrays/item-position.js → dist/types/lib/arrays/item-position.d.cts} +5 -12
  238. package/{src/lib/arrays/join.js → dist/types/lib/arrays/join.d.cts} +4 -9
  239. package/dist/types/lib/arrays/shuffle.d.cts +3 -0
  240. package/dist/types/lib/arrays/sort.d.cts +32 -0
  241. package/dist/types/lib/arrays/split-array.d.cts +6 -0
  242. package/dist/types/lib/arrays/unique.d.cts +3 -0
  243. package/dist/types/lib/auth/index.d.cts +1 -0
  244. package/dist/types/lib/auth/route-manager.d.cts +28 -0
  245. package/dist/types/lib/checks.d.cts +33 -0
  246. package/dist/types/lib/date/days.d.cts +7 -0
  247. package/dist/types/lib/date/index.d.cts +3 -0
  248. package/dist/types/lib/date/months.d.cts +11 -0
  249. package/dist/types/lib/date/time.d.cts +21 -0
  250. package/dist/types/lib/form/form-data.d.cts +9 -0
  251. package/dist/types/lib/form/index.d.cts +2 -0
  252. package/{src/lib/form/sanitize.js → dist/types/lib/form/sanitize.d.cts} +19 -39
  253. package/{src/lib/functions/callback.js → dist/types/lib/functions/callback.d.cts} +3 -3
  254. package/dist/types/lib/functions/debounce.d.cts +3 -0
  255. package/dist/types/lib/functions/env.d.cts +3 -0
  256. package/{src/lib/functions/functional.js → dist/types/lib/functions/functional.d.cts} +8 -49
  257. package/dist/types/lib/functions/index.d.cts +5 -0
  258. package/dist/types/lib/functions/throttle.d.cts +3 -0
  259. package/dist/types/lib/functions/timeout.d.cts +5 -0
  260. package/dist/types/lib/hash.d.cts +3 -0
  261. package/dist/types/lib/index.d.cts +43 -0
  262. package/dist/types/lib/numbers/index.d.cts +5 -0
  263. package/dist/types/lib/numbers/math.d.cts +4 -0
  264. package/dist/types/lib/objects/camelcase-keys.d.cts +3 -0
  265. package/dist/types/lib/objects/empty.d.cts +4 -0
  266. package/dist/types/lib/objects/equal.d.cts +4 -0
  267. package/dist/types/lib/objects/extend.d.cts +6 -0
  268. package/dist/types/lib/objects/flatten.d.cts +6 -0
  269. package/dist/types/lib/objects/index.d.cts +13 -0
  270. package/dist/types/lib/objects/json.d.cts +3 -0
  271. package/dist/types/lib/objects/loop.d.cts +4 -0
  272. package/dist/types/lib/objects/mix/mix.d.cts +44 -0
  273. package/{src/lib/objects/nested-property.js → dist/types/lib/objects/nested-property.d.cts} +4 -21
  274. package/dist/types/lib/objects/normalize-object.d.cts +3 -0
  275. package/dist/types/lib/objects/omit-empty.d.cts +3 -0
  276. package/dist/types/lib/objects/size.d.cts +3 -0
  277. package/dist/types/lib/objects/split.d.cts +14 -0
  278. package/dist/types/lib/promises/index.d.cts +1 -0
  279. package/dist/types/lib/promises/reject.d.cts +5 -0
  280. package/dist/types/lib/sse.d.cts +18 -0
  281. package/dist/types/lib/strings/convert-case/convert-case.d.cts +10 -0
  282. package/dist/types/lib/strings/index.d.cts +5 -0
  283. package/dist/types/lib/strings/markdown.d.cts +25 -0
  284. package/dist/types/lib/strings/name.d.cts +7 -0
  285. package/dist/types/lib/strings/pluralize.d.cts +3 -0
  286. package/dist/types/lib/strings/query-string.d.cts +10 -0
  287. package/dist/types/lib/style/index.d.cts +3 -0
  288. package/dist/types/lib/symbols/index.d.cts +1 -0
  289. package/dist/types/lib/symbols/symbols.d.cts +4 -0
  290. package/dist/types/node/context.d.cts +2 -0
  291. package/dist/types/node/dirname.d.cts +9 -0
  292. package/dist/types/node/file-cache.d.cts +56 -0
  293. package/dist/types/node/file.d.cts +4 -0
  294. package/dist/types/node/hash.d.cts +3 -0
  295. package/dist/types/node/index.d.cts +7 -0
  296. package/dist/types/node/pkce.d.cts +14 -0
  297. package/dist/types/node/random-string.d.cts +3 -0
  298. package/{src/node/sanitize.js → dist/types/node/sanitize.d.cts} +3 -6
  299. package/dist/types/node/uuid.d.cts +3 -0
  300. package/package.json +18 -15
  301. package/CHANGELOG.md +0 -237
  302. package/eslint.config.js +0 -2
  303. package/src/dom/accessibility.js +0 -58
  304. package/src/dom/actions/index.js +0 -3
  305. package/src/dom/actions/masonry.js +0 -43
  306. package/src/dom/actions/prefer-horizontal-scroll.js +0 -121
  307. package/src/dom/actions/sticky.js +0 -85
  308. package/src/dom/clipboard.js +0 -14
  309. package/src/dom/cookie.js +0 -32
  310. package/src/dom/css-vars.js +0 -19
  311. package/src/dom/font-size.js +0 -40
  312. package/src/dom/hash.js +0 -9
  313. package/src/dom/index.js +0 -23
  314. package/src/dom/media.js +0 -30
  315. package/src/dom/observers/index.js +0 -4
  316. package/src/dom/observers/intersection-observer.js +0 -43
  317. package/src/dom/observers/mutation-observer.js +0 -51
  318. package/src/dom/observers/observer.js +0 -18
  319. package/src/dom/observers/scroll-observer.js +0 -146
  320. package/src/dom/pkce.js +0 -34
  321. package/src/dom/query-params.js +0 -14
  322. package/src/dom/random-string.js +0 -18
  323. package/src/dom/random-string.test.js +0 -13
  324. package/src/dom/sanitize.js +0 -16
  325. package/src/dom/session-store.js +0 -29
  326. package/src/dom/spam-prevention.js +0 -40
  327. package/src/dom/trap-focus.js +0 -70
  328. package/src/dom/ui/aria-current.js +0 -20
  329. package/src/dom/ui/index.js +0 -4
  330. package/src/dom/ui/scroll-container.js +0 -25
  331. package/src/dom/ui/traverse-and-scramble.js +0 -61
  332. package/src/lib/arrays/index.js +0 -6
  333. package/src/lib/arrays/shuffle.js +0 -21
  334. package/src/lib/arrays/sort.js +0 -88
  335. package/src/lib/arrays/sort.spec.js +0 -123
  336. package/src/lib/arrays/split-array.js +0 -15
  337. package/src/lib/arrays/unique.js +0 -3
  338. package/src/lib/auth/index.js +0 -1
  339. package/src/lib/auth/route-manager.js +0 -45
  340. package/src/lib/checks.js +0 -57
  341. package/src/lib/date/days.js +0 -9
  342. package/src/lib/date/index.js +0 -3
  343. package/src/lib/date/months.js +0 -74
  344. package/src/lib/date/time.js +0 -83
  345. package/src/lib/form/form-data.js +0 -73
  346. package/src/lib/form/index.js +0 -2
  347. package/src/lib/form/sanitize.spec.js +0 -126
  348. package/src/lib/functions/debounce.js +0 -18
  349. package/src/lib/functions/env.js +0 -5
  350. package/src/lib/functions/functional.test.js +0 -196
  351. package/src/lib/functions/index.js +0 -5
  352. package/src/lib/functions/throttle.js +0 -11
  353. package/src/lib/functions/timeout.js +0 -15
  354. package/src/lib/hash.js +0 -18
  355. package/src/lib/hash.spec.js +0 -163
  356. package/src/lib/index.js +0 -14
  357. package/src/lib/numbers/index.js +0 -12
  358. package/src/lib/numbers/math.js +0 -9
  359. package/src/lib/numbers/split-unit.test.js +0 -45
  360. package/src/lib/objects/camelcase-keys.js +0 -17
  361. package/src/lib/objects/camelcase-keys.test.js +0 -72
  362. package/src/lib/objects/empty.js +0 -10
  363. package/src/lib/objects/equal.js +0 -9
  364. package/src/lib/objects/extend.js +0 -16
  365. package/src/lib/objects/extend.test.js +0 -35
  366. package/src/lib/objects/flatten.js +0 -19
  367. package/src/lib/objects/index.js +0 -13
  368. package/src/lib/objects/json.js +0 -7
  369. package/src/lib/objects/loop.js +0 -11
  370. package/src/lib/objects/loop.test.js +0 -31
  371. package/src/lib/objects/mix/mix.js +0 -191
  372. package/src/lib/objects/mix/mix.md +0 -78
  373. package/src/lib/objects/mix/mix.test.js +0 -445
  374. package/src/lib/objects/normalize-object.js +0 -10
  375. package/src/lib/objects/omit-empty.js +0 -23
  376. package/src/lib/objects/omit-empty.test.js +0 -85
  377. package/src/lib/objects/size.js +0 -41
  378. package/src/lib/objects/split.js +0 -19
  379. package/src/lib/promises/index.js +0 -1
  380. package/src/lib/promises/reject.js +0 -17
  381. package/src/lib/sse.js +0 -61
  382. package/src/lib/strings/convert-case/convert-case.js +0 -86
  383. package/src/lib/strings/convert-case/convert-case.md +0 -44
  384. package/src/lib/strings/convert-case/convert-case.test.js +0 -50
  385. package/src/lib/strings/index.js +0 -5
  386. package/src/lib/strings/markdown.js +0 -71
  387. package/src/lib/strings/markdown.spec.js +0 -73
  388. package/src/lib/strings/name.js +0 -24
  389. package/src/lib/strings/name.test.js +0 -67
  390. package/src/lib/strings/pluralize.js +0 -2
  391. package/src/lib/strings/query-string.js +0 -18
  392. package/src/lib/style/index.js +0 -13
  393. package/src/lib/symbols/index.js +0 -1
  394. package/src/lib/symbols/symbols.js +0 -9
  395. package/src/node/dirname.js +0 -17
  396. package/src/node/file-cache.js +0 -184
  397. package/src/node/file.js +0 -13
  398. package/src/node/hash.js +0 -5
  399. package/src/node/index.js +0 -7
  400. package/src/node/pkce.js +0 -33
  401. package/src/node/random-string.js +0 -10
  402. package/src/node/random-string.test.js +0 -15
  403. package/src/node/sanitize.spec.js +0 -142
  404. package/src/node/uuid.js +0 -5
  405. package/tsconfig.json +0 -23
  406. package/tsup.config.js +0 -38
  407. package/tsup.config.mjs +0 -63
  408. /package/{src/node/context.js → dist/cjs/node/context.cjs} +0 -0
@@ -1,10 +0,0 @@
1
- import { pipe } from '../functions/functional.js'
2
- import { camelCaseKeys } from './camelcase-keys.js'
3
- import { omitEmpty } from './omit-empty.js'
4
-
5
- // Deprecated. Should remove.
6
- // Not using anymore.
7
- // Because snake_case is quite common.
8
- export function normalizeObject(object) {
9
- return pipe(omitEmpty, camelCaseKeys)(object)
10
- }
@@ -1,23 +0,0 @@
1
- // Written by AI and tested.
2
- export function omitEmpty(obj, shallow = false) {
3
- if (typeof obj !== 'object' || obj === null) return obj
4
- if (obj instanceof Date) return obj
5
-
6
- const result = Array.isArray(obj) ? [] : {}
7
-
8
- for (const [key, value] of Object.entries(obj)) {
9
- if (
10
- value === null ||
11
- value === undefined ||
12
- value === '' ||
13
- (typeof value === 'object' &&
14
- !(value instanceof Date) &&
15
- Object.keys(value).length === 0)
16
- ) {
17
- continue
18
- }
19
- result[key] = shallow ? value : omitEmpty(value)
20
- }
21
-
22
- return result
23
- }
@@ -1,85 +0,0 @@
1
- import { expect, it } from 'vitest'
2
-
3
- import { omitEmpty } from './omit-empty'
4
-
5
- it('Omit Empty Basic', ctx => {
6
- const date = new Date()
7
- const object = {
8
- // Should not be omitted
9
- a: { one: 1 },
10
- b: [1],
11
- c: 1,
12
- d: 0,
13
- e: 'string',
14
- k: date,
15
- l: false,
16
-
17
- // Should be omitted
18
- f: {},
19
- g: [],
20
- h: '',
21
- i: null,
22
- j: undefined,
23
- }
24
-
25
- const expected = {
26
- a: { one: 1 },
27
- b: [1],
28
- c: 1,
29
- d: 0,
30
- e: 'string',
31
- k: date,
32
- l: false,
33
- }
34
-
35
- const result = omitEmpty(object)
36
- expect(result).toEqual(expected)
37
- })
38
-
39
- it('Omit Empty Nested', ctx => {
40
- const object = {
41
- a: {
42
- one: {},
43
- two: [],
44
- three: 1,
45
- four: 'string',
46
- },
47
- }
48
-
49
- const expected = {
50
- a: {
51
- three: 1,
52
- four: 'string',
53
- },
54
- }
55
-
56
- const result = omitEmpty(object)
57
- expect(result).toEqual(expected)
58
- })
59
-
60
- it('Omit Empty Recursive', ctx => {
61
- const object = {
62
- a: {
63
- one: {},
64
- two: [],
65
- three: {
66
- alpha: {},
67
- beta: [],
68
- tetha: 1,
69
- gamma: 'string',
70
- },
71
- },
72
- }
73
-
74
- const expected = {
75
- a: {
76
- three: {
77
- tetha: 1,
78
- gamma: 'string',
79
- },
80
- },
81
- }
82
-
83
- const result = omitEmpty(object)
84
- expect(result).toEqual(expected)
85
- })
@@ -1,41 +0,0 @@
1
- // https://gist.github.com/rajinwonderland/36887887b8a8f12063f1d672e318e12e
2
- export function sizeOf(obj) {
3
- let bytes = 0
4
-
5
- function size(obj) {
6
- if (obj !== null && obj !== undefined) {
7
- switch (typeof obj) {
8
- case 'number':
9
- bytes += 8
10
- break
11
- case 'string':
12
- bytes += obj.length * 2
13
- break
14
- case 'boolean':
15
- bytes += 4
16
- break
17
- case 'object':
18
- // eslint-disable-next-line no-case-declarations
19
- const objClass = Object.prototype.toString.call(obj).slice(8, -1)
20
- if (objClass === 'Object' || objClass === 'Array') {
21
- for (const key in obj) {
22
- // eslint-disable-next-line no-prototype-builtins
23
- if (!obj.hasOwnProperty(key)) continue
24
- size(obj[key])
25
- }
26
- } else bytes += obj.toString().length * 2
27
- break
28
- }
29
- }
30
- return bytes
31
- }
32
-
33
- function formatByteSize(bytes) {
34
- if (bytes < 1024) return bytes + ' bytes'
35
- else if (bytes < 1048576) return (bytes / 1024).toFixed(3) + ' KiB'
36
- else if (bytes < 1073741824) return (bytes / 1048576).toFixed(3) + ' MiB'
37
- else return (bytes / 1073741824).toFixed(3) + ' GiB'
38
- }
39
-
40
- return formatByteSize(size(obj))
41
- }
@@ -1,19 +0,0 @@
1
- /**
2
- * Split on object up based on the keys provided.
3
- * @param {Object} obj
4
- * @param {Array} keys
5
- * @returns
6
- */
7
- export function splitObject(obj, keys) {
8
- const picked = {}
9
- const omitted = { ...obj }
10
-
11
- keys.forEach(key => {
12
- if (key in obj) {
13
- picked[key] = obj[key]
14
- delete omitted[key]
15
- }
16
- })
17
-
18
- return { picked, omitted, p: picked, o: omitted }
19
- }
@@ -1 +0,0 @@
1
- export * from './reject.js'
@@ -1,17 +0,0 @@
1
- import statuses from 'statuses'
2
- import { omitEmpty } from '../objects/omit-empty.js'
3
-
4
- // Rejects a promise with HTTP Status Code
5
- export function reject(props, { includeStack = true } = {}) {
6
- const { status, statusText, body, message } = props
7
- const e = new Error()
8
- const err = {
9
- status,
10
- statusText: statusText || (status && statuses(status)),
11
- body,
12
- message,
13
- stack: includeStack && e.stack,
14
- }
15
-
16
- return Promise.reject(omitEmpty(err))
17
- }
package/src/lib/sse.js DELETED
@@ -1,61 +0,0 @@
1
- // Server Sent Events (SSE)
2
- import { parseJSON } from './objects/json.js'
3
- import { omitEmpty } from './objects/omit-empty.js'
4
-
5
- export function createSSE({ event, data, id, retry }) {
6
- const eventString = event ? `event: ${event}\n` : ''
7
- const idString = id ? `id: ${id}\n` : ''
8
- const retryString = retry ? `retry: ${retry}\n` : ''
9
-
10
- if (typeof data === 'object') data = JSON.stringify(data)
11
- const dataString = data ? `data: ${data}\n` : ''
12
-
13
- return `${eventString}${dataString}${idString}${retryString}\n`
14
- }
15
-
16
- /**
17
- * Parses a single SSE message into a structured object
18
- * @param {string} message - The raw SSE message
19
- * @returns {Object|null} The parsed message or null if invalid
20
- * @property {string} [event] - The event type if specified
21
- * @property {string|Object} data - The message data (parsed as JSON if possible)
22
- * @property {string} [id] - The message ID if specified
23
- * @property {number} [retry] - The retry interval if specified
24
- */
25
- export function parseSSE(message) {
26
- const lines = message.split('\n')
27
- const result = {
28
- event: 'message', // Default event type
29
- data: '',
30
- id: null,
31
- retry: null
32
- }
33
-
34
- for (const line of lines) {
35
- if (line.startsWith('data:')) {
36
- const data = line.slice(5).trim()
37
- result.data = parseJSON(data)
38
- continue
39
- }
40
-
41
- if (line.startsWith('event:')) {
42
- result.event = line.slice(6).trim()
43
- continue
44
- }
45
-
46
- if (line.startsWith('id:')) {
47
- result.id = line.slice(3).trim()
48
- continue
49
- }
50
-
51
- if (line.startsWith('retry:')) {
52
- result.retry = parseInt(line.slice(6).trim(), 10)
53
- continue
54
- }
55
- }
56
-
57
-
58
- const ret = omitEmpty(result)
59
- return ret.data ? ret : null
60
- }
61
-
@@ -1,86 +0,0 @@
1
- // ========================
2
- // Case Conversion Utilities
3
- // Note: All case conversion functions require `toKebab` to work.
4
- // ------------------------
5
- export function toKebab(string) {
6
- if (!string) return ''
7
- return string
8
- .split('')
9
- .map((letter, index) => {
10
- const previousLetter = string[index - 1] || ''
11
- const currentLetter = letter
12
-
13
- if (isDigit(currentLetter) && !isDigit(previousLetter)) {
14
- return `-${currentLetter}`
15
- }
16
-
17
- if (!isCaps(currentLetter)) return currentLetter
18
-
19
- if (previousLetter === '') {
20
- return `${currentLetter.toLowerCase()}`
21
- }
22
-
23
- if (isCaps(previousLetter)) {
24
- return `${currentLetter.toLowerCase()}`
25
- }
26
-
27
- return `-${currentLetter.toLowerCase()}`
28
- })
29
- .join('')
30
- .trim()
31
- .replace(/[-_\s]+/g, '-')
32
- }
33
-
34
- export function toCamel(string) {
35
- return toKebab(string)
36
- .split('-')
37
- .map((word, index) => {
38
- if (index === 0) return word
39
- return word.slice(0, 1).toUpperCase() + word.slice(1).toLowerCase()
40
- })
41
- .join('')
42
- }
43
-
44
- export function toPascal(string) {
45
- const camel = toCamel(string)
46
- return camel.slice(0, 1).toUpperCase() + camel.slice(1)
47
- }
48
-
49
- export function toTitle(string) {
50
- return toKebab(string)
51
- .split('-')
52
- .map(word => {
53
- return word.slice(0, 1).toUpperCase() + word.slice(1)
54
- })
55
- .join(' ')
56
- }
57
-
58
- export function toSlug(string) {
59
- return toKebab(string)
60
- }
61
-
62
- export function toSentence(string) {
63
- const interim = toKebab(string).replace(/-/g, ' ')
64
- return interim.slice(0, 1).toUpperCase() + interim.slice(1)
65
- }
66
-
67
- export function toUpper(string) {
68
- const interim = toKebab(string).replace(/-/g, ' ')
69
- return interim.toUpperCase()
70
- }
71
-
72
- export function toLower(string) {
73
- const interim = toKebab(string).replace(/-/g, ' ')
74
- return interim.toLowerCase()
75
- }
76
-
77
- // Checks whether character is Uppercase.
78
- // Crude version. Checks only A-Z.
79
- function isCaps(char) {
80
- return /\p{Lu}/u.test(char)
81
- }
82
-
83
- // Checks whether character is digit.
84
- function isDigit(char) {
85
- return /[0-9]/.test(char)
86
- }
@@ -1,44 +0,0 @@
1
- # Case Conversion Utilities
2
-
3
- This file contains utilities to convert any string into the following cases:
4
-
5
- 1. `kebab-case`
6
- 2. `camelCase`
7
- 3. `Title Case`
8
- 4. `Sentence case`
9
-
10
- [See my process for creating these case-conversion utilties](https://zellwk.com/blog/case-conversion)
11
-
12
- ## Examples
13
-
14
- ```javascript
15
- toKebab('caseWithSomeWords') // case-with-some-words
16
- toKebab('CaseWithSomeWords') // case-with-some-words
17
- toKebab('case_with_some_words') // case-with-some-words
18
- toKebab('Case with some words') // case-with-some-words
19
- toKebab('Case With Some Words') // case-with-some-words
20
- toKebab('Case_with SomeWords') // case-with-some-words
21
- ```
22
-
23
- ## Installation
24
-
25
- Manual installation:
26
-
27
- - Copy and paste the entire file into your javascript file. 😉
28
- - If you use ES5 Modules, you can import them into your file
29
-
30
- ```js
31
- import { toKebab } from "./convert-case.js"
32
- toKebab('someString')
33
- ```
34
-
35
- NPM:
36
-
37
- - Run `npm install @zellwk/javascript`
38
- - Import `convert-case.js`
39
-
40
- ```js
41
- import { toKebab } from "@zellwk/javascript/convert-case"
42
- toKebab('someString')
43
- ```
44
-
@@ -1,50 +0,0 @@
1
- /* eslint-env jest */
2
- import { describe, expect, it } from 'vitest'
3
- import { toCamel, toKebab, toSentence, toTitle } from './convert-case'
4
-
5
- const cases = {
6
- kebab: 'case-with-long-name100',
7
- snake: 'case_with_long_name100',
8
- camel: 'caseWithLongName100',
9
- pascal: 'CaseWithLongName100',
10
- sentence: 'Case with long name100',
11
- title: 'Case With Long Name100',
12
- constant: 'CASE_WITH_LONG_NAME100',
13
- mixCases: 'case_WITH-Long name100',
14
- }
15
-
16
- describe('To Kebab', _ => {
17
- Object.entries(cases).forEach(c => {
18
- it(`From ${c[0]}`, () => {
19
- const result = toKebab(c[1])
20
- expect(result, c[0]).toBe('case-with-long-name-100')
21
- })
22
- })
23
- })
24
-
25
- describe('To Camel', _ => {
26
- Object.entries(cases).forEach(c => {
27
- it(`From ${c[0]}`, () => {
28
- const result = toCamel(c[1])
29
- expect(result, c[0]).toBe('caseWithLongName100')
30
- })
31
- })
32
- })
33
-
34
- describe('To Sentence', _ => {
35
- Object.entries(cases).forEach(c => {
36
- it(`From ${c[0]}`, () => {
37
- const result = toSentence(c[1])
38
- expect(result, c[0]).toBe('Case with long name 100')
39
- })
40
- })
41
- })
42
-
43
- describe('To Title', _ => {
44
- Object.entries(cases).forEach(c => {
45
- it(`From ${c[0]}`, () => {
46
- const result = toTitle(c[1])
47
- expect(result, c[0]).toBe('Case With Long Name 100')
48
- })
49
- })
50
- })
@@ -1,5 +0,0 @@
1
- export * from './convert-case/convert-case.js'
2
- export * from './markdown.js'
3
- export * from './name.js'
4
- export * from './pluralize.js'
5
- export * from './query-string.js'
@@ -1,71 +0,0 @@
1
- import markdownit from 'markdown-it'
2
- import anchor from 'markdown-it-anchor'
3
-
4
- const md = markdownit({
5
- html: true,
6
- linkify: true,
7
- typographer: true,
8
- })
9
-
10
- md.use(anchor, {
11
- permalink: false,
12
- slugify: s =>
13
- s
14
- .toLowerCase()
15
- .replace(/\s+/g, '-')
16
- .replace(/[^\w-]/g, ''),
17
- })
18
-
19
- /**
20
- * Converts markdown content to HTML with whitespace handling
21
- * @param {string} content - Markdown content to convert
22
- * @param {Object} [options={}] - Conversion options
23
- * @param {boolean} [options.inline=false] - Whether content should be treated as inline markdown
24
- * @returns {string} Converted HTML string
25
- */
26
- export function markdown(content, options = {}) {
27
- const defaultOptions = { inline: false }
28
- const opts = { ...defaultOptions, ...options }
29
-
30
- const { content: treated } = treatMarkdownWhitespace(content, opts)
31
-
32
- if (opts.inline) return md.renderInline(treated)
33
- return md.render(treated)
34
- }
35
-
36
- /**
37
- * Handles whitespace in markdown content to ensure proper rendering
38
- * @param {string} content - Markdown content to process
39
- * @param {Object} [options={}] - Processing options
40
- * @param {boolean} [options.inline=false] - Whether content is inline markdown
41
- * @returns {{ content: string, inline: boolean }} Processed content and inline status
42
- */
43
- export function treatMarkdownWhitespace(content, { inline } = {}) {
44
- if (!content) return { content: '', inline }
45
- const lines = content.split('\n')
46
-
47
- // Check for inline content
48
- if (lines[0] !== '' && inline) return { content, inline: true }
49
-
50
- // If it's not inline content, we need to strip indentation
51
- // For this, we need to check for the first new line with leading spaces
52
- const firstLineWithLeadingSpacesIndex = lines.findIndex(line =>
53
- line.match(/^\s+/),
54
- )
55
- const firstLineWithLeadingSpaces = lines[firstLineWithLeadingSpacesIndex]
56
- const indentation =
57
- firstLineWithLeadingSpaces?.match(/^\s+/)?.[0]?.length ?? 0
58
-
59
- // Once the indentation is found, we strip the indentation from each line. This treats the Markdown whitespace and prevents it from being rendered as code blocks.
60
- const retContent = lines
61
- .map((line, index) => {
62
- if (index < firstLineWithLeadingSpacesIndex) return line + '\n'
63
- return line.slice(indentation) + '\n'
64
- })
65
- .join('')
66
-
67
- return {
68
- content: retContent,
69
- inline,
70
- }
71
- }
@@ -1,73 +0,0 @@
1
- import { describe, expect, test } from 'vitest'
2
- import { markdown, treatMarkdownWhitespace } from './markdown.js'
3
-
4
- describe('markdown', () => {
5
- describe('block (default)', () => {
6
- test('wraps output in <p>', () => {
7
- const result = markdown('hello')
8
- expect(result).toBe('<p>hello</p>\n')
9
- })
10
-
11
- test('renders bold', () => {
12
- const result = markdown('**bold**')
13
- expect(result).toBe('<p><strong>bold</strong></p>\n')
14
- })
15
-
16
- test('renders headings', () => {
17
- const result = markdown('# Hello')
18
- expect(result).toContain('<h1')
19
- expect(result).toContain('Hello</h1>')
20
- })
21
- })
22
-
23
- describe('inline', () => {
24
- test('never produces <p> tags', () => {
25
- const result = markdown('hello', { inline: true })
26
- expect(result).not.toContain('<p>')
27
- expect(result).not.toContain('</p>')
28
- })
29
-
30
- test('plain text renders as-is', () => {
31
- const result = markdown('hello', { inline: true })
32
- expect(result).toBe('hello')
33
- })
34
-
35
- test('renders bold without <p>', () => {
36
- const result = markdown('**bold**', { inline: true })
37
- expect(result).toBe('<strong>bold</strong>')
38
- })
39
-
40
- test('renders em without <p>', () => {
41
- const result = markdown('_em_', { inline: true })
42
- expect(result).toBe('<em>em</em>')
43
- })
44
-
45
- test('renders inline code without <p>', () => {
46
- const result = markdown('`code`', { inline: true })
47
- expect(result).toBe('<code>code</code>')
48
- })
49
- })
50
- })
51
-
52
- describe('treatMarkdownWhitespace', () => {
53
- test('returns empty string for falsy content', () => {
54
- const a = treatMarkdownWhitespace('')
55
- const b = treatMarkdownWhitespace(null)
56
- const c = treatMarkdownWhitespace(undefined)
57
- expect(a.content).toBe('')
58
- expect(b.content).toBe('')
59
- expect(c.content).toBe('')
60
- })
61
-
62
- test('strips leading indentation', () => {
63
- const { content } = treatMarkdownWhitespace('\n hello\n world')
64
- expect(content).not.toContain(' hello')
65
- expect(content).toContain('hello')
66
- expect(content).toContain('world')
67
- })
68
-
69
- test('returns inline content as-is when first line is not empty', () => {
70
- const { content } = treatMarkdownWhitespace('hello world', { inline: true })
71
- expect(content).toBe('hello world')
72
- })
73
- })
@@ -1,24 +0,0 @@
1
- export function parseFullName(name) {
2
- const parts = name.trim().split(/\s+/)
3
-
4
- if (parts.length === 1) {
5
- return { firstName: parts[0], middleName: '', lastName: '' }
6
- }
7
-
8
- if (parts.length === 2) {
9
- return { firstName: parts[0], middleName: '', lastName: parts[1] }
10
- }
11
-
12
- if (parts.length === 3) {
13
- const firstName = parts.slice(0, 2).join(' ')
14
- const lastName = parts[2]
15
- return { firstName, middleName: '', lastName }
16
- }
17
-
18
- // 4+ words: first 2 words = firstName, last word = lastName, middle = middleName
19
- const firstName = parts.slice(0, 2).join(' ')
20
- const lastName = parts[parts.length - 1]
21
- const middleName = parts.slice(2, -1).join(' ')
22
-
23
- return { firstName, middleName, lastName }
24
- }
@@ -1,67 +0,0 @@
1
- import { describe, expect, test } from 'vitest'
2
- import { parseFullName } from './name.js'
3
-
4
- describe('parseFullName', () => {
5
- test('handles single name', () => {
6
- const result = parseFullName('John')
7
- expect(result).toEqual({
8
- firstName: 'John',
9
- middleName: '',
10
- lastName: '',
11
- })
12
- })
13
-
14
- test('handles two names', () => {
15
- const result = parseFullName('John Doe')
16
- expect(result).toEqual({
17
- firstName: 'John',
18
- middleName: '',
19
- lastName: 'Doe',
20
- })
21
- })
22
-
23
- test('handles three names (Chinese pattern)', () => {
24
- const result = parseFullName('Wee Keat Liew')
25
- expect(result).toEqual({
26
- firstName: 'Wee Keat',
27
- middleName: '',
28
- lastName: 'Liew',
29
- })
30
- })
31
-
32
- test('handles four names with middle name', () => {
33
- const result = parseFullName('Mary Jane Michael Doe')
34
- expect(result).toEqual({
35
- firstName: 'Mary Jane',
36
- middleName: 'Michael',
37
- lastName: 'Doe',
38
- })
39
- })
40
-
41
- test('handles five names with multiple middle names', () => {
42
- const result = parseFullName('Mary Jane Catherine Elizabeth Doe')
43
- expect(result).toEqual({
44
- firstName: 'Mary Jane',
45
- middleName: 'Catherine Elizabeth',
46
- lastName: 'Doe',
47
- })
48
- })
49
-
50
- test('handles extra whitespace', () => {
51
- const result = parseFullName(' John Doe ')
52
- expect(result).toEqual({
53
- firstName: 'John',
54
- middleName: '',
55
- lastName: 'Doe',
56
- })
57
- })
58
-
59
- test('handles multiple spaces between words', () => {
60
- const result = parseFullName('Wee Keat Liew')
61
- expect(result).toEqual({
62
- firstName: 'Wee Keat',
63
- middleName: '',
64
- lastName: 'Liew',
65
- })
66
- })
67
- })
@@ -1,2 +0,0 @@
1
- import pluralizeLib from 'pluralize'
2
- export const pluralize = pluralizeLib