@orion-js/echoes 4.5.5 → 4.5.7

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.
@@ -1,9 +1,10 @@
1
1
  import type { EchoesSchema } from '../schema';
2
- import { EchoConfig, EchoEventConfig, EchoRequestConfig, EchoType } from '../types';
2
+ import { EchoBatchEventConfig, EchoConfig, EchoEventConfig, EchoRequestConfig, EchoType } from '../types';
3
3
  /**
4
4
  * @deprecated Use createEchoRequest and createEchoEvent instead
5
5
  */
6
6
  declare const echo: <TParamsSchema extends EchoesSchema, TReturnsSchema extends EchoesSchema, TEchoType extends 'event' | 'request'>(options: EchoConfig<TParamsSchema, TReturnsSchema, TEchoType>) => EchoType<TParamsSchema, TReturnsSchema, TEchoType>;
7
7
  export declare function createEchoRequest<TParamsSchema extends EchoesSchema, TReturnsSchema extends EchoesSchema>(options: EchoRequestConfig<TParamsSchema, TReturnsSchema>): EchoType<TParamsSchema, TReturnsSchema, 'request'>;
8
8
  export declare function createEchoEvent<TParamsSchema extends EchoesSchema, TReturnsSchema extends EchoesSchema>(options: EchoEventConfig<TParamsSchema, TReturnsSchema>): EchoType<TParamsSchema, TReturnsSchema, 'event'>;
9
+ export declare function createEchoBatchEvent<TParamsSchema extends EchoesSchema = any>(options: EchoBatchEventConfig<TParamsSchema>): EchoType<TParamsSchema, any, 'event'>;
9
10
  export { echo };
@@ -19,4 +19,5 @@ export default class EventBus {
19
19
  publish<TParams = any>(options: PublishOptions<TParams>): Promise<any>;
20
20
  close(): Promise<void>;
21
21
  private handleEvent;
22
+ private handleEvents;
22
23
  }
@@ -2,15 +2,17 @@ import type { EchoesEventTransportName, EchoesReceivedEvent, PublishOptions } fr
2
2
  export interface EventSubscriptionDefinition {
3
3
  topic: string;
4
4
  attemptsBeforeDeadLetter?: number;
5
- ordered?: boolean;
6
5
  configVersion?: number;
7
- executionVersion?: 1 | 2;
6
+ maxConcurrency?: number;
7
+ receiverMode: 'single' | 'batch';
8
+ batchSize: number;
8
9
  }
9
10
  export interface EventTransportStartOptions {
10
11
  consume: boolean;
11
12
  publish: boolean;
12
13
  subscriptions: EventSubscriptionDefinition[];
13
14
  onEvent(event: EchoesReceivedEvent): Promise<void>;
15
+ onEvents(events: EchoesReceivedEvent[]): Promise<void>;
14
16
  }
15
17
  export interface EventTransport {
16
18
  readonly name: EchoesEventTransportName;
package/dist/index.cjs CHANGED
@@ -29,6 +29,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
29
29
  // src/index.ts
30
30
  var index_exports = {};
31
31
  __export(index_exports, {
32
+ EchoBatchEvent: () => EchoBatchEvent,
32
33
  EchoEvent: () => EchoEvent,
33
34
  EchoRequest: () => EchoRequest,
34
35
  Echoes: () => Echoes,
@@ -36,6 +37,7 @@ __export(index_exports, {
36
37
  EchoesValidationError: () => EchoesValidationError,
37
38
  cleanEchoesSchema: () => cleanEchoesSchema,
38
39
  configureEchoesRuntime: () => configureEchoesRuntime,
40
+ createEchoBatchEvent: () => createEchoBatchEvent,
39
41
  createEchoEvent: () => createEchoEvent,
40
42
  createEchoRequest: () => createEchoRequest,
41
43
  createEchoesUserError: () => createEchoesUserError,
@@ -756,10 +758,14 @@ var EventBus = class {
756
758
  const subscriptions = Object.entries(this.echoes).filter(([, echo2]) => echo2.type === "event").map(([topic, echo2]) => ({
757
759
  topic,
758
760
  attemptsBeforeDeadLetter: echo2.attemptsBeforeDeadLetter,
759
- ordered: echo2.ordered,
760
761
  configVersion: echo2.configVersion,
761
- executionVersion: echo2.executionVersion
762
+ maxConcurrency: echo2.maxConcurrency,
763
+ receiverMode: echo2.receiverMode ?? "single",
764
+ batchSize: echo2.batchSize ?? 1
762
765
  }));
766
+ if (this.consumeFrom.includes("kafka") && subscriptions.some((subscription) => subscription.receiverMode === "batch")) {
767
+ throw new Error("Echoes batch event receivers are supported only by the Pulse transport.");
768
+ }
763
769
  try {
764
770
  for (const name of selected) {
765
771
  const transport = this.transports[name];
@@ -768,7 +774,8 @@ var EventBus = class {
768
774
  consume: this.consumeFrom.includes(name),
769
775
  publish: this.publishTo === name,
770
776
  subscriptions,
771
- onEvent: (event) => this.handleEvent(event)
777
+ onEvent: (event) => this.handleEvent(event),
778
+ onEvents: (events) => this.handleEvents(events)
772
779
  });
773
780
  }
774
781
  this.started = true;
@@ -817,6 +824,15 @@ var EventBus = class {
817
824
  data: event.data
818
825
  });
819
826
  }
827
+ async handleEvents(events) {
828
+ if (events.length === 0) return;
829
+ const echo2 = this.echoes[events[0].topic];
830
+ if ((echo2 == null ? void 0 : echo2.type) === "event" && echo2.onEvents) {
831
+ await echo2.onEvents(events);
832
+ return;
833
+ }
834
+ for (const event of events) await this.handleEvent(event);
835
+ }
820
836
  };
821
837
 
822
838
  // src/events/PulseManager.ts
@@ -846,18 +862,23 @@ var PulseManager = class {
846
862
  this.subscriptions = await Promise.all(
847
863
  options.subscriptions.map(async (definition) => {
848
864
  const subscribeOptions = this.getSubscribeOptions(subscription, definition);
849
- const active = await this.pulse.subscribe(
865
+ if (definition.receiverMode === "batch") {
866
+ if (typeof this.pulse.subscribeBatch !== "function") {
867
+ throw new Error(
868
+ "Echoes batch event receivers require a version of @orion-js/pulse with subscribeBatch support."
869
+ );
870
+ }
871
+ return await this.pulse.subscribeBatch(
872
+ definition.topic,
873
+ (events) => options.onEvents(events.map((event) => this.createReceivedEvent(event))),
874
+ { ...subscribeOptions, batchSize: definition.batchSize }
875
+ );
876
+ }
877
+ return await this.pulse.subscribe(
850
878
  definition.topic,
851
879
  (event) => options.onEvent(this.createReceivedEvent(event)),
852
880
  subscribeOptions
853
881
  );
854
- if (subscribeOptions.executionVersion === 2 && active.executionVersion !== 2) {
855
- await active.unsubscribe();
856
- throw new Error(
857
- "Echoes executionVersion 2 requires a bridge-capable @orion-js/pulse version and a winning configVersion for this listener."
858
- );
859
- }
860
- return active;
861
882
  })
862
883
  );
863
884
  }
@@ -878,10 +899,9 @@ var PulseManager = class {
878
899
  getSubscribeOptions(defaults = {}, definition) {
879
900
  return {
880
901
  ...defaults,
881
- ...definition.ordered === void 0 ? {} : { ordered: definition.ordered },
882
902
  ...definition.configVersion === void 0 ? {} : { configVersion: definition.configVersion },
883
- ...definition.executionVersion === void 0 ? {} : { executionVersion: definition.executionVersion },
884
- ...definition.attemptsBeforeDeadLetter === void 0 ? {} : { maxRetries: definition.attemptsBeforeDeadLetter }
903
+ ...definition.attemptsBeforeDeadLetter === void 0 ? {} : { maxRetries: definition.attemptsBeforeDeadLetter },
904
+ ...definition.maxConcurrency === void 0 ? {} : { maxConcurrency: definition.maxConcurrency }
885
905
  };
886
906
  }
887
907
  createReceivedEvent(event) {
@@ -1015,6 +1035,18 @@ async function stopService() {
1015
1035
  }
1016
1036
 
1017
1037
  // src/echo/index.ts
1038
+ function receivedEventContext(event) {
1039
+ return {
1040
+ ...event.context || {},
1041
+ transport: event.transport,
1042
+ eventId: event.id,
1043
+ topic: event.topic,
1044
+ headers: event.headers,
1045
+ createdAt: event.createdAt,
1046
+ attempt: event.attempt,
1047
+ data: event.data
1048
+ };
1049
+ }
1018
1050
  var echo = function createNewEcho(options) {
1019
1051
  const resolve = async (params, context) => {
1020
1052
  const cleaned = options.params ? await parseEchoesSchema(options.params, params) : params ?? {};
@@ -1025,26 +1057,17 @@ var echo = function createNewEcho(options) {
1025
1057
  return result;
1026
1058
  };
1027
1059
  const onEvent = async (event) => {
1028
- const context = {
1029
- ...event.context || {},
1030
- transport: event.transport,
1031
- eventId: event.id,
1032
- topic: event.topic,
1033
- headers: event.headers,
1034
- createdAt: event.createdAt,
1035
- attempt: event.attempt,
1036
- data: event.data
1037
- };
1038
- await resolve(event.data.params, context);
1060
+ await resolve(event.data.params, receivedEventContext(event));
1039
1061
  };
1040
1062
  return {
1041
1063
  type: options.type,
1042
1064
  params: options.params,
1043
1065
  returns: options.returns,
1044
1066
  attemptsBeforeDeadLetter: options.type === "event" ? options.attemptsBeforeDeadLetter : void 0,
1045
- ordered: options.type === "event" ? options.ordered : void 0,
1046
1067
  configVersion: options.type === "event" ? options.configVersion : void 0,
1047
- executionVersion: options.type === "event" ? options.executionVersion : void 0,
1068
+ maxConcurrency: options.type === "event" ? options.maxConcurrency : void 0,
1069
+ receiverMode: options.type === "event" ? "single" : void 0,
1070
+ batchSize: options.type === "event" ? 1 : void 0,
1048
1071
  resolve,
1049
1072
  onEvent,
1050
1073
  onMessage: async (messageData) => {
@@ -1082,6 +1105,50 @@ function createEchoRequest(options) {
1082
1105
  function createEchoEvent(options) {
1083
1106
  return echo({ ...options, type: "event" });
1084
1107
  }
1108
+ function createEchoBatchEvent(options) {
1109
+ if (!Number.isInteger(options.batchSize) || options.batchSize <= 0) {
1110
+ throw new Error("batchSize must be a positive integer.");
1111
+ }
1112
+ const resolveBatch = async (events) => {
1113
+ const cleaned = await Promise.all(
1114
+ events.map(async (event) => ({
1115
+ params: options.params ? await parseEchoesSchema(options.params, event.params) : event.params ?? {},
1116
+ context: event.context
1117
+ }))
1118
+ );
1119
+ await options.resolveBatch(cleaned);
1120
+ };
1121
+ const onEvents = async (events) => {
1122
+ await resolveBatch(
1123
+ events.map((event) => ({
1124
+ params: event.data.params,
1125
+ context: receivedEventContext(event)
1126
+ }))
1127
+ );
1128
+ };
1129
+ return {
1130
+ type: "event",
1131
+ params: options.params,
1132
+ attemptsBeforeDeadLetter: options.attemptsBeforeDeadLetter,
1133
+ configVersion: options.configVersion,
1134
+ maxConcurrency: options.maxConcurrency,
1135
+ receiverMode: "batch",
1136
+ batchSize: options.batchSize,
1137
+ resolve: async (params, context) => {
1138
+ await resolveBatch([{ params, context: context ?? {} }]);
1139
+ return void 0;
1140
+ },
1141
+ resolveBatch,
1142
+ onEvent: async (event) => await onEvents([event]),
1143
+ onEvents,
1144
+ onMessage: async () => {
1145
+ throw new Error("Echoes batch event receivers are supported only by the Pulse transport.");
1146
+ },
1147
+ onRequest: async () => {
1148
+ throw new Error("Echoes batch events cannot be invoked as requests.");
1149
+ }
1150
+ };
1151
+ }
1085
1152
 
1086
1153
  // src/schema.ts
1087
1154
  function typedEchoesSchema(schema) {
@@ -1134,6 +1201,28 @@ function EchoEvent(options = {}) {
1134
1201
  return method;
1135
1202
  };
1136
1203
  }
1204
+ function EchoBatchEvent(options) {
1205
+ return (method, context) => {
1206
+ const propertyKey = String(context.name);
1207
+ pendingEchoEntries[propertyKey] = (instance) => {
1208
+ const originalResolveBatch = instance[propertyKey].bind(instance);
1209
+ return createEchoBatchEvent({
1210
+ ...options,
1211
+ resolveBatch: async (events) => {
1212
+ return await runWithEchoesContext(
1213
+ {
1214
+ controllerType: "echo",
1215
+ echoName: propertyKey,
1216
+ params: events.map((event) => event.params)
1217
+ },
1218
+ async () => await originalResolveBatch(events)
1219
+ );
1220
+ }
1221
+ });
1222
+ };
1223
+ return method;
1224
+ };
1225
+ }
1137
1226
  function EchoRequest(options = {}) {
1138
1227
  return (method, context) => {
1139
1228
  const propertyKey = String(context.name);
@@ -1198,6 +1287,7 @@ function getServiceEchoes(target) {
1198
1287
  }
1199
1288
  // Annotate the CommonJS export names for ESM import in node:
1200
1289
  0 && (module.exports = {
1290
+ EchoBatchEvent,
1201
1291
  EchoEvent,
1202
1292
  EchoRequest,
1203
1293
  Echoes,
@@ -1205,6 +1295,7 @@ function getServiceEchoes(target) {
1205
1295
  EchoesValidationError,
1206
1296
  cleanEchoesSchema,
1207
1297
  configureEchoesRuntime,
1298
+ createEchoBatchEvent,
1208
1299
  createEchoEvent,
1209
1300
  createEchoRequest,
1210
1301
  createEchoesUserError,