Skip to content

chore: version packages - #255

Open
connectum-release-bot[bot] wants to merge 1 commit into
mainfrom
changeset-release/main
Open

chore: version packages#255
connectum-release-bot[bot] wants to merge 1 commit into
mainfrom
changeset-release/main

Conversation

@connectum-release-bot

@connectum-release-bot connectum-release-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Version Packages PR generated by the Changesets release workflow. Merging it publishes all packages to npm (OIDC + provenance) and creates the draft GitHub Release. Notes below are produced by scripts/build-release-notes.mjs (highlights-first, deduplicated); full per-package detail lives in each package's CHANGELOG.md.

Highlights

  • Project scaffolding — the new connectum init scaffolds a production-ready project, interactively or fully from flags, composing only the modules you pick (OpenTelemetry, EventBus with an adapter, auth, service catalog, resilience), and connectum generate service adds a service with a starter proto and a defineService skeleton (#229).
  • Reliable AMQP publishing — opt-in publishRetry on @connectum/events-amqp auto-retries connection-class publish failures (never nacks/timeouts) with bounded backoff and honest at-least-once semantics (#222), and the new drainPublishTimeout on @connectum/events gives in-flight publishes a bounded drain window during stop() (#220).
  • Deterministic AMQP failure policyinitialConnectMaxRetries bounds the first connect (#219), and treatTopologyErrorAsFatal stops infinite recovery on deterministic topology drift (404/406) at runtime, mirroring the 1.2.0 startup fail-fast (#218).
  • Observable AMQP lifecycle — the new discriminated onLifecycle callback delivers the full connection-lifecycle event union in guaranteed order (#216), and AmqpTopologyError now carries a machine-readable .object identifying the failing exchange/queue/binding (#217).
  • Broker-free AMQP testing — the new @connectum/events-amqp/testing subpath ships a programmable FakeAmqpAdapter: FIFO publish outcomes with the real typed errors, a deterministic recovery control surface, and delivery with settlement counts (#224).
  • Typed adapter DI@connectum/events exports the EventAdapterFactory type for per-consumer adapter wiring and test seams (#223).

Repo-wide changes

These changeset entries appear identically across multiple packages and are listed once.

  • #243 10a3e58 Thanks @intech! - Update protobuf-es to 2.13.0 and clear the remaining dependency advisories.

    @bufbuild/protobuf, @bufbuild/protoc-gen-es and @bufbuild/protoplugin move to
    2.13.0, and @bufbuild/buf to 1.72.0. The single-instance pin moves with them:
    @bufbuild/protoplugin was still on 2.12.1 and pinned a second copy of
    @bufbuild/protobuf, which is exactly the split the pin exists to prevent -- two
    instances break @connectrpc/connect's protobuf peer and the reflection DTS build.
    The workspace now resolves a single 2.13.0.

    connect-es is unchanged: @connectrpc/connect and @connectrpc/connect-node 2.1.2
    are already the latest published releases.

    Several overrides were pinned to the version that closed an earlier advisory
    and had since been superseded: brace-expansion 5.0.5 -> 5.0.9, js-yaml 4.2.0 ->
    4.3.0 (plus a new pin for the 3.x line @changesets/cli pulls), fast-uri 3.1.2 ->
    3.1.5, basic-ftp 5.2.2 -> 5.3.1, protobufjs 7.6.3 -> 7.6.5, and new pins for
    ip-address, linkify-it, undici and ws. Every target is published and stays
    inside the major already installed.

    pnpm audit now reports no vulnerabilities at any severity, dev included; it
    previously reported 1 critical, 21 high and 14 moderate.

    Affects: @connectum/auth, @connectum/core, @connectum/events, @connectum/healthcheck, @connectum/interceptors, @connectum/otel, @connectum/protoc-gen-catalog, @connectum/reflection, @connectum/testing (9 packages).

  • #254 d9f9fb4 Thanks @intech! - Add configurable RESP2 and RESP3 Redis Streams support while preserving RESP2 as the backward-compatible default, and refresh the Redis, AMQP testcontainer, and authentication dependencies.

    Affects: @connectum/auth, @connectum/events-amqp, @connectum/events-redis (3 packages).

  • #214 e2b613b Thanks @intech! - docs: recovery backoff tuning and publisher shutdown guidance

    • events-amqp: accurate reconnect-delay semantics in README and AmqpRecoveryOptions JSDoc — the amqplib v2 strategy is symmetric jitter around the exponential base (not equal-jitter), with the cap applied before jitter (hence the overshoot above maxDelay). Documented the exact full-jitter workaround (jitter: 1 + halved initialDelay/maxDelay → delay uniform in [0, intended cap], verified against amqplib 2.0.1) with a fragility caveat and upstream tracking links (recovery: allow a custom delay strategy (calculateDelay option) amqp-node/amqplib#855, recovery: separate retry budget for the initial connect amqp-node/amqplib#856).
    • events: new "Publishers and Shutdown" README section — stop() drains consumer handlers only; await-before-stop recipe for at-least-once producers; the stopping-gate limitation for publishes from draining handlers (#212); the planned opt-in drainPublishTimeout (#196).

    Affects: @connectum/events, @connectum/events-amqp (2 packages).

Package changes

@connectum/auth@1.3.0

No package-specific changes beyond the repo-wide items above.

@connectum/cli@1.3.0

Minor

  • #229 8ed62cf Thanks @intech! - feat: connectum init and connectum generate service — project scaffolding

    • connectum init scaffolds a production-ready standalone project, interactively (a @clack/prompts wizard) or fully from flags (--yes / CI / non-TTY). The base is fetched from the dogfooded getting-started example via a degit-style clone, so the starter layout stays in sync with a tested example instead of a drift-prone template copy; the selected modules are composed on top.
    • Modules: OpenTelemetry (--otel), EventBus with an adapter (--events nats|kafka|redpanda|redis|amqp), auth (--auth, JWT + proto-driven authorization), service catalog (--catalog, typed ctx.call/ctx.stream), opt-in resilience interceptors (--resilience timeout,retry,...), and health/reflection toggles. Runtime (node/bun), package manager (pnpm/npm/bun) and the Node execution model (raw .ts >= 25.2 vs tsx >= 22.13) are all first-class choices.
    • Deterministic interceptor order. When several interceptor-adding modules are selected the composition root emits one canonical chain (outermost → innermost): OpenTelemetry → error handler → auth → validation → resilience → custom, with exactly one error handler.
    • Lifecycle fix baked in. buf generate is chained into the generated start / test / typecheck scripts (not a pnpm pre* hook, which silently no-ops), so a fresh clone never fails with an unresolved #gen/... import. Standalone pnpm projects also get the buf build-approval that pnpm 11 requires.
    • connectum generate service <name> adds a service to an existing project: a starter proto plus a defineService skeleton whose rpc handlers throw Code.Unimplemented (a deliberate, documented trade-off — the handler-map key must still exist, so a later proto method addition remains a compile error). --with-events also scaffolds an event-handler service and an ack-by-default EventRoute. It never edits your src/server.ts; it prints the exact registration to add.
    • Generated tests are runtime-agnostic: the e2e test uses the public in-process createLocalClient from @connectum/testing (no socket, identical on Node and Bun); event-enabled projects also get a broker-free MemoryAdapter smoke test.
    • A CI scaffold matrix (cli-scaffold-matrix) scaffolds each named module combination and runs buf generate → typecheck → test, so a broken fragment fails CI.

Patch

  • #229 8ed62cf Thanks @intech! - Fetch the init base project with giget instead of tiged.

    tiged depends on tar, and the releases it pins (^6.1.11) carry a critical
    decompression denial-of-service advisory and a high-severity arbitrary
    file-overwrite advisory. tiged@2.12.8 is its latest release, so upgrading does not
    reach a fixed tar — the constraint is in tiged itself. That matters more here
    than it would elsewhere: a scaffolder exists to download and unpack a remote
    archive, so the extraction path is exactly the exposed one.

    giget is the maintained degit-style downloader from the same project family as
    citty, which this CLI already uses, and it has no dependencies at all. The
    change removes the critical and both high advisories from the CLI's production
    dependency closure and drops nine transitive packages.

    The fetcher was already injectable behind CloneFn, so the change is confined to
    the default implementation. The only externally visible difference is the spec
    format: giget needs its gh: provider prefix, so the base is now requested as
    gh:Connectum-Framework/examples/getting-started#<ref>. connectum init was run
    end to end against the real repository to confirm it.

@connectum/core@1.3.0

No package-specific changes beyond the repo-wide items above.

@connectum/events@1.3.0

Minor

  • #223 774ef46 Thanks @intech! - feat: named EventAdapterFactory type + official DI/testing guidance (#204)

    • New exported EventAdapterFactory (() => EventAdapter) — the previously inline factory shape of createBroadcastSubscribers' adapter option, now a named public type (per-adapter named types are deliberately not added).
    • README gains a "Dependency Injection and Testing" section: the primary pattern is injecting an EventAdapter instance at the composition root (a configured test double does not fit a zero-argument factory without a wrapper); the factory is the secondary pattern for per-consumer connections (broadcast reactors). Test-double guidance: MemoryAdapter for the generic happy path; broker-specific failure semantics via the upcoming @connectum/events-amqp/testing fake (#203).
    • Types + docs only — zero runtime change.
  • #220 8962afa Thanks @intech! - feat: drainPublishTimeout — opt-in symmetric publish drain on shutdown (#196)

    • New EventBusOptions.drainPublishTimeout: during stop(), wait up to the budget for in-flight publish() promises (started before stop()) to settle, before the adapter disconnects and would fail their confirms. Bus-level (L1): zero adapter-contract changes — nats/kafka/redis/amqp get the drain for free.
    • Runs concurrently with the handler drain (drainTimeout) — shutdown waits for the slower of the two budgets, never their sum.
    • Tracked promises carry a no-op observer: a publish settling (even rejecting) after the deadline never becomes an unhandledRejection; the caller's own publish() promise is unaffected.
    • Default undefined (and 0/negative) — disabled: stop() behavior stays bit-for-bit (pinned by a regression test).
    • Documented limitation: publishes issued from draining handlers are not covered — the stopping gate rejects them (relay-pattern design tracked in #212).

@connectum/events-amqp@1.3.0

Minor

  • #222 3a76225 Thanks @intech! - feat: publishRetry — opt-in bounded publish retry for connection-class outcomes (#195)

    • New top-level publishRetry: boolean | AmqpPublishRetryOptions: a publish() failing with AmqpConnectionError (publish during a recovery window; in-flight confirm lost to a drop) retries in place — a short broker blip becomes a transparent delay instead of an instant rejection. Backoff mirrors the recovery formula; maxRetries defaults to a bounded 5. AmqpPublishTimeoutError joins only via retryOnTimeout: true.
    • The auto-retry boundary is the exported isAutoRetriablePublishError — deliberately narrower than the at-least-once republish matrix (a broker nack is republish-safe by policy but never auto-retried inline; deterministic outcomes never retry). Docs distinguish the two boundaries explicitly.
    • At-least-once framing documented honestly: a retry after an in-flight confirm loss may duplicate; x-event-id/messageId stay stable across attempts (incl. externalContract) as the consumer-side dedup anchor.
    • Shutdown-aware and drain-covered: the loop aborts promptly on disconnect() (interruptible backoff) and lives inside the adapter.publish() promise, so the bus-level drainPublishTimeout covers retries automatically. Under single-flight correlation, retries hold the chain (ordering preserved; head-of-line blocking documented). The publish channel is re-resolved per attempt.
    • Default off — publish behavior unchanged unless opted in.
  • #216 82f2c29 Thanks @intech! - feat: discriminated onLifecycle connection-lifecycle callback (#197)

    • New lifecycle.onLifecycle(event) — a single discriminated union (type: connected | disconnected | reconnecting | reconnect-failed | setup-failed | blocked | unblocked) with exactly-once semantics pinned by integration tests. connected carries reconnected: boolean; blocked/unblocked surface RabbitMQ flow control (connection.blocked) for the first time. Scope: per-retry events of the initial connect loop are not yet surfaced (tracked in #198).
    • Setting onLifecycle (like onSetupFailed / failFastOnInitialSetupError) enables the startup validation probe — one extra short-lived connection plus a topology validation pass at connect() (recovery enabled required) — so setup-failed { initial: true } is delivered for a deterministic misconfiguration at boot.
    • Lifecycle callbacks must not throw: exceptions are now isolated in dispatch (a throwing callback can no longer make amqplib's recovery close a healthy connection or skip reconnect scheduling; the union and flat surfaces cannot starve each other).
    • The flat callbacks (onConnected, onDisconnected, onReconnecting, onReconnectFailed, onSetupFailed) are now a compatibility shim over the union and are @deprecated since 1.3.0 (removal not before 2.0). When both are set, flat callbacks fire after onLifecycle.
    • Behavior fix (documented): a socket-level connection cut fired onDisconnected twice — once via the raw connection error re-emit and once via the recovery disconnect event; it now fires exactly once per drop on both surfaces. Disconnect-counter metrics of existing consumers will roughly halve. A graceful server close was and remains single-fire.
    • Behavior fix (documented, recovery: false mode): disconnected is now delivered once per connection loss on the connection close (with the preceding error kept as the cause) — including a server-forced graceful close, which previously surfaced no event at all. The adapter's own disconnect() and a failed-setup discard do not emit it.
    • Hardening: the startup probe connection now carries an error listener (a broker drop during the probe window could previously crash the process via an unhandled error event); a stale reconnect-attempt counter no longer leaks into a later connect() incarnation.
  • #219 d21e3c8 Thanks @intech! - feat: initialConnectMaxRetries — bounded, observable initial connect (#198)

    • New recovery.initialConnectMaxRetries (N retries = N+1 attempts, mirroring maxRetries semantics): expresses "bounded startup, unbounded steady-state", which a single maxRetries cannot (its counter resets on every success). Default unset — behavior unchanged.
    • When set, the adapter owns the initial window with a bounded validate-connect loop — the 1.2.0 startup probe folds into it (validation IS each attempt, no extra connects). Budget exhaustion rejects connect() with a typed AmqpConnectionError after a terminal reconnect-failed — never a silent block.
    • Initial-window observability: per-attempt lifecycle events are now surfaced during the bounded phase (reconnecting { attempt, delay }, setup-failed { initial: true, attempt }) — previously the initial retry loop ran inside amqplib before any wiring could attach and was silent. This closes the documented scope gap from the onLifecycle/treatTopologyErrorAsFatal releases.
    • Backoff replicates amqplib's steady-state formula exactly (same knobs, same cap-before-jitter semantics; pinned by unit tests against the documented formula). failFastOnInitialSetupError still short-circuits deterministic topology errors immediately; the backoff sleep is interruptible by disconnect().
    • Upstream native support remains tracked in recovery: separate retry budget for the initial connect amqp-node/amqplib#856 (this implementation becomes a passthrough if it lands).
  • #217 f0e9040 Thanks @intech! - feat: machine-readable object on AmqpTopologyError (#202)

    • New AmqpTopologyObject discriminated union — { kind: 'exchange' | 'queue', name } or { kind: 'binding', source, destination, destinationType, routingKey } (a binding has no name of its own) — exposed as AmqpTopologyError.object and exported from the barrel.
    • Populated structurally at every broker declare/check/consume site (applyTopology check and assert modes per object, subscribe-path queue declaration/bindings/check-mode verification, consume failures), so CI drift checks and observability never parse broker-reply text. object.kind says what was being declared; why it failed stays with the error class and cause. One documented exception: the config-validation error for a malformed binding declaration (neither queue nor exchange set) carries no object — its destination is exactly the missing piece.
    • AmqpTopologyError constructor now takes an options-bag { cause?, object? }. Construction stays bit-for-bit compatible: message-only instances install no own cause/object keys (pinned by unit tests), so spread clones and own-property log serializers see no new keys unless an object is actually supplied.
  • #218 24e73f6 Thanks @intech! - feat: treatTopologyErrorAsFatal — stop recovery on deterministic topology drift (#201)

    • New opt-in top-level option: when topology drift makes recovery attempts fail deterministically (a checked queue/exchange deleted, an incompatible redeclare), the adapter stops the reconnect cycle on the first such failure instead of retrying forever — it reports setup-failed then the terminal reconnect-failed lifecycle event, and subsequent publishes fail fast with AmqpConnectionError.
    • The gate reads the AMQP reply code of the failure cause — 404 NOT_FOUND / 406 PRECONDITION_FAILED are deterministic; transient causes wrapped into AmqpTopologyError during a setup pass (320 connection-forced, 541 internal-error, 405 resource-locked, mid-setup connection drops) stay in normal recovery. instanceof AmqpTopologyError alone is deliberately NOT the gate. The RabbitMQ cluster classic-queue outage 404 ("home node ... down or inaccessible") is explicitly excluded as transient.
    • The stop is deterministic and complete: the recovery cycle's stopped flag flips synchronously inside the connect-failed handler, before amqplib schedules the next retry; subscription records are cleared (consumers are dead; a later connect() starts from a clean slate — pinned by a reconnect-after-fatal integration test). A fatal classification racing the adapter's own disconnect() is suppressed (no terminal events after a graceful stop began).
    • A subscribe() parked in the recovering wrapper's waiter queue when the cycle dies now rejects with the typed AmqpConnectionError (was amqplib's plain Error("Connection closed")).
    • Scope: steady-state recovery only; boot-time drift remains failFastOnInitialSetupError's job. Setting both covers boot and steady state; the remaining gap (broker unreachable at connect() with drift surfacing before the first successful connect) is covered by neither flag until #198. Default false — behavior unchanged unless opted in.
  • #224 ddc9ec7 Thanks @intech! - feat: programmable FakeAmqpAdapter test double via @connectum/events-amqp/testing (#203)

    • New subpath export @connectum/events-amqp/testing with FakeAmqpAdapter — model AMQP failure semantics in unit tests without a broker: FIFO publish outcomes (control.nextPublish with the real typed error classes, incl. AmqpPublishTimeoutError — the state-UNKNOWN outcome no real broker reproduces deterministically), deterministic connection lifecycle (dropConnection/completeRecovery/exhaustRecovery/failSetup/block), wildcard + competing-consumer delivery with a settlement result ({ delivered, acked, nacked, requeued, failed }), and a published record of bus-facing publishes.
    • Parity by construction and by pinning: lifecycle events go through the real adapter's dispatch (canonical union ordering, deprecated flat shim, exception isolation); the state machine mirrors the real adapter (already connected from live/recovering/retries-exhausted states; mid-recovery subscribe() parks and settles with the recovery outcome; setup-failed/fail-fast gate on AmqpTopologyError like the real probe); incoming envelope headers honored and stripped like the real consumer; handler rejections swallowed like the real nack-on-error path; instanceof holds across the subpath boundary (tsup splitting: true — shared error-class chunk, pinned by a dist-level test).
    • Runtime-pure: the subpath pulls neither amqplib nor node:test into the consumer graph (only @connectum/events + node:crypto).
    • Documented divergences: no timing simulation (recovery advances via explicit control calls); settlement is recorded, not broker-driven (re-deliver with attempt + 1 to model redelivery); no wire-level envelope on published; report-and-proceed on a non-fail-fast startup setup failure.

@connectum/events-redis@1.3.0

No package-specific changes beyond the repo-wide items above.

@connectum/healthcheck@1.3.0

No package-specific changes beyond the repo-wide items above.

@connectum/interceptors@1.3.0

No package-specific changes beyond the repo-wide items above.

@connectum/otel@1.3.0

No package-specific changes beyond the repo-wide items above.

@connectum/protoc-gen-catalog@1.3.0

No package-specific changes beyond the repo-wide items above.

@connectum/reflection@1.3.0

No package-specific changes beyond the repo-wide items above.

@connectum/testing@1.3.0

No package-specific changes beyond the repo-wide items above.

@github-actions github-actions Bot added the type:chore Maintenance: refactoring, dependencies, CI/CD label Aug 21, 2026
@github-actions
github-actions Bot requested a review from intech August 21, 2026 01:30
@github-actions github-actions Bot added pkg:core @connectum/core (Layer 0: Server Foundation) pkg:interceptors @connectum/interceptors (Layer 1) pkg:healthcheck @connectum/healthcheck (Layer 1) pkg:reflection @connectum/reflection (Layer 1) pkg:otel @connectum/otel (Layer 2: OpenTelemetry) pkg:testing @connectum/testing (Layer 2) pkg:cli @connectum/cli (Layer 3) pkg:protoc-gen-catalog @connectum/protoc-gen-catalog (buf plugin: service catalog codegen) labels Aug 21, 2026
@pkg-pr-new

pkg-pr-new Bot commented Aug 21, 2026

Copy link
Copy Markdown

Open in StackBlitz

@connectum/auth

npm i https://pkg.pr.new/@connectum/auth@255

@connectum/cli

npm i https://pkg.pr.new/@connectum/cli@255

@connectum/core

npm i https://pkg.pr.new/@connectum/core@255

@connectum/events

npm i https://pkg.pr.new/@connectum/events@255

@connectum/events-amqp

npm i https://pkg.pr.new/@connectum/events-amqp@255

@connectum/events-kafka

npm i https://pkg.pr.new/@connectum/events-kafka@255

@connectum/events-nats

npm i https://pkg.pr.new/@connectum/events-nats@255

@connectum/events-redis

npm i https://pkg.pr.new/@connectum/events-redis@255

@connectum/healthcheck

npm i https://pkg.pr.new/@connectum/healthcheck@255

@connectum/interceptors

npm i https://pkg.pr.new/@connectum/interceptors@255

@connectum/otel

npm i https://pkg.pr.new/@connectum/otel@255

@connectum/protoc-gen-catalog

npm i https://pkg.pr.new/@connectum/protoc-gen-catalog@255

@connectum/reflection

npm i https://pkg.pr.new/@connectum/reflection@255

@connectum/test-fixtures

npm i https://pkg.pr.new/@connectum/test-fixtures@255

@connectum/testing

npm i https://pkg.pr.new/@connectum/testing@255

commit: f7ce9ad

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg:cli @connectum/cli (Layer 3) pkg:core @connectum/core (Layer 0: Server Foundation) pkg:healthcheck @connectum/healthcheck (Layer 1) pkg:interceptors @connectum/interceptors (Layer 1) pkg:otel @connectum/otel (Layer 2: OpenTelemetry) pkg:protoc-gen-catalog @connectum/protoc-gen-catalog (buf plugin: service catalog codegen) pkg:reflection @connectum/reflection (Layer 1) pkg:testing @connectum/testing (Layer 2) type:chore Maintenance: refactoring, dependencies, CI/CD

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant