更新日志
Changelog 内容以英文为单一来源。
Changelog
All notable changes to this monorepo are recorded here. Releases for each package follow Semantic Versioning; the entries below are grouped by version-date so cross-package changes that ship together stay readable.
The format is loosely based on Keep a Changelog.
2026-06-22 — 0.2.1
@mqttkit/[email protected]
Added — @mqttkit/core 0.2.1
- MQTT 5 shared subscriptions (
$share/<group>/<filter>).parseSharedSubscription()follows §4.8.2;canSubscribe()strips the prefix before route matching and exposesshared.groupto the subscribe policy. Lets you deploy multiple consumer instances behind one broker without custom load-balancing. - Per-route
timeoutandconcurrency.topic({ timeout, concurrency })guards handler execution. Timeout surfaces asphase: 'timeout'; concurrency rejection surfaces asphase: 'overload'. Inflight count is tracked on the route for use by metrics and graceful shutdown. app.onMetric(handler). Emits a structuredMqttMetricEventonce per dispatch and once per publish —{ type, topic, route?, durationMs, result, errorPhase? }. Designed to feed Prometheus / OpenTelemetry / statsd without middleware around every route.- Graceful shutdown.
app.stop({ drain: true, timeout: 30_000 })is now the default behaviour: the dispatcher refuses new inbound dispatches, polls every route'sinflightcount to zero (or until the timeout), then runsonStophooks, cancels in-flight RPC, and stops the broker adapter.app.activeCount()reports the current sum of in-flight handlers for health checks. Pass{ drain: false }for the legacy immediate shutdown. - MQTT 5 user properties on
ctx.ctx.userPropertiesexposes inboundpacket.properties.userPropertiesas a flat read view, so middleware can extracttraceparent, correlation IDs, or any side-band metadata without touching adapter-specific packet shape. - Outbound publish hooks.
app.onBeforePublish(hook)runs immediately before every outbound publish (bothapp.publish()andctx.publish()/ctx.reply()/app.request(), which all funnel through the same path). Hooks receive a mutable{ topic, payload, options }view and can mutateoptions— typical use is mergingtraceparentintooptions.properties.userPropertiesso OTel context propagates across brokers. A throw aborts the publish and surfaces throughonErrorwithphase: 'publish'. - Raw payload on
onError.MqttErrorPayload.payloadcarries the raw buffer for inbound phases (validation/policy/middleware/handler/timeout/overload) and the originalMqttPayloadforpublish. Lets exporters (Sentry, structured logs) capture the offending message body, not just the topic. - New docs pages under the Production section:
Shared Subscriptions,Handler Timeout & Concurrency,Metrics,Graceful Shutdown,Tracing & User Properties(with full OpenTelemetry wiring example).
2026-06-22 — 0.2.0
@mqttkit/[email protected], @mqttkit/[email protected], @mqttkit/[email protected], @mqttkit/[email protected] (initial), @mqttkit/[email protected] (initial).
Added — @mqttkit/core 0.2.0
- Schema validation.
topic({ schema })accepts any Standard Schema v1 validator (zod ≥3.24, valibot ≥1, arktype, …). Validated output is exposed onctx.bodywith full type inference.validateoption controls direction ('inbound' | 'outbound' | 'both' | false). - SchemaProvider extension point.
app.addSchemaProvider(provider)lets non-Standard-Schema libraries (e.g. raw TypeBox) plug in without core depending on them.MqttkitInferExtensions<T>provides type-only registration forctx.bodyinference. - RPC.
app.request(topic, payload, options?)sends a request using MQTT 5responseTopic+correlationDataand resolves on reply.ctx.reply(payload)answers on the device side. - Error lifecycle.
app.onError(handler)and per-routeonErrorreceive a structured{ error, topic, phase, route, ctx }payload.phaseis one ofmiddleware | handler | validation | policy | publish. Validation failures emit aSchemaValidationErrorand skiponMessage. - Testing entry. New
@mqttkit/core/testingsub-export shipscreateTestApp()and an in-memoryTestBrokerwithdispatch()/onPublishhooks. Lets apps be unit-tested without spawning aedes. - Pattern module. Topic-pattern matching extracted into
pattern.tsand exported from the package root.
Added — @mqttkit/aedes 0.2.0
- Forwards MQTT 5 publish properties (
responseTopic,correlationData,contentType,messageExpiryInterval,userProperties,payloadFormatIndicator) when callingbroker.publish. Required forapp.request()RPC round-trips. - Bumps
@mqttkit/corepeer to^0.2.0.
Added — @mqttkit/asyncapi 0.2.0
resolvePayloadSchema(): route schemas that implement Standard Schema are now reduced to a JSON Schema for the generated document. Order:- raw JSON Schema object — used as-is
- Standard Schema with
~jsonSchemaattached — uses the attached schema - fallback:
{ description: 'Validated by <vendor>' }
- Lets
@mqttkit/zod'sjsonify()(and TypeBox's native JSON Schema layout) flow into the AsyncAPI document. - Bumps
@mqttkit/corepeer to^0.2.0.
Added — @mqttkit/typebox 0.1.0 (initial)
typeboxProvider: register withapp.addSchemaProvider(typeboxProvider)and pass rawType.X(...)schemas directly totopic({ schema }). TypeBox schemas detected by theKindsymbol and validated via@sinclair/typebox/value.- Type-only module augmentation so
ctx.bodyis inferred viaStatic<T>. - TypeBox schemas are JSON Schema natively, so
@mqttkit/asyncapioutputs the full payload automatically.
Added — @mqttkit/zod 0.1.0 (initial)
jsonify(schema, options?): attaches a JSON Schema representation under~jsonSchemaand returns the same zod instance. Closes the gap where@mqttkit/asyncapifalls back toValidated by zodbecause zod 3.x doesn't expose JSON Schema by default.- zod ≥3.24 already implements Standard Schema, so runtime validation works without
jsonify— this helper is only needed when emitting AsyncAPI docs.
Examples
- New
examples/schema-validationwithzod,typebox,coexist, andmanualvariants. - New
examples/rpcdemonstratingapp.request()/ctx.reply(). examples/asyncapi-docsnow defaults to the TypeBox variant; added adev:zodscript that shows zod +jsonifyflowing into the AsyncAPI document.
Internal
- Root
tsconfig.jsonexcludes**/dist/**to avoid a parallel-build race where one package's tsup pass discovered another package's mid-clean dist.
2026-XX-XX — initial release
@mqttkit/[email protected], @mqttkit/[email protected], @mqttkit/[email protected].
Initial publish of the framework: ordered middleware, topic router, typed context with decorate() service injection, broker lifecycle events, app.publish() for service-side push, Aedes TCP + MQTT-over-WebSocket adapter, and the AsyncAPI 3.0 documentation plugin.