@horizon-republic/nestjs-jetstream 2.7.1 → 2.8.0

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/dist/index.js CHANGED
@@ -24,9 +24,9 @@ import { Logger } from "@nestjs/common";
24
24
  import { ClientProxy } from "@nestjs/microservices";
25
25
  import {
26
26
  createInbox,
27
- Events,
28
27
  headers as natsHeaders
29
- } from "nats";
28
+ } from "@nats-io/transport-node";
29
+ import { nuid } from "@nats-io/nuid";
30
30
 
31
31
  // src/interfaces/hooks.interface.ts
32
32
  var MessageKind = /* @__PURE__ */ ((MessageKind2) => {
@@ -65,7 +65,7 @@ import {
65
65
  RetentionPolicy,
66
66
  StorageType,
67
67
  StoreCompression
68
- } from "nats";
68
+ } from "@nats-io/jetstream";
69
69
  var JETSTREAM_OPTIONS = /* @__PURE__ */ Symbol("JETSTREAM_OPTIONS");
70
70
  var JETSTREAM_CONNECTION = /* @__PURE__ */ Symbol("JETSTREAM_CONNECTION");
71
71
  var JETSTREAM_CODEC = /* @__PURE__ */ Symbol("JETSTREAM_CODEC");
@@ -197,11 +197,12 @@ var isCoreRpcMode = (rpc) => !rpc || rpc.mode === "core";
197
197
 
198
198
  // src/client/jetstream.record.ts
199
199
  var JetstreamRecord = class {
200
- constructor(data, headers2, timeout, messageId) {
200
+ constructor(data, headers2, timeout, messageId, schedule) {
201
201
  this.data = data;
202
202
  this.headers = headers2;
203
203
  this.timeout = timeout;
204
204
  this.messageId = messageId;
205
+ this.schedule = schedule;
205
206
  }
206
207
  };
207
208
  var JetstreamRecordBuilder = class {
@@ -209,6 +210,7 @@ var JetstreamRecordBuilder = class {
209
210
  headers = /* @__PURE__ */ new Map();
210
211
  timeout;
211
212
  messageId;
213
+ scheduleOptions;
212
214
  constructor(data) {
213
215
  this.data = data;
214
216
  }
@@ -276,17 +278,43 @@ var JetstreamRecordBuilder = class {
276
278
  this.timeout = ms;
277
279
  return this;
278
280
  }
281
+ /**
282
+ * Schedule one-shot delayed delivery.
283
+ *
284
+ * The message is held by NATS and delivered to the event consumer
285
+ * at the specified time. Requires NATS >= 2.12 and `allow_msg_schedules: true`
286
+ * on the event stream (via `events: { stream: { allow_msg_schedules: true } }`).
287
+ *
288
+ * Only meaningful for events (`client.emit()`). If used with RPC
289
+ * (`client.send()`), a warning is logged and the schedule is ignored.
290
+ *
291
+ * @param date - Delivery time. Must be in the future.
292
+ * @throws Error if the date is not in the future.
293
+ */
294
+ scheduleAt(date) {
295
+ const ts = date.getTime();
296
+ if (Number.isNaN(ts)) {
297
+ throw new Error("Schedule date is invalid");
298
+ }
299
+ if (ts <= Date.now()) {
300
+ throw new Error("Schedule date must be in the future");
301
+ }
302
+ this.scheduleOptions = { at: new Date(ts) };
303
+ return this;
304
+ }
279
305
  /**
280
306
  * Build the immutable {@link JetstreamRecord}.
281
307
  *
282
308
  * @returns A frozen record ready to pass to `client.send()` or `client.emit()`.
283
309
  */
284
310
  build() {
311
+ const schedule = this.scheduleOptions ? { at: new Date(this.scheduleOptions.at.getTime()) } : void 0;
285
312
  return new JetstreamRecord(
286
313
  this.data,
287
314
  new Map(this.headers),
288
315
  this.timeout,
289
- this.messageId
316
+ this.messageId,
317
+ schedule
290
318
  );
291
319
  }
292
320
  /** Validate that a header key is not reserved. */
@@ -338,7 +366,7 @@ var JetstreamClient = class extends ClientProxy {
338
366
  this.setupInbox(nc);
339
367
  }
340
368
  this.statusSubscription ??= this.connection.status$.subscribe((status) => {
341
- if (status.type === Events.Disconnect) {
369
+ if (status.type === "disconnect") {
342
370
  this.handleDisconnect();
343
371
  }
344
372
  });
@@ -366,19 +394,38 @@ var JetstreamClient = class extends ClientProxy {
366
394
  * Publish a fire-and-forget event to JetStream.
367
395
  *
368
396
  * Events are published to either the workqueue stream or broadcast stream
369
- * depending on the subject prefix.
397
+ * depending on the subject prefix. When a schedule is present the message
398
+ * is published to a `_sch` subject within the same stream, with the target
399
+ * set to the original event subject.
370
400
  */
371
401
  async dispatchEvent(packet) {
372
402
  await this.connect();
373
- const { data, hdrs, messageId } = this.extractRecordData(packet.data);
374
- const subject = this.buildEventSubject(packet.pattern);
375
- const msgHeaders = this.buildHeaders(hdrs, { subject });
376
- const ack = await this.connection.getJetStreamClient().publish(subject, this.codec.encode(data), {
377
- headers: msgHeaders,
378
- msgID: messageId ?? crypto.randomUUID()
379
- });
380
- if (ack.duplicate) {
381
- this.logger.warn(`Duplicate event publish detected: ${subject} (seq: ${ack.seq})`);
403
+ const { data, hdrs, messageId, schedule } = this.extractRecordData(packet.data);
404
+ const eventSubject = this.buildEventSubject(packet.pattern);
405
+ const msgHeaders = this.buildHeaders(hdrs, { subject: eventSubject });
406
+ if (schedule) {
407
+ const scheduleSubject = this.buildScheduleSubject(eventSubject);
408
+ const ack = await this.connection.getJetStreamClient().publish(scheduleSubject, this.codec.encode(data), {
409
+ headers: msgHeaders,
410
+ msgID: messageId ?? nuid.next(),
411
+ schedule: {
412
+ specification: schedule.at,
413
+ target: eventSubject
414
+ }
415
+ });
416
+ if (ack.duplicate) {
417
+ this.logger.warn(
418
+ `Duplicate scheduled publish detected: ${scheduleSubject} (seq: ${ack.seq})`
419
+ );
420
+ }
421
+ } else {
422
+ const ack = await this.connection.getJetStreamClient().publish(eventSubject, this.codec.encode(data), {
423
+ headers: msgHeaders,
424
+ msgID: messageId ?? nuid.next()
425
+ });
426
+ if (ack.duplicate) {
427
+ this.logger.warn(`Duplicate event publish detected: ${eventSubject} (seq: ${ack.seq})`);
428
+ }
382
429
  }
383
430
  return void 0;
384
431
  }
@@ -390,7 +437,12 @@ var JetstreamClient = class extends ClientProxy {
390
437
  */
391
438
  publish(packet, callback) {
392
439
  const subject = buildSubject(this.targetName, "cmd" /* Command */, packet.pattern);
393
- const { data, hdrs, timeout, messageId } = this.extractRecordData(packet.data);
440
+ const { data, hdrs, timeout, messageId, schedule } = this.extractRecordData(packet.data);
441
+ if (schedule) {
442
+ this.logger.warn(
443
+ "scheduleAt() is ignored for RPC (client.send()). Use client.emit() for scheduled events."
444
+ );
445
+ }
394
446
  const onUnhandled = (err) => {
395
447
  this.logger.error("Unhandled publish error:", err);
396
448
  callback({ err: new Error("Internal transport error"), response: null, isDisposed: true });
@@ -399,7 +451,7 @@ var JetstreamClient = class extends ClientProxy {
399
451
  if (isCoreRpcMode(this.rootOptions.rpc)) {
400
452
  this.publishCoreRpc(subject, data, hdrs, timeout, callback).catch(onUnhandled);
401
453
  } else {
402
- jetStreamCorrelationId = crypto.randomUUID();
454
+ jetStreamCorrelationId = nuid.next();
403
455
  this.publishJetStreamRpc(subject, data, callback, {
404
456
  headers: hdrs,
405
457
  timeout,
@@ -474,7 +526,7 @@ var JetstreamClient = class extends ClientProxy {
474
526
  });
475
527
  await this.connection.getJetStreamClient().publish(subject, this.codec.encode(data), {
476
528
  headers: hdrs,
477
- msgID: messageId ?? crypto.randomUUID()
529
+ msgID: messageId ?? nuid.next()
478
530
  });
479
531
  } catch (err) {
480
532
  const existingTimeout = this.pendingTimeouts.get(correlationId);
@@ -587,17 +639,51 @@ var JetstreamClient = class extends ClientProxy {
587
639
  }
588
640
  return hdrs;
589
641
  }
590
- /** Extract data, headers, and timeout from raw packet data or JetstreamRecord. */
642
+ /** Extract data, headers, timeout, and schedule from raw packet data or JetstreamRecord. */
591
643
  extractRecordData(rawData) {
592
644
  if (rawData instanceof JetstreamRecord) {
593
645
  return {
594
646
  data: rawData.data,
595
647
  hdrs: rawData.headers.size > 0 ? new Map(rawData.headers) : null,
596
648
  timeout: rawData.timeout,
597
- messageId: rawData.messageId
649
+ messageId: rawData.messageId,
650
+ schedule: rawData.schedule
598
651
  };
599
652
  }
600
- return { data: rawData, hdrs: null, timeout: void 0, messageId: void 0 };
653
+ return {
654
+ data: rawData,
655
+ hdrs: null,
656
+ timeout: void 0,
657
+ messageId: void 0,
658
+ schedule: void 0
659
+ };
660
+ }
661
+ /**
662
+ * Build a schedule-holder subject for NATS message scheduling.
663
+ *
664
+ * The schedule-holder subject resides in the same stream as the target but
665
+ * uses a separate `_sch` namespace that is NOT matched by any consumer filter.
666
+ * NATS holds the message and publishes it to the target subject after the delay.
667
+ *
668
+ * Examples:
669
+ * - `{svc}__microservice.ev.order.reminder` → `{svc}__microservice._sch.order.reminder`
670
+ * - `broadcast.config.updated` → `broadcast._sch.config.updated`
671
+ */
672
+ buildScheduleSubject(eventSubject) {
673
+ if (eventSubject.startsWith("broadcast.")) {
674
+ return eventSubject.replace("broadcast.", "broadcast._sch.");
675
+ }
676
+ const targetPrefix = `${internalName(this.targetName)}.`;
677
+ if (!eventSubject.startsWith(targetPrefix)) {
678
+ throw new Error(`Unexpected event subject format: ${eventSubject}`);
679
+ }
680
+ const withoutPrefix = eventSubject.slice(targetPrefix.length);
681
+ const dotIndex = withoutPrefix.indexOf(".");
682
+ if (dotIndex === -1) {
683
+ throw new Error(`Event subject missing pattern segment: ${eventSubject}`);
684
+ }
685
+ const pattern = withoutPrefix.slice(dotIndex + 1);
686
+ return `${targetPrefix}_sch.${pattern}`;
601
687
  }
602
688
  getRpcTimeout() {
603
689
  if (!this.rootOptions.rpc) return DEFAULT_RPC_TIMEOUT;
@@ -607,25 +693,26 @@ var JetstreamClient = class extends ClientProxy {
607
693
  };
608
694
 
609
695
  // src/codec/json.codec.ts
610
- import { JSONCodec as NatsJSONCodec } from "nats";
696
+ var encoder = new TextEncoder();
697
+ var decoder = new TextDecoder();
611
698
  var JsonCodec = class {
612
- inner = NatsJSONCodec();
613
699
  encode(data) {
614
- return this.inner.encode(data);
700
+ return encoder.encode(JSON.stringify(data));
615
701
  }
616
702
  decode(data) {
617
- return this.inner.decode(data);
703
+ return JSON.parse(decoder.decode(data));
618
704
  }
619
705
  };
620
706
 
621
707
  // src/connection/connection.provider.ts
622
708
  import { Logger as Logger2 } from "@nestjs/common";
623
709
  import {
624
- connect,
625
- DebugEvents,
626
- Events as Events2,
627
- NatsError
628
- } from "nats";
710
+ connect
711
+ } from "@nats-io/transport-node";
712
+ import {
713
+ jetstream,
714
+ jetstreamManager
715
+ } from "@nats-io/jetstream";
629
716
  import { defer, from, share, shareReplay, switchMap } from "rxjs";
630
717
  var DEFAULT_OPTIONS = {
631
718
  maxReconnectAttempts: -1,
@@ -679,14 +766,7 @@ var ConnectionProvider = class {
679
766
  async getJetStreamManager() {
680
767
  if (this.jsmInstance) return this.jsmInstance;
681
768
  if (this.jsmPromise) return this.jsmPromise;
682
- this.jsmPromise = (async () => {
683
- const nc = await this.getConnection();
684
- this.jsmInstance = await nc.jetstreamManager();
685
- this.logger.log("JetStream manager initialized");
686
- return this.jsmInstance;
687
- })().finally(() => {
688
- this.jsmPromise = null;
689
- });
769
+ this.jsmPromise = this.initJetStreamManager();
690
770
  return this.jsmPromise;
691
771
  }
692
772
  /**
@@ -702,7 +782,7 @@ var ConnectionProvider = class {
702
782
  if (!this.connection || this.connection.isClosed()) {
703
783
  throw new Error("Not connected \u2014 call getConnection() before getJetStreamClient()");
704
784
  }
705
- this.jsClient ??= this.connection.jetstream();
785
+ this.jsClient ??= jetstream(this.connection);
706
786
  return this.jsClient;
707
787
  }
708
788
  /** Direct access to the raw NATS connection, or `null` if not yet connected. */
@@ -738,6 +818,16 @@ var ConnectionProvider = class {
738
818
  this.jsmPromise = null;
739
819
  }
740
820
  }
821
+ async initJetStreamManager() {
822
+ try {
823
+ const nc = await this.getConnection();
824
+ this.jsmInstance = await jetstreamManager(nc);
825
+ this.logger.log("JetStream manager initialized");
826
+ return this.jsmInstance;
827
+ } finally {
828
+ this.jsmPromise = null;
829
+ }
830
+ }
741
831
  /** Internal: establish the physical connection with reconnect monitoring. */
742
832
  async establish() {
743
833
  const name = internalName(this.options.name);
@@ -754,7 +844,7 @@ var ConnectionProvider = class {
754
844
  this.monitorStatus(nc);
755
845
  return nc;
756
846
  } catch (err) {
757
- if (err instanceof NatsError && err.code === "CONNECTION_REFUSED") {
847
+ if (err instanceof Error && err.message.includes("REFUSED")) {
758
848
  throw new Error(`NATS connection refused: ${this.options.servers.join(", ")}`);
759
849
  }
760
850
  throw err;
@@ -762,27 +852,33 @@ var ConnectionProvider = class {
762
852
  }
763
853
  /** Subscribe to connection status events and emit hooks. */
764
854
  monitorStatus(nc) {
765
- (async () => {
855
+ void (async () => {
766
856
  for await (const status of nc.status()) {
767
857
  switch (status.type) {
768
- case Events2.Disconnect:
858
+ case "disconnect":
769
859
  this.eventBus.emit("disconnect" /* Disconnect */);
770
860
  break;
771
- case Events2.Reconnect:
861
+ case "reconnect":
772
862
  this.jsClient = null;
773
863
  this.jsmInstance = null;
774
864
  this.jsmPromise = null;
775
865
  this.eventBus.emit("reconnect" /* Reconnect */, nc.getServer());
776
866
  break;
777
- case Events2.Error:
778
- this.eventBus.emit("error" /* Error */, new Error(String(status.data)), "connection");
867
+ case "error":
868
+ this.eventBus.emit(
869
+ "error" /* Error */,
870
+ status.error,
871
+ "connection"
872
+ );
779
873
  break;
780
- case Events2.Update:
781
- case Events2.LDM:
782
- case DebugEvents.Reconnecting:
783
- case DebugEvents.PingTimer:
784
- case DebugEvents.StaleConnection:
785
- case DebugEvents.ClientInitiatedReconnect:
874
+ case "update":
875
+ case "ldm":
876
+ case "reconnecting":
877
+ case "ping":
878
+ case "staleConnection":
879
+ case "forceReconnect":
880
+ case "slowConsumer":
881
+ case "close":
786
882
  break;
787
883
  }
788
884
  }
@@ -1044,7 +1140,7 @@ var JetstreamStrategy = class extends Server {
1044
1140
 
1045
1141
  // src/server/core-rpc.server.ts
1046
1142
  import { Logger as Logger4 } from "@nestjs/common";
1047
- import { headers as natsHeaders2 } from "nats";
1143
+ import { headers as natsHeaders2 } from "@nats-io/transport-node";
1048
1144
 
1049
1145
  // src/context/rpc.context.ts
1050
1146
  import { BaseRpcContext } from "@nestjs/microservices";
@@ -1341,7 +1437,7 @@ var CoreRpcServer = class {
1341
1437
 
1342
1438
  // src/server/infrastructure/stream.provider.ts
1343
1439
  import { Logger as Logger5 } from "@nestjs/common";
1344
- import { NatsError as NatsError2 } from "nats";
1440
+ import { JetStreamApiError } from "@nats-io/jetstream";
1345
1441
  var STREAM_NOT_FOUND = 10059;
1346
1442
  var StreamProvider = class {
1347
1443
  constructor(options, connection) {
@@ -1367,12 +1463,22 @@ var StreamProvider = class {
1367
1463
  getSubjects(kind) {
1368
1464
  const name = internalName(this.options.name);
1369
1465
  switch (kind) {
1370
- case "ev" /* Event */:
1371
- return [`${name}.${"ev" /* Event */}.>`];
1466
+ case "ev" /* Event */: {
1467
+ const subjects = [`${name}.${"ev" /* Event */}.>`];
1468
+ if (this.isSchedulingEnabled(kind)) {
1469
+ subjects.push(`${name}._sch.>`);
1470
+ }
1471
+ return subjects;
1472
+ }
1372
1473
  case "cmd" /* Command */:
1373
1474
  return [`${name}.${"cmd" /* Command */}.>`];
1374
- case "broadcast" /* Broadcast */:
1375
- return ["broadcast.>"];
1475
+ case "broadcast" /* Broadcast */: {
1476
+ const subjects = ["broadcast.>"];
1477
+ if (this.isSchedulingEnabled(kind)) {
1478
+ subjects.push("broadcast._sch.>");
1479
+ }
1480
+ return subjects;
1481
+ }
1376
1482
  case "ordered" /* Ordered */:
1377
1483
  return [`${name}.${"ordered" /* Ordered */}.>`];
1378
1484
  }
@@ -1386,7 +1492,7 @@ var StreamProvider = class {
1386
1492
  this.logger.debug(`Stream exists, updating: ${config.name}`);
1387
1493
  return await jsm.streams.update(config.name, config);
1388
1494
  } catch (err) {
1389
- if (err instanceof NatsError2 && err.api_error?.err_code === STREAM_NOT_FOUND) {
1495
+ if (err instanceof JetStreamApiError && err.apiError().err_code === STREAM_NOT_FOUND) {
1390
1496
  this.logger.log(`Creating stream: ${config.name}`);
1391
1497
  return await jsm.streams.add(config);
1392
1498
  }
@@ -1421,6 +1527,11 @@ var StreamProvider = class {
1421
1527
  return DEFAULT_ORDERED_STREAM_CONFIG;
1422
1528
  }
1423
1529
  }
1530
+ /** Check if scheduling is enabled for a stream kind via `allow_msg_schedules` override. */
1531
+ isSchedulingEnabled(kind) {
1532
+ const overrides = this.getOverrides(kind);
1533
+ return overrides.allow_msg_schedules === true;
1534
+ }
1424
1535
  /** Get user-provided overrides for a stream kind. */
1425
1536
  getOverrides(kind) {
1426
1537
  switch (kind) {
@@ -1438,7 +1549,7 @@ var StreamProvider = class {
1438
1549
 
1439
1550
  // src/server/infrastructure/consumer.provider.ts
1440
1551
  import { Logger as Logger6 } from "@nestjs/common";
1441
- import { NatsError as NatsError3 } from "nats";
1552
+ import { JetStreamApiError as JetStreamApiError2 } from "@nats-io/jetstream";
1442
1553
  var CONSUMER_NOT_FOUND = 10014;
1443
1554
  var ConsumerProvider = class {
1444
1555
  constructor(options, connection, streamProvider, patternRegistry) {
@@ -1479,7 +1590,7 @@ var ConsumerProvider = class {
1479
1590
  this.logger.debug(`Consumer exists, updating: ${name}`);
1480
1591
  return await jsm.consumers.update(stream, name, config);
1481
1592
  } catch (err) {
1482
- if (err instanceof NatsError3 && err.api_error?.err_code === CONSUMER_NOT_FOUND) {
1593
+ if (err instanceof JetStreamApiError2 && err.apiError().err_code === CONSUMER_NOT_FOUND) {
1483
1594
  this.logger.log(`Creating consumer: ${name}`);
1484
1595
  return await jsm.consumers.add(stream, config);
1485
1596
  }
@@ -1538,6 +1649,10 @@ var ConsumerProvider = class {
1538
1649
  return DEFAULT_BROADCAST_CONSUMER_CONFIG;
1539
1650
  case "ordered" /* Ordered */:
1540
1651
  throw new Error("Ordered consumers are ephemeral and should not use durable config");
1652
+ default: {
1653
+ const _exhaustive = kind;
1654
+ throw new Error(`Unexpected StreamKind: ${_exhaustive}`);
1655
+ }
1541
1656
  }
1542
1657
  }
1543
1658
  /** Get user-provided overrides for a consumer kind. */
@@ -1551,16 +1666,17 @@ var ConsumerProvider = class {
1551
1666
  return this.options.broadcast?.consumer ?? {};
1552
1667
  case "ordered" /* Ordered */:
1553
1668
  throw new Error("Ordered consumers are ephemeral and should not use durable config");
1669
+ default: {
1670
+ const _exhaustive = kind;
1671
+ throw new Error(`Unexpected StreamKind: ${_exhaustive}`);
1672
+ }
1554
1673
  }
1555
1674
  }
1556
1675
  };
1557
1676
 
1558
1677
  // src/server/infrastructure/message.provider.ts
1559
1678
  import { Logger as Logger7 } from "@nestjs/common";
1560
- import {
1561
- ConsumerEvents,
1562
- DeliverPolicy as DeliverPolicy2
1563
- } from "nats";
1679
+ import { DeliverPolicy as DeliverPolicy2 } from "@nats-io/jetstream";
1564
1680
  import {
1565
1681
  catchError,
1566
1682
  defer as defer2,
@@ -1629,7 +1745,7 @@ var MessageProvider = class {
1629
1745
  * @param orderedConfig - Optional overrides for ordered consumer options.
1630
1746
  */
1631
1747
  async startOrdered(streamName2, filterSubjects, orderedConfig) {
1632
- const consumerOpts = { filterSubjects };
1748
+ const consumerOpts = { filter_subjects: filterSubjects };
1633
1749
  if (orderedConfig?.deliverPolicy !== void 0 && orderedConfig.deliverPolicy !== DeliverPolicy2.All) {
1634
1750
  consumerOpts.deliver_policy = orderedConfig.deliverPolicy;
1635
1751
  }
@@ -1714,10 +1830,10 @@ var MessageProvider = class {
1714
1830
  }
1715
1831
  /** Monitor heartbeats and restart the consumer iterator on prolonged silence. */
1716
1832
  monitorConsumerHealth(messages, name) {
1717
- (async () => {
1718
- for await (const status of await messages.status()) {
1719
- if (status.type === ConsumerEvents.HeartbeatsMissed && status.data >= 2) {
1720
- this.logger.warn(`Consumer ${name}: ${status.data} heartbeats missed, restarting`);
1833
+ void (async () => {
1834
+ for await (const status of messages.status()) {
1835
+ if (status.type === "heartbeats_missed" && status.count >= 2) {
1836
+ this.logger.warn(`Consumer ${name}: ${status.count} heartbeats missed, restarting`);
1721
1837
  messages.stop();
1722
1838
  break;
1723
1839
  }
@@ -2097,7 +2213,7 @@ var EventRouter = class {
2097
2213
 
2098
2214
  // src/server/routing/rpc.router.ts
2099
2215
  import { Logger as Logger10 } from "@nestjs/common";
2100
- import { headers } from "nats";
2216
+ import { headers } from "@nats-io/transport-node";
2101
2217
  import { from as from3, mergeMap as mergeMap2 } from "rxjs";
2102
2218
  var RpcRouter = class {
2103
2219
  constructor(messageProvider, patternRegistry, connection, codec, eventBus, rpcOptions, ackWaitMap) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@horizon-republic/nestjs-jetstream",
3
- "version": "2.7.1",
3
+ "version": "2.8.0",
4
4
  "description": "A NestJS transport for NATS with JetStream events, broadcast fan-out, and Core/JetStream RPC.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -57,7 +57,6 @@
57
57
  "@nestjs/common": "^10.2.0 || ^11.0.0",
58
58
  "@nestjs/core": "^10.2.0 || ^11.0.0",
59
59
  "@nestjs/microservices": "^10.2.0 || ^11.0.0",
60
- "nats": "^2.0.0",
61
60
  "reflect-metadata": "^0.2.0",
62
61
  "rxjs": "^7.8.0"
63
62
  },
@@ -75,12 +74,18 @@
75
74
  "eslint-plugin-sonarjs": "^4.0.2",
76
75
  "eslint-plugin-unused-imports": "^4.4.1",
77
76
  "prettier": "^3.8.1",
77
+ "testcontainers": "^11.13.0",
78
78
  "tsup": "^8.5.1",
79
79
  "tsx": "^4.21.0",
80
80
  "typescript": "~5.9.3",
81
- "typescript-eslint": "^8.57.2",
81
+ "typescript-eslint": "^8.58.0",
82
82
  "vitest": "^4.1.2"
83
83
  },
84
+ "dependencies": {
85
+ "@nats-io/jetstream": "^3.3.1",
86
+ "@nats-io/nuid": "^2.0.3",
87
+ "@nats-io/transport-node": "^3.3.1"
88
+ },
84
89
  "scripts": {
85
90
  "build": "tsup",
86
91
  "build:watch": "tsup --watch",