Utils
Misc utility methods that's useful for our sites
Installation
npm install --save @hdsydsvenskan/utils
Release new version
Follow Semantic Versioning and use np and a version like patch | minor | major | prepatch | preminor | premajor | prerelease | 1.2.3
np patch
Public methods
Tiny helpers
-
resolveValue(value, ...valueArgs)
– value can be a function, a Promise or another value. If a function then it will be called withvalueArgs
. Returns a Promise -
resolveValueRaw(value, ...valueArgs)
– same asresolveValue()
but without the convenience of always returning the value wrapped in a Promise -
resolveValueWithThis(value, thisContext, ...valueArgs)
– value can be a function, a Promise or another value. If a function then it will be called withvalueArgs
and havethis
asthisContext
. Returns a Promise -
resolveNonObjectValue(value, ...valueArgs)
– same asresolveValueRaw()
, but with improved and stricter JSDoc types -
resolveNonObjectValueRaw(value, ...valueArgs)
– same asresolveValueWithThis()
, but with improved and stricter JSDoc types -
resolveNonObjectValueWithThis(value, thisContext, ...valueArgs)
– same asresolveValue()
, but with improved and stricter JSDoc types -
applyToDefaults(defaults, data)
– appliesdata
todefaults
. Mimicks theapplyToDefaults
from Hoek. -
escapedJSONStringify(obj)
– returns an escaped stringified JSON object that can safely be printed in HTML. -
sleep(ms: number, [signal: AbortSignal])
– returns aPromise
that resolves afterms
milliseconds. If thesignal
parameter is provided, the promise will resolve the instant the signal is aborted.
Array helpers
-
arrayIntersect(firstArray, secondArray)
– returnstrue
orfalse
dependening whether the two arrays intersect or not. -
arrayIntersection(firstArray, secondArray)
– returns the values that are present in both arrays. -
arrayNonIntersection(firstArray, secondArray)
– returns the values in the first array that are not present in the second array. -
arrayZip(firstArray, secondArray)
– zips two arrays of the same length into one -
bisectLeft(sortedArray, value)
– find the left-most index of a sorted array where a value can be inserted while maintaining sorted order -
bisectRight(sortedArray, value)
– Similar tobisectLeft
, but finds the right-most index instead. -
ensureArray(maybeArray)
– always returns an array, either the array input, the input wrapped as an array, or if the input isundefined
, then an empty array -
insort(sortedArray, value)
– creates a new sorted array with the value inserted at the correct index
Object helpers
-
deepClone(obj)
– recursively clonesobj
and all objects and arrays it contains.obj
should be either an object or an array. -
deepMerge(target, source)
– recursively merges properties fromsource
intotarget
. Iftarget
is an object (and a property oftarget
is an object) then properties will be merged into that object. Else it will be replaced with any new value fromsource
. -
deepFreeze(obj)
– recursively freezesobj
and all objects and arrays it contains.obj
can be either an object or an array. -
losslessMerge(obj1, obj2)
– creates an object with all keys fromobj1
andobj2
+ with all values from the two merged into arrays. If a value in either was an array, then the content of that array gets merged into the array rather than the array itself. -
objectFilter(obj, [callback(value, key, i)])
– like[].filter()
but returns an object. Defaults to filter outundefined
items -
objectMap(obj, callback(value, key, i))
– DEPRECATED BYobjectMapExtended()
– like[].map()
but returns an object -
objectMapExtended(obj, callback(value, key, i))
– like[].map()
but returns an object -
omit(obj, keys)
– returnsobj
with all keys mentioned inkeys
omitted.keys
being an array of strings -
pick(obj, keys)
– likeomit()
, but rather than enforcing a blacklist of keys, it enforces a whitelist – only including keys of the object that have been listed inkeys
-
pickDerived(obj, targets)
–targets
should be an object with keys that refer to keys inobj
and values that are eithertrue
(then the value inobj
will be picked), afunction
that will be sentobj
and will return a derived value, anobject
which value will be resolved usingparseDerived(obj, theTargetValue)
or a value of another type, which will then be returned as is. -
recursiveObjectFilter(obj, [callback(value, key, i)])
– likeobjectFilter()
, but better, since this one is recursive💪 -
zipObject(keys, values)
– returns an object with keys fromkeys
and key valies fromvalues
Promise helpers
-
catchWrap(promise, message)
– wraps the error message of a possibly rejected promise with this message throughVError
-
objectPromiseAll(obj, [mapMethod(value, key)])
– resolves all Promises inobj
and returns a Promise that resolves to an object with all keys ofobj
and their respective resolved value. IfmapMethod
is set, then it will be called withvalue
andkey
of each item inobj
and is expected to return a value or Promise to resolve to for each. -
recursiveObjectPromiseAll(obj)
– likeobjectPromiseAll
, but recursive
String helpers
-
commaSeparatedStringToArray(value)
– value should be a string with values separated by a comma and an array of non-falsy values will be returned -
escapeHTML(value)
– currently a re-exportedescape-goat.escapeHTML()
, also useable as template tag -
unescapeHTML(value)
– currently a re-exportedescape-goat.unescapeHTML()
, also useable as template tag -
inlineString(value)
– replaces all newlines, including their surrounding whitespace, with a simple single space -
trimNewlines(value)
– replaces all newlines, including their surrounding whitespace, with a simple single newline -
wrapIn([prefix], value, [suffix])
– adds a prefix and/or suffix to a string if that string is non-empty, else just returns an empty-string
Template tags
-
escapeHTML
– currently a re-exportedescape-goat.escapeHTML()
, also useable as a simple standalone function -
unescapeHTML
– currently a re-exportedescape-goat.unescapeHTML()
, also useable as a simple standalone function -
inlineTemplateTag
– same assimpleTemplateTag
, but replaces all newlines, including their surrounding whitespace, with a simple single space + also trims any space in the very beginning and end of the string -
simpleTemplateTag
– noop template literal tag, works as if no template tag has been added. Makes it easy to get syntax highlighting, by aliasing it as eg.html
orjs
-
templateTagWithModifier({ [staticCallback], [valueCallback], [finalCallback] })
– makes it simple to create template tags likeinlineTemplateTag
andtrimNewlines
; -
trimNewlines
– same asinlineTemplateTag
, but replaces with a single newline instead
Caching
-
limitedStore(maxSize)
– returns a limited store that saves items up to a limit ofmaxSize
and then removes the oldest item. The returned object has three methods:set(key, value)
,get(key)
andremove(key)
-
memoize(func(args), maxSize, [{ keyGenerator(args), hitrateCallback, maxAge, store }])
– memoizes the result of the func using a limited cache of max sizemaxSize
with optionally a max age ofmaxAge
, a custom cache key generated bykeyGenerator
, ahitrateCallback
that's called withtrue
for every hit andfalse
for every miss and a customstore
with same API aslimitedStore
. Returns a wrappedfunc
with an addedresetValue(args)
method that can be used to reset the value of a specific cached invocation (useful when eg. a cachedPromise
has been rejected and you want to shorten the wait time). -
lruMemoize(func(args), maxSize, [{ keyGenerator(args), maxAge, store }])
– likememoize()
but defaults to a LRU cache -
extendedCache(maxSize, [{ hitrateCallback, maxAge, store }])
– likememoize()
, but without the memoization function. Returns an object with three methods:set(key, value, expires)
,get(key)
andremove(key)
whereexpires
should be a timestamp in milliseconds
Errors and logging
-
deprecate(name, [message])
– logs aconsole.trace()
the very first time it's called with a newname
, thus avoiding spamming the output with deprecation errors. Tracks state globally. Does not output logs in production. -
ExtendableError
– an extendable helper subclass ofError
, which aids in setting things up correctly. -
findCauseByError(err, FooError)
– likeVError.findCauseByName(err, 'FooError')
but when it returns an error it actually is an error of theFooError
type -
HdsUtilsFetchError(res, parsed)
– fetch relatedError
class, can be used wherever a fetch related error happens -
logSlowPromise(inputPromise, name, { logger, [logLevel], [warnEveryMs], [thresholdInMs]})
– logs (by default atwarn
level) whenever the wrappedPromise
is slower than the set threshold (by default same as the interval) and repeats it on the set interval (by default 500 ms). -
trackDeprecation([scope], [log])
– creates a localdeprecate()
that only tracksname
:s within itself and not globally.log
defaults toconsole.trace()
GraphQL helpers
-
formatFieldsAndFragments({ fields, fragments }, spacing = ' ')
– used in GraphQL fragment extensions to formatfields
andfragments
(both being arrays of strings and optional) for direct inclusion into a GraphQL query string. Thespacing
can be overridden to better suit the insert position in the GraphQL query. -
getFieldsAndDependencies({ dependencies, fields, fragments })
– used in extendable GraphQL queries to format and merge the input data (all being arrays of strings and optional) into{ dependencies, fields }
wheredependencies
are what is to be added to a GraphQL query's dependencies andfields
are what to be inserted into the GraphQL query string.
Randomness helpers
-
seededRandom(seed)
– returns a function that generates a random number. The returned function requires an integer as its only argument, the random number returned will be an integer between0
and the sent in integer (not including the sent in integer). -
createMemoizedSeededListSorter
– makes it possible to sort a list consistently across many places both within and across instances, based on the sent in seed. Check the code in this project as well as the uses in other projects to understand how it works. It's a bit complicated
Validators
-
isEmptyishString(value, [{ treatNonStringsAsNonEmpty = false }])
– checks if the value is a string and if it is "emptyish" – returnstrue
eg. if its falsy, equal to'null'
or'undefined'
or if it just contains whitespace. Else it returnsfalse
-
isFalsyishString(value)
– likeisEmptyishString()
but also checks if the value is equal to'false'
or'0'
-
isValidUUID(stringValue)
– checks whether the string value is setup according to a very basic regexp structure
Misc helpers
-
processFetchResponse(fetchPromise)
– returns parsed JSON on a 2xx success code, else returns an informative error -
readFilesInDir(path)
– returns a promise that resolves to an object with file names as keys and content as values -
renderTpl(template, vars, [{ [customFilters] }])
– replaces named placeholders,{{name}}
, with variable values and applying optional filters,{{name | filter-name}}
. Supported filters are:escape
,inline
,json
. Inspired by Liquid.