Dev Diary #26 - WeKan Reaches Meteor 3.4, The Great Package Purge, and Community Migrations
I’m super duper glad to announce WeKan now runs on 3.4! This has been a long time coming, finally closing the curtain on work that started in dev diary #24. Here’s the big PR if you want to check it out! Now onto the details:
The first order of business was continuing the package removal spree that started last month. Meteor 2 apps tend to accumulate Atmosphere packages the way old houses accumulate junk drawers – you don’t notice how many there are until you try to move.
- #6173 — Fix FilesCollection findOneAsync errors for Avatars and Attachments — Quick fix to kick things off.
ostrio:files’sFilesCollectionprovidesfindOne(), notfindOneAsync(), so we were calling a function that didn’t exist. Switched to the sync method and moved on. - #6174 — Replace konecty:mongo-counter with inline implementation — Removed the package and replaced it with a minimal
incrementCounterfunction using raw MongoDBfindOneAndUpdate. Also added an async version for Meteor 3.0 compatibility. - #6175 — Replace templates:tabs with inline Blaze implementation — Swapped the
templates:tabsAtmosphere package for a lightweight inlinebasicTabs/tabContentBlaze template pair. Zero changes to consumer templates – drop-in replacement. - #6178 — Remove peerlibrary:blaze-components — This was a big one. Removed the unmaintained
peerlibrary:blaze-componentsand all six of its peer dependencies. Migrated every component fromBlazeComponent.extendComponent()to native MeteorTemplate.onCreated/helpers/eventspatterns. Replaced the Mixins global with standalone utility modules. - #6188 — Fix list add-card actions and sort persistence — The blaze-components migration (#6178) broke list header and popup add-card actions. This PR restored them, fixed the inlined add-card form reopening, and removed duplicate list sortable initialization so list moves persist correctly.
- #6190 — Replace underscore with native JavaScript utilities — Replaced ~250 underscore.js calls across ~45 files with native JS equivalents. Added a small shared helper module for patterns that don’t have a clean native one-liner. Removed
underscorefrom local packages and.meteor/packages. - #6191 — Remove raix:handlebar-helpers — Removed the package and re-implemented the operator helpers (
$eq,$neq,$gt,$lt, etc.) as native Blaze helper registrations in a newblazeHelpers.jsfile. - #6195 — Replace useraccounts packages with communitypackages alternatives — A big step for both WeKan and the community. Migrated from the unmaintained
useraccounts:*packages to community-maintainedcommunitypackages:*drop-in replacements. I migrated all three packages and chose Meteor Community Packages as their new home so the community can benefit and carry the torch. Also took the opportunity to remove dead packages likecoffeescriptwhich was no longer needed after the blaze-components removal. - #6196 — Remove unused meteorhacks:aggregate — The only aggregation call was already using
rawCollection().aggregate()directly, so the package was dead weight. Also convertedgetBoardTitleWithMostActivitiesfromPromise.awaittoasync/await. - #6197 — Replace Email.send with Email.sendAsync — Replaced all
Email.send()calls withawait Email.sendAsync(). This also fixed a bug where email sending errors were silently swallowed as unhandled promise rejections instead of being caught by surroundingtry/catchblocks.
And then came the big one.
#6205 — Incoming Impact — This is the PR that bumps WeKan to Meteor 3.4. I had a few days left before my Claude and Codex subscriptions ran out, so I decided to put what remained of them to good use. We could’ve attempted a gradual bump, but that would’ve only lengthened the pain – death by a thousand paper cuts. The application restructuring was by far the lengthiest part of this whole migration journey, mostly because of the overuse of globals and the lack of separation between server and client responsibilities (the classic isomorphism trap).
I don’t want to restate what is already in the PR description — I highly recommend reading it, it’s almost another dev diary of its own! What I’d like to highlight though is I did actually migrate the simple REST packages over at Meteor Community Packages, but ultimately decided it was better for WeKan to drop them entirely. This change specifically is partially why I was itching to bump to 3.4 directly – some changes can only be done when you’ve already upgraded and cannot be done on 2.0. Maybe the core team ought to move the Express change to 2.0 to ease this burden a bit.
On the Meteor core side, this was a busy month too:
#14222 — Fix puppeteer test runner console output — When puppeteer was bumped from 20.4.0 to 23.6.0, msg._text (underscore-prefixed property) became a private ES2022 #text field. This meant test names and pass/fail results were never printed in CI logs – you’d just see “Test number: N” with no useful information. Tracked it down and fixed the property access.
#14223 — Docs: guide LLMs to use test-in-console for package tests — Added documentation directing LLM agents to use ./packages/test-in-console/run.sh instead of ./meteor test-packages, which hangs waiting for a browser connection and produces no terminal output.
#14224 — Add test-headless driver for headless package testing — Born out of the frustration with test-in-console. This is a new test driver package that doesn’t rely on console scraping – results flow via DDP methods instead. Server calls Tinytest._runTests() directly, and if no browser connects within 10 seconds it gracefully prints server-only results. Supports TINYTEST_FILTER for regex filtering. Still open.
#14221 — Remove unused ejson dependency from packages — Removes direct ejson dependency from accounts-password, accounts-passwordless, and session since they get it transitively. Still open.
#14234 — Integrate collection hooks into core — This one’s been brewing in my mind for a while. Over the course of 3.0 migrations, I kept running into collection-hooks everywhere – it even turned up inside redis-oplog. The depth of its penetration into third-party packages made it clear this belongs in core. Bringing it in means it won’t get left behind in future migration cycles (as happened with the fibers/async transition), and we get to shed the monkey-patching workarounds the community package relied on. Still open.
#14262 — Backport express for 2.17 — This one came directly out of the WeKan migration pain. Every time I do a 3.0 migration, the same problem stares me in the face: communitypackages:picker and WebApp need Express, but you can’t use Express until you’re on 3.0. This PR ports the Express change back to 2.x (targeting a possible 2.17 release) so apps can adopt the new WebApp API before making the full 3.0 jump. Still open.
And finally, some community package work:
meteor-partitioner #38 — Meteor 3.0 migration — Work in progress on migrating the meteor-partitioner package to Meteor 3.0. This is the package that enables multi-tenant data partitioning in Meteor apps.
meteor-streamer #44 — Upgrade to Meteor 3.0 — A substantial migration of RocketChat’s meteor-streamer package. Converted permissions, methods, and emit to async/await, replaced findOne with findOneAsync, restructured the repo with a separate test app, wrote 87 new tinytest tests, added ESLint config, and removed the arunoda:streams dependency. This one lives in my fork for now while the PR is reviewed.
Looking back at this month, the numbers tell the story: eleven WeKan PRs, five Meteor core PRs (two merged, three open), and two community package migrations. LLMs have been a huge factor in this. I don’t want to use the term “AI” as there’s no inherent intelligence, just cool mathematical tricks that have been there for a long time, only enabled by the massive leap in data and processing power. Yet it’s an incredible tool in our arsenal as developers. We like to think of ourselves as great engineers — which we are in a sense — but our work also contains lots of grunt work like copying files, moving directories, validating words. Stuff that’s not only better suited for a computer but that also frees us to think more about the critical stuff. So don’t get trapped in the doom and gloom as I was, pondering my future as a software developer in the new era, but be optimistic. Think about all the new doors that’ve been opened instead of the closed windows!