From fc5ca69faa67d9f55a3bc5a777bb46df37f7a9eb Mon Sep 17 00:00:00 2001 From: Maximiliano Salvatti <40447063+msalvatti@users.noreply.github.com> Date: Tue, 4 Aug 2026 07:51:55 -0300 Subject: [PATCH 1/2] chore(release): 1.0.7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Runtime change: the four decorators no longer carry a `reflect-metadata` side-effect import, so `dist/` differs from 1.0.6 — the built bundle no longer references the package at all. The README gained what the fix makes necessary: the Quick Start now shows the `main.ts` entry point with `import 'reflect-metadata'` as its first line, and the peer matrix states that the polyfill belongs to the application. Naming it only as a peer was survivable while the library loaded it, and is not now. --- CHANGELOG.md | 38 ++++++++++++++++++++++++++++++++++++++ README.md | 21 ++++++++++++++++++++- package.json | 4 ++-- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75faa6a..1f340f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,43 @@ versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). --- +## [1.0.7] — 2026-08-04 + +**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-metadata` polyfill.** `@Processor`, `@Process`, + `@OnWorkerEvent` and `@OnQueueEvent` each imported it for its side effect. None of + the other eight `@bymax-one` libraries does — the polyfill is global state the + application initialises once in `main.ts`, and NestJS pulls it in regardless: + importing `@nestjs/common` alone takes `Reflect.defineMetadata` from `undefined` to + `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/common` on 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.ts` entry point**, with `import 'reflect-metadata'` + as its first line, and the peer matrix states plainly that the polyfill belongs to + the application. Previously the README named `reflect-metadata` only as a peer, which + was survivable while the library loaded it and is not now. + +--- + ## [1.0.6] — 2026-08-02 Metadata only. `dist/` is byte-identical to `1.0.5` — verified by diffing a fresh @@ -332,6 +369,7 @@ v6 peer range. --- +[1.0.7]: https://github.com/bymaxone/nest-queue/compare/v1.0.6...v1.0.7 [1.0.6]: https://github.com/bymaxone/nest-queue/releases/tag/v1.0.6 [1.0.5]: https://github.com/bymaxone/nest-queue/releases/tag/v1.0.5 [1.0.4]: https://github.com/bymaxone/nest-queue/releases/tag/v1.0.4 diff --git a/README.md b/README.md index c49306d..5d8cc40 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,12 @@ Both subpaths ship ESM **and** CommonJS with declarations for each format, so a | `./shared` | None | | Optional | `bullmq-otel ^1` (OpenTelemetry) | +> [!IMPORTANT] +> `reflect-metadata` is a **global polyfill the application owns** — import it once at +> the top of `main.ts`. This library never imports it, so it cannot be shipped twice +> into your bundle; NestJS pulls it in as well, which is why a correctly wired +> application already has it before a decorator runs. + --- > [!TIP] @@ -137,7 +143,20 @@ Both subpaths ship ESM **and** CommonJS with declarations for each format, so a ## 🚀 Quick Start ```bash -pnpm add @bymax-one/nest-queue bullmq ioredis +pnpm add @bymax-one/nest-queue bullmq ioredis reflect-metadata +``` + +`reflect-metadata` is loaded **once by your application**, before anything else — this +is the standard NestJS entry point and the decorators in this library depend on it: + +```typescript +// main.ts +import 'reflect-metadata' +import { NestFactory } from '@nestjs/core' +import { AppModule } from './app.module' + +const app = await NestFactory.create(AppModule) +await app.listen(3000) ``` Wire the module in your root `AppModule`: diff --git a/package.json b/package.json index 24ab678..d4512d7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@bymax-one/nest-queue", - "version": "1.0.6", - "description": "NestJS dynamic module wrapping BullMQ \u2014 typed jobs, flows, job schedulers, deduplication, OpenTelemetry, graceful shutdown", + "version": "1.0.7", + "description": "NestJS dynamic module wrapping BullMQ — typed jobs, flows, job schedulers, deduplication, OpenTelemetry, graceful shutdown", "author": "Bymax One ", "license": "MIT", "homepage": "https://github.com/bymaxone/nest-queue#readme", From b80550dda1b96db53ee36080ba01d258134c7dc4 Mon Sep 17 00:00:00 2001 From: Maximiliano Salvatti <40447063+msalvatti@users.noreply.github.com> Date: Tue, 4 Aug 2026 07:58:14 -0300 Subject: [PATCH 2/2] docs(readme): use the standard bootstrap() pattern in the main.ts example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The example used top-level await. A default NestJS project compiles `main.ts` to CommonJS, where top-level await does not exist — so copying the snippet fails to compile, in the one example whose entire purpose is to be copied. It follows the `bootstrap()` shape the NestJS CLI generates, which works under both module systems. --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5d8cc40..bf09d60 100644 --- a/README.md +++ b/README.md @@ -155,8 +155,12 @@ import 'reflect-metadata' import { NestFactory } from '@nestjs/core' import { AppModule } from './app.module' -const app = await NestFactory.create(AppModule) -await app.listen(3000) +async function bootstrap(): Promise { + const app = await NestFactory.create(AppModule) + await app.listen(3000) +} + +void bootstrap() ``` Wire the module in your root `AppModule`: