Skip to content

Utility Functions

Matthew Dzaman edited this page Oct 18, 2019 · 8 revisions

Goals

  • Support clone, each, isArray, isEmpty, isEqual, isObject, isPlainObject, isString, isTypedArray, isUndefined, keys, reduce, and sortBy behavior using bug and vulnerability-free logic
  • Limit dependencies, ideally to zero
  • Limit the overall size of the build (minor)

Decision

Implementing isEqual, isPlainObject, isTypedArray, and a simplified clone is not prohibitively difficult or risky, and avoids introducing a dependency. All other current Lodash function usage has native equivalents.

Options

Lodash Dependency

Using a direct dependency on Lodash would be useful for automated tooling, which can asses security vulnerabilities and packages that are out of date. However, it introduces the first and only dependency, and it is desirable to avoid introducing a dependency as long as the bug and security risk profile is equivalent.

Approximate size: > 500KB

Lodash Vendor File

Instead of a direct dependency on the Lodash project, there could be a dev dependency that is used to build a Lodash vendor file based on the required Lodash functions. With this approach, automated tooling would not support identifying when Lodash is out of date or vulnerable, which is undesirable -- probably more so than introducing a dependency.

Approximate size: 125KB (~4k LOC which is roughly 4x the size of the entire build so far)

Custom Code

See also: You Don't Need Lodash...

Using custom code will make the API a little stricter (e.g. .forEach won't work on Arrays, Objects, Sets, and Maps the way .each will), but that's probably a good thing.

It's possible that custom code will be more likely to have bugs, but that may be outweighed by the cost of flexibility on maintaining the API contract. Custom code could also either be more performant (due to tighter requirements) or less performant due to 3rd party expertise.

Function Coverage Notes
clone πŸ“ Used to clone parameter inputs to template so that modifications to List other QueryParts do not impact the inputs. Cloning of other types supported by the Lodash algorithm is not necessary as those types can be shallow-copied.
each βœ… Used to iterate over Arrays only.
isArray βœ… Used to distinguish between Arrays, Objects, undefined, and single values in parameter types.
isEmpty βœ… Used to determine subquery comparison can be dropped because the input array is empty. Could check length. Could consider supporting Set and Map, but being strict is probably better.
isEqual πŸ“ Used to compare two sources (Array/Object) to see if they are equal. If they are not equal, an error is thrown. The default behavior for re-defining a list could be an error.
isObject βœ… Used to determine distinguish between Array and Object in parameter types.
isPlainObject πŸ“ Used to distinguish between class instances and plain objects when interpreting if a value contains undefined bindings and when determining the bindings are named or positional. Would required non-trivial code.
isString βœ… Used to determine if first arg to List constructor is a string.
isTypedArray πŸ“ Can use isTypedArray from util (which is what Lodash does) but need to be careful about older versions of node.
isUndefined βœ… Used to determine if a value in a data structure is undefined, because undefined bindings should be ignored.
keys βœ… Used to grab keys from an Object. Array support is not leveraged, so Object.keys will work.
reduce βœ… Is currently used to reduce an object, but Object.keys will do the trick.
sortBy βœ… Is used to chain sort, but chaining is not required.
Clone this wiki locally