Highlights
This patch release is mostly about hardening — both the runtime and the release pipeline itself — together with a big batch of dashboard fixes and a couple of performance wins. It also reverts a graphql dependency change from v3.6.3 that caused trouble in some setups. Thanks to everyone who reported issues and sent in PRs.
Reverting the graphql dependency change
v3.6.3 narrowed the graphql version range used by the core packages, and that turned out to break a number of repos with otherwise perfectly valid setups. We've widened it back to ^16.11.0 (#4716). If you pinned or added an override to graphql to get v3.6.3 working, you can take that workaround out now.
Security
- SSRF blocked in asset import (#4721) --
DefaultAssetImportStrategywould fetch whatever URL it was handed, which left room for server-side request forgery when importing assets from untrusted input. It now refuses requests aimed at internal and private network addresses.
In light of a recent increase in supply chain attacks on the npm ecosystem, a good chunk of the work this cycle went into the release pipeline rather than the code you run. We've moved to staged npm publishing, pinned all GitHub Actions to specific commit SHAs, dropped off the deprecated Node 20 runtime, scoped the GitHub App tokens down to least privilege, and gated the publish trigger to maintainers (#4784, #4785, #4786, #4787, #4788, #4789). None of this changes how Vendure behaves, but it tightens up the supply chain around how releases are built and shipped.
Core fixes
Notable fixes to the core:
- Inherited QueryRunner no longer released early (#4717) -- When a
TransactionWrapperinherited aQueryRunnerfrom an enclosing transaction, it would release that runner when it finished, affecting the outer transaction. It now only releases runners it created itself. - Order variant names respect translations (#4738) --
OrderService.findOnewasn't loadingProductVarianttranslations, so variant names could come back in the wrong language. The translations are now loaded as expected. - Asset translation migration skips empty databases (#4733) -- The v3.6 asset-translation migration helper threw when run against a fresh, empty database. It now detects that case and skips cleanly.
Performance
findByCustomerIdn+1 fixed (#4653) -- Filtering onproductVariantrelations infindByCustomerIdwas triggering an n+1 query. The relations are now fetched in a single query.- Lighter dashboard relation query (#4743) -- A heavy relation query behind one of the dashboard list views has been trimmed down, reducing load on larger datasets.
Dashboard improvements
- Custom fields (#4407, #4734, #4431, #4781) -- A round of custom-field fixes: relational custom fields now persist when saving a draft order; custom fields show up on the profile page now that
addCustomFieldsis applied to its route loader; fields the current user isn't allowed to write are stripped from the mutation before submit instead of triggering a permission error; and struct custom fields render properly in narrow containers rather than overflowing. - Form inputs (#4801, #4794, #4759, #4750) -- Select inputs backed by a nullable field can be set back to the empty option; boolean configurable args now initialise with the correct value instead of being left undefined;
AffixedInputforwardsonFocusandonKeyDownso consumers can hook into those events; and the bulk facet value modal no longer loses focus to its dropdown menu on keydown. - List pages (#4746, #4739) -- Multiple values within a single column filter now combine with OR, so filtering on several values returns the union as expected. Column visibility settings also persist properly, alongside a Dialog title context fix.
- AlertsProvider reacts to late-registered extensions (#4747) -- Alerts registered by extensions after the provider mounts are now picked up.
- Tiptap toolbar tracks editor state (#4705) -- The rich-text toolbar now reflects the current selection's formatting state instead of going stale.
- Less layout shift from remote data (#4707) -- Reduced the flicker and layout shift that showed while remote data was loading.
- Static assets skip rate limiting (#4709) -- Static dashboard assets bypass the rate limiter and get a long-lived cache header.
- Quieter logs (#4745) -- The dashboard no longer floods logs with "Uncompiled message detected" warnings.
- Windows
.poglob patterns normalised (#4751) -- Translation file globs now use forward slashes on Windows so they resolve correctly. - Administrator search and seller subtitle (#4778) -- Administrator search now spans multiple fields, and the empty seller subtitle has been tidied up.
- Filter and master toggle on variant generation (#4752) -- The variant generation table now has a filter and a master toggle for selecting rows in bulk.-
What's Changed
- fix(dashboard): fix tiptap toolbar not reacting to state changes by @Knitesik in #4705
- fix(dashboard): Reduce layout shift and flicker from remote data by @dlhck in #4707
- fix(create): Add vite as direct dev dependency in scaffolded projects by @grolmus in #4710
- fix(dashboard): Skip rate limit for static assets and add long-lived cache by @grolmus in #4709
- docs: Revise README by @dlhck in #4737
- fix(core): Load ProductVariant translations in OrderService.findOne by @grolmus in #4738
- fix(dashboard): Apply addCustomFields to profile page route loader by @grolmus in #4734
- Fix relational custom field not saving on draft order by @Ryrahul in #4407
- perf(dashboard): reduce heavy relation query by @dublin74 in #4743
- fix(dashboard): Preserve column visibility and fix Dialog title context by @grolmus in #4739
- fix(core): Block SSRF in DefaultAssetImportStrategy by @grolmus in #4721
- fix(core): prevent double-decoding of ID args in updatePromotion by @Ryrahul in #4740
- fix(core): Skip v3.6 asset translation migration on empty DB by @grolmus in #4733
- fix(dashboard): normalize glob patterns to forward slashes on Windows by @Yanis02015 in #4751
- fix(dashboard): Make AlertsProvider react to extensions registered after mount by @grolmus in #4747
- fix(dashboard): Stop logging "Uncompiled message detected" warnings by @grolmus in #4745
- fix(core): Do not release inherited QueryRunner in TransactionWrapper by @grolmus in #4717
- fix(dashboard): stop keydown propagation in facet values dialog to prevent DropdownMenu focus steal by @Ryrahul in #4750
- fix(dashboard): Apply column filters on list pages using OR filter operator by @grolmus in #4746
- docs: Add deployment overview and fix deployment guides by @dlhck in #4782
- chore: Enable npm staged publishing for releases by @michaelbromley in #4784
- ci: Restrict npm publish dispatch to maintainers (Tier 2) by @michaelbromley in #4785
- ci: Pin all GitHub Actions to SHA and bump off deprecated Node 20 runtime by @michaelbromley in #4786
- ci: Scope GitHub App tokens to least privilege by @michaelbromley in #4787
- fix(ci): Drop actions:write from CLA app token (regression from #4787) by @michaelbromley in #4789
- ci: Gate the npm publish release trigger to maintainers by @michaelbromley in #4788
- fix(dashboard): prevent struct custom field overflow in narrow contai… by @Ryrahul in #4781
- ci: Fix intermittent dashboard port race in Publish & Install by @michaelbromley in #4790
- fix(core, dashboard): Widen graphql version range to ^16.11.0 by @grolmus in #4716
- fix: Remove non permitted customfield from mutation before submit by @Ryrahul in #4431
- fix(dashboard): initialize boolean configurable args by @genm in #4794
- fix(dashboard): forward onFocus and onKeyDown in AffixedInput by @Ryrahul in #4759
- fix(services): findByCustomerId productVariant relation filter breaks by @harshit078 in #4653
- fix(dashboard): Resolve logout stuck in verifying state on failure by @calebcgates in #4757
- fix(admin-ui): remove puppeteer dependency and rely on system Chrome for Karma tests by @michaelbromley in #4798
- fix(ci): Install chromium-headless-shell for dashboard e2e by @michaelbromley in #4800
- feat(dashboard): Filter + master toggle on variant generation table by @grolmus in #4752
- fix: add administrator and seller to createEntityConfigs by @Ryrahul in #4779
- fix(dashboard): allow selecting nullable select items by @casperiv0 in #4801
New Contributors
- @Knitesik made their first contribution in #4705
- @dublin74 made their first contribution in #4743
- @Yanis02015 made their first contribution in #4751
- @genm made their first contribution in #4794
- @calebcgates made their first contribution in #4757
Full Changelog: v3.6.3...v3.6.4