Skip to content

Replace underscore with native JavaScript utilities#6190

Merged
xet7 merged 8 commits intowekan:mainfrom
harryadel:remove-underscore
Mar 19, 2026
Merged

Replace underscore with native JavaScript utilities#6190
xet7 merged 8 commits intowekan:mainfrom
harryadel:remove-underscore

Conversation

@harryadel
Copy link
Contributor

@harryadel harryadel commented Mar 18, 2026

  • Replace all ~250 underscore.js calls across ~45 files with native JavaScript equivalents
  • Add a small shared helper module (imports/lib/collectionHelpers.js) for patterns with no clean native one-liner (findWhere, where, uniqBy, groupBy, indexBy, debounce, once)
  • Remove underscore from both wekan-oidc and wekan-ldap local packages
  • Remove underscore@1.0.13 from .meteor/packages

Note: underscore remains as a transitive dependency of raix:handlebar-helpers in .meteor/versions — no breakage there.

Add findWhere, where, uniqBy, groupBy, indexBy, debounce, and once
helper functions in imports/lib/collectionHelpers.js. These provide
null-safe replacements for underscore methods that have no clean
native one-liner equivalent. Expose them on the Utils global for
client-side usage.
- _.has -> Object.hasOwn
- _.isString -> typeof x === 'string'
- _.isUndefined -> x === undefined
- _.sortBy -> [...arr].sort()
- _.any -> .some()
- _.range -> Array.from()
- _.times -> for loop
- _.contains -> .includes()
- _.filter -> .filter()
- _.pluck -> .map()
- _.findWhere -> findWhere() helper
- _.union -> [...new Set()]
- _.every/.some -> .every()/.some()
- _.once -> once() helper
- _.uniq with property -> uniqBy() helper
- _.sortBy -> [...arr].sort()
- _.chain().groupBy() -> groupBy() helper
- _.each -> .forEach()
- _.isNumber -> typeof x === 'number'
Largest changes in cards.js (~76 calls), boards.js (~38 calls),
and activities.js (~31 calls). Key patterns:

- _.contains -> .includes() with null guards where needed
- _.findWhere/_.where -> findWhere()/where() helpers
- _.pluck -> .map()
- _.union -> [...new Set()]
- _.extend -> Object.assign()
- _.each on objects -> Object.entries().forEach() (argument order swap)
- _.debounce -> debounce() helper
- _.groupBy/_.indexBy -> groupBy()/indexBy() helpers
- _.clone -> spread operator
- _.sortBy -> [...arr].sort()
- Type checks -> native typeof
- server/publications: _.findWhere -> findWhere() helper
- server/notifications: _.clone -> spread operator
- server/rulesHelper: _.min/_.max -> Math.min/Math.max
- server/lib/utils: _.some/_.contains -> .some()/.includes()
- imports/reactiveCache: _.groupBy/_.indexBy -> helpers
- config/router: _.each on object -> Object.entries().forEach()
- sandstorm: _.pluck/_.values -> .map()/Object.values()
- _.pick -> Object.fromEntries/Object.entries filter
- _.extend -> Object.assign (including on Error objects)
- _.pluck -> .map()
- Remove api.use('underscore') from package.js
- Remove import _ from 'underscore'
- _.reduce -> .reduce()
- _.map on objects -> Object.entries().forEach() (argument order swap)
- _.isEmpty -> manual null/length check
- _.isObject -> typeof check
- _.find -> .includes()
- _.last -> .at(-1)
- _.size -> Object.keys().length
- _.debounce -> inline debounce function
- Remove api.use('underscore') from package.js
All application code now uses native JavaScript equivalents.
underscore remains as a transitive dependency of
raix:handlebar-helpers in .meteor/versions.
@xet7 xet7 merged commit 77b57d8 into wekan:main Mar 19, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants