@bymax-one/nest-queue 1.0.9 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +53 -0
- package/README.md +1 -1
- package/dist/server/index.cjs +8 -2
- package/dist/server/index.d.cts +8 -2
- package/dist/server/index.d.ts +8 -2
- package/dist/server/index.mjs +8 -2
- package/package.json +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,57 @@ versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## [1.0.11] — 2026-08-10
|
|
11
|
+
|
|
12
|
+
**Documentation only.** The shipped declaration comments change (`dts` preserves them); no runtime
|
|
13
|
+
code changed.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- The deduplication example — in the `QueueService` JSDoc and in
|
|
18
|
+
`docs/technical_specification.md` — now scopes the dedup `id` by tenant
|
|
19
|
+
(`` `${tenantId}:reindex:${term}` ``). The `id` is a shared key across the queue, so a
|
|
20
|
+
multi-tenant producer keying on the value alone lets one tenant's enqueue suppress another
|
|
21
|
+
tenant's job for the same value; the example previously demonstrated exactly that.
|
|
22
|
+
|
|
23
|
+
## [1.0.10] — 2026-08-06
|
|
24
|
+
|
|
25
|
+
**Documentation and tooling only.** `dist/` is byte-identical to `1.0.9`; no source file
|
|
26
|
+
changed.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- The quality bullet claimed "no suppression comments" while the source carries five
|
|
31
|
+
`// Stryker disable` comments. The claim was about type suppressions and read as false to
|
|
32
|
+
anyone who grepped for it; it now says what is true — no `@ts-ignore` and no
|
|
33
|
+
`eslint-disable`.
|
|
34
|
+
|
|
35
|
+
### Security
|
|
36
|
+
|
|
37
|
+
- **The OSV scan was passing because it had nothing to read.** The workflow ran
|
|
38
|
+
`osv-scanner` with no `actions/checkout` step, so it walked an empty workspace and
|
|
39
|
+
reported "No package sources found" and "No lockfiles found" before exiting 0. A green
|
|
40
|
+
check meant the scanner found no files, which is indistinguishable from finding no
|
|
41
|
+
vulnerabilities. With the checkout in place it scans the lockfile, which is how the next
|
|
42
|
+
item was found.
|
|
43
|
+
- **`js-yaml` is patched to the fixed release** (GHSA-5p4m-2wfm-xmqj, CVSS 7.5). The
|
|
44
|
+
override floors here already scoped it per major but admitted `3.15.0` and `4.3.0`, both
|
|
45
|
+
covered by the advisory; they are raised to `^3.15.1` and `^4.3.1`. It reaches this repo
|
|
46
|
+
only through `jest` -> `babel-plugin-istanbul` -> `@istanbuljs/load-nyc-config`, and
|
|
47
|
+
`dependencies` is empty, so nothing here ships it and no consumer was exposed. `dist/` is
|
|
48
|
+
unaffected.
|
|
49
|
+
|
|
50
|
+
### Added
|
|
51
|
+
|
|
52
|
+
- `check:mutants` gate (`scripts/check-mutation-directives.mjs`) — validates every
|
|
53
|
+
`// Stryker` comment against the grammar Stryker's own parser accepts, rejecting a reason
|
|
54
|
+
written after `--` instead of a colon (silently dropped, and the report then shows
|
|
55
|
+
`Ignored using a comment`), a reason wrapped onto a second comment line (the report keeps
|
|
56
|
+
only the first fragment), and a mutator name Stryker does not know, which matches nothing
|
|
57
|
+
and so silences nothing. Wired into CI and `prepublishOnly`.
|
|
58
|
+
- `docs/mutation_testing_plan.md` carries the suppression policy now shared, word for word,
|
|
59
|
+
across the `@bymax-one/nest-*` libraries.
|
|
60
|
+
|
|
10
61
|
## [1.0.9] — 2026-08-06
|
|
11
62
|
|
|
12
63
|
**Published-artifact change, not a behavioural one.** `dist/` differs from `1.0.8` — this
|
|
@@ -405,6 +456,8 @@ v6 peer range.
|
|
|
405
456
|
|
|
406
457
|
---
|
|
407
458
|
|
|
459
|
+
[1.0.11]: https://github.com/bymaxone/nest-queue/compare/v1.0.10...v1.0.11
|
|
460
|
+
[1.0.10]: https://github.com/bymaxone/nest-queue/compare/v1.0.9...v1.0.10
|
|
408
461
|
[1.0.9]: https://github.com/bymaxone/nest-queue/compare/v1.0.8...v1.0.9
|
|
409
462
|
[1.0.8]: https://github.com/bymaxone/nest-queue/compare/v1.0.7...v1.0.8
|
|
410
463
|
[1.0.7]: https://github.com/bymaxone/nest-queue/compare/v1.0.6...v1.0.7
|
package/README.md
CHANGED
|
@@ -87,7 +87,7 @@ peer dependencies, so you control exact versions and the supply-chain surface st
|
|
|
87
87
|
- ✅ **Stable error catalog** — namespaced codes exported from both subpaths, so a frontend maps a `code` without importing the server
|
|
88
88
|
- ✅ **Dual-format output** — ESM + CJS with declarations for each format, verified against the packed tarball on every PR
|
|
89
89
|
- ✅ **Opt-in observability** — OpenTelemetry passthrough via `bullmq-otel`, plus a `MetricsService` with a configurable TTL cache
|
|
90
|
-
- ✅ **Typed end to end** — TypeScript `strict` with `exactOptionalPropertyTypes` and `noUncheckedIndexedAccess`; zero `any`, no
|
|
90
|
+
- ✅ **Typed end to end** — TypeScript `strict` with `exactOptionalPropertyTypes` and `noUncheckedIndexedAccess`; zero `any`, no `@ts-ignore` and no `eslint-disable`
|
|
91
91
|
|
|
92
92
|
---
|
|
93
93
|
|
package/dist/server/index.cjs
CHANGED
|
@@ -378,6 +378,11 @@ exports.QueueService = class QueueService {
|
|
|
378
378
|
* **producers** and do not change the at-least-once guarantee on the
|
|
379
379
|
* **consumer** side.
|
|
380
380
|
*
|
|
381
|
+
* The deduplication `id` is a shared key across the queue, so a multi-tenant
|
|
382
|
+
* producer MUST scope it by tenant: keyed on the value alone
|
|
383
|
+
* (`` `reindex:${term}` ``), tenant A enqueuing a term suppresses tenant B's job
|
|
384
|
+
* for the same term. Include the tenant (`` `${tenantId}:reindex:${term}` ``).
|
|
385
|
+
*
|
|
381
386
|
* Deduplication modes (`deduplication: { id, ttl?, extend?, replace?, keepLastIfActive? }`):
|
|
382
387
|
* - Simple `{ id }` — collapse duplicates until the in-flight job completes or fails.
|
|
383
388
|
* - Throttle `{ id, ttl }` — ignore duplicates for `ttl` milliseconds.
|
|
@@ -391,9 +396,10 @@ exports.QueueService = class QueueService {
|
|
|
391
396
|
* @param data - Typed job payload.
|
|
392
397
|
* @param options - Per-job BullMQ options (priority, delay, `jobId`, `deduplication`, ...).
|
|
393
398
|
* @returns The created job.
|
|
394
|
-
* @example Throttle: at most one reindex per term every 5 seconds.
|
|
399
|
+
* @example Throttle: at most one reindex per term every 5 seconds. The dedup key
|
|
400
|
+
* carries the tenant so one tenant's term cannot suppress another's.
|
|
395
401
|
* await queueService.enqueue('search', 'reindex', { term }, {
|
|
396
|
-
* deduplication: { id:
|
|
402
|
+
* deduplication: { id: `${tenantId}:reindex:${term}`, ttl: 5_000 },
|
|
397
403
|
* })
|
|
398
404
|
*/
|
|
399
405
|
async enqueue(queueName, jobName, data, options) {
|
package/dist/server/index.d.cts
CHANGED
|
@@ -421,6 +421,11 @@ declare class QueueService {
|
|
|
421
421
|
* **producers** and do not change the at-least-once guarantee on the
|
|
422
422
|
* **consumer** side.
|
|
423
423
|
*
|
|
424
|
+
* The deduplication `id` is a shared key across the queue, so a multi-tenant
|
|
425
|
+
* producer MUST scope it by tenant: keyed on the value alone
|
|
426
|
+
* (`` `reindex:${term}` ``), tenant A enqueuing a term suppresses tenant B's job
|
|
427
|
+
* for the same term. Include the tenant (`` `${tenantId}:reindex:${term}` ``).
|
|
428
|
+
*
|
|
424
429
|
* Deduplication modes (`deduplication: { id, ttl?, extend?, replace?, keepLastIfActive? }`):
|
|
425
430
|
* - Simple `{ id }` — collapse duplicates until the in-flight job completes or fails.
|
|
426
431
|
* - Throttle `{ id, ttl }` — ignore duplicates for `ttl` milliseconds.
|
|
@@ -434,9 +439,10 @@ declare class QueueService {
|
|
|
434
439
|
* @param data - Typed job payload.
|
|
435
440
|
* @param options - Per-job BullMQ options (priority, delay, `jobId`, `deduplication`, ...).
|
|
436
441
|
* @returns The created job.
|
|
437
|
-
* @example Throttle: at most one reindex per term every 5 seconds.
|
|
442
|
+
* @example Throttle: at most one reindex per term every 5 seconds. The dedup key
|
|
443
|
+
* carries the tenant so one tenant's term cannot suppress another's.
|
|
438
444
|
* await queueService.enqueue('search', 'reindex', { term }, {
|
|
439
|
-
* deduplication: { id:
|
|
445
|
+
* deduplication: { id: `${tenantId}:reindex:${term}`, ttl: 5_000 },
|
|
440
446
|
* })
|
|
441
447
|
*/
|
|
442
448
|
enqueue<TData = unknown, TResult = unknown>(queueName: string, jobName: string, data: TData, options?: JobsOptions): Promise<TypedJob<TData, TResult>>;
|
package/dist/server/index.d.ts
CHANGED
|
@@ -421,6 +421,11 @@ declare class QueueService {
|
|
|
421
421
|
* **producers** and do not change the at-least-once guarantee on the
|
|
422
422
|
* **consumer** side.
|
|
423
423
|
*
|
|
424
|
+
* The deduplication `id` is a shared key across the queue, so a multi-tenant
|
|
425
|
+
* producer MUST scope it by tenant: keyed on the value alone
|
|
426
|
+
* (`` `reindex:${term}` ``), tenant A enqueuing a term suppresses tenant B's job
|
|
427
|
+
* for the same term. Include the tenant (`` `${tenantId}:reindex:${term}` ``).
|
|
428
|
+
*
|
|
424
429
|
* Deduplication modes (`deduplication: { id, ttl?, extend?, replace?, keepLastIfActive? }`):
|
|
425
430
|
* - Simple `{ id }` — collapse duplicates until the in-flight job completes or fails.
|
|
426
431
|
* - Throttle `{ id, ttl }` — ignore duplicates for `ttl` milliseconds.
|
|
@@ -434,9 +439,10 @@ declare class QueueService {
|
|
|
434
439
|
* @param data - Typed job payload.
|
|
435
440
|
* @param options - Per-job BullMQ options (priority, delay, `jobId`, `deduplication`, ...).
|
|
436
441
|
* @returns The created job.
|
|
437
|
-
* @example Throttle: at most one reindex per term every 5 seconds.
|
|
442
|
+
* @example Throttle: at most one reindex per term every 5 seconds. The dedup key
|
|
443
|
+
* carries the tenant so one tenant's term cannot suppress another's.
|
|
438
444
|
* await queueService.enqueue('search', 'reindex', { term }, {
|
|
439
|
-
* deduplication: { id:
|
|
445
|
+
* deduplication: { id: `${tenantId}:reindex:${term}`, ttl: 5_000 },
|
|
440
446
|
* })
|
|
441
447
|
*/
|
|
442
448
|
enqueue<TData = unknown, TResult = unknown>(queueName: string, jobName: string, data: TData, options?: JobsOptions): Promise<TypedJob<TData, TResult>>;
|
package/dist/server/index.mjs
CHANGED
|
@@ -376,6 +376,11 @@ var QueueService = class {
|
|
|
376
376
|
* **producers** and do not change the at-least-once guarantee on the
|
|
377
377
|
* **consumer** side.
|
|
378
378
|
*
|
|
379
|
+
* The deduplication `id` is a shared key across the queue, so a multi-tenant
|
|
380
|
+
* producer MUST scope it by tenant: keyed on the value alone
|
|
381
|
+
* (`` `reindex:${term}` ``), tenant A enqueuing a term suppresses tenant B's job
|
|
382
|
+
* for the same term. Include the tenant (`` `${tenantId}:reindex:${term}` ``).
|
|
383
|
+
*
|
|
379
384
|
* Deduplication modes (`deduplication: { id, ttl?, extend?, replace?, keepLastIfActive? }`):
|
|
380
385
|
* - Simple `{ id }` — collapse duplicates until the in-flight job completes or fails.
|
|
381
386
|
* - Throttle `{ id, ttl }` — ignore duplicates for `ttl` milliseconds.
|
|
@@ -389,9 +394,10 @@ var QueueService = class {
|
|
|
389
394
|
* @param data - Typed job payload.
|
|
390
395
|
* @param options - Per-job BullMQ options (priority, delay, `jobId`, `deduplication`, ...).
|
|
391
396
|
* @returns The created job.
|
|
392
|
-
* @example Throttle: at most one reindex per term every 5 seconds.
|
|
397
|
+
* @example Throttle: at most one reindex per term every 5 seconds. The dedup key
|
|
398
|
+
* carries the tenant so one tenant's term cannot suppress another's.
|
|
393
399
|
* await queueService.enqueue('search', 'reindex', { term }, {
|
|
394
|
-
* deduplication: { id:
|
|
400
|
+
* deduplication: { id: `${tenantId}:reindex:${term}`, ttl: 5_000 },
|
|
395
401
|
* })
|
|
396
402
|
*/
|
|
397
403
|
async enqueue(queueName, jobName, data, options) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bymax-one/nest-queue",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.11",
|
|
4
4
|
"description": "NestJS dynamic module wrapping BullMQ — typed jobs, flows, job schedulers, deduplication, OpenTelemetry, graceful shutdown",
|
|
5
5
|
"author": "Bymax One <support@bymax.one>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -56,15 +56,16 @@
|
|
|
56
56
|
"scripts": {
|
|
57
57
|
"build": "pnpm clean && tsup",
|
|
58
58
|
"check:exports": "attw --pack .",
|
|
59
|
+
"check:mutants": "node scripts/check-mutation-directives.mjs",
|
|
59
60
|
"check:published": "node scripts/check-published-surface.mjs",
|
|
60
61
|
"clean": "rm -rf dist coverage",
|
|
61
62
|
"lint": "eslint src scripts test",
|
|
62
63
|
"lint:fix": "eslint src scripts test --fix",
|
|
63
64
|
"mutation": "stryker run",
|
|
65
|
+
"mutation:full": "node -e \"require('node:fs').rmSync('reports/stryker-incremental.json',{force:true,recursive:true})\" && stryker run",
|
|
64
66
|
"mutation:dry-run": "stryker run --dryRunOnly",
|
|
65
|
-
"mutation:incremental": "stryker run --incremental",
|
|
66
67
|
"prepare": "husky",
|
|
67
|
-
"prepublishOnly": "pnpm clean && pnpm typecheck && pnpm test:types && pnpm lint && pnpm test:cov:all && pnpm build && pnpm check:published",
|
|
68
|
+
"prepublishOnly": "pnpm clean && pnpm typecheck && pnpm test:types && pnpm lint && pnpm check:mutants && pnpm test:cov:all && pnpm build && pnpm check:published",
|
|
68
69
|
"release": "npm publish --provenance --access public",
|
|
69
70
|
"size": "node scripts/check-size.mjs",
|
|
70
71
|
"smoke": "node scripts/dogfood-smoke-test.mjs",
|