Releases: bymaxone/nest-queue
Release list
v1.2.3
Nothing that runs in this package changed. A fresh build of the release commit was packed and
compared against the published 1.2.2 tarball: dist/ is identical file for file, and package.json
differs only in the version string. The remaining difference is this CHANGELOG entry, which ships
because CHANGELOG.md does.
It exists because the estate releases on a cadence, so a library whose artifact is unchanged
publishes anyway and says so rather than implying a benefit it does not deliver. There is no
reason to upgrade from 1.2.2, and a consumer on ^1.2.0 gains nothing by resolving to it.
Internal
Not shipped — files is dist, LICENSE, README.md, CHANGELOG.md, and the only file touched
since 1.2.2 is AGENTS.md:
- The shared review-rules block was synchronised with its canonical copy, bringing in an invariant
for keys built from more than one field — the generalised form of the deduplication defect this
package corrected in 1.2.2. - Two repository-specific review rules were corrected: one rested its case on a defect that had
since been fixed, so the claim had become false; the other required an authorship finding to
quote a resolvable commit id, a criterion the shared block superseded by placing author and
committer identity out of scope entirely.
v1.2.2
1.2.1 was tagged but never published, so this release carries its documentation fix as well
as the one below. dist/ changes here for the first time since 1.2.0 — JSDoc reaches the emitted
.d.ts, so a doc-block correction is a change to the published types.
Fixed
- The
enqueuededuplication example asserted a safety property it did not provide. It showed
`${tenantId}:reindex:${term}`and stated that "one tenant's term cannot suppress another's".
Two variable fields joined by a delimiter either may contain do not produce a unique key: with
`${tenantId}:${term}`, the pairs('a', 'b:c')and('a:b', 'c')both yielda:b:c. The
guidance now percent-encodes every variable field, and the claim states what the construction
delivers. This is documentation a consumer copies into their own key-building code, which is why
the shape mattered more than whether:reindex:in particular was reachable. - Carried from 1.2.1: the
MetricsServiceexample inREADME.mdcalled two methods that do not
exist,getMetrics(name)andgetAll([names]), where the service exposesget(name)and a
no-argumentgetAll().
Internal
Not shipped, listed because the tag covers them: bullmq raised from 6.0.10 to 6.3.4 in the
workspace override; fast-uri, qs and fastify floors raised past published advisories; the
README-snippet gate now type-checks through receivers; AGENTS.md and its sync workflow added.
v1.2.0
Breaking, shipped as a minor by choice. The peer ranges move to the next major of each
Redis/BullMQ package and the 'paused' job state is removed from the public status surface —
changes that would normally warrant a major. They ship under a minor because the package has no
downstream consumer yet; every breaking detail is called out below so a first adopter sees it.
Changed
- Peer dependencies migrated to the next major:
bullmq^5→^6,bullmq-otel^1→
^2, andioredis^5→^6. A consumer must upgrade all three together.ioredis6 keeps
'legacy'reply mapping by default, so BullMQ's reply-shape assumptions are unaffected; it does
require Node.js ≥ 20, already covered by this package'sengines.
Removed
'paused'is no longer a job status. BullMQ 6 dropped'paused'from its job-state set —
jobs on a paused queue now live in'wait'. It is therefore removed from theJobStatusunion,
from theJOB_STATUSconstant (JOB_STATUS.PAUSEDno longer exists), and from the
getMetrics().countsshape, which now reports the five remaining statuses (waiting,active,
completed,failed,delayed). The queue-lifecycle'paused'/'resumed'events
(@OnQueueEvent) and thepauseQueue/resumeQueuemethods are unchanged — those describe the
queue, not a job.
Internal
- Dev-tooling bumps:
eslint^10,typescript^6,@types/node^26, plus@eslint/js
^10. These do not ship and do not changedist/. The package'senginesstays at Node ≥ 24. - Mutation gate tightened: Stryker
break/highraised from 95/99 → 100 (the run is at 100%,
0 survivors).
v1.0.11
Documentation only. The shipped declaration comments change (dts preserves them); no runtime
code changed.
Fixed
- The deduplication example — in the
QueueServiceJSDoc and in
docs/technical_specification.md— now scopes the dedupidby tenant
(`${tenantId}:reindex:${term}`). Theidis a shared key across the queue, so a
multi-tenant producer keying on the value alone lets one tenant's enqueue suppress another
tenant's job for the same value; the example previously demonstrated exactly that.
v1.0.10
Documentation and tooling only. dist/ is byte-identical to 1.0.9; no source file
changed.
Fixed
- The quality bullet claimed "no suppression comments" while the source carries five
// Stryker disablecomments. The claim was about type suppressions and read as false to
anyone who grepped for it; it now says what is true — no@ts-ignoreand no
eslint-disable.
Security
- The OSV scan was passing because it had nothing to read. The workflow ran
osv-scannerwith noactions/checkoutstep, so it walked an empty workspace and
reported "No package sources found" and "No lockfiles found" before exiting 0. A green
check meant the scanner found no files, which is indistinguishable from finding no
vulnerabilities. With the checkout in place it scans the lockfile, which is how the next
item was found. js-yamlis patched to the fixed release (GHSA-5p4m-2wfm-xmqj, CVSS 7.5). The
override floors here already scoped it per major but admitted3.15.0and4.3.0, both
covered by the advisory; they are raised to^3.15.1and^4.3.1. It reaches this repo
only throughjest->babel-plugin-istanbul->@istanbuljs/load-nyc-config, and
dependenciesis empty, so nothing here ships it and no consumer was exposed.dist/is
unaffected.
Added
check:mutantsgate (scripts/check-mutation-directives.mjs) — validates every
// Strykercomment against the grammar Stryker's own parser accepts, rejecting a reason
written after--instead of a colon (silently dropped, and the report then shows
Ignored using a comment), a reason wrapped onto a second comment line (the report keeps
only the first fragment), and a mutator name Stryker does not know, which matches nothing
and so silences nothing. Wired into CI andprepublishOnly.docs/mutation_testing_plan.mdcarries the suppression policy now shared, word for word,
across the@bymax-one/nest-*libraries.
v1.0.9
Published-artifact change, not a behavioural one. dist/ differs from 1.0.8 — this
bundler preserves comments and the source gained mutation-suppression notes — but no runtime
path changed. Measured by building both revisions and diffing the output.
Documentation
- The mutation badge and README said 99.06%; the measured score is 99.68%.
Tests
- The withheld Redis connection now has the shape of its guarantee asserted: that the property is
non-enumerable, that redefining it throws, and that the URL's password stays out of both
JSON.stringifyandinspect({ showHidden: true }).
v1.0.8
Runtime change. dist/ differs from 1.0.7.
Security
- The Redis credentials are no longer disclosed when a service that holds them is
serialized.connectionmoves from a plain field on the resolved options to a
non-enumerable accessor, andConnectionResolverkeeps the ioredis client and the
consumer's module options in ECMAScript private fields, as do the maps holding the
Queue,WorkerandQueueEventsinstances. Those objects were all reachable by
walking a service: aurlcarries the password inline, and an ioredis instance carries
options.passwordas a plain field, soJSON.stringify, object spread and
util.inspectonQueueServiceemitted the password in plaintext — which is what a
structured logger does when it renders a provider it was handed, and what an error
reporter does when it captures the scope of a throw.
Reading on purpose is unchanged: options.connection resolves as before, and no public
type or export changed.
v1.0.7
Runtime change. dist/ differs from 1.0.6: the four decorators no longer carry
a reflect-metadata side-effect import, so the built bundle no longer references the
package at all.
Fixed
-
The application owns the
reflect-metadatapolyfill.@Processor,@Process,
@OnWorkerEventand@OnQueueEventeach imported it for its side effect. None of
the other eight@bymax-onelibraries does — the polyfill is global state the
application initialises once inmain.ts, and NestJS pulls it in regardless:
importing@nestjs/commonalone takesReflect.defineMetadatafromundefinedto
function. Nothing here needed to load it.Carrying it also contradicted this package's own
"sideEffects": false, which
asserts that no module has a side effect while importing something whose entire
purpose is one.The cost was measurable in a consumer's bundle: with the import present, esbuild
inlines the polyfill, taking a minimal bundle from 53 kB to 95 kB even when the
application had already loaded it.Nothing changes for a correctly wired application. The decorators are reachable
only through the.subpath, whose bundle imports@nestjs/commonon its first
line — so the polyfill is present before any decorator body runs, which the tests
and a real consumer both confirm.
Changed
- The Quick Start shows the
main.tsentry point, withimport 'reflect-metadata'
as its first line, and the peer matrix states plainly that the polyfill belongs to
the application. Previously the README namedreflect-metadataonly as a peer, which
was survivable while the library loaded it and is not now.
v1.0.6
Metadata only. dist/ is byte-identical to 1.0.5 — verified by diffing a fresh
build against the published tarball — so there is no runtime change.
Fixed
-
The npm package page showed no documentation.
1.0.5reached the registry
with an emptyreadmefield, so the page rendered nothing, even though
README.mdwas in the tarball all along. Publishing goes through the npm CLI
now instead ofpnpm publish, and this release is what carries the README to
the registry.The cause is measurable: across the five published
@bymax-one/*libraries,
every package released under pnpm 11 landed with an emptyreadmeand no
_npmVersion, while every one released under pnpm 10 — which delegated to the
npm CLI — carries both.nest-realtime@1.0.1confirmed it, restoring both
fields in a single release by switching the command.
v1.0.5
Documentation only. dist/ is byte-identical to 1.0.4 — verified by diffing a
fresh build against the published tarball — so there is no runtime change.
Fixed
-
The README's configuration examples did not compile in a strict project.
Eight snippets passedprocess.env.REDIS_URLwhere astringis required:TS2322: Type 'string | undefined' is not assignable to type 'string'.process.env.Xisstring | undefinedunderstrict, so anyone copying the
Quick Start into a strict TypeScript project — the configuration this library
itself uses and recommends — got a type error out of the box. Now shown with a
fallback, which is what the code has to do anyway:connection: { url: process.env.REDIS_URL ?? 'redis://localhost:6379' }
Found by
pnpm check:published, added in the same release, which compiles the
README's own snippets against the built package. Nobody had reported it, and
nothing before this would have.
Added
-
pnpm check:published— a gate that verifies the published surface matches
the documentation, before a tag rather than after it. It scaffolds a throwaway
consumer, symlinks the package into its ownnode_modulesso resolution runs
through theexportsmap intodist/, and then checks that the README's links
resolve, that its TypeScript snippets and the type tests compile against the
built package, and that everyv*.*.*tag has a## [x.y.z]CHANGELOG section.Each of those exists because its absence let a defect reach npm: the 404 link
corrected in1.0.3, the exported type that rejected the README's own snippet
corrected in1.0.4, and a deleted heading that would have turned release notes
into the generic fallback.It runs in CI, in
release.yml, and insideprepublishOnly— the last one
because the first publish of a package is manual by design, which is precisely
the path that bypasses the tag workflow.