@pawells/typescript-common 2.0.0 → 2.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +350 -224
- package/{build → dist}/array/array-chunk.d.ts +1 -1
- package/{build → dist}/array/array-chunk.js +2 -3
- package/{build → dist}/array/array-compact.d.ts +1 -1
- package/{build → dist}/array/array-compact.js +1 -2
- package/{build → dist}/array/array-contains.d.ts +1 -1
- package/{build → dist}/array/array-contains.js +2 -3
- package/{build → dist}/array/array-count-by.d.ts +1 -1
- package/{build → dist}/array/array-count-by.js +2 -3
- package/{build → dist}/array/array-difference.d.ts +12 -5
- package/dist/array/array-difference.d.ts.map +1 -0
- package/dist/array/array-difference.js +70 -0
- package/dist/array/array-element.js +1 -0
- package/{build → dist}/array/array-filter.d.ts +1 -1
- package/{build → dist}/array/array-filter.js +1 -2
- package/{build → dist}/array/array-flatten.d.ts +2 -2
- package/{build → dist}/array/array-flatten.d.ts.map +1 -1
- package/{build → dist}/array/array-flatten.js +1 -2
- package/{build → dist}/array/array-group-by.d.ts +1 -1
- package/{build → dist}/array/array-group-by.d.ts.map +1 -1
- package/{build → dist}/array/array-group-by.js +10 -9
- package/{build → dist}/array/array-intersection.d.ts +12 -5
- package/dist/array/array-intersection.d.ts.map +1 -0
- package/dist/array/array-intersection.js +79 -0
- package/{build → dist}/array/array-partition.d.ts +1 -1
- package/{build → dist}/array/array-partition.js +2 -3
- package/{build → dist}/array/array-range.d.ts +1 -1
- package/{build → dist}/array/array-range.js +1 -2
- package/{build → dist}/array/array-sample.d.ts +2 -2
- package/{build → dist}/array/array-sample.js +3 -5
- package/{build → dist}/array/array-shuffle.d.ts +1 -1
- package/{build → dist}/array/array-shuffle.js +1 -2
- package/{build → dist}/array/array-sort-by.d.ts +1 -1
- package/{build → dist}/array/array-sort-by.js +1 -2
- package/{build → dist}/array/array-zip.d.ts +1 -1
- package/{build → dist}/array/array-zip.js +1 -2
- package/{build → dist}/array/assert.d.ts +5 -5
- package/{build → dist}/array/assert.d.ts.map +1 -1
- package/{build → dist}/array/assert.js +13 -14
- package/{build → dist}/array/index.js +0 -1
- package/{build → dist}/array/types.d.ts +20 -2
- package/{build → dist}/array/types.d.ts.map +1 -1
- package/dist/array/types.js +1 -0
- package/{build → dist}/array/unique.d.ts +1 -1
- package/{build → dist}/array/unique.js +1 -2
- package/dist/asserts/errors.d.ts.map +1 -0
- package/{build → dist}/asserts/errors.js +5 -3
- package/{build → dist}/asserts/generic.d.ts +23 -3
- package/dist/asserts/generic.d.ts.map +1 -0
- package/{build → dist}/asserts/generic.js +33 -7
- package/dist/asserts/index.d.ts +47 -0
- package/dist/asserts/index.d.ts.map +1 -0
- package/dist/asserts/index.js +46 -0
- package/{build → dist}/asserts/internal-utils.d.ts.map +1 -1
- package/{build → dist}/asserts/internal-utils.js +0 -1
- package/{build → dist}/asserts/types.d.ts +56 -17
- package/dist/asserts/types.d.ts.map +1 -0
- package/dist/asserts/types.js +1 -0
- package/{build → dist}/asserts/utils.d.ts +5 -21
- package/dist/asserts/utils.d.ts.map +1 -0
- package/{build → dist}/asserts/utils.js +12 -36
- package/{build → dist}/boolean/assert.d.ts +1 -2
- package/{build → dist}/boolean/assert.d.ts.map +1 -1
- package/{build → dist}/boolean/assert.js +1 -3
- package/dist/boolean/index.d.ts +13 -0
- package/dist/boolean/index.d.ts.map +1 -0
- package/dist/boolean/index.js +12 -0
- package/{build → dist}/enum/enum-entries.d.ts +1 -1
- package/dist/enum/enum-entries.d.ts.map +1 -0
- package/{build → dist}/enum/enum-entries.js +0 -1
- package/{build → dist}/enum/enum-key-by-value.d.ts +1 -1
- package/dist/enum/enum-key-by-value.d.ts.map +1 -0
- package/{build → dist}/enum/enum-key-by-value.js +0 -1
- package/{build → dist}/enum/enum-keys.js +0 -1
- package/{build → dist}/enum/enum-safe-value.d.ts +1 -1
- package/dist/enum/enum-safe-value.d.ts.map +1 -0
- package/{build → dist}/enum/enum-safe-value.js +0 -1
- package/{build → dist}/enum/enum-values.js +0 -1
- package/{build → dist}/enum/index.d.ts +1 -1
- package/dist/enum/index.d.ts.map +1 -0
- package/{build → dist}/enum/index.js +1 -2
- package/dist/enum/types.js +1 -0
- package/{build → dist}/enum/validate-enum-value.d.ts +1 -1
- package/dist/enum/validate-enum-value.d.ts.map +1 -0
- package/{build → dist}/enum/validate-enum-value.js +0 -1
- package/{build → dist}/function/compose.d.ts +6 -0
- package/dist/function/compose.d.ts.map +1 -0
- package/{build → dist}/function/compose.js +0 -1
- package/{build → dist}/function/debounce.d.ts +6 -0
- package/dist/function/debounce.d.ts.map +1 -0
- package/{build → dist}/function/debounce.js +6 -1
- package/{build → dist}/function/index.js +0 -1
- package/dist/function/memoize.d.ts +43 -0
- package/dist/function/memoize.d.ts.map +1 -0
- package/dist/function/memoize.js +59 -0
- package/{build → dist}/function/once.d.ts.map +1 -1
- package/{build → dist}/function/once.js +1 -1
- package/{build → dist}/function/sleep.js +0 -1
- package/{build → dist}/function/throttle.d.ts +7 -0
- package/dist/function/throttle.d.ts.map +1 -0
- package/{build → dist}/function/throttle.js +7 -1
- package/dist/function/types.d.ts +18 -0
- package/dist/function/types.d.ts.map +1 -0
- package/dist/function/types.js +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/{build → dist}/lru-cache.d.ts +19 -0
- package/dist/lru-cache.d.ts.map +1 -0
- package/{build → dist}/lru-cache.js +24 -2
- package/{build → dist}/number/assert.js +0 -1
- package/dist/number/index.d.ts +13 -0
- package/dist/number/index.d.ts.map +1 -0
- package/dist/number/index.js +12 -0
- package/{build → dist}/object/assert-object.d.ts +5 -1
- package/{build → dist}/object/assert-object.d.ts.map +1 -1
- package/{build → dist}/object/assert-object.js +4 -1
- package/{build → dist}/object/assert.d.ts +1 -1
- package/dist/object/assert.d.ts.map +1 -0
- package/{build → dist}/object/assert.js +7 -29
- package/{build → dist}/object/clone.d.ts.map +1 -1
- package/{build → dist}/object/clone.js +8 -5
- package/{build → dist}/object/equals.d.ts.map +1 -1
- package/{build → dist}/object/equals.js +3 -7
- package/dist/object/filter-cached.d.ts +44 -0
- package/{build → dist}/object/filter-cached.d.ts.map +1 -1
- package/{build → dist}/object/filter-cached.js +41 -2
- package/{build → dist}/object/filter.d.ts.map +1 -1
- package/{build → dist}/object/filter.js +12 -5
- package/{build → dist}/object/has-circular-reference.d.ts.map +1 -1
- package/{build → dist}/object/has-circular-reference.js +4 -2
- package/{build → dist}/object/hash.d.ts +4 -0
- package/dist/object/hash.d.ts.map +1 -0
- package/{build → dist}/object/hash.js +20 -7
- package/{build → dist}/object/index.d.ts +2 -2
- package/{build → dist}/object/index.d.ts.map +1 -1
- package/{build → dist}/object/index.js +1 -2
- package/{build → dist}/object/json-circular-replacer.d.ts.map +1 -1
- package/{build → dist}/object/json-circular-replacer.js +0 -1
- package/{build → dist}/object/key-value-pairs.js +0 -1
- package/dist/object/map-cached.d.ts +31 -0
- package/dist/object/map-cached.d.ts.map +1 -0
- package/{build → dist}/object/map-cached.js +34 -6
- package/{build → dist}/object/map.js +0 -1
- package/{build → dist}/object/merge.d.ts.map +1 -1
- package/{build → dist}/object/merge.js +7 -7
- package/{build → dist}/object/object-diff.d.ts +2 -2
- package/{build → dist}/object/object-diff.d.ts.map +1 -1
- package/{build → dist}/object/object-diff.js +11 -5
- package/{build → dist}/object/object-flatten.d.ts +1 -1
- package/{build → dist}/object/object-flatten.d.ts.map +1 -1
- package/{build → dist}/object/object-flatten.js +6 -4
- package/{build → dist}/object/object-invert.js +0 -1
- package/{build → dist}/object/omit.js +0 -1
- package/{build → dist}/object/pick.js +0 -1
- package/{build → dist}/object/property-paths.js +6 -7
- package/dist/object/security-utils.d.ts +193 -0
- package/dist/object/security-utils.d.ts.map +1 -0
- package/dist/object/security-utils.js +297 -0
- package/{build → dist}/object/sort-keys.d.ts +1 -1
- package/{build → dist}/object/sort-keys.d.ts.map +1 -1
- package/{build → dist}/object/sort-keys.js +18 -11
- package/{build → dist}/object/types.d.ts +60 -19
- package/dist/object/types.d.ts.map +1 -0
- package/dist/object/types.js +1 -0
- package/{build → dist}/string/assert.d.ts +5 -0
- package/dist/string/assert.d.ts.map +1 -0
- package/{build → dist}/string/assert.js +11 -1
- package/{build → dist}/string/case-conversion.js +0 -1
- package/{build → dist}/string/comparison.d.ts.map +1 -1
- package/{build → dist}/string/comparison.js +3 -1
- package/{build → dist}/string/formatting.d.ts.map +1 -1
- package/{build → dist}/string/formatting.js +5 -3
- package/{build → dist}/string/index.js +0 -1
- package/{build → dist}/string/transformation.js +0 -1
- package/dist/string/types.d.ts +118 -0
- package/dist/string/types.d.ts.map +1 -0
- package/dist/string/types.js +1 -0
- package/{build → dist}/string/validation.js +0 -1
- package/dist/time/elapsed-time/constants.d.ts +36 -0
- package/{build → dist}/time/elapsed-time/constants.d.ts.map +1 -1
- package/{build → dist}/time/elapsed-time/constants.js +32 -3
- package/{build → dist}/time/elapsed-time/elapsed-time.d.ts +67 -15
- package/dist/time/elapsed-time/elapsed-time.d.ts.map +1 -0
- package/{build → dist}/time/elapsed-time/elapsed-time.js +172 -78
- package/dist/time/elapsed-time/types.d.ts +336 -0
- package/dist/time/elapsed-time/types.d.ts.map +1 -0
- package/dist/time/elapsed-time/types.js +1 -0
- package/{build → dist}/time/elapsed-time/utils.d.ts +1 -1
- package/dist/time/elapsed-time/utils.d.ts.map +1 -0
- package/{build → dist}/time/elapsed-time/utils.js +0 -1
- package/{build → dist}/time/index.d.ts +0 -2
- package/{build → dist}/time/index.d.ts.map +1 -1
- package/{build → dist}/time/index.js +0 -2
- package/{build → dist}/time/stopwatch/entry.d.ts +1 -1
- package/dist/time/stopwatch/entry.d.ts.map +1 -0
- package/{build → dist}/time/stopwatch/entry.js +0 -1
- package/{build → dist}/time/stopwatch/stopwatch.d.ts +9 -3
- package/dist/time/stopwatch/stopwatch.d.ts.map +1 -0
- package/{build → dist}/time/stopwatch/stopwatch.js +9 -4
- package/package.json +58 -81
- package/LICENSE +0 -21
- package/build/array/array-chunk.js.map +0 -1
- package/build/array/array-compact.js.map +0 -1
- package/build/array/array-contains.js.map +0 -1
- package/build/array/array-count-by.js.map +0 -1
- package/build/array/array-difference.d.ts.map +0 -1
- package/build/array/array-difference.js +0 -51
- package/build/array/array-difference.js.map +0 -1
- package/build/array/array-element.js +0 -2
- package/build/array/array-element.js.map +0 -1
- package/build/array/array-filter.js.map +0 -1
- package/build/array/array-flatten.js.map +0 -1
- package/build/array/array-group-by.js.map +0 -1
- package/build/array/array-intersection.d.ts.map +0 -1
- package/build/array/array-intersection.js +0 -57
- package/build/array/array-intersection.js.map +0 -1
- package/build/array/array-partition.js.map +0 -1
- package/build/array/array-range.js.map +0 -1
- package/build/array/array-sample.js.map +0 -1
- package/build/array/array-shuffle.js.map +0 -1
- package/build/array/array-sort-by.js.map +0 -1
- package/build/array/array-zip.js.map +0 -1
- package/build/array/assert.js.map +0 -1
- package/build/array/index.js.map +0 -1
- package/build/array/types.js +0 -2
- package/build/array/types.js.map +0 -1
- package/build/array/unique.js.map +0 -1
- package/build/asserts/errors.d.ts.map +0 -1
- package/build/asserts/errors.js.map +0 -1
- package/build/asserts/generic.d.ts.map +0 -1
- package/build/asserts/generic.js.map +0 -1
- package/build/asserts/index.d.ts +0 -41
- package/build/asserts/index.d.ts.map +0 -1
- package/build/asserts/index.js +0 -41
- package/build/asserts/index.js.map +0 -1
- package/build/asserts/internal-utils.js.map +0 -1
- package/build/asserts/types.d.ts.map +0 -1
- package/build/asserts/types.js +0 -2
- package/build/asserts/types.js.map +0 -1
- package/build/asserts/utils.d.ts.map +0 -1
- package/build/asserts/utils.js.map +0 -1
- package/build/boolean/assert.js.map +0 -1
- package/build/boolean/index.d.ts +0 -9
- package/build/boolean/index.d.ts.map +0 -1
- package/build/boolean/index.js +0 -9
- package/build/boolean/index.js.map +0 -1
- package/build/enum/enum-entries.d.ts.map +0 -1
- package/build/enum/enum-entries.js.map +0 -1
- package/build/enum/enum-key-by-value.d.ts.map +0 -1
- package/build/enum/enum-key-by-value.js.map +0 -1
- package/build/enum/enum-keys.js.map +0 -1
- package/build/enum/enum-safe-value.d.ts.map +0 -1
- package/build/enum/enum-safe-value.js.map +0 -1
- package/build/enum/enum-values.js.map +0 -1
- package/build/enum/index.d.ts.map +0 -1
- package/build/enum/index.js.map +0 -1
- package/build/enum/types.js +0 -2
- package/build/enum/types.js.map +0 -1
- package/build/enum/validate-enum-value.d.ts.map +0 -1
- package/build/enum/validate-enum-value.js.map +0 -1
- package/build/function/compose.d.ts.map +0 -1
- package/build/function/compose.js.map +0 -1
- package/build/function/debounce.d.ts.map +0 -1
- package/build/function/debounce.js.map +0 -1
- package/build/function/index.js.map +0 -1
- package/build/function/memoize.d.ts +0 -30
- package/build/function/memoize.d.ts.map +0 -1
- package/build/function/memoize.js +0 -44
- package/build/function/memoize.js.map +0 -1
- package/build/function/once.js.map +0 -1
- package/build/function/sleep.js.map +0 -1
- package/build/function/throttle.d.ts.map +0 -1
- package/build/function/throttle.js.map +0 -1
- package/build/function/types.d.ts +0 -5
- package/build/function/types.d.ts.map +0 -1
- package/build/function/types.js +0 -2
- package/build/function/types.js.map +0 -1
- package/build/index.d.ts +0 -38
- package/build/index.d.ts.map +0 -1
- package/build/index.js +0 -64
- package/build/index.js.map +0 -1
- package/build/lru-cache.d.ts.map +0 -1
- package/build/lru-cache.js.map +0 -1
- package/build/number/assert.js.map +0 -1
- package/build/number/index.d.ts +0 -9
- package/build/number/index.d.ts.map +0 -1
- package/build/number/index.js +0 -9
- package/build/number/index.js.map +0 -1
- package/build/object/assert-object.js.map +0 -1
- package/build/object/assert.d.ts.map +0 -1
- package/build/object/assert.js.map +0 -1
- package/build/object/clone.js.map +0 -1
- package/build/object/equals.js.map +0 -1
- package/build/object/filter-cached.d.ts +0 -21
- package/build/object/filter-cached.js.map +0 -1
- package/build/object/filter.js.map +0 -1
- package/build/object/has-circular-reference.js.map +0 -1
- package/build/object/hash.d.ts.map +0 -1
- package/build/object/hash.js.map +0 -1
- package/build/object/index.js.map +0 -1
- package/build/object/json-circular-replacer.js.map +0 -1
- package/build/object/key-value-pairs.js.map +0 -1
- package/build/object/map-cached.d.ts +0 -20
- package/build/object/map-cached.d.ts.map +0 -1
- package/build/object/map-cached.js.map +0 -1
- package/build/object/map.js.map +0 -1
- package/build/object/merge.js.map +0 -1
- package/build/object/object-diff.js.map +0 -1
- package/build/object/object-flatten.js.map +0 -1
- package/build/object/object-invert.js.map +0 -1
- package/build/object/omit.js.map +0 -1
- package/build/object/pick.js.map +0 -1
- package/build/object/property-paths.js.map +0 -1
- package/build/object/security-utils.d.ts +0 -59
- package/build/object/security-utils.d.ts.map +0 -1
- package/build/object/security-utils.js +0 -161
- package/build/object/security-utils.js.map +0 -1
- package/build/object/sort-keys.js.map +0 -1
- package/build/object/types.d.ts.map +0 -1
- package/build/object/types.js +0 -6
- package/build/object/types.js.map +0 -1
- package/build/string/assert.d.ts.map +0 -1
- package/build/string/assert.js.map +0 -1
- package/build/string/case-conversion.js.map +0 -1
- package/build/string/comparison.js.map +0 -1
- package/build/string/formatting.js.map +0 -1
- package/build/string/index.js.map +0 -1
- package/build/string/transformation.js.map +0 -1
- package/build/string/types.d.ts +0 -44
- package/build/string/types.d.ts.map +0 -1
- package/build/string/types.js +0 -2
- package/build/string/types.js.map +0 -1
- package/build/string/validation.js.map +0 -1
- package/build/time/elapsed-time/constants.d.ts +0 -10
- package/build/time/elapsed-time/constants.js.map +0 -1
- package/build/time/elapsed-time/elapsed-time.d.ts.map +0 -1
- package/build/time/elapsed-time/elapsed-time.js.map +0 -1
- package/build/time/elapsed-time/types.d.ts +0 -150
- package/build/time/elapsed-time/types.d.ts.map +0 -1
- package/build/time/elapsed-time/types.js +0 -2
- package/build/time/elapsed-time/types.js.map +0 -1
- package/build/time/elapsed-time/utils.d.ts.map +0 -1
- package/build/time/elapsed-time/utils.js.map +0 -1
- package/build/time/index.js.map +0 -1
- package/build/time/stopwatch/entry-types.d.ts +0 -13
- package/build/time/stopwatch/entry-types.d.ts.map +0 -1
- package/build/time/stopwatch/entry-types.js +0 -2
- package/build/time/stopwatch/entry-types.js.map +0 -1
- package/build/time/stopwatch/entry.d.ts.map +0 -1
- package/build/time/stopwatch/entry.js.map +0 -1
- package/build/time/stopwatch/stopwatch.d.ts.map +0 -1
- package/build/time/stopwatch/stopwatch.js.map +0 -1
- /package/{build → dist}/array/array-chunk.d.ts.map +0 -0
- /package/{build → dist}/array/array-compact.d.ts.map +0 -0
- /package/{build → dist}/array/array-contains.d.ts.map +0 -0
- /package/{build → dist}/array/array-count-by.d.ts.map +0 -0
- /package/{build → dist}/array/array-element.d.ts +0 -0
- /package/{build → dist}/array/array-element.d.ts.map +0 -0
- /package/{build → dist}/array/array-filter.d.ts.map +0 -0
- /package/{build → dist}/array/array-partition.d.ts.map +0 -0
- /package/{build → dist}/array/array-range.d.ts.map +0 -0
- /package/{build → dist}/array/array-sample.d.ts.map +0 -0
- /package/{build → dist}/array/array-shuffle.d.ts.map +0 -0
- /package/{build → dist}/array/array-sort-by.d.ts.map +0 -0
- /package/{build → dist}/array/array-zip.d.ts.map +0 -0
- /package/{build → dist}/array/index.d.ts +0 -0
- /package/{build → dist}/array/index.d.ts.map +0 -0
- /package/{build → dist}/array/unique.d.ts.map +0 -0
- /package/{build → dist}/asserts/errors.d.ts +0 -0
- /package/{build → dist}/asserts/internal-utils.d.ts +0 -0
- /package/{build → dist}/enum/enum-keys.d.ts +0 -0
- /package/{build → dist}/enum/enum-keys.d.ts.map +0 -0
- /package/{build → dist}/enum/enum-values.d.ts +0 -0
- /package/{build → dist}/enum/enum-values.d.ts.map +0 -0
- /package/{build → dist}/enum/types.d.ts +0 -0
- /package/{build → dist}/enum/types.d.ts.map +0 -0
- /package/{build → dist}/function/index.d.ts +0 -0
- /package/{build → dist}/function/index.d.ts.map +0 -0
- /package/{build → dist}/function/once.d.ts +0 -0
- /package/{build → dist}/function/sleep.d.ts +0 -0
- /package/{build → dist}/function/sleep.d.ts.map +0 -0
- /package/{build → dist}/number/assert.d.ts +0 -0
- /package/{build → dist}/number/assert.d.ts.map +0 -0
- /package/{build → dist}/object/clone.d.ts +0 -0
- /package/{build → dist}/object/equals.d.ts +0 -0
- /package/{build → dist}/object/filter.d.ts +0 -0
- /package/{build → dist}/object/has-circular-reference.d.ts +0 -0
- /package/{build → dist}/object/json-circular-replacer.d.ts +0 -0
- /package/{build → dist}/object/key-value-pairs.d.ts +0 -0
- /package/{build → dist}/object/key-value-pairs.d.ts.map +0 -0
- /package/{build → dist}/object/map.d.ts +0 -0
- /package/{build → dist}/object/map.d.ts.map +0 -0
- /package/{build → dist}/object/merge.d.ts +0 -0
- /package/{build → dist}/object/object-invert.d.ts +0 -0
- /package/{build → dist}/object/object-invert.d.ts.map +0 -0
- /package/{build → dist}/object/omit.d.ts +0 -0
- /package/{build → dist}/object/omit.d.ts.map +0 -0
- /package/{build → dist}/object/pick.d.ts +0 -0
- /package/{build → dist}/object/pick.d.ts.map +0 -0
- /package/{build → dist}/object/property-paths.d.ts +0 -0
- /package/{build → dist}/object/property-paths.d.ts.map +0 -0
- /package/{build → dist}/string/case-conversion.d.ts +0 -0
- /package/{build → dist}/string/case-conversion.d.ts.map +0 -0
- /package/{build → dist}/string/comparison.d.ts +0 -0
- /package/{build → dist}/string/formatting.d.ts +0 -0
- /package/{build → dist}/string/index.d.ts +0 -0
- /package/{build → dist}/string/index.d.ts.map +0 -0
- /package/{build → dist}/string/transformation.d.ts +0 -0
- /package/{build → dist}/string/transformation.d.ts.map +0 -0
- /package/{build → dist}/string/validation.d.ts +0 -0
- /package/{build → dist}/string/validation.d.ts.map +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { TPropertyMapper, ICachedObjectMapOptions } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a cached version of {@link MapObject} for improved performance
|
|
4
|
+
* when mapping the same objects repeatedly.
|
|
5
|
+
*
|
|
6
|
+
* Results are cached by hashing the object. Cache entries are evicted in
|
|
7
|
+
* approximately 20% batches when the limit is reached.
|
|
8
|
+
*
|
|
9
|
+
* @template T - The object type being mapped
|
|
10
|
+
* @param options - Configuration options for cache behaviour
|
|
11
|
+
* @returns A cached map function with parameters:
|
|
12
|
+
* - `cursor` - The object to be mapped
|
|
13
|
+
* - `mapper` - Function to map each property value
|
|
14
|
+
* - `mapperKey` - Optional stable string identifier for the mapper. When omitted,
|
|
15
|
+
* `Function.toString()` is used as the cache key, which may cause cache collisions
|
|
16
|
+
* for closures with identical source text but different captured variables.
|
|
17
|
+
* Always provide an explicit `mapperKey` when the mapper captures mutable state.
|
|
18
|
+
*
|
|
19
|
+
* @warning When `mapperKey` is not provided, the function uses `Function.toString()` as
|
|
20
|
+
* the cache key. This approach is expensive for large functions and causes cache collisions
|
|
21
|
+
* for closures with identical source code but different captured values. Always supply an
|
|
22
|
+
* explicit `mapperKey` to avoid unexpected cache behavior.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const cachedMap = MapObjectCached<User>();
|
|
27
|
+
* const display = await cachedMap(user, (key, value) => String(value));
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function MapObjectCached<T extends object>(options?: ICachedObjectMapOptions): (cursor: T, mapper: TPropertyMapper<T>, mapperKey?: string) => Promise<Record<keyof T, unknown>>;
|
|
31
|
+
//# sourceMappingURL=map-cached.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"map-cached.d.ts","sourceRoot":"","sources":["../../src/object/map-cached.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAM3E;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,OAAO,GAAE,uBAA4B,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,CAmHzL"}
|
|
@@ -12,7 +12,18 @@ const CACHE_EVICTION_PERCENTAGE = 0.2; // 20%
|
|
|
12
12
|
*
|
|
13
13
|
* @template T - The object type being mapped
|
|
14
14
|
* @param options - Configuration options for cache behaviour
|
|
15
|
-
* @returns A cached map function
|
|
15
|
+
* @returns A cached map function with parameters:
|
|
16
|
+
* - `cursor` - The object to be mapped
|
|
17
|
+
* - `mapper` - Function to map each property value
|
|
18
|
+
* - `mapperKey` - Optional stable string identifier for the mapper. When omitted,
|
|
19
|
+
* `Function.toString()` is used as the cache key, which may cause cache collisions
|
|
20
|
+
* for closures with identical source text but different captured variables.
|
|
21
|
+
* Always provide an explicit `mapperKey` when the mapper captures mutable state.
|
|
22
|
+
*
|
|
23
|
+
* @warning When `mapperKey` is not provided, the function uses `Function.toString()` as
|
|
24
|
+
* the cache key. This approach is expensive for large functions and causes cache collisions
|
|
25
|
+
* for closures with identical source code but different captured values. Always supply an
|
|
26
|
+
* explicit `mapperKey` to avoid unexpected cache behavior.
|
|
16
27
|
*
|
|
17
28
|
* @example
|
|
18
29
|
* ```typescript
|
|
@@ -30,6 +41,11 @@ export function MapObjectCached(options = {}) {
|
|
|
30
41
|
*
|
|
31
42
|
* The eviction strategy targets the most-populated bucket to reclaim the most
|
|
32
43
|
* memory in a single pass while preserving results for other active mappers.
|
|
44
|
+
*
|
|
45
|
+
* PERFORMANCE NOTE: For distributed mapper load, eviction triggers too frequently.
|
|
46
|
+
* A true global LRU across all mappers would be more efficient but would require
|
|
47
|
+
* tracking access order globally. Refactoring to use the library's own LRUCache
|
|
48
|
+
* (if available) instead of per-mapper Maps would improve this further.
|
|
33
49
|
*/
|
|
34
50
|
const clearOldestEntries = () => {
|
|
35
51
|
if (cache.size === 0)
|
|
@@ -46,6 +62,8 @@ export function MapObjectCached(options = {}) {
|
|
|
46
62
|
}
|
|
47
63
|
}
|
|
48
64
|
if (largestCache) {
|
|
65
|
+
// Capture the original bucket size before eviction
|
|
66
|
+
const originalBucketSize = largestCache.size;
|
|
49
67
|
// Remove approximately 20% of entries from the largest cache
|
|
50
68
|
const entriesToRemove = Math.ceil(largestSize * CACHE_EVICTION_PERCENTAGE);
|
|
51
69
|
let removed = 0;
|
|
@@ -58,8 +76,13 @@ export function MapObjectCached(options = {}) {
|
|
|
58
76
|
// If the cache is now empty, remove it completely
|
|
59
77
|
if (largestCache.size === 0) {
|
|
60
78
|
cache.delete(largestCacheKey);
|
|
79
|
+
// Account for all entries that were in the bucket (not just the ones we explicitly removed)
|
|
80
|
+
totalCachedEntries -= originalBucketSize;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
// Only remove the entries we explicitly deleted
|
|
84
|
+
totalCachedEntries -= removed;
|
|
61
85
|
}
|
|
62
|
-
totalCachedEntries -= removed;
|
|
63
86
|
}
|
|
64
87
|
};
|
|
65
88
|
return (cursor, mapper, mapperKey) => {
|
|
@@ -68,9 +91,10 @@ export function MapObjectCached(options = {}) {
|
|
|
68
91
|
return Promise.resolve({});
|
|
69
92
|
}
|
|
70
93
|
// Use the explicitly provided mapperKey when available.
|
|
71
|
-
//
|
|
72
|
-
//
|
|
73
|
-
//
|
|
94
|
+
// NOTE: When mapperKey is not provided, uses Function.toString() as cache key.
|
|
95
|
+
// This is expensive for large functions and causes cache collisions for closures
|
|
96
|
+
// with identical source code but different captured values.
|
|
97
|
+
// Always provide explicit mapperKey for correct behavior.
|
|
74
98
|
const resolvedMapperKey = mapperKey ?? mapper.toString();
|
|
75
99
|
// Try to get the object cache for this mapper
|
|
76
100
|
let objectCache = cache.get(resolvedMapperKey);
|
|
@@ -100,8 +124,12 @@ export function MapObjectCached(options = {}) {
|
|
|
100
124
|
// Ensure the cache size does not exceed the limit
|
|
101
125
|
if (totalCachedEntries > maxCacheSize) {
|
|
102
126
|
clearOldestEntries();
|
|
127
|
+
// Recompute counter to eliminate drift
|
|
128
|
+
totalCachedEntries = 0;
|
|
129
|
+
for (const bucket of cache.values()) {
|
|
130
|
+
totalCachedEntries += bucket.size;
|
|
131
|
+
}
|
|
103
132
|
}
|
|
104
133
|
return Promise.resolve(result);
|
|
105
134
|
};
|
|
106
135
|
}
|
|
107
|
-
//# sourceMappingURL=map-cached.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/object/merge.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/object/merge.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CA0BvF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FilterDangerousKeys } from './security-utils.js';
|
|
2
2
|
/**
|
|
3
3
|
* Merges two objects deeply with security protections.
|
|
4
4
|
*
|
|
@@ -28,22 +28,22 @@ export function ObjectMerge(target, source) {
|
|
|
28
28
|
if (!source || typeof source !== 'object')
|
|
29
29
|
return target;
|
|
30
30
|
// Security: Filter out dangerous keys from source object
|
|
31
|
-
const safeSource =
|
|
31
|
+
const safeSource = FilterDangerousKeys(source);
|
|
32
32
|
const output = { ...target };
|
|
33
33
|
// Object.keys() returns only own enumerable properties — no further guard needed.
|
|
34
34
|
for (const key of Object.keys(safeSource)) {
|
|
35
|
-
const
|
|
35
|
+
const outputRecord = output;
|
|
36
|
+
const targetValue = outputRecord[key];
|
|
36
37
|
const sourceValue = safeSource[key];
|
|
37
38
|
if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
|
|
38
|
-
|
|
39
|
+
outputRecord[key] = [...targetValue, ...sourceValue];
|
|
39
40
|
}
|
|
40
41
|
else if (targetValue && typeof targetValue === 'object' && sourceValue && typeof sourceValue === 'object') {
|
|
41
|
-
|
|
42
|
+
outputRecord[key] = ObjectMerge(targetValue, sourceValue);
|
|
42
43
|
}
|
|
43
44
|
else {
|
|
44
|
-
|
|
45
|
+
outputRecord[key] = sourceValue;
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
return output;
|
|
48
49
|
}
|
|
49
|
-
//# sourceMappingURL=merge.js.map
|
|
@@ -16,8 +16,8 @@ export interface IObjectDiffResult {
|
|
|
16
16
|
* Returns three groups:
|
|
17
17
|
* - **added** — keys in `objB` that are absent from `objA`
|
|
18
18
|
* - **removed** — keys in `objA` that are absent from `objB`
|
|
19
|
-
* - **changed** — keys present in both whose values
|
|
20
|
-
* (compared via `
|
|
19
|
+
* - **changed** — keys present in both whose values differ
|
|
20
|
+
* (compared via `ObjectEquals` for deep value equality)
|
|
21
21
|
*
|
|
22
22
|
* **Important**: Comparison is performed with deep equality (`ObjectEquals`),
|
|
23
23
|
* which correctly handles nested objects regardless of key insertion order,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object-diff.d.ts","sourceRoot":"","sources":["../../src/object/object-diff.ts"],"names":[],"mappings":"AAEA,sEAAsE;AACtE,MAAM,WAAW,iBAAiB;IACjC,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,EAAE,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACxD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,UAAU,CACzB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,iBAAiB,
|
|
1
|
+
{"version":3,"file":"object-diff.d.ts","sourceRoot":"","sources":["../../src/object/object-diff.ts"],"names":[],"mappings":"AAEA,sEAAsE;AACtE,MAAM,WAAW,iBAAiB;IACjC,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,EAAE,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACxD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,UAAU,CACzB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,iBAAiB,CA0BnB"}
|
|
@@ -5,8 +5,8 @@ import { ObjectEquals } from './equals.js';
|
|
|
5
5
|
* Returns three groups:
|
|
6
6
|
* - **added** — keys in `objB` that are absent from `objA`
|
|
7
7
|
* - **removed** — keys in `objA` that are absent from `objB`
|
|
8
|
-
* - **changed** — keys present in both whose values
|
|
9
|
-
* (compared via `
|
|
8
|
+
* - **changed** — keys present in both whose values differ
|
|
9
|
+
* (compared via `ObjectEquals` for deep value equality)
|
|
10
10
|
*
|
|
11
11
|
* **Important**: Comparison is performed with deep equality (`ObjectEquals`),
|
|
12
12
|
* which correctly handles nested objects regardless of key insertion order,
|
|
@@ -32,8 +32,15 @@ import { ObjectEquals } from './equals.js';
|
|
|
32
32
|
*/
|
|
33
33
|
export function ObjectDiff(objA, objB) {
|
|
34
34
|
const result = { added: {}, removed: {}, changed: {} };
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
// Combine keys from both objects efficiently
|
|
36
|
+
const allKeys = new Map();
|
|
37
|
+
for (const key of Object.keys(objA)) {
|
|
38
|
+
allKeys.set(key, true);
|
|
39
|
+
}
|
|
40
|
+
for (const key of Object.keys(objB)) {
|
|
41
|
+
allKeys.set(key, true);
|
|
42
|
+
}
|
|
43
|
+
for (const key of allKeys.keys()) {
|
|
37
44
|
const inA = Object.hasOwn(objA, key);
|
|
38
45
|
const inB = Object.hasOwn(objB, key);
|
|
39
46
|
if (inA && !inB) {
|
|
@@ -48,4 +55,3 @@ export function ObjectDiff(objA, objB) {
|
|
|
48
55
|
}
|
|
49
56
|
return result;
|
|
50
57
|
}
|
|
51
|
-
//# sourceMappingURL=object-diff.js.map
|
|
@@ -18,5 +18,5 @@
|
|
|
18
18
|
* // { 'a/b': 1 }
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
|
-
export declare function ObjectFlatten(obj: Record<string, unknown>, separator?: string
|
|
21
|
+
export declare function ObjectFlatten(obj: Record<string, unknown>, separator?: string): Record<string, unknown>;
|
|
22
22
|
//# sourceMappingURL=object-flatten.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object-flatten.d.ts","sourceRoot":"","sources":["../../src/object/object-flatten.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,SAAS,SAAM,
|
|
1
|
+
{"version":3,"file":"object-flatten.d.ts","sourceRoot":"","sources":["../../src/object/object-flatten.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAC5B,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,SAAS,SAAM,GACb,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzB"}
|
|
@@ -18,16 +18,19 @@
|
|
|
18
18
|
* // { 'a/b': 1 }
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
|
-
export function ObjectFlatten(obj, separator = '.'
|
|
21
|
+
export function ObjectFlatten(obj, separator = '.') {
|
|
22
|
+
return flattenRecursive(obj, separator, '');
|
|
23
|
+
}
|
|
24
|
+
function flattenRecursive(obj, separator, prefix) {
|
|
22
25
|
const result = {};
|
|
23
26
|
for (const key of Object.keys(obj)) {
|
|
24
27
|
const value = obj[key];
|
|
25
|
-
const newKey =
|
|
28
|
+
const newKey = prefix ? `${prefix}${separator}${key}` : key;
|
|
26
29
|
if (value !== null &&
|
|
27
30
|
typeof value === 'object' &&
|
|
28
31
|
!Array.isArray(value) &&
|
|
29
32
|
!(value instanceof Date)) {
|
|
30
|
-
Object.assign(result,
|
|
33
|
+
Object.assign(result, flattenRecursive(value, separator, newKey));
|
|
31
34
|
}
|
|
32
35
|
else {
|
|
33
36
|
result[newKey] = value;
|
|
@@ -35,4 +38,3 @@ export function ObjectFlatten(obj, separator = '.', _prefix = '') {
|
|
|
35
38
|
}
|
|
36
39
|
return result;
|
|
37
40
|
}
|
|
38
|
-
//# sourceMappingURL=object-flatten.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IsPropertyPathSafe, IsPropertyKeySafe } from './security-utils.js';
|
|
2
2
|
/**
|
|
3
3
|
* Safely gets a nested property from an object using a path string with dot notation.
|
|
4
4
|
* Returns the default value if the path doesn't exist or any intermediate value is null/undefined.
|
|
@@ -59,14 +59,14 @@ export function ObjectGetPropertyByPath(obj, path, defaultValue) {
|
|
|
59
59
|
return defaultValue;
|
|
60
60
|
}
|
|
61
61
|
// Security validation: Check if the path is safe
|
|
62
|
-
if (!
|
|
62
|
+
if (!IsPropertyPathSafe(path)) {
|
|
63
63
|
return defaultValue;
|
|
64
64
|
}
|
|
65
65
|
const keys = path.split('.');
|
|
66
66
|
let result = obj;
|
|
67
67
|
for (const key of keys) {
|
|
68
68
|
// Security check for each key
|
|
69
|
-
if (!
|
|
69
|
+
if (!IsPropertyKeySafe(key)) {
|
|
70
70
|
return defaultValue;
|
|
71
71
|
}
|
|
72
72
|
if (result === null || result === undefined || typeof result !== 'object') {
|
|
@@ -147,7 +147,7 @@ export function ObjectSetPropertyByPath(obj, path, value) {
|
|
|
147
147
|
return;
|
|
148
148
|
}
|
|
149
149
|
// Security validation: Check if the path is safe
|
|
150
|
-
if (!
|
|
150
|
+
if (!IsPropertyPathSafe(path)) {
|
|
151
151
|
return;
|
|
152
152
|
}
|
|
153
153
|
const keys = path.split('.');
|
|
@@ -156,13 +156,13 @@ export function ObjectSetPropertyByPath(obj, path, value) {
|
|
|
156
156
|
return;
|
|
157
157
|
}
|
|
158
158
|
// Additional security check for the final key
|
|
159
|
-
if (!
|
|
159
|
+
if (!IsPropertyKeySafe(lastKey)) {
|
|
160
160
|
return;
|
|
161
161
|
}
|
|
162
162
|
let current = obj;
|
|
163
163
|
for (const key of keys) {
|
|
164
164
|
// Security check for each intermediate key
|
|
165
|
-
if (!
|
|
165
|
+
if (!IsPropertyKeySafe(key)) {
|
|
166
166
|
return;
|
|
167
167
|
}
|
|
168
168
|
if (current[key] === null || current[key] === undefined || typeof current[key] !== 'object') {
|
|
@@ -172,4 +172,3 @@ export function ObjectSetPropertyByPath(obj, path, value) {
|
|
|
172
172
|
}
|
|
173
173
|
current[lastKey] = value;
|
|
174
174
|
}
|
|
175
|
-
//# sourceMappingURL=property-paths.js.map
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security utilities for object manipulation functions
|
|
3
|
+
* Provides protection against prototype pollution, path traversal, and other security vulnerabilities
|
|
4
|
+
*
|
|
5
|
+
* Sensitive data patterns considered by these utilities include:
|
|
6
|
+
* - Prototype pollution vectors: `__proto__`, `constructor`, `prototype`
|
|
7
|
+
* - Path traversal sequences: `..`, encoded dots (`%2e%2e`, `%252e%252e`)
|
|
8
|
+
* - Null byte injections: `\0`, `%00`
|
|
9
|
+
* - Unicode attacks: BOM characters, reversed BOM, invalid unicode sequences
|
|
10
|
+
* - Malformed input: consecutive dots, leading/trailing dots, empty segments
|
|
11
|
+
*
|
|
12
|
+
* @author Security Auditor Agent
|
|
13
|
+
* @version 1.0.0
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Validates if a property key is safe to use (not dangerous for prototype pollution)
|
|
17
|
+
*
|
|
18
|
+
* Blocks dangerous property names and path traversal patterns:
|
|
19
|
+
* - Prototype pollution vectors: `__proto__`, `constructor`, `prototype`
|
|
20
|
+
* - Path traversal: `..`, URL-encoded variants (`%2e%2e`, `%252e%252e`)
|
|
21
|
+
* - Null bytes: `\0` (literal), `%00` (URL-encoded)
|
|
22
|
+
* - Unicode attacks: BOM characters and invalid sequences
|
|
23
|
+
*
|
|
24
|
+
* @param key - The property key to validate
|
|
25
|
+
* @returns True if the key is safe to use as an object property, false if it's a known attack vector
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* IsPropertyKeySafe('name'); // true
|
|
30
|
+
* IsPropertyKeySafe('user_id'); // true
|
|
31
|
+
* IsPropertyKeySafe('__proto__'); // false (prototype pollution)
|
|
32
|
+
* IsPropertyKeySafe('constructor'); // false (prototype pollution)
|
|
33
|
+
* IsPropertyKeySafe('..'); // false (path traversal)
|
|
34
|
+
* IsPropertyKeySafe('%2e%2e'); // false (encoded path traversal)
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function IsPropertyKeySafe(key: string): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Validates a property path for security issues
|
|
40
|
+
*
|
|
41
|
+
* Detects and blocks malformed or dangerous paths:
|
|
42
|
+
* - Leading or trailing dots: `.name`, `path.`
|
|
43
|
+
* - Consecutive dots: `user..name` (double dot traversal)
|
|
44
|
+
* - Each path segment is validated via `IsPropertyKeySafe`
|
|
45
|
+
*
|
|
46
|
+
* Used by `ObjectGetPropertyByPath` and `ObjectSetPropertyByPath` to prevent
|
|
47
|
+
* prototype pollution and path traversal attacks. Safe for untrusted input
|
|
48
|
+
* when `validatePaths: true` is passed to ObjectFilter.
|
|
49
|
+
*
|
|
50
|
+
* @param path - The property path to validate using dot notation (e.g., `user.profile.name`)
|
|
51
|
+
* @returns True if the path is safe, false if it contains security risks
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* IsPropertyPathSafe('user.profile.name'); // true
|
|
56
|
+
* IsPropertyPathSafe('user..name'); // false (double dot)
|
|
57
|
+
* IsPropertyPathSafe('.user.name'); // false (leading dot)
|
|
58
|
+
* IsPropertyPathSafe('user.name.'); // false (trailing dot)
|
|
59
|
+
* IsPropertyPathSafe('user.__proto__.name'); // false (dangerous segment)
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare function IsPropertyPathSafe(path: string): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Sanitizes a property key by removing or replacing dangerous characters
|
|
65
|
+
*
|
|
66
|
+
* Returns `null` if the key contains dangerous patterns (prototype pollution vectors,
|
|
67
|
+
* path traversal sequences) that cannot be safely sanitized. Otherwise returns the
|
|
68
|
+
* key with leading/trailing whitespace trimmed.
|
|
69
|
+
*
|
|
70
|
+
* @param key - The property key to sanitize
|
|
71
|
+
* @returns The sanitized key (with whitespace trimmed), or `null` if the key is dangerous
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* SanitizePropertyKey(' user.name '); // 'user.name'
|
|
76
|
+
* SanitizePropertyKey('__proto__'); // null (dangerous)
|
|
77
|
+
* SanitizePropertyKey('valid-key'); // 'valid-key'
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare function SanitizePropertyKey(key: string): string | null;
|
|
81
|
+
/**
|
|
82
|
+
* Filters out dangerous keys from an object
|
|
83
|
+
*
|
|
84
|
+
* Creates a new object containing only properties whose keys pass the `IsPropertyKeySafe` check.
|
|
85
|
+
* Blocks prototype pollution vectors: `__proto__`, `constructor`, `prototype`.
|
|
86
|
+
* Safe for untrusted input. Used internally by ObjectClone and ObjectMerge.
|
|
87
|
+
*
|
|
88
|
+
* @template T - The type of the object
|
|
89
|
+
* @param obj - The object to filter
|
|
90
|
+
* @returns New object with only safe keys (subset of input properties)
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* FilterDangerousKeys({ name: 'John', __proto__: {}, valid: true });
|
|
95
|
+
* // { name: 'John', valid: true }
|
|
96
|
+
*
|
|
97
|
+
* FilterDangerousKeys({ a: 1, constructor: 'bad', b: 2 });
|
|
98
|
+
* // { a: 1, b: 2 }
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export declare function FilterDangerousKeys<T extends Record<string, unknown>>(obj: T): Partial<T>;
|
|
102
|
+
/**
|
|
103
|
+
* Interface for circular reference detection utility
|
|
104
|
+
*
|
|
105
|
+
* Provides methods to track visited objects during recursive traversal,
|
|
106
|
+
* enabling detection and handling of circular references in object graphs.
|
|
107
|
+
*
|
|
108
|
+
* @remarks
|
|
109
|
+
* Uses a WeakSet internally for memory-efficient object tracking. Suitable for
|
|
110
|
+
* single-threaded traversal; not thread-safe for concurrent use.
|
|
111
|
+
*/
|
|
112
|
+
export interface ICircularReferenceDetector {
|
|
113
|
+
/**
|
|
114
|
+
* Marks an object as visited
|
|
115
|
+
* @param obj - Object to mark as visited
|
|
116
|
+
*/
|
|
117
|
+
markVisited(obj: object): void;
|
|
118
|
+
/**
|
|
119
|
+
* Checks if an object has been visited (circular reference indicator)
|
|
120
|
+
* @param obj - Object to check
|
|
121
|
+
* @returns True if object was already marked as visited
|
|
122
|
+
*/
|
|
123
|
+
isVisited(obj: object): boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Clears all visited object entries, resetting the detector
|
|
126
|
+
*/
|
|
127
|
+
clear(): void;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Creates a circular reference detection utility using WeakSet
|
|
131
|
+
*
|
|
132
|
+
* Provides an efficient way to track visited objects during recursive traversal
|
|
133
|
+
* of object graphs, enabling detection and handling of circular references.
|
|
134
|
+
* The internal WeakSet allows garbage collection of visited objects when they
|
|
135
|
+
* are no longer referenced elsewhere.
|
|
136
|
+
*
|
|
137
|
+
* @returns An {@link ICircularReferenceDetector} instance with methods to track visited objects
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* // Create detector once and reuse across multiple calls:
|
|
142
|
+
* const detector = CreateCircularReferenceDetector();
|
|
143
|
+
*
|
|
144
|
+
* function traverse(obj: unknown): void {
|
|
145
|
+
* if (typeof obj !== 'object' || obj === null) return;
|
|
146
|
+
*
|
|
147
|
+
* if (detector.isVisited(obj)) {
|
|
148
|
+
* console.log('Circular reference detected!');
|
|
149
|
+
* return;
|
|
150
|
+
* }
|
|
151
|
+
*
|
|
152
|
+
* detector.markVisited(obj);
|
|
153
|
+
* // Process obj...
|
|
154
|
+
* }
|
|
155
|
+
*
|
|
156
|
+
* for (const obj of objects) {
|
|
157
|
+
* detector.clear(); // Reset between unrelated traversals
|
|
158
|
+
* traverse(obj);
|
|
159
|
+
* }
|
|
160
|
+
* ```
|
|
161
|
+
*
|
|
162
|
+
* @remarks
|
|
163
|
+
* Do NOT create a new detector inside a loop for each object. Create once and reuse,
|
|
164
|
+
* calling `clear()` between unrelated traversals. Each call to this function creates
|
|
165
|
+
* a new WeakSet instance, so reusing is more efficient.
|
|
166
|
+
*/
|
|
167
|
+
export declare function CreateCircularReferenceDetector(): ICircularReferenceDetector;
|
|
168
|
+
/**
|
|
169
|
+
* Validates input for common security issues
|
|
170
|
+
*
|
|
171
|
+
* Checks for:
|
|
172
|
+
* - String length exceeding `maxLength` (default: 10,000 chars) to prevent DoS
|
|
173
|
+
* - Path traversal patterns: `..`, encoded variants, null bytes, unicode attacks
|
|
174
|
+
* - Null/undefined are considered safe (falsy validation only)
|
|
175
|
+
*
|
|
176
|
+
* Designed primarily for property path validation in `ObjectSetPropertyByPath` and
|
|
177
|
+
* related functions. Not a general-purpose string validator.
|
|
178
|
+
*
|
|
179
|
+
* @param input - Input to validate (typically a property path or key string)
|
|
180
|
+
* @param maxLength - Maximum allowed string length in characters (default: 10,000)
|
|
181
|
+
* @returns True if input is safe, false if it exceeds length or contains attack patterns
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```typescript
|
|
185
|
+
* IsInputSafe('user.profile.name'); // true
|
|
186
|
+
* IsInputSafe('user..name'); // false (path traversal)
|
|
187
|
+
* IsInputSafe('a'.repeat(20000)); // false (exceeds default length)
|
|
188
|
+
* IsInputSafe(null); // true (null is safe)
|
|
189
|
+
* IsInputSafe('%2e%2e'); // false (encoded traversal)
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
export declare function IsInputSafe(input: unknown, maxLength?: number): boolean;
|
|
193
|
+
//# sourceMappingURL=security-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security-utils.d.ts","sourceRoot":"","sources":["../../src/object/security-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA+CH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAkBtD;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAkBxD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAO9D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAUzF;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,0BAA0B;IAC1C;;;OAGG;IACH,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/B;;;;OAIG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAEhC;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,+BAA+B,IAAI,0BAA0B,CA6B5E;AAKD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,GAAE,MAAiC,GAAG,OAAO,CAqBjG"}
|