mq (@techteamer/mq)

A standalone, MIT-licensed RabbitMQ wrapper library for Node.js, published to npm as @techteamer/mq. It is NOT a FaceKom service in itself — it is a reusable messaging client/server toolkit authored by TechTeamer and consumed by FaceKom/vuer backend services to talk to RabbitMQ. The repo builds a dual CommonJS + ESM npm package from TypeScript source; there is no long-running process, no HTTP server, no Dockerfile here.

Role in FaceKom

This is an upstream dependency, published openly on npm (publishConfig.access: public, package.json:69-71) and GitHub (TechTeamer/mq). FaceKom backends import it to get RPC / Pub-Sub / Gathering / work-queue patterns over AMQP. The only direct FaceKom coupling visible in-tree is the test config, which points TLS certs at a vuer_docker path (see vuer_docker and Configuration below). “vuer” is FaceKom’s product codename.


1. Purpose & role

  • package.json:1-7 — name @techteamer/mq, version 7.2.0, description “A RabbitMQ wrapper for node”, main: dist/cjs/index.js, module: dist/mjs/index.js, dual exports map for import/require.
  • README.md:1-34 — title “TechTeamer MQ”, install via yarn add @techteamer/mq, build via yarn run build, tests require renaming a sample test config. npm / Travis / Coveralls badges.
  • index.js:1-32 — the package entry: imports 13 classes from ./src/*.js and re-exports them: QueueClient, QueueConfig, QueueConnection, ConnectionPool, QueueMessage, QueueServer, QueueManager, RPCClient, RPCError, RPCServer, Publisher, Subscriber, GatheringClient, GatheringServer. (Note: src/QueueResponse.ts is the 15th .ts file in src/ but is not re-exported here.)

It implements four messaging patterns on top of amqplib:

PatternClient classServer classAMQP mechanism
RPC (request/response)RPCClientRPCServersendToQueue + per-call reply queue, correlationId matching (RPCClient.ts:128-159, RPCServer.ts:193-254)
Pub/Sub (fan-out broadcast)PublisherSubscriberfanout exchange, exclusive auto-delete queue per subscriber (Publisher.ts:54-58, Subscriber.ts:86-102)
Work queue (point-to-point, durable)QueueClientQueueServernamed durable queue, prefetch, retry counter (QueueClient.ts:32-36, QueueServer.ts:36-50)
Gathering (scatter→gather from N servers)GatheringClientGatheringServerfanout exchange + status queue, counts responses vs serverCount (GatheringClient.ts:120-174, GatheringServer.ts:122-201)

2. Tech stack & runtime

  • Language: TypeScript (15 .ts files in src/), compiled with tsc. index.js is plain ESM JS.
  • Runtime: Node.js. package.json:23-25 engines: "node": "^22.13.0 || >=24". "type": "module" (package.json:33).
  • Package manager: Yarn (classic; yarn.lock present, 270 KB; README and CI use yarn). Resolutions block at package.json:72-77.
  • Runtime dependency (only one): amqplib ^0.10.9 (package.json:34-37). Also a stray runtime dep @typescript-eslint/parser is listed under dependencies (package.json:35) — unusual; everything else is dev.
  • Peer dependency: protobufjs ^7.2.3 (package.json:66-68) — optional, only relevant if a caller passes a non-JSON ContentSchema / MessageModel.
  • Build tooling: typescript ^5.4.5, dual-target tsc. Test runner: vitest ^4.1.4 (package.json:64); coverage via c8 ^9.1.0. Lint: eslint ^9.19.0 flat config. Release: semantic-release ^24 (package.json:61).

Vitest, not Jest — despite the name

The repo depends on and configures Jest ESLint plugins (eslint-plugin-jest, eslint-plugin-jest-formatting) and eslint.config.mjs wires jest globals, but the actual test runner is vitest (package.json scripts test: vitest run; every test/*.test.ts imports { describe, it, assert, beforeAll, afterAll } from 'vitest', e.g. test/RPC.test.ts:2). The Jest references are legacy lint config. The CI workflow even uploads coverage to a test/coverage/jest/lcov.info path (.github/workflows/pull-request.yaml:135), but the test script writes lcov to ./test/coverage/ (package.json:31) — these paths are inconsistent.


3. Build & run

This is a library, not an app — “run” means build the npm artifact and run tests against a live RabbitMQ. There is no bin/, no CLI entrypoint, no Dockerfile, no start command in this repo.

package.json “scripts” (verbatim, every entry)

ScriptCommand (verbatim)What it does
buildrm -fr dist/* && tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && ./fixup.shCleans dist/, compiles ESM build (→ dist/mjs) and CJS build (→ dist/cjs), then runs fixup.sh.
linteslint . --max-warnings 0 --ignore-pattern "test/*" && echo 'npm run eslint --max-warnings 0'Lints everything except test/* with zero-warning tolerance, then echoes a (cosmetic) confirmation line.
lint:fixeslint . --fix && eslint --max-warnings 0 .Auto-fixes, then re-lints with zero-warning tolerance (lint must be clean after fix).
testvitest runRuns the vitest suite once (non-watch). Requires a reachable RabbitMQ + a test/config/TestConfig.ts.
test:cic8 --temp-directory=./test/coverage/tmp vitest run && c8 report --reporter=text-lcov --report-dir=./test/coverage/ --reporter=lcovonlyRuns vitest under c8 coverage, then emits an lcov-only report into test/coverage/. Used by CI.

Publish requires a fresh build

README.md:31-34: “Before publish always run the build process!” — the published package needs dist/, which is .gitignored (/.gitignore:4). Actual publishing is automated by semantic-release (release.config.mjs), not a manual npm publish.

Build helper scripts (top-level .sh)

  • fixup.sh (fixup.sh:1-11) — after tsc produces both builds, writes dist/cjs/package.json containing {"type":"commonjs"} and dist/mjs/package.json containing {"type":"module"}. This is the standard dual-package trick so Node resolves each subtree with the correct module system.
  • jstsconvert.sh (jstsconvert.sh:1-36) — a one-off migration helper (NOT used by build/CI). Takes a folder path argument and renames every *.js in that folder to *.ts (mv). Leftover from the JS→TS migration; safe to ignore for normal dev.

Entrypoints

  • Package consumers: dist/cjs/index.js (require) / dist/mjs/index.js (import), declared in exports (package.json:7-12).
  • Source entry: index.js (re-export barrel) + src/*.ts.

4. Top-level structure

Verified by find (excluding .git, node_modules). No vendored dirs are tracked (node_modules/ and dist/ are git-ignored).

PathWhat it is
index.jsESM barrel re-exporting all 13 public classes (index.js:17-32).
src/All TypeScript source — 15 .ts files, the entire library (see §6).
test/Vitest suites (14 *.test.ts) + test/config/ + consoleInspector.ts test helper.
test/config/LoadConfig.ts, TestConfig.ts (TLS local), TestConfig-ci.ts (plain guest) — see §7.
.github/workflows/pull-request.yaml — the only CI workflow (lint/audit/test/sonar/build).
maintenance/Dependency-update audit notes (2026-04-07.md, 2026-05-04.md) listing deferred dep upgrades + yarn audit/yarn outdated logs. Documentation only.
security/Security audit notes (2026-04-07.md 685 KB, 2026-05-04.md) — yarn audit “before/after” logs for vulnerable transitive deps (e.g. request, uuid, postcss). Documentation only.
package.jsonManifest (deps, scripts, engines, exports).
tsconfig*.jsonTS compiler configs (base + esm + cjs).
eslint.config.mjsFlat ESLint config (shared across TechTeamer repos — see gotcha).
release.config.mjssemantic-release config.
sonar-project.propertiesSonarCloud project config.
fixup.sh, jstsconvert.shBuild helper + migration helper (§3).
CHANGELOG.mdAuto-generated by semantic-release (angular preset).
.editorconfig, .gitignore, .npmignoreEditor/VCS/publish ignore rules.

maintenance/ and security/ are bookkeeping, not code

Both folders hold dated Markdown reports of pending dependency upgrades and yarn audit output (maintenance/2026-05-04.md:1-25, security/2026-05-04.md:1-25). The security/2026-04-07.md file is ~685 KB of captured audit logs. They have no effect on the build.


5. First-party bin/ helper scripts

There is no first-party bin/ directory in this repo

Confirmed by full find of the tree. eslint.config.mjs:111-121 defines lint overrides for bin/* / bin/**/*, but those globs match nothing here — that config is a shared template copied across TechTeamer/FaceKom repos and references many directories that do not exist in mq (server/, engines/, client/, customization/ui/, db/, bin/; eslint.config.mjs:72-139). The only executable scripts are the two top-level build helpers documented in §3: fixup.sh and jstsconvert.sh.


6. Key modules (src/)

Read in full. Listed roughly foundational → high-level.

Connection & config layer

  • QueueConfig.ts (173 lines) — config value object. Defaults: url: 'amqps://localhost:5672', rpcTimeoutMs: 10000, rpcQueueMaxSize: 100, logger: console, shuffleUrls: false (QueueConfig.ts:77-108). Holds per-component assert-queue/assert-exchange option bags (e.g. rpcServerAssertQueueOptions, subscriberAssertExchangeOptions, …). Nested RabbitMqOptions class for TLS (rejectUnauthorized, cert, key, ca[], optional timeout) (QueueConfig.ts:11-33). Statics: isValidConfig (checks url own-prop), urlStringToObject (parses an amqp URL into {protocol,hostname,port,username,password,vhost} via node:url), urlObjectToLogString (QueueConfig.ts:142-170).
  • QueueConnection.ts (222 lines) — extends EventEmitter. Wraps a single amqplib connection + one shared ConfirmChannel. Uses the promise channel API connect from amqplib/channel_api (QueueConnection.ts:3). connect() memoizes via _connectionPromise; reads cert/key/ca files from disk with readFileSync (QueueConnection.ts:56-65). Supports multiple hosts / URL arrays with optional shuffleUrls random ordering and sequential failover (_connectWithMultipleUrls, QueueConnection.ts:108-155). Re-emits error/close/blocked/unblocked connection events and error/close/return/drain channel events; guards error emit on listenerCount('error') > 0 to avoid uncaught exceptions (QueueConnection.ts:81-106, 198-219). getChannel() lazily creates a createConfirmChannel (QueueConnection.ts:176-196).
  • ConnectionPool.ts (107 lines) — manages multiple named QueueManager connections. setupQueueManagers() accepts either a single config (backwards-compatible) or a Record<name, config> map with a designated default (defaultConnectionName, default 'default') (ConnectionPool.ts:22-58). connect() connects all in parallel; reconnect() sequentially (ConnectionPool.ts:94-104). Imports ConsoleInspector from ../test/... for its logger type (ConnectionPool.ts:3) — a test-dir import leaking into src.

Message model

  • QueueMessage.ts (96 lines) — the wire format. Fields status, data, timeOut, attachments: Map<string,Buffer>, ContentSchema (default JSON). Custom binary framing in serialize(): a 1-byte '+' marker + 4-byte big-endian JSON length + JSON body + concatenated attachment buffers (QueueMessage.ts:28-50). unserialize() understands both the '+' framed format (with attachments) and a bare '{' legacy JSON message; throws on unknown format (QueueMessage.ts:52-73). fromJSON tolerant parse returns an error-status message on failure.
  • QueueResponse.ts (96 lines) — server-side response builder with status constants OK / NOT_FOUND / ERROR and helpers ok()/notFound()/error(), plus an attachments map. Used by RPCServer and GatheringServer handlers.
  • RPCError.ts (5 lines) — empty class RPCError extends Error {}. Exported but not thrown internally (consumer-facing marker type).

Messaging primitives

  • Publisher.ts (116 lines) — base publisher. assertExchange defaults true → asserts a fanout exchange (Publisher.ts:54-58). send() builds a MessageModel (default QueueMessage), serializes, channel.publish(...) with confirm callback and drain back-pressure handling (Publisher.ts:69-112). sendAction(action, data, …) wraps {action, data}. Pluggable MessageModel / ContentSchema.
  • Subscriber.ts (232 lines) — base consumer for fan-out. Asserts fanout exchange, an exclusive auto-delete anonymous queue, binds it, consumes (Subscriber.ts:86-102). Action registry via registerAction(action, handler) (Subscriber.ts:73-81). _processMessage enforces a per-message timeout (request.timeOut ?? _timeoutMs), ack/nack with double-ack guards, and a redelivery retry counter keyed by consumerTag capped at maxRetry (Subscriber.ts:154-221).
  • RPCClient.ts (235 lines) — request side. Lazily asserts an exclusive auto-delete reply queue (or named, optionally bound to a direct exchange via bindDirectExchangeName) and consumes it noAck (RPCClient.ts:171-198). call() enforces rpcQueueMaxSize, registers a crypto.randomUUID() correlationId with a per-call timeout, sendToQueue(name, …, {correlationId, replyTo}) (RPCClient.ts:128-159). _onReply matches by correlationId, resolves data (or full message if resolveWithFullResponse), rejects on non-ok status (RPCClient.ts:205-232). callAction(action, data, …) convenience.
  • RPCServer.ts (265 lines) — response side. Asserts a durable named queue, optional direct exchange, prefetch, consumes (RPCServer.ts:94-113). _processMessage runs the registered action handler under a response timeout, builds a reply via QueueResponse, replies to msg.properties.replyTo (via sendToQueue or publish to the bound direct exchange), and acks (RPCServer.ts:193-254). Distinct error paths: request-decode error, response timeout, response error — each sends a typed error reply (RPCServer.ts:129-181).
  • QueueClient.ts (39 lines) — extends Publisher. A point-to-point durable work-queue producer: asserts a named durable queue (instead of an exchange) and publishes with the queue name as routing key (QueueClient.ts:11-37).
  • QueueServer.ts (53 lines) — extends Subscriber. Consumes the named durable queue directly (asserts durable queue, prefetch, consume) rather than binding to a fan-out exchange (QueueServer.ts:36-50). Inherits Subscriber’s retry/timeout/ack machinery.
  • GatheringClient.ts (283 lines) — scatter side. Publishes to a fanout exchange, then collects replies on a reply queue, distinguishing type:'status' vs type:'reply' messages and counting responses against the live consumerCount of a shared status queue (GatheringClient.ts:120-174, 225-280). Supports acceptNotFound, resolveWithFullResponse, serverCount, and per-request timeout with responseCount/serverCount reporting.
  • GatheringServer.ts (298 lines) — gather side. Binds an exclusive queue to the fan-out exchange, also owns a non-exclusive shared status queue (GatheringServer.ts:49-78). For each announcement: runs the action handler under a timeout, then replies (type:'reply') on OK, or sends a status message + nack(requeue=false) on NOT_FOUND/timeout/error (GatheringServer.ts:122-201). Implicit status: undefined answer → NOT_FOUND, else OK (GatheringServer.ts:160-167).

Orchestrator

  • QueueManager.ts (341 lines) — the main façade. Owns one QueueConnection + a QueueConfig, and eight Maps of named entities (rpcClients, rpcServers, publishers, subscribers, queueClients, queueServers, gatheringClients, gatheringServers) (QueueManager.ts:39-53). connect() opens the connection then initialize()s every registered entity in order (QueueManager.ts:55-95); reconnect() closes + reconnects. Factory getters getRPCClient/getRPCServer/getPublisher/getSubscriber/getGatheringClient/getGatheringServer/getQueueClient/getQueueServer each: return the cached instance if present, accept an optional OverrideClass subclass (validated via _isSubClass, else throw) plus an options bag, and merge per-type defaults from config (e.g. RPC server prefetchCount:1, subscriber maxRetry:5) (QueueManager.ts:112-338). This is the class FaceKom consumers instantiate.

7. Configuration

Library config — QueueConfig (consumer-supplied)

Callers pass an IQueueConfig object (interface at QueueConfig.ts:35-55). There is no getconfig / AJV / dotenv in this repo — config is plain constructor objects, validated only by QueueConfig.isValidConfig (presence of url). Notable knobs (defaults in QueueConfig.ts:78-108):

  • url — amqp(s) URL or an array of URLs or an object with a hostname array (multi-host failover, QueueConnection.ts:108-150). Default amqps://localhost:5672.
  • options — TLS: rejectUnauthorized (default false), cert, key, ca[] (file paths, read at connect time), optional timeout.
  • rpcTimeoutMs (10000), rpcQueueMaxSize (100), logger (default console), shuffleUrls (false).
  • Per-component option bags: rpcClientExchangeOptions, rpcServerAssertQueueOptions, publisherAssertExchangeOptions, subscriberAssertQueueOptions, gatheringServerAssertExchangeOptions, queueClientAssertQueueOptions, etc.

Test config (the only env-driven config)

  • test/config/LoadConfig.ts (:1-13) — selects config by env: if process.env.NODE_ENV === 'ci'TestConfig-ci, else dynamic-imports TestConfig (and logs an error if that file is missing).
  • test/config/TestConfig.ts (:1-17) — local TLS config: url: 'amqps://localhost:5671', with cert/key/ca read from /workspace/vuer_docker/workspace/cert/vuer_mq_cert/... (TestConfig.ts:4). This is the one direct FaceKom/vuer coupling in the codebase — it expects the vuer_docker dev environment’s generated MQ certificates. .gitignore:3 ignores test/config/TestConfig.js (the legacy JS form).
  • test/config/TestConfig-ci.ts (:1-12) — plain config for CI: url: 'amqp://guest:guest@localhost:5672', rejectUnauthorized: false. Matches the RabbitMQ service container in CI.
  • Both wrap a ConsoleInspector (test logger, test/consoleInspector.ts) cast as Console.

Tests need a real RabbitMQ + a hand-created config

README.md:22-29: to run tests you must rename a sample config to TestConfig.js and provide valid values. In this clone the config files are already .ts and present, but TestConfig.ts hard-codes an absolute /workspace/vuer_docker/... cert path that only exists inside the FaceKom docker dev env. For a generic local run, use NODE_ENV=ci against a guest RabbitMQ on localhost:5672, or edit TestConfig.ts.

Build config

  • tsconfig-base.json (:1-25) — shared: baseUrl: src, rootDir: ., declaration: true, lib: [esnext], types: [node], moduleResolution: node, strict: false, allowJs: true, noFallthroughCasesInSwitch: true; includes src + index.js, excludes node_modules/dist.
  • tsconfig.json (:1-8) — ESM build: module: esnext, target: esnext, outDir: dist/mjs.
  • tsconfig-cjs.json (:1-8) — CJS build: module: commonjs, target: es2022, outDir: dist/cjs.

Other tool configs

  • release.config.mjs (:1-22) — semantic-release: branches master + beta(prerelease); tagFormat: '${version}'; plugins commit-analyzer, release-notes-generator, changelog, npm, github, git; angular preset. → drives versioning + npm/GitHub publish.
  • sonar-project.properties (:1-9) — SonarCloud TechTeamer_mq / org techteamer; sources ., coverage excludes test/** + index.js; lcov path test/coverage/lcov.info.
  • eslint.config.mjs — flat config extending standard, plugin:n/recommended, plugin:jest-formatting/strict; no-console: error globally (relaxed for the non-existent engines/,db/,bin/,client/ dirs). Ignores dist/.

8. Tests

  • Framework: vitest (package.json:30-31, all test/*.test.ts import from 'vitest'). Coverage via c8.
  • Location: test/ — 14 spec files: RPC.test.ts, RPCAction.test.ts, Pubsub.test.ts, PubSubAction.test.ts, Queue.test.ts, QuorumQueues.test.ts, Gathering.test.ts, Gathering-multi-server.test.ts, GatheringAction.test.ts, ConnectionPool.test.ts, QueueConnection.test.ts, QueueManager.test.ts, QueueConfig.test.ts, QueueMessage.test.ts. Helper: test/consoleInspector.ts (records logger calls instead of printing; test/consoleInspector.ts:1-37).
  • Nature: Integration tests against a live broker — they new QueueManager(config) and connect() to RabbitMQ (e.g. test/RPC.test.ts:1-20, test/QuorumQueues.test.ts:10-29). Queue/exchange names are namespaced techteamer-mq-js-test-*. QuorumQueues.test.ts exercises x-queue-type: quorum via the manager’s assert-option overrides.
  • How to run locally: yarn test (needs test/config/TestConfig.ts + a reachable broker, default TLS amqps://localhost:5671). Easiest path: NODE_ENV=ci yarn test against a plain RabbitMQ on localhost:5672 (amqp://guest:guest@localhost:5672).
  • CI: .github/workflows/pull-request.yaml runs on every PR — jobs lint, audit (yarn audit + improved-yarn-audit --min-severity critical), test (yarn test:ci with a rabbitmq:4.1.4 service container on ports 5672/5671, NODE_ENV: ci), sonar (SonarCloud scan, needs test), build (yarn build, needs lint+audit+test+sonar). Node version pinned to 24 (pull-request.yaml:11).

9. Dependencies on other FaceKom services

No runtime coupling to FaceKom services

As a generic library, mq does not itself call any FaceKom HTTP endpoint, DB, Redis, or named RabbitMQ queue. Its only external runtime is RabbitMQ (AMQP 0.9.1 via amqplib) — the broker URL is entirely supplied by the consumer.

Evidenced FaceKom touch-points (all build/test-time, not runtime):

  • test/config/TestConfig.ts:4 references /workspace/vuer_docker/workspace/cert/vuer_mq_cert — the MQ TLS certs generated by the FaceKom/vuer docker dev environment (vuer_docker). This is how FaceKom services (e.g. vuer_cv and other vuer backends) and this library’s tests are expected to authenticate to the shared broker over amqps://...:5671.
  • CHANGELOG.md lines reference internal Jira tickets FKITDEV-3756, FKITDEV-6045 — confirming this repo is maintained inside the FaceKom (FKITDEV) program even though published publicly.

For how a FaceKom backend uses this library, instantiate QueueManager with the broker config, register RPC/queue/subscriber/gathering actions, and connect() — see §6 QueueManager.


10. Verified gotchas

rejectUnauthorized defaults to false

Both QueueConfig’s RabbitMqOptions default (QueueConfig.ts:21) and both test configs disable TLS cert verification. Production callers using amqps:// should override options.rejectUnauthorized: true and supply a proper ca, or they get unverified TLS.

One shared confirm channel per connection

QueueConnection.getChannel() memoizes a single ConfirmChannel and hands it to every entity (QueueConnection.ts:176-196). All publishers/consumers on one QueueManager share that channel; a channel-level error closes it for everyone. Use multiple connections via ConnectionPool to isolate.

Custom wire format — not interoperable with plain JSON producers unless framed

QueueMessage.serialize() emits a proprietary '+'-prefixed length-framed binary envelope (QueueMessage.ts:28-50). unserialize can still read a bare '{...}' JSON body, but anything else throws “unrecognized format”. Non-mq producers/consumers must match this framing (or send bare JSON with a top-level status).

Subscriber/Queue retry is keyed by consumerTag, capped at maxRetry

On redelivery, Subscriber increments a per-consumerTag counter and, once it exceeds maxRetry (default 5 from QueueManager), acks and drops the message (Subscriber.ts:154-175). Failures are not dead-lettered by the library.

eslint.config.mjs is a shared multi-repo template

It configures globals/rules for server/, engines/, client/, customization/ui/, db/, bin/none of which exist in mq (eslint.config.mjs:72-139). Do not infer repo structure from it. The real source lives only in src/ and test/.

ConnectionPool imports from the test directory

src/ConnectionPool.ts:3 imports ConsoleInspector from ../test/consoleInspector purely for a logger type annotation. This couples a src/ file to test/; it compiles because tsconfig includes index.js+src but skipLibCheck/loose settings tolerate it. Worth noting if the test dir is ever stripped from a build context.

Shallow clone — limited git history

This source-only clone shows a single reachable commit on master (4926e0a ci [fkitdev-8416] improve github actions (#88), 2026-05-19). Use CHANGELOG.md for release history rather than git log.


Unverified / gaps

  • maintenance/2026-04-07.md, security/2026-04-07.md — read only the headers/structure of the dated audit notes (the security/2026-04-07.md file is ~685 KB of captured yarn audit logs). Their contents are dependency-vulnerability dumps with no bearing on architecture; not read line-by-line.
  • Test specs — confirmed the framework (vitest), import patterns, and broker-integration nature by reading RPC.test.ts (head), QuorumQueues.test.ts (full), and consoleInspector.ts (full); the remaining ~11 *.test.ts files were surveyed structurally (names + grep for shared techteamer-mq-js-test-* naming), not read in full.
  • CHANGELOG.md — read the top ~30 lines + ticket refs; full release history not transcribed.
  • No Git-LFS pointer files were found in this repo (no model weights/binaries) — this is a pure-source library; nothing was withheld for being a binary blob.
  • Downstream consumers — that FaceKom backends import @techteamer/mq is inferred from the vuer_docker cert path and FKITDEV changelog tickets; the actual import sites live in other repos (e.g. vuer_cv) and were not inspected here.

Sources

Files read in full unless noted:

  • package.json, README.md, index.js
  • tsconfig-base.json, tsconfig.json, tsconfig-cjs.json
  • fixup.sh, jstsconvert.sh
  • eslint.config.mjs, release.config.mjs, sonar-project.properties, .npmignore, .gitignore
  • src/QueueConfig.ts, src/QueueConnection.ts, src/ConnectionPool.ts, src/QueueMessage.ts, src/QueueResponse.ts, src/RPCError.ts, src/Publisher.ts, src/Subscriber.ts, src/RPCClient.ts, src/RPCServer.ts, src/QueueClient.ts, src/QueueServer.ts, src/GatheringClient.ts, src/GatheringServer.ts, src/QueueManager.ts
  • .github/workflows/pull-request.yaml
  • test/config/LoadConfig.ts, test/config/TestConfig.ts, test/config/TestConfig-ci.ts, test/consoleInspector.ts, test/QuorumQueues.test.ts (full), test/RPC.test.ts (head)
  • CHANGELOG.md (head + grep), maintenance/2026-05-04.md (head), security/2026-05-04.md (head)
  • Directory listing via find (whole tree); git -C log/branch for HEAD + branches