@ezez/utils 3.0.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/dist/cap.js.map +1 -1
- package/dist/coalesce.d.ts.map +1 -1
- package/dist/coalesce.js.map +1 -1
- package/dist/compareArrays.d.ts.map +1 -1
- package/dist/compareProps.d.ts.map +1 -1
- package/dist/compareProps.js.map +1 -1
- package/dist/deserialize.d.ts.map +1 -1
- package/dist/deserialize.js.map +1 -1
- package/dist/ensureArray.d.ts.map +1 -1
- package/dist/ensureArray.js.map +1 -1
- package/dist/ensureDate.js.map +1 -1
- package/dist/ensureError.js.map +1 -1
- package/dist/ensurePrefix.js.map +1 -1
- package/dist/ensureSuffix.js.map +1 -1
- package/dist/ensureTimestamp.js.map +1 -1
- package/dist/escapeRegExp.d.ts.map +1 -1
- package/dist/escapeRegExp.js +1 -1
- package/dist/escapeRegExp.js.map +1 -1
- package/dist/formatDate.js +1 -1
- package/dist/formatDate.js.map +1 -1
- package/dist/get.js.map +1 -1
- package/dist/getMultiple.d.ts.map +1 -1
- package/dist/getMultiple.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/insertSeparator.d.ts.map +1 -1
- package/dist/insertSeparator.js.map +1 -1
- package/dist/isEmpty.js.map +1 -1
- package/dist/isNumericString.js +1 -1
- package/dist/isNumericString.js.map +1 -1
- package/dist/last.d.ts.map +1 -1
- package/dist/later.d.ts.map +1 -1
- package/dist/mapAsync.d.ts.map +1 -1
- package/dist/mapAsync.js.map +1 -1
- package/dist/mapValues.d.ts.map +1 -1
- package/dist/mapValues.js.map +1 -1
- package/dist/match.d.ts.map +1 -1
- package/dist/match.js.map +1 -1
- package/dist/memoize.d.ts +3 -0
- package/dist/memoize.d.ts.map +1 -0
- package/dist/memoize.js +19 -0
- package/dist/memoize.js.map +1 -0
- package/dist/merge.d.ts +11 -7
- package/dist/merge.d.ts.map +1 -1
- package/dist/merge.js.map +1 -1
- package/dist/mostFrequent.d.ts.map +1 -1
- package/dist/mostFrequent.js.map +1 -1
- package/dist/occurrences.js.map +1 -1
- package/dist/omit.d.ts +1 -1
- package/dist/omit.d.ts.map +1 -1
- package/dist/omit.js.map +1 -1
- package/dist/pick.d.ts.map +1 -1
- package/dist/pick.js.map +1 -1
- package/dist/pull.d.ts.map +1 -1
- package/dist/pull.js.map +1 -1
- package/dist/remove.d.ts.map +1 -1
- package/dist/remove.js +1 -1
- package/dist/remove.js.map +1 -1
- package/dist/removeCommonProperties.d.ts.map +1 -1
- package/dist/removeCommonProperties.js +3 -1
- package/dist/removeCommonProperties.js.map +1 -1
- package/dist/replace.js +1 -1
- package/dist/replace.js.map +1 -1
- package/dist/replaceDeep.d.ts +5 -1
- package/dist/replaceDeep.d.ts.map +1 -1
- package/dist/replaceDeep.js +3 -20
- package/dist/replaceDeep.js.map +1 -1
- package/dist/replaceDeepByFn.d.ts +7 -0
- package/dist/replaceDeepByFn.d.ts.map +1 -0
- package/dist/replaceDeepByFn.js +47 -0
- package/dist/replaceDeepByFn.js.map +1 -0
- package/dist/safe.js.map +1 -1
- package/dist/sample.d.ts +3 -1
- package/dist/sample.d.ts.map +1 -1
- package/dist/sample.js.map +1 -1
- package/dist/samples.d.ts.map +1 -1
- package/dist/samples.js.map +1 -1
- package/dist/seq.d.ts.map +1 -1
- package/dist/seq.js +1 -1
- package/dist/seq.js.map +1 -1
- package/dist/serialize.d.ts.map +1 -1
- package/dist/serialize.js +56 -18
- package/dist/serialize.js.map +1 -1
- package/dist/set.js.map +1 -1
- package/dist/setImmutable.js.map +1 -1
- package/dist/shuffle.d.ts.map +1 -1
- package/dist/sortBy.d.ts.map +1 -1
- package/dist/sortBy.js.map +1 -1
- package/dist/sortProps.d.ts.map +1 -1
- package/dist/sortProps.js.map +1 -1
- package/dist/stripPrefix.js.map +1 -1
- package/dist/stripSuffix.js.map +1 -1
- package/dist/throttle.d.ts.map +1 -1
- package/dist/throttle.js.map +1 -1
- package/dist/toggle.d.ts.map +1 -1
- package/dist/toggle.js.map +1 -1
- package/dist/trim.d.ts +3 -0
- package/dist/trim.d.ts.map +1 -0
- package/dist/trim.js +10 -0
- package/dist/trim.js.map +1 -0
- package/dist/trimEnd.d.ts +3 -0
- package/dist/trimEnd.d.ts.map +1 -0
- package/dist/trimEnd.js +12 -0
- package/dist/trimEnd.js.map +1 -0
- package/dist/trimStart.d.ts +3 -0
- package/dist/trimStart.d.ts.map +1 -0
- package/dist/trimStart.js +12 -0
- package/dist/trimStart.js.map +1 -0
- package/dist/truthy.d.ts +1 -1
- package/dist/truthy.d.ts.map +1 -1
- package/dist/unique.d.ts.map +1 -1
- package/dist/utils/utils.d.ts +6 -0
- package/dist/utils/utils.d.ts.map +1 -0
- package/dist/utils/utils.js +10 -0
- package/dist/utils/utils.js.map +1 -0
- package/dist/waitFor.d.ts.map +1 -1
- package/dist/waitFor.js +1 -1
- package/dist/waitFor.js.map +1 -1
- package/dist/waitSync.js.map +1 -1
- package/docs/assets/icons.js +15 -0
- package/docs/assets/icons.svg +1 -0
- package/docs/assets/main.js +4 -3
- package/docs/assets/navigation.js +1 -0
- package/docs/assets/search.js +1 -1
- package/docs/assets/style.css +544 -394
- package/docs/documents/CHANGELOG.html +337 -0
- package/docs/functions/index.cap.html +5 -0
- package/docs/functions/index.capitalize.html +13 -0
- package/docs/functions/index.coalesce.html +16 -0
- package/docs/functions/index.compareArrays.html +8 -0
- package/docs/functions/index.compareProps.html +11 -0
- package/docs/functions/index.deserialize.html +6 -0
- package/docs/functions/index.ensureArray.html +3 -0
- package/docs/functions/index.ensureDate.html +10 -0
- package/docs/functions/index.ensureError.html +14 -0
- package/docs/functions/index.ensurePrefix.html +10 -0
- package/docs/functions/index.ensureSuffix.html +10 -0
- package/docs/functions/index.ensureTimestamp.html +10 -0
- package/docs/functions/index.escapeRegExp.html +7 -0
- package/docs/functions/index.formatDate.html +6 -0
- package/docs/functions/index.get.html +26 -0
- package/docs/functions/index.getMultiple.html +16 -0
- package/docs/functions/index.insertSeparator.html +7 -0
- package/docs/functions/index.isEmpty.html +33 -0
- package/docs/functions/index.isNumericString.html +5 -0
- package/docs/functions/index.isPlainObject.html +18 -0
- package/docs/functions/index.last.html +15 -0
- package/docs/functions/index.later-1.html +6 -0
- package/docs/functions/index.mapAsync.html +8 -0
- package/docs/functions/index.mapValues.html +14 -0
- package/docs/functions/index.match.html +4 -0
- package/docs/functions/index.memoize.html +8 -0
- package/docs/functions/index.merge.html +13 -0
- package/docs/functions/index.mostFrequent.html +2 -0
- package/docs/functions/index.noop.html +2 -0
- package/docs/functions/index.occurrences.html +14 -0
- package/docs/functions/index.omit.html +18 -0
- package/docs/functions/index.pick.html +13 -0
- package/docs/functions/index.pull.html +2 -0
- package/docs/functions/index.remove.html +2 -0
- package/docs/functions/index.removeCommonProperties.html +18 -0
- package/docs/functions/index.replace.html +10 -0
- package/docs/functions/index.replaceDeep.html +15 -0
- package/docs/functions/index.rethrow.html +2 -0
- package/docs/functions/index.round.html +7 -0
- package/docs/functions/index.safe.html +7 -0
- package/docs/functions/index.sample.html +6 -0
- package/docs/functions/index.samples.html +7 -0
- package/docs/functions/index.scale.html +5 -0
- package/docs/functions/index.seq.html +17 -0
- package/docs/functions/index.seqEarlyBreak.html +12 -0
- package/docs/functions/index.serialize.html +14 -0
- package/docs/functions/index.set.html +26 -0
- package/docs/functions/index.setImmutable.html +25 -0
- package/docs/functions/index.shuffle.html +3 -0
- package/docs/functions/index.sortBy.html +6 -0
- package/docs/functions/index.sortProps.html +10 -0
- package/docs/functions/index.stripPrefix.html +4 -0
- package/docs/functions/index.stripSuffix.html +4 -0
- package/docs/functions/index.throttle.html +14 -0
- package/docs/functions/index.toggle.html +5 -0
- package/docs/functions/index.trim.html +8 -0
- package/docs/functions/index.trimEnd.html +8 -0
- package/docs/functions/index.trimStart.html +8 -0
- package/docs/functions/index.truthy.html +7 -0
- package/docs/functions/index.unique.html +6 -0
- package/docs/functions/index.wait.html +3 -0
- package/docs/functions/index.waitFor.html +10 -0
- package/docs/functions/index.waitSync.html +3 -0
- package/docs/index.html +18 -204
- package/docs/interfaces/index.ComparePropsOptions.html +5 -0
- package/docs/interfaces/index.GetMultipleSource.html +3 -0
- package/docs/interfaces/index.GetSource.html +3 -0
- package/docs/interfaces/index.IsNumericStringOptions.html +5 -0
- package/docs/interfaces/index.OccurencesOptions.html +3 -0
- package/docs/interfaces/index.SetImmutableSource.html +3 -0
- package/docs/interfaces/index.SetSource.html +3 -0
- package/docs/interfaces/index.ThrottleOptions.html +5 -0
- package/docs/interfaces/index.ThrottledFunctionExtras.html +5 -0
- package/docs/modules/index.html +86 -0
- package/docs/types/index.CustomDeserializers.html +1 -0
- package/docs/types/index.CustomSerializers.html +1 -0
- package/docs/types/index.Later.html +4 -0
- package/docs/types/index.MapValuesFn.html +14 -0
- package/docs/types/index.MatchCallback.html +1 -0
- package/docs/types/index.MergeTwo.html +3 -0
- package/docs/types/index.SeqEarlyBreaker.html +4 -0
- package/docs/types/index.SeqFn.html +3 -0
- package/docs/types/index.SeqFunctions.html +4 -0
- package/docs/types/index.SetImmutablePath.html +4 -0
- package/docs/types/index.ThrottledFunction.html +1 -0
- package/docs/variables/index.mapValuesUNSET.html +2 -0
- package/docs/variables/index.mergeUNSET.html +4 -0
- package/esm/cap.js.map +1 -1
- package/esm/coalesce.d.ts.map +1 -1
- package/esm/coalesce.js.map +1 -1
- package/esm/compareArrays.d.ts.map +1 -1
- package/esm/compareProps.d.ts.map +1 -1
- package/esm/compareProps.js.map +1 -1
- package/esm/deserialize.d.ts.map +1 -1
- package/esm/deserialize.js.map +1 -1
- package/esm/ensureArray.d.ts.map +1 -1
- package/esm/ensureArray.js.map +1 -1
- package/esm/ensureDate.js.map +1 -1
- package/esm/ensureError.js.map +1 -1
- package/esm/ensurePrefix.js.map +1 -1
- package/esm/ensureSuffix.js.map +1 -1
- package/esm/ensureTimestamp.js.map +1 -1
- package/esm/escapeRegExp.d.ts.map +1 -1
- package/esm/escapeRegExp.js +1 -1
- package/esm/escapeRegExp.js.map +1 -1
- package/esm/formatDate.js +1 -1
- package/esm/formatDate.js.map +1 -1
- package/esm/get.js.map +1 -1
- package/esm/getMultiple.d.ts.map +1 -1
- package/esm/getMultiple.js.map +1 -1
- package/esm/index.d.ts +4 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +4 -0
- package/esm/index.js.map +1 -1
- package/esm/insertSeparator.d.ts.map +1 -1
- package/esm/insertSeparator.js.map +1 -1
- package/esm/isEmpty.js.map +1 -1
- package/esm/isNumericString.js +1 -1
- package/esm/isNumericString.js.map +1 -1
- package/esm/last.d.ts.map +1 -1
- package/esm/later.d.ts.map +1 -1
- package/esm/mapAsync.d.ts.map +1 -1
- package/esm/mapAsync.js.map +1 -1
- package/esm/mapValues.d.ts.map +1 -1
- package/esm/mapValues.js.map +1 -1
- package/esm/match.d.ts.map +1 -1
- package/esm/match.js.map +1 -1
- package/esm/memoize.d.ts +3 -0
- package/esm/memoize.d.ts.map +1 -0
- package/esm/memoize.js +16 -0
- package/esm/memoize.js.map +1 -0
- package/esm/merge.d.ts +11 -7
- package/esm/merge.d.ts.map +1 -1
- package/esm/merge.js.map +1 -1
- package/esm/mostFrequent.d.ts.map +1 -1
- package/esm/mostFrequent.js.map +1 -1
- package/esm/occurrences.js.map +1 -1
- package/esm/omit.d.ts +1 -1
- package/esm/omit.d.ts.map +1 -1
- package/esm/omit.js.map +1 -1
- package/esm/pick.d.ts.map +1 -1
- package/esm/pick.js.map +1 -1
- package/esm/pull.d.ts.map +1 -1
- package/esm/pull.js.map +1 -1
- package/esm/remove.d.ts.map +1 -1
- package/esm/remove.js +1 -1
- package/esm/remove.js.map +1 -1
- package/esm/removeCommonProperties.d.ts.map +1 -1
- package/esm/removeCommonProperties.js +3 -1
- package/esm/removeCommonProperties.js.map +1 -1
- package/esm/replace.js +1 -1
- package/esm/replace.js.map +1 -1
- package/esm/replaceDeep.d.ts +5 -1
- package/esm/replaceDeep.d.ts.map +1 -1
- package/esm/replaceDeep.js +3 -20
- package/esm/replaceDeep.js.map +1 -1
- package/esm/replaceDeepByFn.d.ts +7 -0
- package/esm/replaceDeepByFn.d.ts.map +1 -0
- package/esm/replaceDeepByFn.js +44 -0
- package/esm/replaceDeepByFn.js.map +1 -0
- package/esm/safe.js.map +1 -1
- package/esm/sample.d.ts +3 -1
- package/esm/sample.d.ts.map +1 -1
- package/esm/sample.js.map +1 -1
- package/esm/samples.d.ts.map +1 -1
- package/esm/samples.js.map +1 -1
- package/esm/seq.d.ts.map +1 -1
- package/esm/seq.js +1 -1
- package/esm/seq.js.map +1 -1
- package/esm/serialize.d.ts.map +1 -1
- package/esm/serialize.js +56 -18
- package/esm/serialize.js.map +1 -1
- package/esm/set.js.map +1 -1
- package/esm/setImmutable.js.map +1 -1
- package/esm/shuffle.d.ts.map +1 -1
- package/esm/sortBy.d.ts.map +1 -1
- package/esm/sortBy.js.map +1 -1
- package/esm/sortProps.d.ts.map +1 -1
- package/esm/sortProps.js.map +1 -1
- package/esm/stripPrefix.js.map +1 -1
- package/esm/stripSuffix.js.map +1 -1
- package/esm/throttle.d.ts.map +1 -1
- package/esm/throttle.js.map +1 -1
- package/esm/toggle.d.ts.map +1 -1
- package/esm/toggle.js.map +1 -1
- package/esm/trim.d.ts +3 -0
- package/esm/trim.d.ts.map +1 -0
- package/esm/trim.js +7 -0
- package/esm/trim.js.map +1 -0
- package/esm/trimEnd.d.ts +3 -0
- package/esm/trimEnd.d.ts.map +1 -0
- package/esm/trimEnd.js +9 -0
- package/esm/trimEnd.js.map +1 -0
- package/esm/trimStart.d.ts +3 -0
- package/esm/trimStart.d.ts.map +1 -0
- package/esm/trimStart.js +9 -0
- package/esm/trimStart.js.map +1 -0
- package/esm/truthy.d.ts +1 -1
- package/esm/truthy.d.ts.map +1 -1
- package/esm/unique.d.ts.map +1 -1
- package/esm/utils/utils.d.ts +6 -0
- package/esm/utils/utils.d.ts.map +1 -0
- package/esm/utils/utils.js +7 -0
- package/esm/utils/utils.js.map +1 -0
- package/esm/waitFor.d.ts.map +1 -1
- package/esm/waitFor.js +1 -1
- package/esm/waitFor.js.map +1 -1
- package/esm/waitSync.js.map +1 -1
- package/package.json +10 -17
- package/pnpm-lock.yaml +661 -386
- package/src/compareProps.ts +9 -2
- package/src/deserialize.spec.ts +13 -0
- package/src/escapeRegExp.spec.ts +5 -3
- package/src/escapeRegExp.ts +3 -2
- package/src/formatDate.ts +2 -2
- package/src/get.spec.ts +1 -0
- package/src/getMultiple.ts +1 -0
- package/src/index.ts +4 -0
- package/src/isNumericString.ts +3 -3
- package/src/memoize.spec.ts +90 -0
- package/src/memoize.ts +35 -0
- package/src/merge.ts +30 -8
- package/src/mostFrequent.ts +1 -0
- package/src/omit.ts +8 -2
- package/src/pick.ts +1 -1
- package/src/remove.ts +1 -1
- package/src/removeCommonProperties.ts +4 -2
- package/src/replace.ts +1 -1
- package/src/replaceDeep.spec.ts +91 -0
- package/src/replaceDeep.ts +22 -27
- package/src/replaceDeepByFn.spec.ts +162 -0
- package/src/replaceDeepByFn.ts +93 -0
- package/src/rethrow.ts +1 -1
- package/src/sample.spec.ts +1 -0
- package/src/sample.ts +18 -2
- package/src/samples.ts +1 -1
- package/src/seq.spec.ts +6 -3
- package/src/seq.ts +1 -1
- package/src/serialize.spec.ts +43 -0
- package/src/serialize.ts +66 -19
- package/src/set.ts +1 -1
- package/src/setImmutable.ts +1 -1
- package/src/sortBy.ts +1 -1
- package/src/throttle.ts +1 -1
- package/src/trim.spec.ts +22 -0
- package/src/trim.ts +23 -0
- package/src/trimEnd.spec.ts +20 -0
- package/src/trimEnd.ts +22 -0
- package/src/trimStart.spec.ts +20 -0
- package/src/trimStart.ts +22 -0
- package/src/utils/utils.ts +11 -0
- package/src/waitFor.spec.ts +7 -2
- package/src/waitFor.ts +1 -1
- package/typedoc.cjs +2 -4
- package/docs/assets/pages.css +0 -14
- package/docs/functions/cap.html +0 -149
- package/docs/functions/capitalize.html +0 -154
- package/docs/functions/coalesce.html +0 -159
- package/docs/functions/compareArrays.html +0 -162
- package/docs/functions/compareProps.html +0 -161
- package/docs/functions/deserialize.html +0 -153
- package/docs/functions/ensureArray.html +0 -147
- package/docs/functions/ensureDate.html +0 -149
- package/docs/functions/ensureError.html +0 -153
- package/docs/functions/ensurePrefix.html +0 -151
- package/docs/functions/ensureSuffix.html +0 -151
- package/docs/functions/ensureTimestamp.html +0 -149
- package/docs/functions/escapeRegExp.html +0 -145
- package/docs/functions/formatDate.html +0 -147
- package/docs/functions/get.html +0 -171
- package/docs/functions/getMultiple.html +0 -162
- package/docs/functions/insertSeparator.html +0 -156
- package/docs/functions/isEmpty.html +0 -172
- package/docs/functions/isNumericString.html +0 -146
- package/docs/functions/isPlainObject.html +0 -156
- package/docs/functions/last.html +0 -159
- package/docs/functions/later-1.html +0 -144
- package/docs/functions/mapAsync.html +0 -177
- package/docs/functions/mapValues.html +0 -163
- package/docs/functions/match.html +0 -155
- package/docs/functions/merge.html +0 -497
- package/docs/functions/mostFrequent.html +0 -144
- package/docs/functions/noop.html +0 -134
- package/docs/functions/occurrences.html +0 -158
- package/docs/functions/omit.html +0 -162
- package/docs/functions/pick.html +0 -162
- package/docs/functions/pull.html +0 -146
- package/docs/functions/remove.html +0 -162
- package/docs/functions/removeCommonProperties.html +0 -161
- package/docs/functions/replace.html +0 -151
- package/docs/functions/replaceDeep.html +0 -158
- package/docs/functions/rethrow.html +0 -139
- package/docs/functions/round.html +0 -148
- package/docs/functions/safe.html +0 -189
- package/docs/functions/sample.html +0 -146
- package/docs/functions/samples.html +0 -156
- package/docs/functions/scale.html +0 -150
- package/docs/functions/seq.html +0 -161
- package/docs/functions/seqEarlyBreak.html +0 -159
- package/docs/functions/serialize.html +0 -158
- package/docs/functions/set.html +0 -171
- package/docs/functions/setImmutable.html +0 -170
- package/docs/functions/shuffle.html +0 -146
- package/docs/functions/sortBy.html +0 -168
- package/docs/functions/sortProps.html +0 -156
- package/docs/functions/stripPrefix.html +0 -145
- package/docs/functions/stripSuffix.html +0 -145
- package/docs/functions/throttle.html +0 -164
- package/docs/functions/toggle.html +0 -151
- package/docs/functions/truthy.html +0 -151
- package/docs/functions/unique.html +0 -149
- package/docs/functions/wait.html +0 -142
- package/docs/functions/waitFor.html +0 -161
- package/docs/functions/waitSync.html +0 -142
- package/docs/interfaces/ComparePropsOptions.html +0 -70
- package/docs/interfaces/GetMultipleSource.html +0 -139
- package/docs/interfaces/GetSource.html +0 -139
- package/docs/interfaces/IsNumericStringOptions.html +0 -91
- package/docs/interfaces/OccurencesOptions.html +0 -72
- package/docs/interfaces/SetImmutableSource.html +0 -139
- package/docs/interfaces/SetSource.html +0 -139
- package/docs/interfaces/ThrottleOptions.html +0 -81
- package/docs/interfaces/ThrottledFunctionExtras.html +0 -97
- package/docs/modules.html +0 -217
- package/docs/pages/CHANGELOG.html +0 -924
- package/docs/pages/Introduction.html +0 -127
- package/docs/types/CustomDeserializers.html +0 -156
- package/docs/types/CustomSerializers.html +0 -156
- package/docs/types/Later.html +0 -170
- package/docs/types/MapValuesFn.html +0 -167
- package/docs/types/MatchCallback.html +0 -146
- package/docs/types/SeqEarlyBreaker.html +0 -147
- package/docs/types/SeqFn.html +0 -145
- package/docs/types/SeqFunctions.html +0 -138
- package/docs/types/SetImmutablePath.html +0 -132
- package/docs/types/ThrottledFunction.html +0 -146
- package/docs/variables/mapValuesUNSET.html +0 -134
- package/docs/variables/mergeUNSET.html +0 -136
- package/tutorials/Introduction.md +0 -1
package/src/compareProps.ts
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import { unique } from "./unique.js";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Options for `compareProps` function.
|
|
5
|
+
*/
|
|
3
6
|
interface ComparePropsOptions {
|
|
7
|
+
/**
|
|
8
|
+
* If `true`, missing properties in the first object will be considered as equal to explicit `undefined` properties
|
|
9
|
+
* in the second.
|
|
10
|
+
*/
|
|
4
11
|
missingEqualsUndefined?: boolean;
|
|
5
12
|
}
|
|
6
13
|
|
|
7
14
|
/**
|
|
8
15
|
* Compare two objects and return an array of the properties that are different.
|
|
9
|
-
* By default, if first object doesn't have a property at all and second object has it defined as `undefined`
|
|
10
|
-
* considered as a difference. To change this behavior set `missingEqualsUndefined` option to `true`.
|
|
16
|
+
* By default, if the first object doesn't have a property at all and the second object has it defined as `undefined`
|
|
17
|
+
* this will be considered as a difference. To change this behavior, set `missingEqualsUndefined` option to `true`.
|
|
11
18
|
* @param a - first object
|
|
12
19
|
* @param b - second object
|
|
13
20
|
* @param options - options
|
package/src/deserialize.spec.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { deserialize } from "./deserialize";
|
|
|
5
5
|
class Person {
|
|
6
6
|
public name: string;
|
|
7
7
|
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
8
9
|
public constructor(name: string) {
|
|
9
10
|
this.name = name;
|
|
10
11
|
}
|
|
@@ -66,4 +67,16 @@ describe("deserialize", () => {
|
|
|
66
67
|
it("throws on unknown data type", () => {
|
|
67
68
|
must(() => deserialize(`"v:test"`)).throw("Unsupported data type: v");
|
|
68
69
|
});
|
|
70
|
+
|
|
71
|
+
it("supports deserializers with things like Date", async () => {
|
|
72
|
+
const customSerializers: CustomDeserializers = {
|
|
73
|
+
D: (value) => {
|
|
74
|
+
return new Date(Number(value));
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const result = deserialize(`"D:1714398481437"`, customSerializers);
|
|
79
|
+
must(result).be.instanceof(Date);
|
|
80
|
+
must(result.getTime()).equal(1714398481437);
|
|
81
|
+
});
|
|
69
82
|
});
|
package/src/escapeRegExp.spec.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { escapeRegExp } from "./escapeRegExp.js";
|
|
|
3
3
|
describe("escapeRegExp", () => {
|
|
4
4
|
it("it should escape dot", () => {
|
|
5
5
|
const userName = ".";
|
|
6
|
-
const regex = new RegExp(`^(maciek|${escapeRegExp(userName)})
|
|
6
|
+
const regex = new RegExp(`^(maciek|${escapeRegExp(userName)})$`, "u");
|
|
7
7
|
const result = regex.test("maciek");
|
|
8
8
|
result.must.be.true();
|
|
9
9
|
|
|
@@ -22,10 +22,12 @@ describe("escapeRegExp", () => {
|
|
|
22
22
|
|
|
23
23
|
it("should escape complex string", () => {
|
|
24
24
|
const userName = "([{^|";
|
|
25
|
-
const fn = () => new RegExp(`^(maciek|${escapeRegExp(userName)})
|
|
25
|
+
const fn = () => new RegExp(`^(maciek|${escapeRegExp(userName)})$`, "u");
|
|
26
26
|
fn.must.not.throw();
|
|
27
27
|
|
|
28
|
-
const fnNoEscape = () => new RegExp(`^(maciek|${userName})
|
|
28
|
+
const fnNoEscape = () => new RegExp(`^(maciek|${userName})$`, "u");
|
|
29
29
|
fnNoEscape.must.throw();
|
|
30
30
|
});
|
|
31
|
+
|
|
32
|
+
// @TODO add tests for missing u flag, test if this flag changed anything in fn behavior
|
|
31
33
|
});
|
package/src/escapeRegExp.ts
CHANGED
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
* Escapes a string to be used in a regular expression.
|
|
3
3
|
* From: https://stackoverflow.com/a/3561711
|
|
4
4
|
* @param string - string to escape
|
|
5
|
-
* @example
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
6
7
|
* const badName = "([{^|";
|
|
7
8
|
* const regex = new RegExp(`^(maciek|${escapeRegExp(badName)})$`); // won't crash
|
|
8
9
|
* regex.test(badName); // true
|
|
9
10
|
* ```
|
|
10
11
|
*/
|
|
11
12
|
const escapeRegExp = (string: string) => {
|
|
12
|
-
return string.replace(/[/\-\\^$*+?.()|[\]{}]/
|
|
13
|
+
return string.replace(/[/\-\\^$*+?.()|[\]{}]/gu, "\\$&");
|
|
13
14
|
};
|
|
14
15
|
|
|
15
16
|
export {
|
package/src/formatDate.ts
CHANGED
|
@@ -9,9 +9,9 @@ import { ensureDate } from "./ensureDate.js";
|
|
|
9
9
|
* Important: this is work in progress. All locale-based values are not supported yet. Formats that heavily depend on
|
|
10
10
|
* locale won't ever be supported.
|
|
11
11
|
*/
|
|
12
|
-
const formatDate = (date: Date | number, format: string, locale = "en-US"): string => { // eslint-disable-line max-lines-per-function
|
|
12
|
+
const formatDate = (date: Date | number, format: string, locale = "en-US"): string => { // eslint-disable-line max-lines-per-function
|
|
13
13
|
const d = ensureDate(date);
|
|
14
|
-
return format.replace(/%([%a-zA-Z])/
|
|
14
|
+
return format.replace(/%([%a-zA-Z])/gu, (_, c) => {
|
|
15
15
|
switch (c) {
|
|
16
16
|
case "%": return "%";
|
|
17
17
|
// Day
|
package/src/get.spec.ts
CHANGED
|
@@ -55,6 +55,7 @@ describe("get", () => {
|
|
|
55
55
|
|
|
56
56
|
it("doesn't parse string as js code, behaves NOT like lodash", () => {
|
|
57
57
|
// Lodash intention-guessing example, inconsistency detected
|
|
58
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
58
59
|
const name = get(testObject, "product[name]");
|
|
59
60
|
(name === undefined).must.be.true();
|
|
60
61
|
|
package/src/getMultiple.ts
CHANGED
|
@@ -29,6 +29,7 @@ const DEFAULT = {};
|
|
|
29
29
|
* @returns {*} - found value or default value
|
|
30
30
|
*/
|
|
31
31
|
const getMultiple = (source: Source, defaultValue: unknown, ...paths: (string | string[])[]): unknown => {
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
32
33
|
const length = paths.length;
|
|
33
34
|
for (let i = 0; i < length; i++) {
|
|
34
35
|
const properties = paths[i]!;
|
package/src/index.ts
CHANGED
|
@@ -24,6 +24,7 @@ export * from "./later.js";
|
|
|
24
24
|
export * from "./mapAsync.js";
|
|
25
25
|
export * from "./mapValues.js";
|
|
26
26
|
export * from "./match.js";
|
|
27
|
+
export * from "./memoize.js";
|
|
27
28
|
export * from "./merge.js";
|
|
28
29
|
export * from "./mostFrequent.js";
|
|
29
30
|
export * from "./noop.js";
|
|
@@ -52,6 +53,9 @@ export * from "./stripPrefix.js";
|
|
|
52
53
|
export * from "./stripSuffix.js";
|
|
53
54
|
export * from "./throttle.js";
|
|
54
55
|
export * from "./toggle.js";
|
|
56
|
+
export * from "./trim.js";
|
|
57
|
+
export * from "./trimEnd.js";
|
|
58
|
+
export * from "./trimStart.js";
|
|
55
59
|
export * from "./truthy.js";
|
|
56
60
|
export * from "./unique.js";
|
|
57
61
|
export * from "./wait.js";
|
package/src/isNumericString.ts
CHANGED
|
@@ -14,10 +14,10 @@ const NOT_FOUND = -1;
|
|
|
14
14
|
* @param {object} [options] - Options object
|
|
15
15
|
* @param {boolean} [options.allowFloats=false] - Allow floats
|
|
16
16
|
* @param {boolean} [options.allowExponents=false] - Allow exponents
|
|
17
|
-
* @param {boolean} [options.allowInfinity=false] - Allow
|
|
17
|
+
* @param {boolean} [options.allowInfinity=false] - Allow Infinity and -Infinity (casing matters)
|
|
18
18
|
* @param {boolean} [options.allowNaN=false] - Allow NaN (casing matters)
|
|
19
19
|
*/
|
|
20
|
-
const isNumericString = (string: string, options: Options = {}) => { // eslint-disable-line max-statements, max-lines-per-function
|
|
20
|
+
const isNumericString = (string: string, options: Options = {}) => { // eslint-disable-line max-statements, max-lines-per-function
|
|
21
21
|
if (typeof string !== "string") {
|
|
22
22
|
throw new TypeError("Expected a string");
|
|
23
23
|
}
|
|
@@ -82,7 +82,7 @@ const isNumericString = (string: string, options: Options = {}) => { // eslint-d
|
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
return Boolean(/^[\de.+-]
|
|
85
|
+
return Boolean(/^[\de.+-]+$/u.exec(normalized));
|
|
86
86
|
};
|
|
87
87
|
|
|
88
88
|
export {
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
2
|
+
import must from "must";
|
|
3
|
+
|
|
4
|
+
import createSpy from "../test/createSpy";
|
|
5
|
+
|
|
6
|
+
import { memoize } from "./memoize";
|
|
7
|
+
|
|
8
|
+
describe("memoize", () => {
|
|
9
|
+
it("should memoize the result if called with the same arguments", async () => {
|
|
10
|
+
const sum = createSpy((a: number, b: number) => a + b);
|
|
11
|
+
const memoizedSum = memoize(sum);
|
|
12
|
+
|
|
13
|
+
must(memoizedSum(1, 2)).equal(3);
|
|
14
|
+
must(sum.__spy.calls.length).equal(1);
|
|
15
|
+
must(memoizedSum(1, 2)).equal(3);
|
|
16
|
+
must(memoizedSum(1, 2)).equal(3);
|
|
17
|
+
must(memoizedSum(1, 2)).equal(3);
|
|
18
|
+
must(sum.__spy.calls.length).equal(1);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should trigger the function again if arguments are changed", async () => {
|
|
22
|
+
const sum = createSpy((a: number, b: number) => a + b);
|
|
23
|
+
const memoizedSum = memoize(sum);
|
|
24
|
+
|
|
25
|
+
must(memoizedSum(1, 2)).equal(3);
|
|
26
|
+
must(sum.__spy.calls.length).equal(1);
|
|
27
|
+
must(memoizedSum(1, 2)).equal(3);
|
|
28
|
+
must(sum.__spy.calls.length).equal(1);
|
|
29
|
+
must(memoizedSum(1, 3)).equal(4);
|
|
30
|
+
must(sum.__spy.calls.length).equal(2);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("should remember only one value", () => {
|
|
34
|
+
const sum = createSpy((a: number, b: number) => a + b);
|
|
35
|
+
const memoizedSum = memoize(sum);
|
|
36
|
+
|
|
37
|
+
must(memoizedSum(1, 2)).equal(3);
|
|
38
|
+
must(sum.__spy.calls.length).equal(1);
|
|
39
|
+
must(memoizedSum(1, 2)).equal(3);
|
|
40
|
+
must(sum.__spy.calls.length).equal(1);
|
|
41
|
+
must(memoizedSum(1, 3)).equal(4);
|
|
42
|
+
must(sum.__spy.calls.length).equal(2);
|
|
43
|
+
must(memoizedSum(1, 2)).equal(3);
|
|
44
|
+
must(sum.__spy.calls.length).equal(3);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should recalc if arguments amount changes", async () => {
|
|
48
|
+
const sum = createSpy((a: number, b: number) => a + b);
|
|
49
|
+
const memoizedSum = memoize(sum);
|
|
50
|
+
|
|
51
|
+
must(memoizedSum(1, 2)).equal(3);
|
|
52
|
+
must(sum.__spy.calls.length).equal(1);
|
|
53
|
+
must(memoizedSum(1, 2, 0)).equal(3);
|
|
54
|
+
must(sum.__spy.calls.length).equal(2);
|
|
55
|
+
must(memoizedSum(1, 2)).equal(3);
|
|
56
|
+
must(sum.__spy.calls.length).equal(3);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("works with common pitfall values", async () => {
|
|
60
|
+
const sum = createSpy((a: number, b: number) => a + b);
|
|
61
|
+
const memoizedSum = memoize(sum);
|
|
62
|
+
|
|
63
|
+
memoizedSum(1, NaN);
|
|
64
|
+
must(sum.__spy.calls.length).equal(1);
|
|
65
|
+
memoizedSum(1, NaN);
|
|
66
|
+
must(sum.__spy.calls.length).equal(1);
|
|
67
|
+
|
|
68
|
+
memoizedSum(1, 0);
|
|
69
|
+
must(sum.__spy.calls.length).equal(2);
|
|
70
|
+
memoizedSum(1, -0);
|
|
71
|
+
must(sum.__spy.calls.length).equal(3);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("compares by reference", async () => {
|
|
75
|
+
const fn = createSpy((a: unknown) => null);
|
|
76
|
+
const memoizedFn = memoize(fn);
|
|
77
|
+
|
|
78
|
+
const arr: never[] = [];
|
|
79
|
+
|
|
80
|
+
memoizedFn([]);
|
|
81
|
+
must(fn.__spy.calls.length).equal(1);
|
|
82
|
+
memoizedFn([]);
|
|
83
|
+
must(fn.__spy.calls.length).equal(2);
|
|
84
|
+
|
|
85
|
+
memoizedFn(arr);
|
|
86
|
+
must(fn.__spy.calls.length).equal(3);
|
|
87
|
+
memoizedFn(arr);
|
|
88
|
+
must(fn.__spy.calls.length).equal(3);
|
|
89
|
+
});
|
|
90
|
+
});
|
package/src/memoize.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memoizes a function, caching the result of the last call.
|
|
3
|
+
* If the function is called with the same arguments (and the same context!) again, it will return the cached result.
|
|
4
|
+
*
|
|
5
|
+
* It caches only the last call, so it's not suitable for functions that are called with different arguments in a short
|
|
6
|
+
* time.
|
|
7
|
+
*
|
|
8
|
+
* Warning: Your function must be 100% pure, and it can't access anything dynamic outside its scope.
|
|
9
|
+
*
|
|
10
|
+
* @param fn - function to memoize
|
|
11
|
+
* @returns memoized function
|
|
12
|
+
*/
|
|
13
|
+
const memoize = <Args extends unknown[], Ret>(fn: (...args: Args) => Ret) => {
|
|
14
|
+
let lastArgs: Args | undefined, lastResult: Ret, lastThis: unknown;
|
|
15
|
+
|
|
16
|
+
return function memoized(this: unknown, ...args: Args): Ret {
|
|
17
|
+
if (
|
|
18
|
+
lastThis === this
|
|
19
|
+
&& lastArgs?.length === args.length
|
|
20
|
+
&& args.every((arg, i) => Object.is(arg, lastArgs![i]))
|
|
21
|
+
) {
|
|
22
|
+
return lastResult;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
lastThis = this;
|
|
26
|
+
lastArgs = args;
|
|
27
|
+
lastResult = fn.apply(this, args);
|
|
28
|
+
|
|
29
|
+
return lastResult;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
memoize,
|
|
35
|
+
};
|
package/src/merge.ts
CHANGED
|
@@ -1,19 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Special value that can be set as a value in an object.
|
|
3
|
-
* If this value is merged with previous value
|
|
3
|
+
* If this value is merged with the previous value, the property in a final object will be removed;
|
|
4
4
|
* @see {@link merge}
|
|
5
5
|
*/
|
|
6
6
|
const UNSET = typeof Symbol !== "undefined" ? Symbol("UNSET") : {};
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Merges two objects into one. If the same property is present in both objects, the value from the second object is
|
|
10
|
+
* used.
|
|
11
|
+
*/
|
|
12
|
+
type MergeTwo<T, U> = {
|
|
13
|
+
[K in keyof T | keyof U]: K extends keyof U
|
|
14
|
+
? U[K]
|
|
15
|
+
: K extends keyof T
|
|
16
|
+
? T[K]
|
|
17
|
+
: never;
|
|
18
|
+
};
|
|
19
|
+
|
|
8
20
|
interface Merge {
|
|
9
21
|
<A>(a: A): A;
|
|
10
|
-
<A, B>(a: A, b: B): A
|
|
11
|
-
<A, B, C>(a: A, b: B, c: C): A
|
|
12
|
-
<A, B, C, D>(a: A, b: B, c: C, d: D): A
|
|
13
|
-
<A, B, C, D, E>(a: A, b: B, c: C, d: D, e: E): A
|
|
14
|
-
<A, B, C, D, E, F>(a: A, b: B, c: C, d: D, e: E, f: F):
|
|
15
|
-
|
|
16
|
-
|
|
22
|
+
<A, B>(a: A, b: B): MergeTwo<A, B>;
|
|
23
|
+
<A, B, C>(a: A, b: B, c: C): MergeTwo<MergeTwo<A, B>, C>;
|
|
24
|
+
<A, B, C, D>(a: A, b: B, c: C, d: D): MergeTwo<MergeTwo<MergeTwo<A, B>, C>, D>;
|
|
25
|
+
<A, B, C, D, E>(a: A, b: B, c: C, d: D, e: E): MergeTwo<MergeTwo<MergeTwo<MergeTwo<A, B>, C>, D>, E>;
|
|
26
|
+
<A, B, C, D, E, F>(a: A, b: B, c: C, d: D, e: E, f: F): MergeTwo<
|
|
27
|
+
MergeTwo<MergeTwo<MergeTwo<MergeTwo<A, B>, C>, D>, E>, F
|
|
28
|
+
>;
|
|
29
|
+
<A, B, C, D, E, F, G>(a: A, b: B, c: C, d: D, e: E, f: F, g: G): MergeTwo<
|
|
30
|
+
MergeTwo<MergeTwo<MergeTwo<MergeTwo<MergeTwo<A, B>, C>, D>, E>, F>, G
|
|
31
|
+
>;
|
|
32
|
+
<A, B, C, D, E, F, G, H>(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H): MergeTwo<
|
|
33
|
+
MergeTwo<MergeTwo<MergeTwo<MergeTwo<MergeTwo<MergeTwo<A, B>, C>, D>, E>, F>, G>, H
|
|
34
|
+
>;
|
|
17
35
|
<A, B extends object>(a: A, ...args: B[]): unknown;
|
|
18
36
|
}
|
|
19
37
|
|
|
@@ -56,3 +74,7 @@ export {
|
|
|
56
74
|
merge,
|
|
57
75
|
UNSET as mergeUNSET,
|
|
58
76
|
};
|
|
77
|
+
|
|
78
|
+
export type {
|
|
79
|
+
MergeTwo,
|
|
80
|
+
};
|
package/src/mostFrequent.ts
CHANGED
package/src/omit.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
// TODO verify & maybe fix typings when object is an Array
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Returns
|
|
4
|
+
* Returns a cloned source object but without specified properties.
|
|
5
|
+
*
|
|
6
|
+
* TypeScript tip: if you want to omit properties that TS think does not exist in the object, call the function like
|
|
7
|
+
* that:
|
|
8
|
+
* ```typescript
|
|
9
|
+
* omit<Record<string, unknown>>(source, ["property"]);
|
|
10
|
+
* ```
|
|
5
11
|
*
|
|
6
12
|
* @param {Object} object - source object
|
|
7
13
|
* @param {Array.<string>} props - properties to skip
|
|
@@ -13,7 +19,7 @@
|
|
|
13
19
|
* // { 1: "world" }
|
|
14
20
|
* @returns {Object} - new object without given properties
|
|
15
21
|
*/
|
|
16
|
-
const omit = <T extends object, K extends keyof T>(
|
|
22
|
+
const omit = <T extends object, K extends keyof T = keyof T>(
|
|
17
23
|
object: T | null, props: K[],
|
|
18
24
|
): T extends null ? { [key: string]: never } : Omit<T, K> => {
|
|
19
25
|
if (!object || (typeof object !== "object" && typeof object !== "function")) {
|
package/src/pick.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// TODO verify & maybe fix typings when object is an Array
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Returns new object with
|
|
4
|
+
* Returns a new object with given properties copied from a source object.
|
|
5
5
|
*
|
|
6
6
|
* @param {Object} object - source object
|
|
7
7
|
* @param {Array.<string>} props - properties to copy
|
package/src/remove.ts
CHANGED
|
@@ -28,8 +28,10 @@ const removeCommonProperties = (source: Obj, target1: Obj, ...targetN: Obj[]) =>
|
|
|
28
28
|
for (const key of keys) {
|
|
29
29
|
const allTheSame = targets.every((target) => JSON.stringify(target[key]) === JSON.stringify(source[key]));
|
|
30
30
|
if (allTheSame) {
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
targets.forEach((target) => {
|
|
32
|
+
// eslint-disable-next-line no-param-reassign,@typescript-eslint/no-dynamic-delete
|
|
33
|
+
delete target[key];
|
|
34
|
+
});
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
};
|
package/src/replace.ts
CHANGED
|
@@ -12,7 +12,7 @@ const replace = (source: string, replaceMap: Record<string, string>) => {
|
|
|
12
12
|
if (keys.length === 0) {
|
|
13
13
|
return source;
|
|
14
14
|
}
|
|
15
|
-
const regex = new RegExp(keys.map(escapeRegExp).join("|"), "
|
|
15
|
+
const regex = new RegExp(keys.map(escapeRegExp).join("|"), "gu");
|
|
16
16
|
return source.replace(regex, (matched) => replaceMap[matched]!);
|
|
17
17
|
};
|
|
18
18
|
|
package/src/replaceDeep.spec.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { replaceDeep } from "./replaceDeep";
|
|
2
2
|
|
|
3
|
+
class MyClass {
|
|
4
|
+
public value: number;
|
|
5
|
+
|
|
6
|
+
public constructor(value: number) {
|
|
7
|
+
this.value = value;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
3
11
|
describe("replaceDeep", () => {
|
|
4
12
|
it("should replace given value in a deep object", () => {
|
|
5
13
|
const source = [
|
|
@@ -68,4 +76,87 @@ describe("replaceDeep", () => {
|
|
|
68
76
|
b: 123,
|
|
69
77
|
});
|
|
70
78
|
});
|
|
79
|
+
|
|
80
|
+
it("should allow to replace nils", async () => {
|
|
81
|
+
must(replaceDeep(null, null, 300)).equal(300);
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
|
|
83
|
+
must(replaceDeep(undefined, undefined, 300)).equal(300);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("does not mutate original object", () => {
|
|
87
|
+
const source = {
|
|
88
|
+
a: 1,
|
|
89
|
+
b: {
|
|
90
|
+
c: 2,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
const result = replaceDeep(source, 2, 3);
|
|
94
|
+
must(result).not.equal(source);
|
|
95
|
+
must(result.b).not.equal(source.b);
|
|
96
|
+
must(result).eql({
|
|
97
|
+
a: 1,
|
|
98
|
+
b: {
|
|
99
|
+
c: 3,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("does not mutate original array", async () => {
|
|
105
|
+
const source = [1, 2, 3, [2, 3]];
|
|
106
|
+
const result = replaceDeep(source, 2, 4);
|
|
107
|
+
must(result).not.equal(source);
|
|
108
|
+
must(result[3]).not.equal(source[3]);
|
|
109
|
+
must(result).eql([1, 4, 3, [4, 3]]);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("mutates original object when enabled", () => {
|
|
113
|
+
const source = {
|
|
114
|
+
a: 1,
|
|
115
|
+
b: {
|
|
116
|
+
c: 2,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
const result = replaceDeep(source, 2, 3, { mutate: true });
|
|
120
|
+
must(result).equal(source);
|
|
121
|
+
must(result.b).equal(source.b);
|
|
122
|
+
must(result).eql({
|
|
123
|
+
a: 1,
|
|
124
|
+
b: {
|
|
125
|
+
c: 3,
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("mutates original array when enabled", async () => {
|
|
131
|
+
const source = [1, 2, 3, [2, 3]];
|
|
132
|
+
const result = replaceDeep(source, 2, 4, { mutate: true });
|
|
133
|
+
must(result).equal(source);
|
|
134
|
+
must(result[3]).equal(source[3]);
|
|
135
|
+
must(result).eql([1, 4, 3, [4, 3]]);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it("does not get into instances by default", async () => {
|
|
139
|
+
const source = new MyClass(100);
|
|
140
|
+
const result = replaceDeep(source, 100, 200);
|
|
141
|
+
must(result).equal(source);
|
|
142
|
+
must(source.value).equal(100);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("gets into instances when allowed", async () => {
|
|
146
|
+
const source = new MyClass(100);
|
|
147
|
+
const result = replaceDeep(source, 100, 200, {
|
|
148
|
+
replaceInstancesProps: true,
|
|
149
|
+
mutate: true,
|
|
150
|
+
});
|
|
151
|
+
must(result).equal(source);
|
|
152
|
+
must(source.value).equal(200);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("requires `mutate` option if `replaceInstancesProps` is defined", async () => {
|
|
156
|
+
const source = new MyClass(100);
|
|
157
|
+
must(() => replaceDeep(source, 100, 200, {
|
|
158
|
+
replaceInstancesProps: true,
|
|
159
|
+
mutate: false,
|
|
160
|
+
})).throw("`replaceInstancesProps` option requires `mutate` to be enabled");
|
|
161
|
+
});
|
|
71
162
|
});
|
package/src/replaceDeep.ts
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
|
+
import { replaceDeepByFn } from "./replaceDeepByFn.js";
|
|
2
|
+
|
|
3
|
+
type Options = {
|
|
4
|
+
/**
|
|
5
|
+
* If true, the source objects and arrays will be mutated. Default is false.
|
|
6
|
+
*/
|
|
7
|
+
mutate?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* If true, the function will go into instances for replacement. Otherwise, it will only replace properties of plain
|
|
10
|
+
* objects. Default is false.
|
|
11
|
+
* Warning: This option requires `mutate` to be enabled, because we can't clone instances.
|
|
12
|
+
*/
|
|
13
|
+
replaceInstancesProps?: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
1
16
|
/**
|
|
2
17
|
* Replaces all occurrences of `search` with `value` in `source` object/array. Comparison is done with `Object.is`.
|
|
3
18
|
* If `source` is exactly the `search` a `value` will be returned. It does not do a substring replacements.
|
|
4
19
|
*
|
|
5
|
-
*
|
|
20
|
+
* Warnings:
|
|
21
|
+
* - By default, it does not mutate the `source`/deep objects/arrays, but it can be enabled with `mutate` option.
|
|
22
|
+
* - By default, it does not go into instances for replacement, only plain objects.
|
|
23
|
+
* - If your instances are cross-referenced, you may end up in an infinite loop.
|
|
6
24
|
*
|
|
7
25
|
* TypeScript users: This is way too dynamic to type properly, therefore, typing assumes the most basic form of
|
|
8
26
|
* replacement where search and value are of the same type. If that's not the case for you - you'll have to typecast.
|
|
@@ -10,33 +28,10 @@
|
|
|
10
28
|
* @param source - source object/array/value
|
|
11
29
|
* @param search - value to search for
|
|
12
30
|
* @param value - value to replace with
|
|
31
|
+
* @param options - optional options
|
|
13
32
|
*/
|
|
14
|
-
const replaceDeep = <T>(source: T, search: unknown, value: unknown): T => {
|
|
15
|
-
|
|
16
|
-
return value as T;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (source == null) {
|
|
20
|
-
return source;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (typeof source === "object") {
|
|
24
|
-
if (Array.isArray(source)) {
|
|
25
|
-
for (let i = 0; i < source.length; i++) {
|
|
26
|
-
// eslint-disable-next-line no-param-reassign,@typescript-eslint/no-unsafe-assignment
|
|
27
|
-
source[i] = replaceDeep(source[i], search, value);
|
|
28
|
-
}
|
|
29
|
-
return source;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return Object.keys(source).reduce<Record<string, unknown>>((acc, key) => {
|
|
33
|
-
// eslint-disable-next-line no-param-reassign
|
|
34
|
-
acc[key] = replaceDeep((source as Record<string, unknown>)[key], search, value);
|
|
35
|
-
return acc;
|
|
36
|
-
}, {}) as T;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return source;
|
|
33
|
+
const replaceDeep = <T>(source: T, search: unknown, value: unknown, options?: Options): T => {
|
|
34
|
+
return replaceDeepByFn(source, (v) => Object.is(v, search), () => value, options);
|
|
40
35
|
};
|
|
41
36
|
|
|
42
37
|
export {
|