@celerity-sdk/topic 0.4.0 → 0.5.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.cjs CHANGED
@@ -6,6 +6,9 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
8
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
9
12
  var __export = (target, all) => {
10
13
  for (var name in all)
11
14
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -28,136 +31,25 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
31
  ));
29
32
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
33
 
31
- // src/index.ts
32
- var index_exports = {};
33
- __export(index_exports, {
34
- DEFAULT_TOPIC_TOKEN: () => DEFAULT_TOPIC_TOKEN,
35
- RedisTopicClient: () => RedisTopicClient,
36
- SNSTopicClient: () => SNSTopicClient,
37
- Topic: () => Topic,
38
- TopicClient: () => TopicClient,
39
- TopicError: () => TopicError,
40
- TopicLayer: () => TopicLayer,
41
- createTopicClient: () => createTopicClient,
42
- getTopic: () => getTopic,
43
- topicToken: () => topicToken
44
- });
45
- module.exports = __toCommonJS(index_exports);
46
-
47
- // src/types.ts
48
- var TopicClient = /* @__PURE__ */ Symbol.for("TopicClient");
49
-
50
- // src/providers/sns/sns-topic-client.ts
51
- var import_client_sns2 = require("@aws-sdk/client-sns");
52
-
53
- // src/providers/sns/sns-topic.ts
54
- var import_debug = __toESM(require("debug"), 1);
55
- var import_client_sns = require("@aws-sdk/client-sns");
56
-
57
34
  // src/errors.ts
58
- var TopicError = class extends Error {
59
- static {
60
- __name(this, "TopicError");
61
- }
62
- topic;
63
- constructor(message, topic, options) {
64
- super(message, options), this.topic = topic;
65
- this.name = "TopicError";
66
- }
67
- };
68
-
69
- // src/providers/sns/sns-topic.ts
70
- var debug = (0, import_debug.default)("celerity:topic:sns");
71
- var SNS_MAX_BATCH_SIZE = 10;
72
- var SNSTopic = class {
73
- static {
74
- __name(this, "SNSTopic");
75
- }
76
- topicArn;
77
- client;
78
- tracer;
79
- constructor(topicArn, client, tracer) {
80
- this.topicArn = topicArn;
81
- this.client = client;
82
- this.tracer = tracer;
83
- }
84
- async publish(body, options) {
85
- debug("publish %s", this.topicArn);
86
- return this.traced("celerity.topic.publish", {
87
- "topic.arn": this.topicArn
88
- }, async () => {
89
- try {
90
- const result = await this.client.send(new import_client_sns.PublishCommand({
91
- TopicArn: this.topicArn,
92
- Message: JSON.stringify(body),
93
- MessageGroupId: options?.groupId,
94
- MessageDeduplicationId: options?.deduplicationId,
95
- Subject: options?.subject,
96
- MessageAttributes: options?.attributes ? toSNSAttributes(options.attributes) : void 0
97
- }));
98
- return {
99
- messageId: result.MessageId
100
- };
101
- } catch (error) {
102
- throw new TopicError(`Failed to publish message to topic "${this.topicArn}"`, this.topicArn, {
103
- cause: error
104
- });
35
+ var TopicError;
36
+ var init_errors = __esm({
37
+ "src/errors.ts"() {
38
+ "use strict";
39
+ TopicError = class extends Error {
40
+ static {
41
+ __name(this, "TopicError");
105
42
  }
106
- });
107
- }
108
- async publishBatch(entries) {
109
- debug("publishBatch %s (%d entries)", this.topicArn, entries.length);
110
- return this.traced("celerity.topic.publish_batch", {
111
- "topic.arn": this.topicArn,
112
- "topic.message_count": entries.length
113
- }, async () => {
114
- const successful = [];
115
- const failed = [];
116
- for (let i = 0; i < entries.length; i += SNS_MAX_BATCH_SIZE) {
117
- const chunk = entries.slice(i, i + SNS_MAX_BATCH_SIZE);
118
- const snsEntries = chunk.map((entry) => ({
119
- Id: entry.id,
120
- Message: JSON.stringify(entry.body),
121
- MessageGroupId: entry.options?.groupId,
122
- MessageDeduplicationId: entry.options?.deduplicationId,
123
- Subject: entry.options?.subject,
124
- MessageAttributes: entry.options?.attributes ? toSNSAttributes(entry.options.attributes) : void 0
125
- }));
126
- try {
127
- const result = await this.client.send(new import_client_sns.PublishBatchCommand({
128
- TopicArn: this.topicArn,
129
- PublishBatchRequestEntries: snsEntries
130
- }));
131
- for (const s of result.Successful ?? []) {
132
- successful.push({
133
- id: s.Id,
134
- messageId: s.MessageId
135
- });
136
- }
137
- for (const f of result.Failed ?? []) {
138
- failed.push({
139
- id: f.Id,
140
- code: f.Code,
141
- message: f.Message ?? "Unknown error"
142
- });
143
- }
144
- } catch (error) {
145
- throw new TopicError(`Failed to publish message batch to topic "${this.topicArn}"`, this.topicArn, {
146
- cause: error
147
- });
148
- }
43
+ topic;
44
+ constructor(message, topic, options) {
45
+ super(message, options), this.topic = topic;
46
+ this.name = "TopicError";
149
47
  }
150
- return {
151
- successful,
152
- failed
153
- };
154
- });
155
- }
156
- traced(name, attributes, fn) {
157
- if (!this.tracer) return fn();
158
- return this.tracer.withSpan(name, (span) => fn(span), attributes);
48
+ };
159
49
  }
160
- };
50
+ });
51
+
52
+ // src/providers/sns/sns-topic.ts
161
53
  function toSNSAttributes(attrs) {
162
54
  const result = {};
163
55
  for (const [key, value] of Object.entries(attrs)) {
@@ -168,139 +60,171 @@ function toSNSAttributes(attrs) {
168
60
  }
169
61
  return result;
170
62
  }
171
- __name(toSNSAttributes, "toSNSAttributes");
63
+ var import_debug, import_client_sns, debug, SNS_MAX_BATCH_SIZE, SNSTopic;
64
+ var init_sns_topic = __esm({
65
+ "src/providers/sns/sns-topic.ts"() {
66
+ "use strict";
67
+ import_debug = __toESM(require("debug"), 1);
68
+ import_client_sns = require("@aws-sdk/client-sns");
69
+ init_errors();
70
+ debug = (0, import_debug.default)("celerity:topic:sns");
71
+ SNS_MAX_BATCH_SIZE = 10;
72
+ SNSTopic = class {
73
+ static {
74
+ __name(this, "SNSTopic");
75
+ }
76
+ topicArn;
77
+ client;
78
+ tracer;
79
+ constructor(topicArn, client, tracer) {
80
+ this.topicArn = topicArn;
81
+ this.client = client;
82
+ this.tracer = tracer;
83
+ }
84
+ async publish(body, options) {
85
+ debug("publish %s", this.topicArn);
86
+ return this.traced("celerity.topic.publish", {
87
+ "topic.arn": this.topicArn
88
+ }, async () => {
89
+ try {
90
+ const result = await this.client.send(new import_client_sns.PublishCommand({
91
+ TopicArn: this.topicArn,
92
+ Message: JSON.stringify(body),
93
+ MessageGroupId: options?.groupId,
94
+ MessageDeduplicationId: options?.deduplicationId,
95
+ Subject: options?.subject,
96
+ MessageAttributes: options?.attributes ? toSNSAttributes(options.attributes) : void 0
97
+ }));
98
+ return {
99
+ messageId: result.MessageId
100
+ };
101
+ } catch (error) {
102
+ throw new TopicError(`Failed to publish message to topic "${this.topicArn}"`, this.topicArn, {
103
+ cause: error
104
+ });
105
+ }
106
+ });
107
+ }
108
+ async publishBatch(entries) {
109
+ debug("publishBatch %s (%d entries)", this.topicArn, entries.length);
110
+ return this.traced("celerity.topic.publish_batch", {
111
+ "topic.arn": this.topicArn,
112
+ "topic.message_count": entries.length
113
+ }, async () => {
114
+ const successful = [];
115
+ const failed = [];
116
+ for (let i = 0; i < entries.length; i += SNS_MAX_BATCH_SIZE) {
117
+ const chunk = entries.slice(i, i + SNS_MAX_BATCH_SIZE);
118
+ const snsEntries = chunk.map((entry) => ({
119
+ Id: entry.id,
120
+ Message: JSON.stringify(entry.body),
121
+ MessageGroupId: entry.options?.groupId,
122
+ MessageDeduplicationId: entry.options?.deduplicationId,
123
+ Subject: entry.options?.subject,
124
+ MessageAttributes: entry.options?.attributes ? toSNSAttributes(entry.options.attributes) : void 0
125
+ }));
126
+ try {
127
+ const result = await this.client.send(new import_client_sns.PublishBatchCommand({
128
+ TopicArn: this.topicArn,
129
+ PublishBatchRequestEntries: snsEntries
130
+ }));
131
+ for (const s of result.Successful ?? []) {
132
+ successful.push({
133
+ id: s.Id,
134
+ messageId: s.MessageId
135
+ });
136
+ }
137
+ for (const f of result.Failed ?? []) {
138
+ failed.push({
139
+ id: f.Id,
140
+ code: f.Code,
141
+ message: f.Message ?? "Unknown error"
142
+ });
143
+ }
144
+ } catch (error) {
145
+ throw new TopicError(`Failed to publish message batch to topic "${this.topicArn}"`, this.topicArn, {
146
+ cause: error
147
+ });
148
+ }
149
+ }
150
+ return {
151
+ successful,
152
+ failed
153
+ };
154
+ });
155
+ }
156
+ traced(name, attributes, fn) {
157
+ if (!this.tracer) return fn();
158
+ return this.tracer.withSpan(name, (span) => fn(span), attributes);
159
+ }
160
+ };
161
+ __name(toSNSAttributes, "toSNSAttributes");
162
+ }
163
+ });
172
164
 
173
165
  // src/providers/sns/config.ts
174
166
  function captureSNSConfig() {
175
167
  return {
176
168
  region: process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION,
177
- endpoint: process.env.AWS_ENDPOINT_URL,
169
+ endpoint: process.env.CELERITY_AWS_SNS_ENDPOINT ?? process.env.AWS_ENDPOINT_URL,
178
170
  credentials: process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY ? {
179
171
  accessKeyId: process.env.AWS_ACCESS_KEY_ID,
180
172
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
181
173
  } : void 0
182
174
  };
183
175
  }
184
- __name(captureSNSConfig, "captureSNSConfig");
185
-
186
- // src/providers/sns/sns-topic-client.ts
187
- var SNSTopicClient = class {
188
- static {
189
- __name(this, "SNSTopicClient");
190
- }
191
- tracer;
192
- client = null;
193
- config;
194
- constructor(config, tracer) {
195
- this.tracer = tracer;
196
- this.config = config ?? captureSNSConfig();
197
- }
198
- topic(name) {
199
- return new SNSTopic(name, this.getClient(), this.tracer);
200
- }
201
- close() {
202
- this.client?.destroy();
203
- this.client = null;
204
- }
205
- getClient() {
206
- if (!this.client) {
207
- this.client = new import_client_sns2.SNSClient({
208
- region: this.config.region,
209
- endpoint: this.config.endpoint,
210
- credentials: this.config.credentials
211
- });
212
- }
213
- return this.client;
176
+ var init_config = __esm({
177
+ "src/providers/sns/config.ts"() {
178
+ "use strict";
179
+ __name(captureSNSConfig, "captureSNSConfig");
214
180
  }
215
- };
181
+ });
216
182
 
217
- // src/providers/redis/redis-topic.ts
218
- var import_node_crypto = require("crypto");
219
- var import_debug2 = __toESM(require("debug"), 1);
220
- var debug2 = (0, import_debug2.default)("celerity:topic:redis");
221
- var RedisTopic = class {
222
- static {
223
- __name(this, "RedisTopic");
224
- }
225
- channelName;
226
- client;
227
- tracer;
228
- constructor(channelName, client, tracer) {
229
- this.channelName = channelName;
230
- this.client = client;
231
- this.tracer = tracer;
232
- }
233
- async publish(body, options) {
234
- debug2("publish %s", this.channelName);
235
- return this.traced("celerity.topic.publish", {
236
- "topic.channel": this.channelName
237
- }, async () => {
238
- try {
239
- const messageId = (0, import_node_crypto.randomUUID)();
240
- const payload = buildEnvelope(body, messageId, options);
241
- await this.client.publish(this.channelName, payload);
242
- return {
243
- messageId
244
- };
245
- } catch (error) {
246
- throw new TopicError(`Failed to publish message to channel "${this.channelName}"`, this.channelName, {
247
- cause: error
248
- });
183
+ // src/providers/sns/sns-topic-client.ts
184
+ var sns_topic_client_exports = {};
185
+ __export(sns_topic_client_exports, {
186
+ SNSTopicClient: () => SNSTopicClient
187
+ });
188
+ var import_client_sns2, SNSTopicClient;
189
+ var init_sns_topic_client = __esm({
190
+ "src/providers/sns/sns-topic-client.ts"() {
191
+ "use strict";
192
+ import_client_sns2 = require("@aws-sdk/client-sns");
193
+ init_sns_topic();
194
+ init_config();
195
+ SNSTopicClient = class {
196
+ static {
197
+ __name(this, "SNSTopicClient");
249
198
  }
250
- });
251
- }
252
- async publishBatch(entries) {
253
- debug2("publishBatch %s (%d entries)", this.channelName, entries.length);
254
- return this.traced("celerity.topic.publish_batch", {
255
- "topic.channel": this.channelName,
256
- "topic.message_count": entries.length
257
- }, async () => {
258
- const successful = [];
259
- const failed = [];
260
- const messageIds = [];
261
- const pipeline = this.client.pipeline();
262
- for (const entry of entries) {
263
- const messageId = (0, import_node_crypto.randomUUID)();
264
- messageIds.push(messageId);
265
- const payload = buildEnvelope(entry.body, messageId, entry.options);
266
- pipeline.publish(this.channelName, payload);
199
+ tracer;
200
+ client = null;
201
+ config;
202
+ constructor(config, tracer) {
203
+ this.tracer = tracer;
204
+ this.config = config ?? captureSNSConfig();
267
205
  }
268
- try {
269
- const results = await pipeline.exec();
270
- if (!results) {
271
- throw new Error("Pipeline returned null");
272
- }
273
- for (let i = 0; i < entries.length; i++) {
274
- const [err] = results[i];
275
- if (err) {
276
- failed.push({
277
- id: entries[i].id,
278
- code: err.name ?? "PipelineError",
279
- message: err.message
280
- });
281
- } else {
282
- successful.push({
283
- id: entries[i].id,
284
- messageId: messageIds[i]
285
- });
286
- }
206
+ topic(name) {
207
+ return new SNSTopic(name, this.getClient(), this.tracer);
208
+ }
209
+ close() {
210
+ this.client?.destroy();
211
+ this.client = null;
212
+ }
213
+ getClient() {
214
+ if (!this.client) {
215
+ this.client = new import_client_sns2.SNSClient({
216
+ region: this.config.region,
217
+ endpoint: this.config.endpoint,
218
+ credentials: this.config.credentials
219
+ });
287
220
  }
288
- } catch (error) {
289
- throw new TopicError(`Failed to publish message batch to channel "${this.channelName}"`, this.channelName, {
290
- cause: error
291
- });
221
+ return this.client;
292
222
  }
293
- return {
294
- successful,
295
- failed
296
- };
297
- });
298
- }
299
- traced(name, attributes, fn) {
300
- if (!this.tracer) return fn();
301
- return this.tracer.withSpan(name, (span) => fn(span), attributes);
223
+ };
302
224
  }
303
- };
225
+ });
226
+
227
+ // src/providers/redis/redis-topic.ts
304
228
  function buildEnvelope(body, messageId, options) {
305
229
  const envelope = {
306
230
  body: JSON.stringify(body),
@@ -314,59 +238,202 @@ function buildEnvelope(body, messageId, options) {
314
238
  }
315
239
  return JSON.stringify(envelope);
316
240
  }
317
- __name(buildEnvelope, "buildEnvelope");
241
+ var import_node_crypto, import_debug2, debug2, RedisTopic;
242
+ var init_redis_topic = __esm({
243
+ "src/providers/redis/redis-topic.ts"() {
244
+ "use strict";
245
+ import_node_crypto = require("crypto");
246
+ import_debug2 = __toESM(require("debug"), 1);
247
+ init_errors();
248
+ debug2 = (0, import_debug2.default)("celerity:topic:redis");
249
+ RedisTopic = class {
250
+ static {
251
+ __name(this, "RedisTopic");
252
+ }
253
+ channelName;
254
+ client;
255
+ tracer;
256
+ constructor(channelName, client, tracer) {
257
+ this.channelName = channelName;
258
+ this.client = client;
259
+ this.tracer = tracer;
260
+ }
261
+ async publish(body, options) {
262
+ debug2("publish %s", this.channelName);
263
+ return this.traced("celerity.topic.publish", {
264
+ "topic.channel": this.channelName
265
+ }, async () => {
266
+ try {
267
+ const messageId = (0, import_node_crypto.randomUUID)();
268
+ const payload = buildEnvelope(body, messageId, options);
269
+ await this.client.publish(this.channelName, payload);
270
+ return {
271
+ messageId
272
+ };
273
+ } catch (error) {
274
+ throw new TopicError(`Failed to publish message to channel "${this.channelName}"`, this.channelName, {
275
+ cause: error
276
+ });
277
+ }
278
+ });
279
+ }
280
+ async publishBatch(entries) {
281
+ debug2("publishBatch %s (%d entries)", this.channelName, entries.length);
282
+ return this.traced("celerity.topic.publish_batch", {
283
+ "topic.channel": this.channelName,
284
+ "topic.message_count": entries.length
285
+ }, async () => {
286
+ const successful = [];
287
+ const failed = [];
288
+ const messageIds = [];
289
+ const pipeline = this.client.pipeline();
290
+ for (const entry of entries) {
291
+ const messageId = (0, import_node_crypto.randomUUID)();
292
+ messageIds.push(messageId);
293
+ const payload = buildEnvelope(entry.body, messageId, entry.options);
294
+ pipeline.publish(this.channelName, payload);
295
+ }
296
+ try {
297
+ const results = await pipeline.exec();
298
+ if (!results) {
299
+ throw new Error("Pipeline returned null");
300
+ }
301
+ for (let i = 0; i < entries.length; i++) {
302
+ const [err] = results[i];
303
+ if (err) {
304
+ failed.push({
305
+ id: entries[i].id,
306
+ code: err.name ?? "PipelineError",
307
+ message: err.message
308
+ });
309
+ } else {
310
+ successful.push({
311
+ id: entries[i].id,
312
+ messageId: messageIds[i]
313
+ });
314
+ }
315
+ }
316
+ } catch (error) {
317
+ throw new TopicError(`Failed to publish message batch to channel "${this.channelName}"`, this.channelName, {
318
+ cause: error
319
+ });
320
+ }
321
+ return {
322
+ successful,
323
+ failed
324
+ };
325
+ });
326
+ }
327
+ traced(name, attributes, fn) {
328
+ if (!this.tracer) return fn();
329
+ return this.tracer.withSpan(name, (span) => fn(span), attributes);
330
+ }
331
+ };
332
+ __name(buildEnvelope, "buildEnvelope");
333
+ }
334
+ });
318
335
 
319
336
  // src/providers/redis/config.ts
320
- var DEFAULT_REDIS_URL = "redis://localhost:6379";
321
337
  function captureRedisConfig() {
322
338
  return {
323
- url: process.env.CELERITY_LOCAL_REDIS_URL ?? DEFAULT_REDIS_URL
339
+ url: process.env.CELERITY_REDIS_ENDPOINT ?? DEFAULT_REDIS_URL
324
340
  };
325
341
  }
326
- __name(captureRedisConfig, "captureRedisConfig");
342
+ var DEFAULT_REDIS_URL;
343
+ var init_config2 = __esm({
344
+ "src/providers/redis/config.ts"() {
345
+ "use strict";
346
+ DEFAULT_REDIS_URL = "redis://localhost:6379";
347
+ __name(captureRedisConfig, "captureRedisConfig");
348
+ }
349
+ });
327
350
 
328
351
  // src/providers/redis/redis-topic-client.ts
329
- var RedisTopicClient = class {
330
- static {
331
- __name(this, "RedisTopicClient");
332
- }
333
- tracer;
334
- client = null;
335
- config;
336
- constructor(config, tracer) {
337
- this.tracer = tracer;
338
- this.config = config ?? captureRedisConfig();
339
- }
340
- topic(name) {
341
- return new RedisTopic(name, this.getClient(), this.tracer);
342
- }
343
- async close() {
344
- if (this.client) {
345
- await this.client.quit();
346
- this.client = null;
347
- }
348
- }
349
- getClient() {
350
- if (!this.client) {
351
- const Redis = require("ioredis").default ?? require("ioredis");
352
- this.client = new Redis(this.config.url);
353
- }
354
- return this.client;
352
+ var redis_topic_client_exports = {};
353
+ __export(redis_topic_client_exports, {
354
+ RedisTopicClient: () => RedisTopicClient
355
+ });
356
+ var RedisTopicClient;
357
+ var init_redis_topic_client = __esm({
358
+ "src/providers/redis/redis-topic-client.ts"() {
359
+ "use strict";
360
+ init_redis_topic();
361
+ init_config2();
362
+ RedisTopicClient = class {
363
+ static {
364
+ __name(this, "RedisTopicClient");
365
+ }
366
+ tracer;
367
+ client = null;
368
+ ioredisModule = null;
369
+ config;
370
+ constructor(config, tracer) {
371
+ this.tracer = tracer;
372
+ this.config = config ?? captureRedisConfig();
373
+ }
374
+ topic(name) {
375
+ const channel = `celerity:topic:channel:${name}`;
376
+ return new RedisTopic(channel, this.getClient(), this.tracer);
377
+ }
378
+ async close() {
379
+ if (this.client) {
380
+ await this.client.quit();
381
+ this.client = null;
382
+ }
383
+ }
384
+ async ensureIoRedis() {
385
+ if (!this.ioredisModule) {
386
+ const pkg = "ioredis";
387
+ this.ioredisModule = await import(pkg);
388
+ }
389
+ }
390
+ getClient() {
391
+ if (!this.client) {
392
+ const ioredis = this.ioredisModule;
393
+ const Redis = ioredis.default ?? ioredis;
394
+ this.client = new Redis(this.config.url);
395
+ }
396
+ return this.client;
397
+ }
398
+ };
355
399
  }
356
- };
400
+ });
401
+
402
+ // src/index.ts
403
+ var index_exports = {};
404
+ __export(index_exports, {
405
+ DEFAULT_TOPIC_TOKEN: () => DEFAULT_TOPIC_TOKEN,
406
+ Topic: () => Topic,
407
+ TopicClient: () => TopicClient,
408
+ TopicError: () => TopicError,
409
+ TopicLayer: () => TopicLayer,
410
+ createTopicClient: () => createTopicClient,
411
+ getTopic: () => getTopic,
412
+ topicToken: () => topicToken
413
+ });
414
+ module.exports = __toCommonJS(index_exports);
415
+
416
+ // src/types.ts
417
+ var TopicClient = /* @__PURE__ */ Symbol.for("TopicClient");
357
418
 
358
419
  // src/factory.ts
359
420
  var import_config3 = require("@celerity-sdk/config");
360
- function createTopicClient(options) {
421
+ async function createTopicClient(options) {
361
422
  const resolved = (0, import_config3.resolveConfig)("topic");
362
423
  const provider = options?.provider ?? resolved.provider;
363
424
  switch (provider) {
364
- case "aws":
365
- return new SNSTopicClient(options?.aws, options?.tracer);
425
+ case "aws": {
426
+ const { SNSTopicClient: SNSTopicClient2 } = await Promise.resolve().then(() => (init_sns_topic_client(), sns_topic_client_exports));
427
+ return new SNSTopicClient2(options?.aws, options?.tracer);
428
+ }
366
429
  // Local environments always use Redis pub/sub regardless of deploy target.
367
430
  // The Celerity CLI manages the Redis instance and local-events sidecar.
368
- case "local":
369
- return new RedisTopicClient(options?.local, options?.tracer);
431
+ case "local": {
432
+ const { RedisTopicClient: RedisTopicClient2 } = await Promise.resolve().then(() => (init_redis_topic_client(), redis_topic_client_exports));
433
+ const client = new RedisTopicClient2(options?.local, options?.tracer);
434
+ await client.ensureIoRedis();
435
+ return client;
436
+ }
370
437
  // case "gcp":
371
438
  // v1: Google Cloud Pub/Sub
372
439
  // case "azure":
@@ -424,7 +491,7 @@ var TopicLayer = class {
424
491
  async handle(context, next) {
425
492
  if (!this.initialized) {
426
493
  const tracer = context.container.has(import_common2.TRACER_TOKEN) ? await context.container.resolve(import_common2.TRACER_TOKEN) : void 0;
427
- const client = createTopicClient({
494
+ const client = await createTopicClient({
428
495
  tracer
429
496
  });
430
497
  debug3("registering TopicClient");
@@ -459,11 +526,12 @@ var TopicLayer = class {
459
526
  return next();
460
527
  }
461
528
  };
529
+
530
+ // src/index.ts
531
+ init_errors();
462
532
  // Annotate the CommonJS export names for ESM import in node:
463
533
  0 && (module.exports = {
464
534
  DEFAULT_TOPIC_TOKEN,
465
- RedisTopicClient,
466
- SNSTopicClient,
467
535
  Topic,
468
536
  TopicClient,
469
537
  TopicError,