@splendidlabz/utils 1.11.3 → 1.11.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/dom/accessibility.cjs +53 -0
- package/dist/cjs/dom/actions/index.cjs +410 -0
- package/dist/cjs/dom/actions/masonry.cjs +152 -0
- package/dist/cjs/dom/actions/prefer-horizontal-scroll.cjs +157 -0
- package/dist/cjs/dom/actions/sticky.cjs +213 -0
- package/dist/cjs/dom/bounding-box.cjs +70 -0
- package/dist/cjs/dom/clipboard.cjs +37 -0
- package/dist/cjs/dom/cookie.cjs +57 -0
- package/dist/cjs/dom/css-vars.cjs +57 -0
- package/dist/cjs/dom/events.cjs +59 -0
- package/{src/dom/focusable.js → dist/cjs/dom/focusable.cjs} +51 -73
- package/dist/cjs/dom/font-size.cjs +80 -0
- package/dist/cjs/dom/get-element.cjs +98 -0
- package/dist/cjs/dom/hash.cjs +35 -0
- package/dist/cjs/dom/index.cjs +1267 -0
- package/dist/cjs/dom/keyboard.cjs +51 -0
- package/dist/cjs/dom/local-store.cjs +79 -0
- package/dist/cjs/dom/media.cjs +59 -0
- package/dist/cjs/dom/observers/index.cjs +253 -0
- package/dist/cjs/dom/observers/intersection-observer.cjs +91 -0
- package/dist/cjs/dom/observers/mutation-observer.cjs +95 -0
- package/dist/cjs/dom/observers/observer.cjs +48 -0
- package/dist/cjs/dom/observers/resize-observer.cjs +84 -0
- package/dist/cjs/dom/observers/scroll-observer.cjs +177 -0
- package/dist/cjs/dom/pkce.cjs +53 -0
- package/dist/cjs/dom/query-params.cjs +38 -0
- package/dist/cjs/dom/random-string.cjs +38 -0
- package/dist/cjs/dom/sanitize.cjs +65 -0
- package/dist/cjs/dom/session-store.cjs +49 -0
- package/dist/cjs/dom/spam-prevention.cjs +50 -0
- package/dist/cjs/dom/trap-focus.cjs +197 -0
- package/dist/cjs/dom/ui/aria-current.cjs +43 -0
- package/dist/cjs/dom/ui/inconsistent-button-fix.cjs +35 -0
- package/dist/cjs/dom/ui/index.cjs +105 -0
- package/dist/cjs/dom/ui/scroll-container.cjs +47 -0
- package/dist/cjs/dom/ui/traverse-and-scramble.cjs +50 -0
- package/dist/cjs/lib/arrays/index.cjs +139 -0
- package/dist/cjs/lib/arrays/item-position.cjs +42 -0
- package/dist/cjs/lib/arrays/join.cjs +43 -0
- package/dist/cjs/lib/arrays/shuffle.cjs +42 -0
- package/dist/cjs/lib/arrays/sort.cjs +67 -0
- package/dist/cjs/lib/arrays/split-array.cjs +41 -0
- package/dist/cjs/lib/arrays/unique.cjs +31 -0
- package/dist/cjs/lib/auth/index.cjs +53 -0
- package/dist/cjs/lib/auth/route-manager.cjs +51 -0
- package/dist/cjs/lib/checks.cjs +63 -0
- package/dist/cjs/lib/date/days.cjs +37 -0
- package/dist/cjs/lib/date/index.cjs +208 -0
- package/dist/cjs/lib/date/months.cjs +102 -0
- package/dist/cjs/lib/date/time.cjs +117 -0
- package/dist/cjs/lib/form/form-data.cjs +83 -0
- package/dist/cjs/lib/form/index.cjs +122 -0
- package/dist/cjs/lib/form/sanitize.cjs +61 -0
- package/dist/cjs/lib/functions/callback.cjs +31 -0
- package/dist/cjs/lib/functions/debounce.cjs +43 -0
- package/dist/cjs/lib/functions/env.cjs +32 -0
- package/dist/cjs/lib/functions/functional.cjs +82 -0
- package/dist/cjs/lib/functions/index.cjs +142 -0
- package/dist/cjs/lib/functions/throttle.cjs +38 -0
- package/dist/cjs/lib/functions/timeout.cjs +41 -0
- package/dist/cjs/lib/hash.cjs +43 -0
- package/dist/cjs/lib/index.cjs +1178 -0
- package/dist/cjs/lib/numbers/index.cjs +49 -0
- package/dist/cjs/lib/numbers/math.cjs +36 -0
- package/dist/cjs/lib/objects/camelcase-keys.cjs +80 -0
- package/dist/cjs/lib/objects/empty.cjs +39 -0
- package/dist/cjs/lib/objects/equal.cjs +47 -0
- package/dist/cjs/lib/objects/extend.cjs +147 -0
- package/dist/cjs/lib/objects/flatten.cjs +48 -0
- package/dist/cjs/lib/objects/index.cjs +378 -0
- package/dist/cjs/lib/objects/json.cjs +35 -0
- package/dist/cjs/lib/objects/loop.cjs +40 -0
- package/dist/cjs/lib/objects/mix/mix.cjs +115 -0
- package/dist/cjs/lib/objects/nested-property.cjs +45 -0
- package/dist/cjs/lib/objects/normalize-object.cjs +106 -0
- package/dist/cjs/lib/objects/omit-empty.cjs +40 -0
- package/dist/cjs/lib/objects/size.cjs +63 -0
- package/dist/cjs/lib/objects/split.cjs +39 -0
- package/dist/cjs/lib/promises/index.cjs +69 -0
- package/dist/cjs/lib/promises/reject.cjs +67 -0
- package/dist/cjs/lib/sse.cjs +99 -0
- package/dist/cjs/lib/strings/convert-case/convert-case.cjs +96 -0
- package/dist/cjs/lib/strings/index.cjs +197 -0
- package/dist/cjs/lib/strings/markdown.cjs +76 -0
- package/dist/cjs/lib/strings/name.cjs +46 -0
- package/dist/cjs/lib/strings/pluralize.cjs +40 -0
- package/dist/cjs/lib/strings/query-string.cjs +43 -0
- package/dist/cjs/lib/style/index.cjs +64 -0
- package/dist/cjs/lib/symbols/index.cjs +40 -0
- package/dist/cjs/lib/symbols/symbols.cjs +38 -0
- package/dist/cjs/node/dirname.cjs +49 -0
- package/dist/cjs/node/file-cache.cjs +200 -0
- package/dist/cjs/node/file.cjs +50 -0
- package/dist/cjs/node/hash.cjs +42 -0
- package/dist/cjs/node/index.cjs +296 -0
- package/dist/cjs/node/pkce.cjs +64 -0
- package/dist/cjs/node/random-string.cjs +43 -0
- package/dist/cjs/node/sanitize.cjs +65 -0
- package/dist/cjs/node/uuid.cjs +42 -0
- package/dist/esm/dom/accessibility.js +26 -0
- package/dist/esm/dom/actions/index.js +3 -0
- package/dist/esm/dom/actions/masonry.js +38 -0
- package/dist/esm/dom/actions/prefer-horizontal-scroll.js +90 -0
- package/dist/esm/dom/actions/sticky.js +70 -0
- package/dist/esm/dom/bounding-box.js +44 -0
- package/dist/esm/dom/clipboard.js +12 -0
- package/dist/esm/dom/cookie.js +31 -0
- package/dist/esm/dom/css-vars.js +21 -0
- package/dist/esm/dom/events.js +31 -0
- package/dist/esm/dom/focusable.js +117 -0
- package/dist/esm/dom/font-size.js +40 -0
- package/dist/esm/dom/get-element.js +66 -0
- package/dist/esm/dom/hash.js +10 -0
- package/dist/esm/dom/index.js +23 -0
- package/dist/esm/dom/keyboard.js +22 -0
- package/{src → dist/esm}/dom/local-store.js +16 -28
- package/dist/esm/dom/media.js +32 -0
- package/dist/esm/dom/observers/index.js +4 -0
- package/dist/esm/dom/observers/intersection-observer.js +36 -0
- package/dist/esm/dom/observers/mutation-observer.js +40 -0
- package/dist/esm/dom/observers/observer.js +15 -0
- package/dist/esm/dom/observers/resize-observer.js +29 -0
- package/dist/esm/dom/observers/scroll-observer.js +95 -0
- package/dist/esm/dom/pkce.js +20 -0
- package/dist/esm/dom/query-params.js +13 -0
- package/dist/esm/dom/random-string.js +12 -0
- package/dist/esm/dom/sanitize.js +8 -0
- package/dist/esm/dom/session-store.js +24 -0
- package/dist/esm/dom/spam-prevention.js +25 -0
- package/dist/esm/dom/trap-focus.js +51 -0
- package/dist/esm/dom/ui/aria-current.js +17 -0
- package/dist/esm/dom/ui/inconsistent-button-fix.js +10 -0
- package/dist/esm/dom/ui/index.js +4 -0
- package/dist/esm/dom/ui/scroll-container.js +22 -0
- package/dist/esm/dom/ui/traverse-and-scramble.js +25 -0
- package/dist/esm/lib/arrays/index.js +6 -0
- package/dist/esm/lib/arrays/item-position.js +15 -0
- package/dist/esm/lib/arrays/join.js +12 -0
- package/dist/esm/lib/arrays/shuffle.js +17 -0
- package/dist/esm/lib/arrays/sort.js +36 -0
- package/dist/esm/lib/arrays/split-array.js +16 -0
- package/dist/esm/lib/arrays/unique.js +6 -0
- package/dist/esm/lib/auth/index.js +1 -0
- package/dist/esm/lib/auth/route-manager.js +25 -0
- package/dist/esm/lib/checks.js +34 -0
- package/dist/esm/lib/date/days.js +12 -0
- package/dist/esm/lib/date/index.js +3 -0
- package/dist/esm/lib/date/months.js +77 -0
- package/dist/esm/lib/date/time.js +75 -0
- package/dist/esm/lib/form/form-data.js +57 -0
- package/dist/esm/lib/form/index.js +2 -0
- package/dist/esm/lib/form/sanitize.js +34 -0
- package/dist/esm/lib/functions/callback.js +6 -0
- package/dist/esm/lib/functions/debounce.js +18 -0
- package/dist/esm/lib/functions/env.js +7 -0
- package/dist/esm/lib/functions/functional.js +52 -0
- package/dist/esm/lib/functions/index.js +5 -0
- package/dist/esm/lib/functions/throttle.js +13 -0
- package/dist/esm/lib/functions/timeout.js +14 -0
- package/dist/esm/lib/hash.js +18 -0
- package/dist/esm/lib/index.js +14 -0
- package/dist/esm/lib/numbers/index.js +11 -0
- package/dist/esm/lib/numbers/math.js +10 -0
- package/dist/esm/lib/objects/camelcase-keys.js +16 -0
- package/dist/esm/lib/objects/empty.js +13 -0
- package/dist/esm/lib/objects/equal.js +11 -0
- package/dist/esm/lib/objects/extend.js +13 -0
- package/dist/esm/lib/objects/flatten.js +17 -0
- package/dist/esm/lib/objects/index.js +13 -0
- package/dist/esm/lib/objects/json.js +10 -0
- package/dist/esm/lib/objects/loop.js +14 -0
- package/dist/esm/lib/objects/mix/mix.js +88 -0
- package/dist/esm/lib/objects/nested-property.js +18 -0
- package/dist/esm/lib/objects/normalize-object.js +9 -0
- package/dist/esm/lib/objects/omit-empty.js +15 -0
- package/dist/esm/lib/objects/size.js +38 -0
- package/dist/esm/lib/objects/split.js +14 -0
- package/dist/esm/lib/promises/index.js +1 -0
- package/dist/esm/lib/promises/reject.js +17 -0
- package/dist/esm/lib/sse.js +50 -0
- package/dist/esm/lib/strings/convert-case/convert-case.js +64 -0
- package/dist/esm/lib/strings/index.js +5 -0
- package/dist/esm/lib/strings/markdown.js +40 -0
- package/dist/esm/lib/strings/name.js +21 -0
- package/dist/esm/lib/strings/pluralize.js +5 -0
- package/dist/esm/lib/strings/query-string.js +16 -0
- package/dist/esm/lib/style/index.js +12 -0
- package/dist/esm/lib/symbols/index.js +1 -0
- package/dist/esm/lib/symbols/symbols.js +12 -0
- package/dist/esm/node/context.js +0 -0
- package/dist/esm/node/dirname.js +13 -0
- package/dist/esm/node/file-cache.js +121 -0
- package/dist/esm/node/file.js +14 -0
- package/dist/esm/node/hash.js +7 -0
- package/dist/esm/node/index.js +7 -0
- package/dist/esm/node/pkce.js +20 -0
- package/dist/esm/node/random-string.js +8 -0
- package/dist/esm/node/sanitize.js +8 -0
- package/dist/esm/node/uuid.js +7 -0
- package/dist/types/dom/accessibility.d.cts +30 -0
- package/dist/types/dom/actions/index.d.cts +3 -0
- package/dist/types/dom/actions/masonry.d.cts +5 -0
- package/dist/types/dom/actions/prefer-horizontal-scroll.d.cts +5 -0
- package/dist/types/dom/actions/sticky.d.cts +5 -0
- package/{src/dom/bounding-box.js → dist/types/dom/bounding-box.d.cts} +8 -49
- package/dist/types/dom/clipboard.d.cts +7 -0
- package/dist/types/dom/cookie.d.cts +7 -0
- package/dist/types/dom/css-vars.d.cts +6 -0
- package/{src/dom/events.js → dist/types/dom/events.d.cts} +52 -31
- package/dist/types/dom/focusable.d.cts +78 -0
- package/dist/types/dom/font-size.d.cts +8 -0
- package/{src/dom/get-element.js → dist/types/dom/get-element.d.cts} +25 -99
- package/dist/types/dom/hash.d.cts +3 -0
- package/dist/types/dom/index.d.cts +31 -0
- package/{src/dom/keyboard.js → dist/types/dom/keyboard.d.cts} +7 -19
- package/dist/types/dom/local-store.d.cts +31 -0
- package/dist/types/dom/media.d.cts +5 -0
- package/dist/types/dom/observers/index.d.cts +4 -0
- package/dist/types/dom/observers/intersection-observer.d.cts +10 -0
- package/dist/types/dom/observers/mutation-observer.d.cts +9 -0
- package/dist/types/dom/observers/observer.d.cts +3 -0
- package/{src/dom/observers/resize-observer.js → dist/types/dom/observers/resize-observer.d.cts} +6 -32
- package/dist/types/dom/observers/scroll-observer.d.cts +40 -0
- package/dist/types/dom/pkce.d.cts +8 -0
- package/dist/types/dom/query-params.d.cts +6 -0
- package/dist/types/dom/random-string.d.cts +9 -0
- package/dist/types/dom/sanitize.d.cts +10 -0
- package/dist/types/dom/session-store.d.cts +7 -0
- package/dist/types/dom/spam-prevention.d.cts +14 -0
- package/dist/types/dom/trap-focus.d.cts +32 -0
- package/dist/types/dom/ui/aria-current.d.cts +7 -0
- package/{src/dom/ui/inconsistent-button-fix.js → dist/types/dom/ui/inconsistent-button-fix.d.cts} +5 -11
- package/dist/types/dom/ui/index.d.cts +4 -0
- package/dist/types/dom/ui/scroll-container.d.cts +3 -0
- package/dist/types/dom/ui/traverse-and-scramble.d.cts +21 -0
- package/dist/types/lib/arrays/index.d.cts +6 -0
- package/{src/lib/arrays/item-position.js → dist/types/lib/arrays/item-position.d.cts} +5 -12
- package/{src/lib/arrays/join.js → dist/types/lib/arrays/join.d.cts} +4 -9
- package/dist/types/lib/arrays/shuffle.d.cts +3 -0
- package/dist/types/lib/arrays/sort.d.cts +32 -0
- package/dist/types/lib/arrays/split-array.d.cts +6 -0
- package/dist/types/lib/arrays/unique.d.cts +3 -0
- package/dist/types/lib/auth/index.d.cts +1 -0
- package/dist/types/lib/auth/route-manager.d.cts +28 -0
- package/dist/types/lib/checks.d.cts +33 -0
- package/dist/types/lib/date/days.d.cts +7 -0
- package/dist/types/lib/date/index.d.cts +3 -0
- package/dist/types/lib/date/months.d.cts +11 -0
- package/dist/types/lib/date/time.d.cts +21 -0
- package/dist/types/lib/form/form-data.d.cts +9 -0
- package/dist/types/lib/form/index.d.cts +2 -0
- package/{src/lib/form/sanitize.js → dist/types/lib/form/sanitize.d.cts} +19 -39
- package/{src/lib/functions/callback.js → dist/types/lib/functions/callback.d.cts} +3 -3
- package/dist/types/lib/functions/debounce.d.cts +3 -0
- package/dist/types/lib/functions/env.d.cts +3 -0
- package/{src/lib/functions/functional.js → dist/types/lib/functions/functional.d.cts} +8 -49
- package/dist/types/lib/functions/index.d.cts +5 -0
- package/dist/types/lib/functions/throttle.d.cts +3 -0
- package/dist/types/lib/functions/timeout.d.cts +5 -0
- package/dist/types/lib/hash.d.cts +3 -0
- package/dist/types/lib/index.d.cts +43 -0
- package/dist/types/lib/numbers/index.d.cts +5 -0
- package/dist/types/lib/numbers/math.d.cts +4 -0
- package/dist/types/lib/objects/camelcase-keys.d.cts +3 -0
- package/dist/types/lib/objects/empty.d.cts +4 -0
- package/dist/types/lib/objects/equal.d.cts +4 -0
- package/dist/types/lib/objects/extend.d.cts +6 -0
- package/dist/types/lib/objects/flatten.d.cts +6 -0
- package/dist/types/lib/objects/index.d.cts +13 -0
- package/dist/types/lib/objects/json.d.cts +3 -0
- package/dist/types/lib/objects/loop.d.cts +4 -0
- package/dist/types/lib/objects/mix/mix.d.cts +44 -0
- package/{src/lib/objects/nested-property.js → dist/types/lib/objects/nested-property.d.cts} +4 -21
- package/dist/types/lib/objects/normalize-object.d.cts +3 -0
- package/dist/types/lib/objects/omit-empty.d.cts +3 -0
- package/dist/types/lib/objects/size.d.cts +3 -0
- package/dist/types/lib/objects/split.d.cts +14 -0
- package/dist/types/lib/promises/index.d.cts +1 -0
- package/dist/types/lib/promises/reject.d.cts +5 -0
- package/dist/types/lib/sse.d.cts +18 -0
- package/dist/types/lib/strings/convert-case/convert-case.d.cts +10 -0
- package/dist/types/lib/strings/index.d.cts +5 -0
- package/dist/types/lib/strings/markdown.d.cts +25 -0
- package/dist/types/lib/strings/name.d.cts +7 -0
- package/dist/types/lib/strings/pluralize.d.cts +3 -0
- package/dist/types/lib/strings/query-string.d.cts +10 -0
- package/dist/types/lib/style/index.d.cts +3 -0
- package/dist/types/lib/symbols/index.d.cts +1 -0
- package/dist/types/lib/symbols/symbols.d.cts +4 -0
- package/dist/types/node/context.d.cts +2 -0
- package/dist/types/node/dirname.d.cts +9 -0
- package/dist/types/node/file-cache.d.cts +56 -0
- package/dist/types/node/file.d.cts +4 -0
- package/dist/types/node/hash.d.cts +3 -0
- package/dist/types/node/index.d.cts +7 -0
- package/dist/types/node/pkce.d.cts +14 -0
- package/dist/types/node/random-string.d.cts +3 -0
- package/{src/node/sanitize.js → dist/types/node/sanitize.d.cts} +3 -6
- package/dist/types/node/uuid.d.cts +3 -0
- package/package.json +4 -1
- package/CHANGELOG.md +0 -237
- package/eslint.config.js +0 -2
- package/src/dom/accessibility.js +0 -58
- package/src/dom/actions/index.js +0 -3
- package/src/dom/actions/masonry.js +0 -43
- package/src/dom/actions/prefer-horizontal-scroll.js +0 -121
- package/src/dom/actions/sticky.js +0 -85
- package/src/dom/clipboard.js +0 -14
- package/src/dom/cookie.js +0 -32
- package/src/dom/css-vars.js +0 -19
- package/src/dom/font-size.js +0 -40
- package/src/dom/hash.js +0 -9
- package/src/dom/index.js +0 -23
- package/src/dom/media.js +0 -30
- package/src/dom/observers/index.js +0 -4
- package/src/dom/observers/intersection-observer.js +0 -43
- package/src/dom/observers/mutation-observer.js +0 -51
- package/src/dom/observers/observer.js +0 -18
- package/src/dom/observers/scroll-observer.js +0 -146
- package/src/dom/pkce.js +0 -34
- package/src/dom/query-params.js +0 -14
- package/src/dom/random-string.js +0 -18
- package/src/dom/random-string.test.js +0 -13
- package/src/dom/sanitize.js +0 -16
- package/src/dom/session-store.js +0 -29
- package/src/dom/spam-prevention.js +0 -40
- package/src/dom/trap-focus.js +0 -70
- package/src/dom/ui/aria-current.js +0 -20
- package/src/dom/ui/index.js +0 -4
- package/src/dom/ui/scroll-container.js +0 -25
- package/src/dom/ui/traverse-and-scramble.js +0 -61
- package/src/lib/arrays/index.js +0 -6
- package/src/lib/arrays/shuffle.js +0 -21
- package/src/lib/arrays/sort.js +0 -88
- package/src/lib/arrays/sort.spec.js +0 -123
- package/src/lib/arrays/split-array.js +0 -15
- package/src/lib/arrays/unique.js +0 -3
- package/src/lib/auth/index.js +0 -1
- package/src/lib/auth/route-manager.js +0 -45
- package/src/lib/checks.js +0 -57
- package/src/lib/date/days.js +0 -9
- package/src/lib/date/index.js +0 -3
- package/src/lib/date/months.js +0 -74
- package/src/lib/date/time.js +0 -83
- package/src/lib/form/form-data.js +0 -73
- package/src/lib/form/index.js +0 -2
- package/src/lib/form/sanitize.spec.js +0 -126
- package/src/lib/functions/debounce.js +0 -18
- package/src/lib/functions/env.js +0 -5
- package/src/lib/functions/functional.test.js +0 -196
- package/src/lib/functions/index.js +0 -5
- package/src/lib/functions/throttle.js +0 -11
- package/src/lib/functions/timeout.js +0 -15
- package/src/lib/hash.js +0 -18
- package/src/lib/hash.spec.js +0 -163
- package/src/lib/index.js +0 -14
- package/src/lib/numbers/index.js +0 -12
- package/src/lib/numbers/math.js +0 -9
- package/src/lib/numbers/split-unit.test.js +0 -45
- package/src/lib/objects/camelcase-keys.js +0 -17
- package/src/lib/objects/camelcase-keys.test.js +0 -72
- package/src/lib/objects/empty.js +0 -10
- package/src/lib/objects/equal.js +0 -9
- package/src/lib/objects/extend.js +0 -16
- package/src/lib/objects/extend.test.js +0 -35
- package/src/lib/objects/flatten.js +0 -19
- package/src/lib/objects/index.js +0 -13
- package/src/lib/objects/json.js +0 -7
- package/src/lib/objects/loop.js +0 -11
- package/src/lib/objects/loop.test.js +0 -31
- package/src/lib/objects/mix/mix.js +0 -191
- package/src/lib/objects/mix/mix.md +0 -78
- package/src/lib/objects/mix/mix.test.js +0 -445
- package/src/lib/objects/normalize-object.js +0 -10
- package/src/lib/objects/omit-empty.js +0 -23
- package/src/lib/objects/omit-empty.test.js +0 -85
- package/src/lib/objects/size.js +0 -41
- package/src/lib/objects/split.js +0 -19
- package/src/lib/promises/index.js +0 -1
- package/src/lib/promises/reject.js +0 -17
- package/src/lib/sse.js +0 -61
- package/src/lib/strings/convert-case/convert-case.js +0 -86
- package/src/lib/strings/convert-case/convert-case.md +0 -44
- package/src/lib/strings/convert-case/convert-case.test.js +0 -50
- package/src/lib/strings/index.js +0 -5
- package/src/lib/strings/markdown.js +0 -71
- package/src/lib/strings/markdown.spec.js +0 -73
- package/src/lib/strings/name.js +0 -24
- package/src/lib/strings/name.test.js +0 -67
- package/src/lib/strings/pluralize.js +0 -2
- package/src/lib/strings/query-string.js +0 -18
- package/src/lib/style/index.js +0 -13
- package/src/lib/symbols/index.js +0 -1
- package/src/lib/symbols/symbols.js +0 -9
- package/src/node/dirname.js +0 -17
- package/src/node/file-cache.js +0 -184
- package/src/node/file.js +0 -13
- package/src/node/hash.js +0 -5
- package/src/node/index.js +0 -7
- package/src/node/pkce.js +0 -33
- package/src/node/random-string.js +0 -10
- package/src/node/random-string.test.js +0 -15
- package/src/node/sanitize.spec.js +0 -142
- package/src/node/uuid.js +0 -5
- package/tsconfig.json +0 -23
- package/tsup.config.js +0 -38
- package/tsup.config.mjs +0 -63
- /package/{src/node/context.js → dist/cjs/node/context.cjs} +0 -0
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
const DEFAULT_OPTIONS = { array: 'replace' } // Can be concat or replace
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Deep merges multiple objects into a new object with intelligent handling of arrays and nested objects.
|
|
5
|
-
*
|
|
6
|
-
* @param {...Object} sources - Objects to merge. Null and undefined values are skipped.
|
|
7
|
-
* @return {Object} A new object containing the merged properties from all sources.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* const obj1 = { a: 1, b: { x: 10 } }
|
|
11
|
-
* const obj2 = { b: { y: 20 }, c: 3 }
|
|
12
|
-
* const result = mix(obj1, obj2)
|
|
13
|
-
* // Returns: { a: 1, b: { x: 10, y: 20 }, c: 3 }
|
|
14
|
-
*/
|
|
15
|
-
export const mix = createMix()
|
|
16
|
-
export const concatMix = createMix({ array: 'concat' })
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Creates a customized mix function with specific options for array handling.
|
|
20
|
-
*
|
|
21
|
-
* @param {Object} [userOptions={}] - Configuration options for the mix function.
|
|
22
|
-
* @param {('replace'|'concat')} [userOptions.array='replace'] - How to handle array merging:
|
|
23
|
-
* - 'replace': Arrays from later sources completely replace arrays from earlier sources
|
|
24
|
-
* - 'concat': Arrays are concatenated together
|
|
25
|
-
* @return {Function} A mix function configured with the provided options.
|
|
26
|
-
*
|
|
27
|
-
* @example
|
|
28
|
-
* // Create mix function that concatenates arrays
|
|
29
|
-
* const concatMix = createMix({ array: 'concat' })
|
|
30
|
-
* const obj1 = { items: [1, 2] }
|
|
31
|
-
* const obj2 = { items: [3, 4] }
|
|
32
|
-
* const result = concatMix(obj1, obj2)
|
|
33
|
-
* // Returns: { items: [1, 2, 3, 4] }
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* // Create mix function that replaces arrays (default behavior)
|
|
37
|
-
* const replaceMix = createMix({ array: 'replace' })
|
|
38
|
-
* const obj1 = { items: [1, 2] }
|
|
39
|
-
* const obj2 = { items: [3, 4] }
|
|
40
|
-
* const result = replaceMix(obj1, obj2)
|
|
41
|
-
* // Returns: { items: [3, 4] }
|
|
42
|
-
*/
|
|
43
|
-
export function createMix(userOptions = {}) {
|
|
44
|
-
const options = { ...DEFAULT_OPTIONS, ...userOptions }
|
|
45
|
-
|
|
46
|
-
function _mix(...sources) {
|
|
47
|
-
const result = {}
|
|
48
|
-
for (const source of sources) {
|
|
49
|
-
// Skip null or undefined sources
|
|
50
|
-
if (source == null) continue
|
|
51
|
-
merge(result, source, options)
|
|
52
|
-
}
|
|
53
|
-
return result
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return _mix
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Recursively merges properties from input object into output object.
|
|
61
|
-
* Handles property descriptors, prevents prototype pollution, and deep clones values.
|
|
62
|
-
*
|
|
63
|
-
* @param {Object} output - The target object to merge properties into.
|
|
64
|
-
* @param {Object} input - The source object to merge properties from.
|
|
65
|
-
* @param {Object} options - Merge options including array handling strategy.
|
|
66
|
-
* @property {('replace'|'concat')} options.array - How to handle array merging.
|
|
67
|
-
*/
|
|
68
|
-
function merge(output, input, options) {
|
|
69
|
-
const props = Object.keys(input)
|
|
70
|
-
|
|
71
|
-
for (const prop of props) {
|
|
72
|
-
// Prevents Prototype Pollution
|
|
73
|
-
if (prop === '__proto__') continue
|
|
74
|
-
|
|
75
|
-
const descriptor = Object.getOwnPropertyDescriptor(input, prop)
|
|
76
|
-
const value = descriptor.value
|
|
77
|
-
if (value) descriptor.value = cloneDescriptorValue(value)
|
|
78
|
-
|
|
79
|
-
// If don't have prop => Define property
|
|
80
|
-
if (!output[prop]) {
|
|
81
|
-
Object.defineProperty(output, prop, descriptor)
|
|
82
|
-
continue
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// If have prop, but type is not object => Overwrite by redefining property
|
|
86
|
-
if (typeof output[prop] !== 'object') {
|
|
87
|
-
Object.defineProperty(output, prop, descriptor)
|
|
88
|
-
continue
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Incoming non-object (primitive/null) => always overwrite
|
|
92
|
-
if (descriptor.value == null || typeof descriptor.value !== 'object') {
|
|
93
|
-
Object.defineProperty(output, prop, descriptor)
|
|
94
|
-
continue
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// If have prop, and incoming is Array => concat or replace
|
|
98
|
-
if (objectType(descriptor.value) === '[object Array]') {
|
|
99
|
-
output[prop] =
|
|
100
|
-
options.array === 'replace'
|
|
101
|
-
? descriptor.value.slice()
|
|
102
|
-
: output[prop].concat(descriptor.value)
|
|
103
|
-
continue
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// If have prop, but type is Object => Merge.
|
|
107
|
-
merge(output[prop], descriptor.value, options)
|
|
108
|
-
|
|
109
|
-
// Not sure if I have to deal with overwriting maps / dates. When it comes, I guess!
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Creates a deep clone of a property descriptor value.
|
|
115
|
-
* Handles arrays, objects, dates, maps, sets, and other types appropriately.
|
|
116
|
-
*
|
|
117
|
-
* @param {*} value - The value to clone.
|
|
118
|
-
* @return {*} A deep clone of the input value.
|
|
119
|
-
* @property {Array} value - Cloned recursively with all elements deep cloned.
|
|
120
|
-
* @property {Object} value - Cloned with all properties and descriptors preserved.
|
|
121
|
-
* @property {Date} value - Cloned as new Date with same time value.
|
|
122
|
-
* @property {Map} value - Cloned with all entries deep cloned.
|
|
123
|
-
* @property {Set} value - Cloned with all entries deep cloned.
|
|
124
|
-
*/
|
|
125
|
-
function cloneDescriptorValue(value) {
|
|
126
|
-
// Arrays
|
|
127
|
-
if (objectType(value) === '[object Array]') {
|
|
128
|
-
const array = []
|
|
129
|
-
for (let v of value) {
|
|
130
|
-
v = cloneDescriptorValue(v)
|
|
131
|
-
array.push(v)
|
|
132
|
-
}
|
|
133
|
-
return array
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Objects
|
|
137
|
-
if (objectType(value) === '[object Object]') {
|
|
138
|
-
const obj = {}
|
|
139
|
-
const props = Object.keys(value)
|
|
140
|
-
for (const prop of props) {
|
|
141
|
-
const descriptor = Object.getOwnPropertyDescriptor(value, prop)
|
|
142
|
-
if (descriptor.value)
|
|
143
|
-
descriptor.value = cloneDescriptorValue(descriptor.value)
|
|
144
|
-
Object.defineProperty(obj, prop, descriptor)
|
|
145
|
-
}
|
|
146
|
-
return obj
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Other Types of Objects
|
|
150
|
-
if (objectType(value) === '[object Date]') {
|
|
151
|
-
return new Date(value.getTime())
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
if (objectType(value) === '[object Map]') {
|
|
155
|
-
const map = new Map()
|
|
156
|
-
for (const entry of value) {
|
|
157
|
-
map.set(entry[0], cloneDescriptorValue(entry[1]))
|
|
158
|
-
}
|
|
159
|
-
return map
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
if (objectType(value) === '[object Set]') {
|
|
163
|
-
const set = new Set()
|
|
164
|
-
for (const entry of value.entries()) {
|
|
165
|
-
set.add(cloneDescriptorValue(entry[0]))
|
|
166
|
-
}
|
|
167
|
-
return set
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Types we don't need to clone or cannot clone.
|
|
171
|
-
// Examples:
|
|
172
|
-
// - Primitives don't need to clone
|
|
173
|
-
// - Functions cannot clone
|
|
174
|
-
return value
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Returns the precise object type of a value using Object.prototype.toString.
|
|
179
|
-
*
|
|
180
|
-
* @param {*} value - The value to get the type of.
|
|
181
|
-
* @return {string} The object type string (e.g., '[object Array]', '[object Object]', '[object Date]').
|
|
182
|
-
*
|
|
183
|
-
* @example
|
|
184
|
-
* objectType([]) // '[object Array]'
|
|
185
|
-
* objectType({}) // '[object Object]'
|
|
186
|
-
* objectType(new Date()) // '[object Date]'
|
|
187
|
-
* objectType(null) // '[object Null]'
|
|
188
|
-
*/
|
|
189
|
-
function objectType(value) {
|
|
190
|
-
return Object.prototype.toString.call(value)
|
|
191
|
-
}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
# Mix
|
|
2
|
-
|
|
3
|
-
- Merges objects. Like `Object.assign`, but performs a deep merge so won't be any mutation.
|
|
4
|
-
- [Why I created `mix`](https://zellwk.com/blog/copy-properties-of-one-object-to-another-object)
|
|
5
|
-
|
|
6
|
-
## Usage
|
|
7
|
-
|
|
8
|
-
Import the module and use it.
|
|
9
|
-
|
|
10
|
-
```js
|
|
11
|
-
import mix from '@zellwk/javascript/mix'
|
|
12
|
-
mix(target, source)
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Example
|
|
16
|
-
|
|
17
|
-
Pass objects into mix to combine them. Mix creates a new object for you automatically. Nothing will get mutated.
|
|
18
|
-
|
|
19
|
-
```js
|
|
20
|
-
let count = 0
|
|
21
|
-
const one = { one: 'one' }
|
|
22
|
-
const two = { two: 'two' }
|
|
23
|
-
const mixed = mix(one, two)
|
|
24
|
-
|
|
25
|
-
// Output
|
|
26
|
-
// {
|
|
27
|
-
// one: 'one',
|
|
28
|
-
// two: 'two',
|
|
29
|
-
// }
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Features
|
|
33
|
-
|
|
34
|
-
1. It copies accessors.
|
|
35
|
-
2. It performs a deep merge so no mutation can happen
|
|
36
|
-
|
|
37
|
-
### Copying accessors
|
|
38
|
-
|
|
39
|
-
Mix copies accessors along with other properties. Most other deep merging libraries don't do this. `Object.assign` doesn't do this either.
|
|
40
|
-
|
|
41
|
-
```js
|
|
42
|
-
let count = 0
|
|
43
|
-
const one = { one: 'one' }
|
|
44
|
-
const two = { two: 'two' }
|
|
45
|
-
const three = {
|
|
46
|
-
get count () {
|
|
47
|
-
return count
|
|
48
|
-
},
|
|
49
|
-
set count (value) {
|
|
50
|
-
count = value
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
const mixed = mix({}, one, two, three)
|
|
54
|
-
|
|
55
|
-
// Output
|
|
56
|
-
// {
|
|
57
|
-
// one: 'one',
|
|
58
|
-
// two: 'two',
|
|
59
|
-
// get count () { return count } ,
|
|
60
|
-
// set count (value) { count = value }
|
|
61
|
-
// }
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### Deep Merging
|
|
65
|
-
|
|
66
|
-
`mix` copies nested objects and arrays so you don't have to worry about mutation.
|
|
67
|
-
|
|
68
|
-
```js
|
|
69
|
-
const one = {}
|
|
70
|
-
const two = { nested: { value: 'two' } }
|
|
71
|
-
const three = mix(one, two)
|
|
72
|
-
|
|
73
|
-
// Nested values do not get mutated
|
|
74
|
-
three.nested.value = 'three'
|
|
75
|
-
console.log(two.nested.value) // 'two'
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
That's it!
|
|
@@ -1,445 +0,0 @@
|
|
|
1
|
-
import { expect, it } from 'vitest'
|
|
2
|
-
|
|
3
|
-
import { concatMix, createMix, mix } from './mix.js'
|
|
4
|
-
|
|
5
|
-
it('Merge objects', () => {
|
|
6
|
-
const one = { one: 'one', overwrite: 'nope' }
|
|
7
|
-
const two = { two: 'two', overwrite: 'yes' }
|
|
8
|
-
const three = mix(one, two)
|
|
9
|
-
|
|
10
|
-
expect(three).toEqual({
|
|
11
|
-
one: 'one',
|
|
12
|
-
two: 'two',
|
|
13
|
-
overwrite: 'yes',
|
|
14
|
-
})
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
it('Empty + Nested', () => {
|
|
18
|
-
const one = {}
|
|
19
|
-
const two = {
|
|
20
|
-
nested: {
|
|
21
|
-
value: 'nested-two',
|
|
22
|
-
deep: {
|
|
23
|
-
value: 'deep-two',
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
}
|
|
27
|
-
const three = mix(one, two)
|
|
28
|
-
|
|
29
|
-
expect(three).toEqual(two)
|
|
30
|
-
expect(three.nested.value).toBe('nested-two')
|
|
31
|
-
expect(three.nested.deep.value).toBe('deep-two')
|
|
32
|
-
|
|
33
|
-
// Prevents mutation of nested object
|
|
34
|
-
three.nested.value = 'three'
|
|
35
|
-
expect(two.nested.value).toBe('nested-two')
|
|
36
|
-
|
|
37
|
-
// Prevents mutation of deeply nested object
|
|
38
|
-
three.nested.deep.value = 'deep-three'
|
|
39
|
-
expect(two.nested.deep.value).toBe('deep-two')
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('Double Nested Objects', () => {
|
|
43
|
-
const one = {
|
|
44
|
-
one: 'one',
|
|
45
|
-
nested: {
|
|
46
|
-
one: 'nested-one',
|
|
47
|
-
deep: {
|
|
48
|
-
one: 'deep-one',
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const two = {
|
|
54
|
-
two: 'two',
|
|
55
|
-
nested: {
|
|
56
|
-
two: 'nested-two',
|
|
57
|
-
deep: {
|
|
58
|
-
two: 'deep-two',
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const three = mix(one, two)
|
|
64
|
-
|
|
65
|
-
expect(three.one).toBe('one')
|
|
66
|
-
expect(three.two).toBe('two')
|
|
67
|
-
expect(three.nested.one).toBe('nested-one')
|
|
68
|
-
expect(three.nested.two).toBe('nested-two')
|
|
69
|
-
expect(three.nested.deep.one).toBe('deep-one')
|
|
70
|
-
expect(three.nested.deep.two).toBe('deep-two')
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
it('Accessors', () => {
|
|
74
|
-
let count = 0
|
|
75
|
-
const one = {}
|
|
76
|
-
const two = {
|
|
77
|
-
get count() {
|
|
78
|
-
return count
|
|
79
|
-
},
|
|
80
|
-
set count(value) {
|
|
81
|
-
count = value
|
|
82
|
-
},
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const three = mix(one, two)
|
|
86
|
-
expect(three).toEqual(two)
|
|
87
|
-
|
|
88
|
-
const propertyDescriptor = Object.getOwnPropertyDescriptor(three, 'count')
|
|
89
|
-
three.count = 3
|
|
90
|
-
expect(three.count).toBe(3)
|
|
91
|
-
expect(typeof propertyDescriptor.get).toBe('function')
|
|
92
|
-
expect(typeof propertyDescriptor.set).toBe('function')
|
|
93
|
-
expect(two.count !== three.count)
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
it('Empty + Nested accessors', () => {
|
|
97
|
-
let count = 0
|
|
98
|
-
const one = {}
|
|
99
|
-
const two = {
|
|
100
|
-
nested: {
|
|
101
|
-
get count() {
|
|
102
|
-
return count
|
|
103
|
-
},
|
|
104
|
-
set count(value) {
|
|
105
|
-
count = value
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const three = mix(one, two)
|
|
111
|
-
expect(three).toEqual(two)
|
|
112
|
-
expect(two.nested).not.toBe(three.nested)
|
|
113
|
-
|
|
114
|
-
const descriptor = Object.getOwnPropertyDescriptor(three.nested, 'count')
|
|
115
|
-
expect(typeof descriptor.get).toBe('function')
|
|
116
|
-
expect(typeof descriptor.set).toBe('function')
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
it('Double nested with Accessors', () => {
|
|
120
|
-
let count = 0
|
|
121
|
-
const one = {
|
|
122
|
-
nested: {
|
|
123
|
-
get accessOne() {
|
|
124
|
-
return count
|
|
125
|
-
},
|
|
126
|
-
set accessOne(value) {
|
|
127
|
-
count = value
|
|
128
|
-
},
|
|
129
|
-
},
|
|
130
|
-
}
|
|
131
|
-
const two = {
|
|
132
|
-
nested: {
|
|
133
|
-
get accessTwo() {
|
|
134
|
-
return count
|
|
135
|
-
},
|
|
136
|
-
set accessTwo(value) {
|
|
137
|
-
count = value
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const three = mix(one, two)
|
|
143
|
-
expect(one.nested).not.toBe(three.nested)
|
|
144
|
-
expect(two.nested).not.toBe(three.nested)
|
|
145
|
-
|
|
146
|
-
const accessOne = Object.getOwnPropertyDescriptor(three.nested, 'accessOne')
|
|
147
|
-
const accessTwo = Object.getOwnPropertyDescriptor(three.nested, 'accessTwo')
|
|
148
|
-
|
|
149
|
-
expect(typeof accessOne.get).toBe('function')
|
|
150
|
-
expect(typeof accessOne.set).toBe('function')
|
|
151
|
-
expect(typeof accessTwo.get).toBe('function')
|
|
152
|
-
expect(typeof accessTwo.set).toBe('function')
|
|
153
|
-
})
|
|
154
|
-
|
|
155
|
-
it('Nested arrays', () => {
|
|
156
|
-
const one = {}
|
|
157
|
-
const two = { array: [1, 2, 3] }
|
|
158
|
-
const three = mix(one, two)
|
|
159
|
-
|
|
160
|
-
expect(three).toEqual(two)
|
|
161
|
-
expect(typeof three.array.push).toBe('function')
|
|
162
|
-
|
|
163
|
-
// Prevent mutation
|
|
164
|
-
three.array.push(4)
|
|
165
|
-
expect(two.array).toHaveLength(3)
|
|
166
|
-
expect(three.array).toHaveLength(4)
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
it('Double objects with nested same array', () => {
|
|
170
|
-
const one = {
|
|
171
|
-
array: [1, 2, 3],
|
|
172
|
-
}
|
|
173
|
-
const two = {
|
|
174
|
-
array: [4, 5, 6],
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
const three = mix(one, two)
|
|
178
|
-
expect(typeof three.array.push).toBe('function')
|
|
179
|
-
expect(three.array).toHaveLength(3)
|
|
180
|
-
expect(three.array).toEqual([4, 5, 6])
|
|
181
|
-
})
|
|
182
|
-
|
|
183
|
-
it('Objects in Arrays', () => {
|
|
184
|
-
const one = {}
|
|
185
|
-
const two = {
|
|
186
|
-
array: [
|
|
187
|
-
1,
|
|
188
|
-
{ value: 2 },
|
|
189
|
-
3,
|
|
190
|
-
{
|
|
191
|
-
get count() {
|
|
192
|
-
return 1
|
|
193
|
-
},
|
|
194
|
-
},
|
|
195
|
-
],
|
|
196
|
-
}
|
|
197
|
-
const three = mix(one, two)
|
|
198
|
-
|
|
199
|
-
expect(three).toEqual(two)
|
|
200
|
-
expect(typeof three.array.push).toBe('function')
|
|
201
|
-
expect(two.array[1]).not.toBe(three.array[1])
|
|
202
|
-
|
|
203
|
-
// Ensures accessors are copied over
|
|
204
|
-
const descriptor = Object.getOwnPropertyDescriptor(three.array[3], 'count')
|
|
205
|
-
expect(typeof descriptor.get).toBe('function')
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
it('Deep nested arrays', () => {
|
|
209
|
-
const one = {}
|
|
210
|
-
const two = {
|
|
211
|
-
array: [1, [2], 3],
|
|
212
|
-
}
|
|
213
|
-
const three = mix(one, two)
|
|
214
|
-
|
|
215
|
-
expect(three).toEqual(two)
|
|
216
|
-
expect(three.array).toHaveLength(3)
|
|
217
|
-
expect(three.array[1]).toHaveLength(1)
|
|
218
|
-
expect(two.array[1]).not.toBe(three.array[1])
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
it('concatMix: concatenates arrays', () => {
|
|
222
|
-
const one = {
|
|
223
|
-
array: [1, 2, 3],
|
|
224
|
-
}
|
|
225
|
-
const two = {
|
|
226
|
-
array: [4, 5, 6],
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const three = concatMix(one, two)
|
|
230
|
-
expect(typeof three.array.push).toBe('function')
|
|
231
|
-
expect(three.array).toHaveLength(6)
|
|
232
|
-
expect(three.array).toEqual([1, 2, 3, 4, 5, 6])
|
|
233
|
-
})
|
|
234
|
-
|
|
235
|
-
it('concatMix: empty array concat', () => {
|
|
236
|
-
const one = {}
|
|
237
|
-
const two = { array: [1, 2, 3] }
|
|
238
|
-
const three = concatMix(one, two)
|
|
239
|
-
|
|
240
|
-
expect(three).toEqual(two)
|
|
241
|
-
expect(typeof three.array.push).toBe('function')
|
|
242
|
-
expect(three.array).toHaveLength(3)
|
|
243
|
-
|
|
244
|
-
// Prevent mutation
|
|
245
|
-
three.array.push(4)
|
|
246
|
-
expect(two.array).toHaveLength(3)
|
|
247
|
-
expect(three.array).toHaveLength(4)
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
it('concatMix: nested objects with concatenated arrays', () => {
|
|
251
|
-
const one = {
|
|
252
|
-
nested: {
|
|
253
|
-
items: [1, 2],
|
|
254
|
-
other: 'value1',
|
|
255
|
-
},
|
|
256
|
-
}
|
|
257
|
-
const two = {
|
|
258
|
-
nested: {
|
|
259
|
-
items: [3, 4],
|
|
260
|
-
other: 'value2',
|
|
261
|
-
},
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
const three = concatMix(one, two)
|
|
265
|
-
expect(three.nested.items).toEqual([1, 2, 3, 4])
|
|
266
|
-
expect(three.nested.other).toBe('value2')
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
it('Functions (cannot be cloned)', () => {
|
|
270
|
-
const one = {}
|
|
271
|
-
const two = {
|
|
272
|
-
nested: {
|
|
273
|
-
identity(i) {
|
|
274
|
-
return i
|
|
275
|
-
},
|
|
276
|
-
deep: {
|
|
277
|
-
identity(i) {
|
|
278
|
-
return i
|
|
279
|
-
},
|
|
280
|
-
},
|
|
281
|
-
},
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
const three = mix(one, two)
|
|
285
|
-
expect(three).toEqual(two)
|
|
286
|
-
expect(three.nested.identity).toBe(two.nested.identity)
|
|
287
|
-
expect(three.nested.deep.identity).toBe(two.nested.deep.identity)
|
|
288
|
-
})
|
|
289
|
-
|
|
290
|
-
it('Nested Dates', () => {
|
|
291
|
-
const one = {}
|
|
292
|
-
const two = {
|
|
293
|
-
date: new Date(),
|
|
294
|
-
nested: {
|
|
295
|
-
date: new Date(),
|
|
296
|
-
},
|
|
297
|
-
}
|
|
298
|
-
const three = mix(one, two)
|
|
299
|
-
|
|
300
|
-
expect(three.date).not.toBe(two.date)
|
|
301
|
-
expect(three.date.getTime()).toBe(two.date.getTime())
|
|
302
|
-
expect(three.nested.date).not.toBe(two.nested.date)
|
|
303
|
-
})
|
|
304
|
-
|
|
305
|
-
it('Nested Maps', () => {
|
|
306
|
-
const one = {}
|
|
307
|
-
const two = {
|
|
308
|
-
map: new Map(),
|
|
309
|
-
nested: {
|
|
310
|
-
map: new Map(),
|
|
311
|
-
},
|
|
312
|
-
}
|
|
313
|
-
const a = { one: 1 }
|
|
314
|
-
const b = { two: 2 }
|
|
315
|
-
two.map.set('item', { one: 1 })
|
|
316
|
-
two.map.set(a, b)
|
|
317
|
-
two.nested.map.set('item', { one: 1 })
|
|
318
|
-
|
|
319
|
-
const three = mix(one, two)
|
|
320
|
-
|
|
321
|
-
expect(three.map).not.toBe(two.map)
|
|
322
|
-
expect(three.map).toEqual(two.map)
|
|
323
|
-
expect(three.map.get('item')).toEqual({ one: 1 })
|
|
324
|
-
expect(three.map.get('item')).not.toBe(two.map.get('item'))
|
|
325
|
-
|
|
326
|
-
expect(three.nested.map).toEqual(two.nested.map)
|
|
327
|
-
expect(three.nested.map).not.toBe(two.nested.map)
|
|
328
|
-
|
|
329
|
-
expect(three.map.get(a)).toEqual(b)
|
|
330
|
-
expect(three.map.get(a)).not.toBe(two.map.get(a))
|
|
331
|
-
|
|
332
|
-
// Note: WeakMap keys are not enumerable... so they cannot be cloned.
|
|
333
|
-
// That's why we're not testing WeakMap
|
|
334
|
-
})
|
|
335
|
-
|
|
336
|
-
it('Nested Sets', () => {
|
|
337
|
-
const one = {}
|
|
338
|
-
const two = {
|
|
339
|
-
set: new Set(),
|
|
340
|
-
nested: {
|
|
341
|
-
set: new Set(),
|
|
342
|
-
},
|
|
343
|
-
}
|
|
344
|
-
const a = { object: 'test' }
|
|
345
|
-
two.set.add('one')
|
|
346
|
-
two.set.add(a)
|
|
347
|
-
two.nested.set.add('nested')
|
|
348
|
-
|
|
349
|
-
const three = mix(one, two)
|
|
350
|
-
|
|
351
|
-
expect(three.set).not.toBe(two.set)
|
|
352
|
-
expect(three.set).toEqual(two.set)
|
|
353
|
-
expect(three.set.has('one')).toBe(true)
|
|
354
|
-
expect(three.set.has(a)).toBe(false)
|
|
355
|
-
|
|
356
|
-
expect(three.nested.set).not.toBe(two.nested.set)
|
|
357
|
-
expect(three.nested.set).toEqual(two.nested.set)
|
|
358
|
-
expect(three.nested.set.has('nested')).toBe(true)
|
|
359
|
-
|
|
360
|
-
// Note: WeakSet contains objects only... so there's no point creating a deep clone. You won't be able to access them.
|
|
361
|
-
// That's why we're not testing WeakSet
|
|
362
|
-
})
|
|
363
|
-
|
|
364
|
-
// Prevents Prototype Pollution
|
|
365
|
-
// https://codeburst.io/what-is-prototype-pollution-49482fc4b638
|
|
366
|
-
it('Safe Merge', () => {
|
|
367
|
-
const polluted = JSON.parse('{"__proto__": {"admin": true}}')
|
|
368
|
-
const mixed = mix(polluted)
|
|
369
|
-
|
|
370
|
-
/* eslint-disable */
|
|
371
|
-
expect(mixed.__proto__).toEqual({})
|
|
372
|
-
/* eslint-enable */
|
|
373
|
-
})
|
|
374
|
-
|
|
375
|
-
it('should skip null and undefined sources', () => {
|
|
376
|
-
const obj1 = { a: 1 }
|
|
377
|
-
const obj2 = { b: 2 }
|
|
378
|
-
const expected = { a: 1, b: 2 }
|
|
379
|
-
|
|
380
|
-
expect(mix(obj1, null, obj2)).toEqual(expected)
|
|
381
|
-
expect(mix(null, obj1, obj2)).toEqual(expected)
|
|
382
|
-
expect(mix(obj1, obj2, null)).toEqual(expected)
|
|
383
|
-
|
|
384
|
-
expect(mix(obj1, undefined, obj2)).toEqual(expected)
|
|
385
|
-
expect(mix(undefined, obj1, obj2)).toEqual(expected)
|
|
386
|
-
expect(mix(obj1, obj2, undefined)).toEqual(expected)
|
|
387
|
-
|
|
388
|
-
expect(mix(null, obj1, undefined, obj2, null)).toEqual(expected)
|
|
389
|
-
})
|
|
390
|
-
|
|
391
|
-
it('should not skip null and false properties', () => {
|
|
392
|
-
const obj1 = { a: 1, b: 2, c: 3 }
|
|
393
|
-
const obj2 = { a: null, b: false, c: undefined }
|
|
394
|
-
const expected = { a: null, b: false, c: undefined }
|
|
395
|
-
|
|
396
|
-
expect(mix(obj1, obj2)).toEqual(expected)
|
|
397
|
-
})
|
|
398
|
-
|
|
399
|
-
it('Real Nested Example', () => {
|
|
400
|
-
const defaultOpts = {
|
|
401
|
-
transforms: {
|
|
402
|
-
extractFromFileName: { date: 'pubDate', slug: 'slug' },
|
|
403
|
-
setLatestDate: {
|
|
404
|
-
targetProperty: 'date',
|
|
405
|
-
sourceProperties: ['pubDate', 'updateDate'],
|
|
406
|
-
},
|
|
407
|
-
generateExcerpt: true,
|
|
408
|
-
stripFileNumbering: true,
|
|
409
|
-
stripMore: true,
|
|
410
|
-
},
|
|
411
|
-
sort: {
|
|
412
|
-
props: ['data.date', 'data.pubDate', 'data.title'],
|
|
413
|
-
reverse: true,
|
|
414
|
-
},
|
|
415
|
-
filter: 'published',
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
const newOptions = {
|
|
419
|
-
transforms: {
|
|
420
|
-
extractFromFileName: false,
|
|
421
|
-
generateExcerpt: false,
|
|
422
|
-
stripMore: false,
|
|
423
|
-
// stripFileNumbering: true,
|
|
424
|
-
},
|
|
425
|
-
sort: { props: ['filePath'], reverse: false },
|
|
426
|
-
filter: false,
|
|
427
|
-
}
|
|
428
|
-
const expected = {
|
|
429
|
-
transforms: {
|
|
430
|
-
setLatestDate: {
|
|
431
|
-
targetProperty: 'date',
|
|
432
|
-
sourceProperties: ['pubDate', 'updateDate'],
|
|
433
|
-
},
|
|
434
|
-
extractFromFileName: false,
|
|
435
|
-
generateExcerpt: false,
|
|
436
|
-
stripFileNumbering: true,
|
|
437
|
-
stripMore: false,
|
|
438
|
-
},
|
|
439
|
-
sort: { props: ['filePath'], reverse: false },
|
|
440
|
-
filter: false,
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
const mixReplace = createMix({ array: 'replace' })
|
|
444
|
-
expect(mixReplace(defaultOpts, newOptions)).toEqual(expected)
|
|
445
|
-
})
|