@design-edito/tools 0.4.5 → 0.4.6
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/TODO.md +269 -0
- package/agnostic/arrays/dedupe/index.js +9 -7
- package/agnostic/arrays/dedupe/index.test.js +24 -0
- package/agnostic/arrays/find-duplicates/index.js +34 -22
- package/agnostic/arrays/find-duplicates/index.test.js +31 -0
- package/agnostic/arrays/index.d.ts +2 -2
- package/agnostic/arrays/index.js +2 -2
- package/agnostic/arrays/is-array-of/index.js +28 -26
- package/agnostic/arrays/is-array-of/index.test.js +56 -0
- package/agnostic/arrays/make/index.js +11 -6
- package/agnostic/arrays/make/index.test.js +10 -0
- package/agnostic/arrays/random-pick/index.js +38 -22
- package/agnostic/arrays/random-pick/index.test.js +23 -0
- package/agnostic/arrays/shuffle/index.js +15 -11
- package/agnostic/arrays/shuffle/index.test.js +14 -0
- package/agnostic/booleans/is-falsy/index.js +24 -15
- package/agnostic/booleans/is-falsy/index.test.js +26 -0
- package/agnostic/colors/channels/index.js +139 -936
- package/agnostic/colors/channels/index.test.js +64 -0
- package/agnostic/colors/contrast/index.js +24 -643
- package/agnostic/colors/contrast/index.test.js +21 -0
- package/agnostic/colors/convert/index.js +811 -837
- package/agnostic/colors/convert/index.test.js +98 -0
- package/agnostic/colors/cssColorsMap.js +153 -0
- package/agnostic/colors/distance/index.js +66 -538
- package/agnostic/colors/distance/index.test.js +21 -0
- package/agnostic/colors/grayscale/index.js +95 -872
- package/agnostic/colors/grayscale/index.test.js +34 -0
- package/agnostic/colors/index.d.ts +2 -2
- package/agnostic/colors/index.js +2 -2
- package/agnostic/colors/invert/index.js +34 -719
- package/agnostic/colors/invert/index.test.js +31 -0
- package/agnostic/colors/lerp/index.js +75 -804
- package/agnostic/colors/lerp/index.test.js +55 -0
- package/agnostic/colors/luminance/index.js +17 -625
- package/agnostic/colors/luminance/index.test.js +30 -0
- package/agnostic/colors/palette/index.js +83 -917
- package/agnostic/colors/palette/index.test.js +35 -0
- package/agnostic/colors/rotate/index.js +35 -835
- package/agnostic/colors/rotate/index.test.js +45 -0
- package/agnostic/colors/tidy/index.js +79 -530
- package/agnostic/colors/tidy/index.test.js +45 -0
- package/agnostic/colors/typechecks/index.js +188 -250
- package/agnostic/colors/typechecks/index.test.js +113 -0
- package/agnostic/colors/types.js +1 -0
- package/agnostic/css/bem/index.js +134 -171
- package/agnostic/css/clss/index.js +64 -29
- package/agnostic/css/clss/index.test.js +60 -0
- package/agnostic/css/generate-nice-color/index.js +26 -71
- package/agnostic/css/generate-nice-color/index.test.js +8 -0
- package/agnostic/css/index.d.ts +2 -2
- package/agnostic/css/index.js +2 -2
- package/agnostic/css/is-valid-css-class-name/index.js +14 -8
- package/agnostic/css/is-valid-css-class-name/index.test.js +36 -0
- package/agnostic/css/scale/index.js +37 -50
- package/agnostic/css/scale/index.test.js +71 -0
- package/agnostic/css/styles-set/index.js +151 -178
- package/agnostic/errors/index.d.ts +1 -1
- package/agnostic/errors/index.js +1 -1
- package/agnostic/errors/register/index.js +45 -49
- package/agnostic/errors/unknown-to-string/index.js +17 -10
- package/agnostic/errors/unknown-to-string/index.test.js +35 -0
- package/agnostic/html/get-node-ancestors/index.js +29 -29
- package/agnostic/html/get-node-ancestors/index.test.js +58 -0
- package/agnostic/html/get-position-inside-parent/index.js +13 -8
- package/agnostic/html/get-position-inside-parent/index.test.js +56 -0
- package/agnostic/html/hyper-json/cast/index.js +128 -2931
- package/agnostic/html/hyper-json/index.js +23 -2954
- package/agnostic/html/hyper-json/method/index.js +10 -14
- package/agnostic/html/hyper-json/serialize/index.js +88 -222
- package/agnostic/html/hyper-json/smart-tags/coalesced/add/index.js +14 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/addclass/index.js +27 -2937
- package/agnostic/html/hyper-json/smart-tags/coalesced/and/index.js +13 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/append/index.js +34 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/at/index.js +42 -2935
- package/agnostic/html/hyper-json/smart-tags/coalesced/call/index.js +47 -2937
- package/agnostic/html/hyper-json/smart-tags/coalesced/clone/index.js +10 -2939
- package/agnostic/html/hyper-json/smart-tags/coalesced/deleteproperties/index.js +45 -2936
- package/agnostic/html/hyper-json/smart-tags/coalesced/equals/index.js +22 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/getattribute/index.js +26 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/getproperties/index.js +19 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/getproperty/index.js +67 -2935
- package/agnostic/html/hyper-json/smart-tags/coalesced/hjparse/index.js +21 -2937
- package/agnostic/html/hyper-json/smart-tags/coalesced/hjstringify/index.js +89 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/if/index.js +20 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/index.d.ts +18 -18
- package/agnostic/html/hyper-json/smart-tags/coalesced/index.js +18 -18
- package/agnostic/html/hyper-json/smart-tags/coalesced/initialize/index.js +37 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/join/index.js +16 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/length/index.js +21 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/map/index.js +31 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/negate/index.js +10 -2939
- package/agnostic/html/hyper-json/smart-tags/coalesced/notrailing/index.js +33 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/or/index.js +13 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/pickrandom/index.js +17 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/populate/index.js +59 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/print/index.js +23 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/push/index.js +10 -2939
- package/agnostic/html/hyper-json/smart-tags/coalesced/pusheach/index.js +26 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/recordtoarray/index.js +10 -2939
- package/agnostic/html/hyper-json/smart-tags/coalesced/removeattribute/index.js +53 -2935
- package/agnostic/html/hyper-json/smart-tags/coalesced/removeclass/index.js +27 -2937
- package/agnostic/html/hyper-json/smart-tags/coalesced/renameproperty/index.js +31 -2937
- package/agnostic/html/hyper-json/smart-tags/coalesced/replace/index.js +55 -2940
- package/agnostic/html/hyper-json/smart-tags/coalesced/select/index.js +29 -2935
- package/agnostic/html/hyper-json/smart-tags/coalesced/set/index.js +29 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/setattribute/index.js +53 -2935
- package/agnostic/html/hyper-json/smart-tags/coalesced/setproperty/index.js +232 -2936
- package/agnostic/html/hyper-json/smart-tags/coalesced/sorton/index.js +89 -2936
- package/agnostic/html/hyper-json/smart-tags/coalesced/split/index.js +20 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/spread/index.js +23 -2939
- package/agnostic/html/hyper-json/smart-tags/coalesced/toarray/index.js +11 -2939
- package/agnostic/html/hyper-json/smart-tags/coalesced/toboolean/index.js +11 -2939
- package/agnostic/html/hyper-json/smart-tags/coalesced/toelement/index.js +17 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/toggleclass/index.js +27 -2937
- package/agnostic/html/hyper-json/smart-tags/coalesced/tonodelist/index.js +11 -2939
- package/agnostic/html/hyper-json/smart-tags/coalesced/tonull/index.js +10 -2939
- package/agnostic/html/hyper-json/smart-tags/coalesced/tonumber/index.js +11 -2939
- package/agnostic/html/hyper-json/smart-tags/coalesced/torecord/index.js +11 -2939
- package/agnostic/html/hyper-json/smart-tags/coalesced/toref/index.js +11 -2939
- package/agnostic/html/hyper-json/smart-tags/coalesced/tostring/index.js +11 -2939
- package/agnostic/html/hyper-json/smart-tags/coalesced/totext/index.js +11 -2939
- package/agnostic/html/hyper-json/smart-tags/coalesced/transformselected/index.js +84 -2938
- package/agnostic/html/hyper-json/smart-tags/coalesced/trim/index.js +14 -2938
- package/agnostic/html/hyper-json/smart-tags/index.js +28 -181
- package/agnostic/html/hyper-json/smart-tags/isolated/any/index.js +12 -195
- package/agnostic/html/hyper-json/smart-tags/isolated/array/index.js +12 -195
- package/agnostic/html/hyper-json/smart-tags/isolated/boolean/index.js +12 -2939
- package/agnostic/html/hyper-json/smart-tags/isolated/element/index.js +24 -2938
- package/agnostic/html/hyper-json/smart-tags/isolated/get/index.js +18 -2938
- package/agnostic/html/hyper-json/smart-tags/isolated/guess/index.js +56 -2937
- package/agnostic/html/hyper-json/smart-tags/isolated/index.d.ts +1 -1
- package/agnostic/html/hyper-json/smart-tags/isolated/index.js +1 -1
- package/agnostic/html/hyper-json/smart-tags/isolated/nodelist/index.js +18 -2938
- package/agnostic/html/hyper-json/smart-tags/isolated/null/index.js +9 -193
- package/agnostic/html/hyper-json/smart-tags/isolated/number/index.js +16 -2938
- package/agnostic/html/hyper-json/smart-tags/isolated/record/index.js +12 -2938
- package/agnostic/html/hyper-json/smart-tags/isolated/ref/index.js +40 -2935
- package/agnostic/html/hyper-json/smart-tags/isolated/string/index.js +16 -2938
- package/agnostic/html/hyper-json/smart-tags/isolated/text/index.js +18 -2938
- package/agnostic/html/hyper-json/transformer/index.js +112 -148
- package/agnostic/html/hyper-json/tree/index.js +411 -2928
- package/agnostic/html/hyper-json/types/index.js +27 -18
- package/agnostic/html/hyper-json/utils/index.js +497 -2921
- package/agnostic/html/index.d.ts +2 -2
- package/agnostic/html/index.js +2 -2
- package/agnostic/html/insert-node/index.js +27 -16
- package/agnostic/html/insert-node/index.test.js +73 -0
- package/agnostic/html/placeholders/index.js +26 -29
- package/agnostic/html/replace-in-element/index.js +31 -48
- package/agnostic/html/replace-in-element/index.test.js +80 -0
- package/agnostic/html/selector-to-element/index.js +53 -39
- package/agnostic/html/selector-to-element/index.test.js +69 -0
- package/agnostic/html/string-to-nodes/index.js +24 -25
- package/agnostic/html/string-to-nodes/index.test.js +54 -0
- package/agnostic/index.d.ts +6 -6
- package/agnostic/index.js +6 -6
- package/agnostic/misc/assert/index.js +60 -66
- package/agnostic/misc/cast/index.js +123 -57
- package/agnostic/misc/cast/index.test.js +134 -0
- package/agnostic/misc/connection/index.js +55 -36
- package/agnostic/misc/connection/index.test.js +143 -0
- package/agnostic/misc/crawler/index.js +68 -46
- package/agnostic/misc/crawler/index.test.js +56 -0
- package/agnostic/misc/crossenv/detect-runtime/index.js +41 -13
- package/agnostic/misc/crossenv/detect-runtime/index.test.js +24 -0
- package/agnostic/misc/crossenv/types.js +21 -14
- package/agnostic/misc/crossenv/window/index.js +45 -24
- package/agnostic/misc/crossenv/window/index.test.js +24 -0
- package/agnostic/misc/data-size/index.js +182 -294
- package/agnostic/misc/data-size/index.test.js +100 -0
- package/agnostic/misc/data-size/types.js +1 -0
- package/agnostic/misc/index.d.ts +5 -5
- package/agnostic/misc/index.js +5 -5
- package/agnostic/misc/is-constructor-function/index.js +12 -6
- package/agnostic/misc/is-constructor-function/index.test.js +36 -0
- package/agnostic/misc/is-nullish/index.js +24 -11
- package/agnostic/misc/is-nullish/index.test.js +44 -0
- package/agnostic/misc/logs/logger/index.js +115 -140
- package/agnostic/misc/logs/make-text-block/index.js +13 -13
- package/agnostic/misc/logs/styles/index.js +29 -48
- package/agnostic/misc/lorem-ipsum/index.js +51 -201
- package/agnostic/misc/lorem-ipsum/index.test.js +49 -0
- package/agnostic/misc/normalize-extension/index.js +99 -88
- package/agnostic/misc/normalize-extension/index.test.js +40 -0
- package/agnostic/misc/outcome/index.js +20 -14
- package/agnostic/misc/outcome/index.test.js +40 -0
- package/agnostic/numbers/absolute-modulo/index.js +9 -6
- package/agnostic/numbers/absolute-modulo/index.test.js +23 -0
- package/agnostic/numbers/approximate-rational/index.js +86 -69
- package/agnostic/numbers/approximate-rational/index.test.js +90 -0
- package/agnostic/numbers/clamp/index.js +12 -8
- package/agnostic/numbers/clamp/index.test.js +24 -0
- package/agnostic/numbers/geometric-progressions/index.js +25 -16
- package/agnostic/numbers/geometric-progressions/index.test.js +45 -0
- package/agnostic/numbers/index.d.ts +2 -2
- package/agnostic/numbers/index.js +2 -2
- package/agnostic/numbers/interpolate/index.js +25 -10
- package/agnostic/numbers/interpolate/index.test.js +40 -0
- package/agnostic/numbers/round/index.js +30 -15
- package/agnostic/numbers/round/index.test.js +56 -0
- package/agnostic/objects/deep-get-property/index.js +30 -27
- package/agnostic/objects/deep-get-property/index.test.js +59 -0
- package/agnostic/objects/enums/is-in-enum/index.js +17 -11
- package/agnostic/objects/enums/is-in-enum/index.test.js +100 -0
- package/agnostic/objects/flatten-getters/index.js +15 -14
- package/agnostic/objects/flatten-getters/index.test.js +78 -0
- package/agnostic/objects/index.d.ts +2 -2
- package/agnostic/objects/index.js +2 -2
- package/agnostic/objects/is-object/index.js +16 -9
- package/agnostic/objects/is-object/index.test.js +60 -0
- package/agnostic/objects/is-record/index.js +12 -7
- package/agnostic/objects/is-record/index.test.js +48 -0
- package/agnostic/objects/record-format/index.js +18 -12
- package/agnostic/objects/record-format/index.test.js +92 -0
- package/agnostic/objects/record-map/index.js +16 -11
- package/agnostic/objects/record-map/index.test.js +56 -0
- package/agnostic/objects/sort-keys/index.js +15 -11
- package/agnostic/objects/sort-keys/index.test.js +37 -0
- package/agnostic/objects/validation/index.js +21 -8
- package/agnostic/objects/validation/index.test.js +72 -0
- package/agnostic/optim/index.d.ts +1 -1
- package/agnostic/optim/index.js +1 -1
- package/agnostic/optim/memoize/index.js +24 -16
- package/agnostic/optim/memoize/index.test.js +30 -0
- package/agnostic/optim/throttle-debounce/index.js +120 -102
- package/agnostic/optim/throttle-debounce/index.test.js +44 -0
- package/agnostic/optim/throttle-debounce/types.js +1 -0
- package/agnostic/random/hex-char/index.js +8 -10
- package/agnostic/random/hex-char/index.test.js +20 -0
- package/agnostic/random/index.d.ts +1 -1
- package/agnostic/random/index.js +1 -1
- package/agnostic/random/random/index.js +17 -14
- package/agnostic/random/random/index.test.js +73 -0
- package/agnostic/random/uuid/index.js +28 -20
- package/agnostic/random/uuid/index.test.js +45 -0
- package/agnostic/regexps/index.js +126 -84
- package/agnostic/regexps/index.test.js +108 -0
- package/agnostic/sanitization/file-name/index.js +24 -8
- package/agnostic/sanitization/file-name/index.test.js +23 -0
- package/agnostic/sanitization/html/index.js +172 -122
- package/agnostic/sanitization/path/index.js +23 -15
- package/agnostic/sanitization/path/index.test.js +18 -0
- package/agnostic/sanitization/types.js +1 -0
- package/agnostic/sanitization/user-input/index.js +36 -24
- package/agnostic/sanitization/user-input/index.test.js +31 -0
- package/agnostic/strings/char-codes/index.js +123 -55
- package/agnostic/strings/matches/index.js +35 -16
- package/agnostic/strings/normalize-indent/index.js +34 -16
- package/agnostic/strings/parse-table/index.js +153 -86
- package/agnostic/strings/replace-all/index.js +36 -15
- package/agnostic/strings/to-alphanum/index.js +23 -8
- package/agnostic/strings/trim/index.js +22 -9
- package/agnostic/time/dates/format-date/index.js +140 -72
- package/agnostic/time/duration/index.js +106 -140
- package/agnostic/time/timeout/index.js +24 -16
- package/agnostic/time/transitions/index.js +200 -158
- package/agnostic/time/wait/index.js +10 -8
- package/agnostic/typescript/types.js +1 -0
- package/components/BeforeAfter/index.controlled.js +95 -0
- package/components/BeforeAfter/index.js +54 -189
- package/components/BeforeAfter/utils.js +9 -0
- package/components/Disclaimer/index.js +50 -110
- package/components/Drawer/index.js +81 -196
- package/components/EventListener/index.js +29 -80
- package/components/Gallery/index.js +146 -221
- package/components/Gallery/utils.js +12 -0
- package/components/Image/index.js +66 -293
- package/components/IntersectionObserver/index.js +62 -110
- package/components/Overlayer/index.js +59 -103
- package/components/Paginator/index.js +124 -155
- package/components/ResizeObserver/index.js +66 -119
- package/components/ResizeObserver/style.module.css +0 -0
- package/components/Scrllgngn/index.js +171 -468
- package/components/ScrollListener/index.js +97 -276
- package/components/ScrollListener/utils.js +51 -0
- package/components/Sequencer/index.controlled.js +67 -0
- package/components/Sequencer/index.js +105 -262
- package/components/ShadowRoot/index.js +42 -96
- package/components/Subtitles/index.js +107 -244
- package/components/Subtitles/types.js +1 -0
- package/components/Subtitles/utils.js +102 -0
- package/components/Theatre/index.js +88 -136
- package/components/UIModule/index.js +156 -199
- package/components/Video/index.js +292 -857
- package/components/Video/utils.js +137 -0
- package/components/_WIP_AudioQuote/index.js +1 -0
- package/components/_WIP_Icon/index.js +1 -0
- package/components/index.d.ts +5 -5
- package/components/index.js +5 -5
- package/components/public-classnames.js +18 -0
- package/components/utils/index.js +11 -11
- package/components/utils/types.js +1 -0
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/node/@aws-s3/index.test.js +6 -0
- package/node/@aws-s3/storage/directory/copy-dir/index.js +66 -72
- package/node/@aws-s3/storage/directory/index.d.ts +2 -2
- package/node/@aws-s3/storage/directory/index.js +2 -2
- package/node/@aws-s3/storage/directory/list/index.js +32 -42
- package/node/@aws-s3/storage/directory/move-dir/index.js +68 -86
- package/node/@aws-s3/storage/directory/remove-dir/index.js +56 -67
- package/node/@aws-s3/storage/file/copy/index.js +41 -53
- package/node/@aws-s3/storage/file/download/index.js +29 -40
- package/node/@aws-s3/storage/file/exists/index.js +35 -43
- package/node/@aws-s3/storage/file/index.d.ts +1 -1
- package/node/@aws-s3/storage/file/index.js +1 -1
- package/node/@aws-s3/storage/file/move/index.js +57 -63
- package/node/@aws-s3/storage/file/remove/index.js +35 -43
- package/node/@aws-s3/storage/file/stat/index.js +33 -47
- package/node/@aws-s3/storage/file/upload/index.js +52 -63
- package/node/@design-edito/index.js +1 -0
- package/node/@express/@multer/index.js +61 -55
- package/node/@google-cloud/storage/bucket/get-metadata/index.js +25 -29
- package/node/@google-cloud/storage/directory/copy-dir/index.js +35 -41
- package/node/@google-cloud/storage/directory/index.d.ts +1 -1
- package/node/@google-cloud/storage/directory/index.js +1 -1
- package/node/@google-cloud/storage/directory/list/index.js +28 -35
- package/node/@google-cloud/storage/directory/move-dir/index.js +43 -42
- package/node/@google-cloud/storage/directory/remove-dir/index.js +34 -38
- package/node/@google-cloud/storage/file/copy/index.js +35 -40
- package/node/@google-cloud/storage/file/download/index.js +27 -34
- package/node/@google-cloud/storage/file/exists/index.js +25 -31
- package/node/@google-cloud/storage/file/generate-signed-url/index.js +33 -35
- package/node/@google-cloud/storage/file/get-metadata/index.js +28 -31
- package/node/@google-cloud/storage/file/get-permissions/index.js +25 -31
- package/node/@google-cloud/storage/file/index.d.ts +2 -2
- package/node/@google-cloud/storage/file/index.js +2 -2
- package/node/@google-cloud/storage/file/move/index.js +38 -42
- package/node/@google-cloud/storage/file/remove/index.js +34 -35
- package/node/@google-cloud/storage/file/revoke-signed-urls/index.js +32 -95
- package/node/@google-cloud/storage/file/stat/index.js +34 -38
- package/node/@google-cloud/storage/file/update-metadata/index.js +30 -31
- package/node/@google-cloud/storage/file/upload/index.js +44 -46
- package/node/@google-cloud/storage/index.d.ts +1 -1
- package/node/@google-cloud/storage/index.js +1 -1
- package/node/cloud-storage/clients/index.js +35 -15
- package/node/cloud-storage/operations/copy-dir/index.js +30 -203
- package/node/cloud-storage/operations/copy-file/index.js +30 -152
- package/node/cloud-storage/operations/download-file/index.js +30 -103
- package/node/cloud-storage/operations/exists-file/index.js +30 -103
- package/node/cloud-storage/operations/index.d.ts +2 -2
- package/node/cloud-storage/operations/index.js +2 -2
- package/node/cloud-storage/operations/list-dir/index.js +29 -98
- package/node/cloud-storage/operations/move-dir/index.js +30 -169
- package/node/cloud-storage/operations/move-file/index.js +30 -157
- package/node/cloud-storage/operations/remove-dir/index.js +29 -159
- package/node/cloud-storage/operations/remove-file/index.js +29 -121
- package/node/cloud-storage/operations/stat-file/index.js +29 -124
- package/node/cloud-storage/operations/upload-file/index.js +30 -162
- package/node/encryption/@aes-256-gcm/buffer/index.js +31 -72
- package/node/encryption/@aes-256-gcm/uint8-array/index.js +55 -55
- package/node/encryption/key/index.js +19 -12
- package/node/files/index.d.ts +1 -1
- package/node/files/index.js +1 -1
- package/node/files/is-in-directory/index.js +11 -8
- package/node/files/read-write/index.js +11 -15
- package/node/files/subpaths/index.js +156 -121
- package/node/ftps/directory/copy-dir/index.js +55 -62
- package/node/ftps/directory/list/index.js +24 -29
- package/node/ftps/directory/move-dir/index.js +38 -38
- package/node/ftps/directory/remove-dir/index.js +39 -42
- package/node/ftps/file/copy/index.js +42 -47
- package/node/ftps/file/download/index.js +29 -34
- package/node/ftps/file/exists/index.js +38 -36
- package/node/ftps/file/index.d.ts +2 -2
- package/node/ftps/file/index.js +2 -2
- package/node/ftps/file/move/index.js +46 -44
- package/node/ftps/file/remove/index.js +36 -39
- package/node/ftps/file/stat/index.js +30 -38
- package/node/ftps/file/upload/index.js +40 -44
- package/node/images/create/index.js +10 -562
- package/node/images/format/index.js +264 -815
- package/node/images/metadata/index.js +10 -571
- package/node/images/transform/index.js +169 -1022
- package/node/images/transform/operations/blur/index.js +11 -24
- package/node/images/transform/operations/brighten/index.js +11 -24
- package/node/images/transform/operations/extend/index.js +25 -589
- package/node/images/transform/operations/extract/index.js +15 -28
- package/node/images/transform/operations/flatten/index.js +20 -584
- package/node/images/transform/operations/flip/index.js +2 -6
- package/node/images/transform/operations/flop/index.js +2 -6
- package/node/images/transform/operations/hue/index.js +13 -26
- package/node/images/transform/operations/index.d.ts +5 -5
- package/node/images/transform/operations/index.js +5 -5
- package/node/images/transform/operations/level/index.js +14 -30
- package/node/images/transform/operations/lighten/index.js +13 -26
- package/node/images/transform/operations/normalize/index.js +14 -27
- package/node/images/transform/operations/overlay/index.js +89 -673
- package/node/images/transform/operations/resize/index.js +46 -610
- package/node/images/transform/operations/rotate/index.js +20 -584
- package/node/images/transform/operations/saturate/index.js +14 -27
- package/node/images/types.js +34 -31
- package/node/images/utils/index.js +84 -568
- package/node/index.d.ts +5 -5
- package/node/index.js +5 -5
- package/node/process/on-exit/index.js +45 -26
- package/node/process/prompt-continue/index.js +29 -14
- package/node/process/spawner/index.js +104 -134
- package/node/sftp/directory/copy-dir/index.js +52 -60
- package/node/sftp/directory/index.d.ts +1 -1
- package/node/sftp/directory/index.js +1 -1
- package/node/sftp/directory/list/index.js +22 -29
- package/node/sftp/directory/move-dir/index.js +35 -35
- package/node/sftp/directory/remove-dir/index.js +39 -42
- package/node/sftp/file/copy/index.js +37 -45
- package/node/sftp/file/download/index.js +26 -32
- package/node/sftp/file/exists/index.js +29 -29
- package/node/sftp/file/index.d.ts +1 -1
- package/node/sftp/file/index.js +1 -1
- package/node/sftp/file/move/index.js +39 -38
- package/node/sftp/file/remove/index.js +31 -34
- package/node/sftp/file/stat/index.js +26 -37
- package/node/sftp/file/upload/index.js +34 -38
- package/package.json +1 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { recordMap } from './index.js';
|
|
3
|
+
describe('recordMap', () => {
|
|
4
|
+
it('maps values using the mapper function', () => {
|
|
5
|
+
const record = { a: 1, b: 2, c: 3 };
|
|
6
|
+
const result = recordMap(record, val => val * 2);
|
|
7
|
+
expect(result).toEqual({ a: 2, b: 4, c: 6 });
|
|
8
|
+
});
|
|
9
|
+
it('preserves keys while transforming values', () => {
|
|
10
|
+
const record = { x: 'hello', y: 'world' };
|
|
11
|
+
const result = recordMap(record, val => val.toUpperCase());
|
|
12
|
+
expect(result).toEqual({ x: 'HELLO', y: 'WORLD' });
|
|
13
|
+
});
|
|
14
|
+
it('provides both value and key to mapper function', () => {
|
|
15
|
+
const record = { a: 1, b: 2 };
|
|
16
|
+
const result = recordMap(record, (val, key) => `${key}:${val}`);
|
|
17
|
+
expect(result).toEqual({ a: 'a:1', b: 'b:2' });
|
|
18
|
+
});
|
|
19
|
+
it('handles empty records', () => {
|
|
20
|
+
const record = {};
|
|
21
|
+
const result = recordMap(record, val => val);
|
|
22
|
+
expect(result).toEqual({});
|
|
23
|
+
});
|
|
24
|
+
it('handles records with different value types', () => {
|
|
25
|
+
const record = { num: 5, str: 'test', bool: true };
|
|
26
|
+
const result = recordMap(record, val => String(val));
|
|
27
|
+
expect(result).toEqual({ num: '5', str: 'test', bool: 'true' });
|
|
28
|
+
});
|
|
29
|
+
it('handles mapper that changes value type', () => {
|
|
30
|
+
const record = { a: 1, b: 2, c: 3 };
|
|
31
|
+
const result = recordMap(record, val => val > 2);
|
|
32
|
+
expect(result).toEqual({ a: false, b: false, c: true });
|
|
33
|
+
});
|
|
34
|
+
it('handles mapper that returns objects', () => {
|
|
35
|
+
const record = { a: 1, b: 2 };
|
|
36
|
+
const result = recordMap(record, val => ({ value: val }));
|
|
37
|
+
expect(result).toEqual({ a: { value: 1 }, b: { value: 2 } });
|
|
38
|
+
});
|
|
39
|
+
it('handles mapper that returns arrays', () => {
|
|
40
|
+
const record = { a: 1, b: 2 };
|
|
41
|
+
const result = recordMap(record, val => [val, val * 2]);
|
|
42
|
+
expect(result).toEqual({ a: [1, 2], b: [2, 4] });
|
|
43
|
+
});
|
|
44
|
+
it('only processes own properties', () => {
|
|
45
|
+
const parent = { inherited: 'value' };
|
|
46
|
+
const record = Object.create(parent);
|
|
47
|
+
record.own = 'ownValue';
|
|
48
|
+
const result = recordMap(record, val => val.toUpperCase());
|
|
49
|
+
expect(result).toEqual({ own: 'OWNVALUE' });
|
|
50
|
+
});
|
|
51
|
+
it('handles numeric string keys', () => {
|
|
52
|
+
const record = { '0': 'zero', '1': 'one', '2': 'two' };
|
|
53
|
+
const result = recordMap(record, val => val.toUpperCase());
|
|
54
|
+
expect(result).toEqual({ '0': 'ZERO', '1': 'ONE', '2': 'TWO' });
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Returns a new object with the keys sorted according to the provided sorter.
|
|
3
|
+
*
|
|
4
|
+
* @template T - The type of the input object.
|
|
5
|
+
* @param {T} obj - The object whose keys should be sorted.
|
|
6
|
+
* @param {(a: keyof T, b: keyof T) => number} [sorter] - Optional function used to compare keys for sorting. Defaults to alphabetical order.
|
|
7
|
+
* @returns {{ [K in keyof T]: T[K] }} A new object with the same keys and values as the input, but sorted by key.
|
|
8
|
+
*/
|
|
9
|
+
export function sortKeys(obj, sorter = (a, b) => String(a).localeCompare(String(b))) {
|
|
10
|
+
const out = {};
|
|
11
|
+
const keys = Object.keys(obj);
|
|
12
|
+
for (const key of keys.sort(sorter)) {
|
|
13
|
+
out[key] = obj[key];
|
|
14
|
+
}
|
|
15
|
+
return out;
|
|
9
16
|
}
|
|
10
|
-
export {
|
|
11
|
-
sortKeys
|
|
12
|
-
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { sortKeys } from './index.js';
|
|
3
|
+
describe('sortKeys', () => {
|
|
4
|
+
it('returns a new object with keys sorted alphabetically by default', () => {
|
|
5
|
+
const inp = { b: 2, a: 1, c: 3 };
|
|
6
|
+
const out = sortKeys(inp);
|
|
7
|
+
expect(Object.keys(out)).toEqual(['a', 'b', 'c']);
|
|
8
|
+
expect(out).toEqual({ a: 1, b: 2, c: 3 });
|
|
9
|
+
});
|
|
10
|
+
it('preserves the value types for each key', () => {
|
|
11
|
+
const inp = { b: 'str', a: 42 };
|
|
12
|
+
const out = sortKeys(inp, (a, b) => a.localeCompare(b));
|
|
13
|
+
expect(out.a).toBe(42);
|
|
14
|
+
expect(out.b).toBe('str');
|
|
15
|
+
});
|
|
16
|
+
it('does not modify the original object', () => {
|
|
17
|
+
const inp = { b: 2, a: 1 };
|
|
18
|
+
const copy = { ...inp };
|
|
19
|
+
sortKeys(inp, (a, b) => a.localeCompare(b));
|
|
20
|
+
expect(inp).toEqual(copy);
|
|
21
|
+
});
|
|
22
|
+
it('works with custom sorter', () => {
|
|
23
|
+
const inp = { a: 1, b: 2, c: 3 };
|
|
24
|
+
const out = sortKeys(inp, (a, b) => b.localeCompare(a)); // reverse
|
|
25
|
+
expect(Object.keys(out)).toEqual(['c', 'b', 'a']);
|
|
26
|
+
});
|
|
27
|
+
it('works with single-key objects', () => {
|
|
28
|
+
const inp = { only: 1 };
|
|
29
|
+
const out = sortKeys(inp, (a, b) => a.localeCompare(b));
|
|
30
|
+
expect(out).toEqual({ only: 1 });
|
|
31
|
+
});
|
|
32
|
+
it('works with empty objects', () => {
|
|
33
|
+
const inp = {};
|
|
34
|
+
const out = sortKeys(inp, (a, b) => a.localeCompare(b));
|
|
35
|
+
expect(out).toEqual({});
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -1,9 +1,22 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
// [WIP]
|
|
2
|
+
// Has all keys from
|
|
3
|
+
// Has extra keys from
|
|
4
|
+
// Has same keys from
|
|
5
|
+
// Has equal properties than (maybe option for not just shallow equivalence?)
|
|
6
|
+
// Has extra properties than
|
|
7
|
+
// Has same properties than
|
|
8
|
+
/**
|
|
9
|
+
* Checks if an object contains all the key-value pairs from a partial object.
|
|
10
|
+
*
|
|
11
|
+
* Performs a shallow equality check for each property in `partial`.
|
|
12
|
+
*
|
|
13
|
+
* @template T - The type of the full object.
|
|
14
|
+
* @param {T} obj - The object to validate.
|
|
15
|
+
* @param {Partial<T>} partial - The partial object with key-value pairs to check.
|
|
16
|
+
* @returns {boolean} `true` if all entries in `partial` match those in `obj`, otherwise `false`.
|
|
17
|
+
*/
|
|
18
|
+
export function fromPartial(obj, partial) {
|
|
19
|
+
return Object.entries(partial).every(([key, val]) => {
|
|
20
|
+
return obj[key] === val;
|
|
21
|
+
});
|
|
6
22
|
}
|
|
7
|
-
export {
|
|
8
|
-
fromPartial
|
|
9
|
-
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { fromPartial } from './index.js';
|
|
3
|
+
describe('fromPartial', () => {
|
|
4
|
+
it('returns true when all partial entries match', () => {
|
|
5
|
+
const obj = { a: 1, b: 2, c: 3 };
|
|
6
|
+
const partial = { a: 1, b: 2 };
|
|
7
|
+
expect(fromPartial(obj, partial)).toBe(true);
|
|
8
|
+
});
|
|
9
|
+
it('returns true when partial is empty', () => {
|
|
10
|
+
const obj = { a: 1, b: 2 };
|
|
11
|
+
const partial = {};
|
|
12
|
+
expect(fromPartial(obj, partial)).toBe(true);
|
|
13
|
+
});
|
|
14
|
+
it('returns false when any partial entry does not match', () => {
|
|
15
|
+
const obj = { a: 1, b: 2, c: 3 };
|
|
16
|
+
const partial = { a: 1, b: 3 };
|
|
17
|
+
expect(fromPartial(obj, partial)).toBe(false);
|
|
18
|
+
});
|
|
19
|
+
it('returns false when partial has key not in object', () => {
|
|
20
|
+
const obj = { a: 1, b: 2 };
|
|
21
|
+
const partial = { a: 1, c: 3 };
|
|
22
|
+
expect(fromPartial(obj, partial)).toBe(false);
|
|
23
|
+
});
|
|
24
|
+
it('handles string values', () => {
|
|
25
|
+
const obj = { name: 'John', age: 30 };
|
|
26
|
+
const partial = { name: 'John' };
|
|
27
|
+
expect(fromPartial(obj, partial)).toBe(true);
|
|
28
|
+
});
|
|
29
|
+
it('handles boolean values', () => {
|
|
30
|
+
const obj = { active: true, verified: false };
|
|
31
|
+
const partial = { active: true };
|
|
32
|
+
expect(fromPartial(obj, partial)).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
it('handles null values', () => {
|
|
35
|
+
const obj = { a: null, b: 2 };
|
|
36
|
+
const partial = { a: null };
|
|
37
|
+
expect(fromPartial(obj, partial)).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
it('handles undefined values', () => {
|
|
40
|
+
const obj = { a: undefined, b: 2 };
|
|
41
|
+
const partial = { a: undefined };
|
|
42
|
+
expect(fromPartial(obj, partial)).toBe(true);
|
|
43
|
+
});
|
|
44
|
+
it('performs shallow equality check', () => {
|
|
45
|
+
const obj = { nested: { a: 1 } };
|
|
46
|
+
const partial = { nested: { a: 1 } };
|
|
47
|
+
// Shallow check: objects are compared by reference
|
|
48
|
+
expect(fromPartial(obj, partial)).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
it('handles arrays with shallow equality', () => {
|
|
51
|
+
const obj = { items: [1, 2, 3] };
|
|
52
|
+
const partial = { items: [1, 2, 3] };
|
|
53
|
+
// Shallow check: arrays are compared by reference
|
|
54
|
+
expect(fromPartial(obj, partial)).toBe(false);
|
|
55
|
+
});
|
|
56
|
+
it('handles arrays with same reference', () => {
|
|
57
|
+
const items = [1, 2, 3];
|
|
58
|
+
const obj = { items };
|
|
59
|
+
const partial = { items };
|
|
60
|
+
expect(fromPartial(obj, partial)).toBe(true);
|
|
61
|
+
});
|
|
62
|
+
it('handles multiple matching entries', () => {
|
|
63
|
+
const obj = { a: 1, b: 2, c: 3, d: 4, e: 5 };
|
|
64
|
+
const partial = { a: 1, c: 3, e: 5 };
|
|
65
|
+
expect(fromPartial(obj, partial)).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
it('handles objects with no matching entries', () => {
|
|
68
|
+
const obj = { a: 1, b: 2 };
|
|
69
|
+
const partial = { a: 2, b: 1 };
|
|
70
|
+
expect(fromPartial(obj, partial)).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
});
|
package/agnostic/optim/index.js
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
function
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Creates a memoized version of a function, caching the result for repeated calls with the same arguments.
|
|
3
|
+
*
|
|
4
|
+
* Only performs shallow equality checks on arguments (strict equality `===`).
|
|
5
|
+
*
|
|
6
|
+
* @template T - The type of the function to memoize.
|
|
7
|
+
* @param {T} toMemoizeFunc - The function to memoize.
|
|
8
|
+
* @returns {T} A memoized version of the input function.
|
|
9
|
+
*/
|
|
10
|
+
export function memoize(toMemoizeFunc) {
|
|
11
|
+
let cachedArgs;
|
|
12
|
+
let cachedResult;
|
|
13
|
+
const memoizedFunc = (...args) => {
|
|
14
|
+
const argsMatch = cachedArgs !== undefined
|
|
15
|
+
&& args.length === cachedArgs.length
|
|
16
|
+
&& args.every((arg, i) => arg === cachedArgs?.[i]);
|
|
17
|
+
if (argsMatch && cachedResult !== undefined)
|
|
18
|
+
return cachedResult.value;
|
|
19
|
+
const result = toMemoizeFunc(...args);
|
|
20
|
+
cachedArgs = args;
|
|
21
|
+
cachedResult = { value: result };
|
|
22
|
+
return result;
|
|
23
|
+
};
|
|
24
|
+
return memoizedFunc;
|
|
14
25
|
}
|
|
15
|
-
export {
|
|
16
|
-
memoize
|
|
17
|
-
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { memoize } from './index.js';
|
|
3
|
+
describe('memoize', () => {
|
|
4
|
+
it('returns the same result for identical arguments without re-calling the wrapped function', () => {
|
|
5
|
+
let callCount = 0;
|
|
6
|
+
const fn = (...args) => {
|
|
7
|
+
callCount += 1;
|
|
8
|
+
return args.reduce((sum, n) => sum + n, 0);
|
|
9
|
+
};
|
|
10
|
+
const mem = memoize(fn);
|
|
11
|
+
const r1 = mem(1, 2, 3);
|
|
12
|
+
const r2 = mem(1, 2, 3);
|
|
13
|
+
expect(r1).toBe(6);
|
|
14
|
+
expect(r2).toBe(6);
|
|
15
|
+
expect(callCount).toBe(1);
|
|
16
|
+
});
|
|
17
|
+
it('recomputes when arguments change (shallow equality)', () => {
|
|
18
|
+
let callCount = 0;
|
|
19
|
+
const fn = (obj) => {
|
|
20
|
+
callCount += 1;
|
|
21
|
+
return obj.v * 2;
|
|
22
|
+
};
|
|
23
|
+
const mem = memoize(fn);
|
|
24
|
+
const r1 = mem({ v: 2 });
|
|
25
|
+
const r2 = mem({ v: 2 });
|
|
26
|
+
expect(r1).toBe(4);
|
|
27
|
+
expect(r2).toBe(4);
|
|
28
|
+
expect(callCount).toBe(2);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -1,112 +1,130 @@
|
|
|
1
|
-
|
|
2
|
-
function
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Returns a throttled version of the function passed as an argument
|
|
3
|
+
* @param toThrottleFunc - The function that has to be throttled
|
|
4
|
+
* @param delayMs - The throttle delay in ms
|
|
5
|
+
*/
|
|
6
|
+
export function throttle(toThrottleFunc, delayMs) {
|
|
7
|
+
let currentDelayMs = delayMs;
|
|
8
|
+
let lastArgs = [];
|
|
9
|
+
let lastExecutedOn = 0;
|
|
10
|
+
let lastReturnValue;
|
|
11
|
+
let nextExecutionTimeout = null;
|
|
12
|
+
/** Schedules a next call according to the delay */
|
|
13
|
+
function scheduleNextCall() {
|
|
14
|
+
if (nextExecutionTimeout !== null) {
|
|
15
|
+
clearTimeout(nextExecutionTimeout);
|
|
16
|
+
nextExecutionTimeout = null;
|
|
17
|
+
}
|
|
18
|
+
const now = Date.now();
|
|
19
|
+
const nextExecutionTimestamp = lastExecutedOn + currentDelayMs;
|
|
20
|
+
const msTillNextExecution = nextExecutionTimestamp - now;
|
|
21
|
+
nextExecutionTimeout = setTimeout(() => {
|
|
22
|
+
nextExecutionTimeout = null;
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
24
|
+
const returnValue = toThrottleFunc(...lastArgs);
|
|
25
|
+
lastReturnValue = returnValue;
|
|
26
|
+
lastExecutedOn = now;
|
|
27
|
+
}, msTillNextExecution) ?? null;
|
|
12
28
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
/** The throttled function */
|
|
30
|
+
function throttled(...args) {
|
|
31
|
+
const now = Date.now();
|
|
32
|
+
lastArgs = args;
|
|
33
|
+
if (now - lastExecutedOn >= delayMs) {
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
35
|
+
const returnValue = toThrottleFunc(...lastArgs);
|
|
36
|
+
lastReturnValue = returnValue;
|
|
37
|
+
lastExecutedOn = now;
|
|
38
|
+
return {
|
|
39
|
+
returnValue: lastReturnValue,
|
|
40
|
+
lastExecutedOn,
|
|
41
|
+
delayMs: currentDelayMs,
|
|
42
|
+
isCached: false
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (nextExecutionTimeout === null)
|
|
46
|
+
scheduleNextCall();
|
|
47
|
+
return {
|
|
48
|
+
returnValue: lastReturnValue,
|
|
49
|
+
lastExecutedOn,
|
|
50
|
+
delayMs: currentDelayMs,
|
|
51
|
+
isCached: true
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** Changes the throttle delay */
|
|
55
|
+
function setDelay(delayMs) {
|
|
56
|
+
currentDelayMs = delayMs;
|
|
57
|
+
if (nextExecutionTimeout !== null)
|
|
58
|
+
scheduleNextCall();
|
|
36
59
|
}
|
|
37
|
-
if (nextExecutionTimeout === null) scheduleNextCall();
|
|
38
60
|
return {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
delayMs: currentDelayMs,
|
|
42
|
-
isCached: true
|
|
61
|
+
throttled,
|
|
62
|
+
setDelay
|
|
43
63
|
};
|
|
44
|
-
}
|
|
45
|
-
function setDelay(delayMs2) {
|
|
46
|
-
currentDelayMs = delayMs2;
|
|
47
|
-
if (nextExecutionTimeout !== null) scheduleNextCall();
|
|
48
|
-
}
|
|
49
|
-
return {
|
|
50
|
-
throttled,
|
|
51
|
-
setDelay
|
|
52
|
-
};
|
|
53
64
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Returns a debounced version of the function passed as an argument
|
|
67
|
+
* @param toDebounceFunc - The function that has to be debounced
|
|
68
|
+
* @param delayMs - The debounce delay in ms
|
|
69
|
+
*/
|
|
70
|
+
export function debounce(toDebounceFunc, delayMs) {
|
|
71
|
+
let currentDelayMs = delayMs;
|
|
72
|
+
let lastArgs = [];
|
|
73
|
+
let lastCalledOn = 0;
|
|
74
|
+
let lastExecutedOn = 0;
|
|
75
|
+
let lastReturnValue;
|
|
76
|
+
let nextExecutionTimeout = null;
|
|
77
|
+
/** Schedules a next call according to the delay */
|
|
78
|
+
function scheduleNextCall() {
|
|
79
|
+
if (nextExecutionTimeout !== null) {
|
|
80
|
+
clearTimeout(nextExecutionTimeout);
|
|
81
|
+
nextExecutionTimeout = null;
|
|
82
|
+
}
|
|
83
|
+
const now = Date.now();
|
|
84
|
+
const nextExecutionTimestamp = lastCalledOn + currentDelayMs;
|
|
85
|
+
const msTillNextExecution = nextExecutionTimestamp - now;
|
|
86
|
+
nextExecutionTimeout = setTimeout(() => {
|
|
87
|
+
nextExecutionTimeout = null;
|
|
88
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
89
|
+
const returnValue = toDebounceFunc(...lastArgs);
|
|
90
|
+
lastReturnValue = returnValue;
|
|
91
|
+
lastExecutedOn = now;
|
|
92
|
+
}, msTillNextExecution) ?? null;
|
|
93
|
+
}
|
|
94
|
+
/** The debounced function */
|
|
95
|
+
function debounced(...args) {
|
|
96
|
+
const now = Date.now();
|
|
97
|
+
lastArgs = args;
|
|
98
|
+
if (now - lastCalledOn >= currentDelayMs) {
|
|
99
|
+
lastCalledOn = now;
|
|
100
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
101
|
+
const returnValue = toDebounceFunc(...lastArgs);
|
|
102
|
+
lastReturnValue = returnValue;
|
|
103
|
+
lastExecutedOn = now;
|
|
104
|
+
return {
|
|
105
|
+
returnValue: lastReturnValue,
|
|
106
|
+
lastExecutedOn,
|
|
107
|
+
delayMs: currentDelayMs,
|
|
108
|
+
isCached: false
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
lastCalledOn = now;
|
|
112
|
+
scheduleNextCall();
|
|
113
|
+
return {
|
|
114
|
+
returnValue: lastReturnValue,
|
|
115
|
+
lastExecutedOn,
|
|
116
|
+
delayMs: currentDelayMs,
|
|
117
|
+
isCached: true
|
|
118
|
+
};
|
|
65
119
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const returnValue = toDebounceFunc(...lastArgs);
|
|
72
|
-
lastReturnValue = returnValue;
|
|
73
|
-
lastExecutedOn = now;
|
|
74
|
-
}, msTillNextExecution) ?? null;
|
|
75
|
-
}
|
|
76
|
-
function debounced(...args) {
|
|
77
|
-
const now = Date.now();
|
|
78
|
-
lastArgs = args;
|
|
79
|
-
if (now - lastCalledOn >= currentDelayMs) {
|
|
80
|
-
lastCalledOn = now;
|
|
81
|
-
const returnValue = toDebounceFunc(...lastArgs);
|
|
82
|
-
lastReturnValue = returnValue;
|
|
83
|
-
lastExecutedOn = now;
|
|
84
|
-
return {
|
|
85
|
-
returnValue: lastReturnValue,
|
|
86
|
-
lastExecutedOn,
|
|
87
|
-
delayMs: currentDelayMs,
|
|
88
|
-
isCached: false
|
|
89
|
-
};
|
|
120
|
+
/** Changes the debounce delay */
|
|
121
|
+
function setDelay(delayMs) {
|
|
122
|
+
currentDelayMs = delayMs;
|
|
123
|
+
if (nextExecutionTimeout !== null)
|
|
124
|
+
scheduleNextCall();
|
|
90
125
|
}
|
|
91
|
-
lastCalledOn = now;
|
|
92
|
-
scheduleNextCall();
|
|
93
126
|
return {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
delayMs: currentDelayMs,
|
|
97
|
-
isCached: true
|
|
127
|
+
debounced,
|
|
128
|
+
setDelay
|
|
98
129
|
};
|
|
99
|
-
}
|
|
100
|
-
function setDelay(delayMs2) {
|
|
101
|
-
currentDelayMs = delayMs2;
|
|
102
|
-
if (nextExecutionTimeout !== null) scheduleNextCall();
|
|
103
|
-
}
|
|
104
|
-
return {
|
|
105
|
-
debounced,
|
|
106
|
-
setDelay
|
|
107
|
-
};
|
|
108
130
|
}
|
|
109
|
-
export {
|
|
110
|
-
debounce,
|
|
111
|
-
throttle
|
|
112
|
-
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { throttle, debounce } from './index.js';
|
|
3
|
+
describe('throttle', () => {
|
|
4
|
+
it('calls the wrapped function immediately and then throttles subsequent calls', async () => {
|
|
5
|
+
vi.useFakeTimers();
|
|
6
|
+
const fn = vi.fn((x) => x * 2);
|
|
7
|
+
const { throttled } = throttle(fn, 100);
|
|
8
|
+
const first = throttled(1);
|
|
9
|
+
const second = throttled(2);
|
|
10
|
+
expect(first.isCached).toBe(false);
|
|
11
|
+
expect(first.returnValue).toBe(2);
|
|
12
|
+
expect(second.isCached).toBe(true);
|
|
13
|
+
expect(fn).toHaveBeenCalledTimes(1);
|
|
14
|
+
// Fast-forward past the throttle delay to trigger the scheduled call
|
|
15
|
+
vi.advanceTimersByTime(100);
|
|
16
|
+
expect(fn).toHaveBeenCalledTimes(2);
|
|
17
|
+
vi.useRealTimers();
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
describe('debounce', () => {
|
|
21
|
+
it('fires immediately on first call, then debounces subsequent calls and uses latest arguments', async () => {
|
|
22
|
+
vi.useFakeTimers();
|
|
23
|
+
const fn = vi.fn((x) => x * 3);
|
|
24
|
+
const { debounced } = debounce(fn, 100);
|
|
25
|
+
// First call executes immediately (leading edge)
|
|
26
|
+
debounced(1);
|
|
27
|
+
expect(fn).toHaveBeenCalledTimes(1);
|
|
28
|
+
expect(fn).toHaveBeenLastCalledWith(1);
|
|
29
|
+
// Subsequent rapid calls within the debounce window are deferred
|
|
30
|
+
debounced(2);
|
|
31
|
+
debounced(3);
|
|
32
|
+
expect(fn).toHaveBeenCalledTimes(1);
|
|
33
|
+
// After the delay, the deferred call should run once with the latest args
|
|
34
|
+
vi.advanceTimersByTime(100);
|
|
35
|
+
expect(fn).toHaveBeenCalledTimes(2);
|
|
36
|
+
expect(fn).toHaveBeenLastCalledWith(3);
|
|
37
|
+
// After an inactivity window, a new call should again execute immediately
|
|
38
|
+
vi.advanceTimersByTime(200);
|
|
39
|
+
debounced(4);
|
|
40
|
+
expect(fn).toHaveBeenCalledTimes(3);
|
|
41
|
+
expect(fn).toHaveBeenLastCalledWith(4);
|
|
42
|
+
vi.useRealTimers();
|
|
43
|
+
});
|
|
44
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
/** List of hex chars (0-9a-f) */
|
|
2
|
+
export const hexChars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
|
|
3
|
+
/** Generates a random hexadecimal char (0-9a-f) */
|
|
4
|
+
export function randomHexChar() {
|
|
5
|
+
const nbr = Math.floor(Math.random() * 16);
|
|
6
|
+
const char = hexChars[nbr];
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
8
|
+
return char;
|
|
7
9
|
}
|
|
8
|
-
export {
|
|
9
|
-
hexChars,
|
|
10
|
-
randomHexChar
|
|
11
|
-
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { hexChars, randomHexChar } from './index.js';
|
|
3
|
+
describe('hexChars', () => {
|
|
4
|
+
it('contains 16 hexadecimal characters', () => {
|
|
5
|
+
expect(hexChars.length).toBe(16);
|
|
6
|
+
expect(hexChars[0]).toBe('0');
|
|
7
|
+
expect(hexChars[15]).toBe('f');
|
|
8
|
+
});
|
|
9
|
+
});
|
|
10
|
+
describe('randomHexChar', () => {
|
|
11
|
+
it('returns a single hexadecimal character from hexChars', () => {
|
|
12
|
+
const char = randomHexChar();
|
|
13
|
+
expect(char.length).toBe(1);
|
|
14
|
+
expect(hexChars.includes(char)).toBe(true);
|
|
15
|
+
});
|
|
16
|
+
it('always returns characters from the allowed set over multiple calls', () => {
|
|
17
|
+
const results = Array.from({ length: 32 }, () => randomHexChar());
|
|
18
|
+
expect(results.every(c => hexChars.includes(c))).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
});
|
package/agnostic/random/index.js
CHANGED