@celerity-sdk/topic 0.3.1 → 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.
@@ -0,0 +1,161 @@
1
+ import {
2
+ TopicError,
3
+ __name
4
+ } from "./chunk-T4LCI5X5.js";
5
+
6
+ // src/providers/sns/sns-topic-client.ts
7
+ import { SNSClient } from "@aws-sdk/client-sns";
8
+
9
+ // src/providers/sns/sns-topic.ts
10
+ import createDebug from "debug";
11
+ import { PublishCommand, PublishBatchCommand } from "@aws-sdk/client-sns";
12
+ var debug = createDebug("celerity:topic:sns");
13
+ var SNS_MAX_BATCH_SIZE = 10;
14
+ var SNSTopic = class {
15
+ static {
16
+ __name(this, "SNSTopic");
17
+ }
18
+ topicArn;
19
+ client;
20
+ tracer;
21
+ constructor(topicArn, client, tracer) {
22
+ this.topicArn = topicArn;
23
+ this.client = client;
24
+ this.tracer = tracer;
25
+ }
26
+ async publish(body, options) {
27
+ debug("publish %s", this.topicArn);
28
+ return this.traced("celerity.topic.publish", {
29
+ "topic.arn": this.topicArn
30
+ }, async () => {
31
+ try {
32
+ const result = await this.client.send(new PublishCommand({
33
+ TopicArn: this.topicArn,
34
+ Message: JSON.stringify(body),
35
+ MessageGroupId: options?.groupId,
36
+ MessageDeduplicationId: options?.deduplicationId,
37
+ Subject: options?.subject,
38
+ MessageAttributes: options?.attributes ? toSNSAttributes(options.attributes) : void 0
39
+ }));
40
+ return {
41
+ messageId: result.MessageId
42
+ };
43
+ } catch (error) {
44
+ throw new TopicError(`Failed to publish message to topic "${this.topicArn}"`, this.topicArn, {
45
+ cause: error
46
+ });
47
+ }
48
+ });
49
+ }
50
+ async publishBatch(entries) {
51
+ debug("publishBatch %s (%d entries)", this.topicArn, entries.length);
52
+ return this.traced("celerity.topic.publish_batch", {
53
+ "topic.arn": this.topicArn,
54
+ "topic.message_count": entries.length
55
+ }, async () => {
56
+ const successful = [];
57
+ const failed = [];
58
+ for (let i = 0; i < entries.length; i += SNS_MAX_BATCH_SIZE) {
59
+ const chunk = entries.slice(i, i + SNS_MAX_BATCH_SIZE);
60
+ const snsEntries = chunk.map((entry) => ({
61
+ Id: entry.id,
62
+ Message: JSON.stringify(entry.body),
63
+ MessageGroupId: entry.options?.groupId,
64
+ MessageDeduplicationId: entry.options?.deduplicationId,
65
+ Subject: entry.options?.subject,
66
+ MessageAttributes: entry.options?.attributes ? toSNSAttributes(entry.options.attributes) : void 0
67
+ }));
68
+ try {
69
+ const result = await this.client.send(new PublishBatchCommand({
70
+ TopicArn: this.topicArn,
71
+ PublishBatchRequestEntries: snsEntries
72
+ }));
73
+ for (const s of result.Successful ?? []) {
74
+ successful.push({
75
+ id: s.Id,
76
+ messageId: s.MessageId
77
+ });
78
+ }
79
+ for (const f of result.Failed ?? []) {
80
+ failed.push({
81
+ id: f.Id,
82
+ code: f.Code,
83
+ message: f.Message ?? "Unknown error"
84
+ });
85
+ }
86
+ } catch (error) {
87
+ throw new TopicError(`Failed to publish message batch to topic "${this.topicArn}"`, this.topicArn, {
88
+ cause: error
89
+ });
90
+ }
91
+ }
92
+ return {
93
+ successful,
94
+ failed
95
+ };
96
+ });
97
+ }
98
+ traced(name, attributes, fn) {
99
+ if (!this.tracer) return fn();
100
+ return this.tracer.withSpan(name, (span) => fn(span), attributes);
101
+ }
102
+ };
103
+ function toSNSAttributes(attrs) {
104
+ const result = {};
105
+ for (const [key, value] of Object.entries(attrs)) {
106
+ result[key] = {
107
+ DataType: "String",
108
+ StringValue: value
109
+ };
110
+ }
111
+ return result;
112
+ }
113
+ __name(toSNSAttributes, "toSNSAttributes");
114
+
115
+ // src/providers/sns/config.ts
116
+ function captureSNSConfig() {
117
+ return {
118
+ region: process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION,
119
+ endpoint: process.env.CELERITY_AWS_SNS_ENDPOINT ?? process.env.AWS_ENDPOINT_URL,
120
+ credentials: process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY ? {
121
+ accessKeyId: process.env.AWS_ACCESS_KEY_ID,
122
+ secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
123
+ } : void 0
124
+ };
125
+ }
126
+ __name(captureSNSConfig, "captureSNSConfig");
127
+
128
+ // src/providers/sns/sns-topic-client.ts
129
+ var SNSTopicClient = class {
130
+ static {
131
+ __name(this, "SNSTopicClient");
132
+ }
133
+ tracer;
134
+ client = null;
135
+ config;
136
+ constructor(config, tracer) {
137
+ this.tracer = tracer;
138
+ this.config = config ?? captureSNSConfig();
139
+ }
140
+ topic(name) {
141
+ return new SNSTopic(name, this.getClient(), this.tracer);
142
+ }
143
+ close() {
144
+ this.client?.destroy();
145
+ this.client = null;
146
+ }
147
+ getClient() {
148
+ if (!this.client) {
149
+ this.client = new SNSClient({
150
+ region: this.config.region,
151
+ endpoint: this.config.endpoint,
152
+ credentials: this.config.credentials
153
+ });
154
+ }
155
+ return this.client;
156
+ }
157
+ };
158
+ export {
159
+ SNSTopicClient
160
+ };
161
+ //# sourceMappingURL=sns-topic-client-643MNMBF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/providers/sns/sns-topic-client.ts","../src/providers/sns/sns-topic.ts","../src/providers/sns/config.ts"],"sourcesContent":["import { SNSClient } from \"@aws-sdk/client-sns\";\nimport type { CelerityTracer } from \"@celerity-sdk/types\";\nimport type { TopicClient, Topic } from \"../../types\";\nimport { SNSTopic } from \"./sns-topic\";\nimport type { SNSTopicConfig } from \"./types\";\nimport { captureSNSConfig } from \"./config\";\n\nexport class SNSTopicClient implements TopicClient {\n private client: SNSClient | null = null;\n private readonly config: SNSTopicConfig;\n\n constructor(\n config?: SNSTopicConfig,\n private readonly tracer?: CelerityTracer,\n ) {\n this.config = config ?? captureSNSConfig();\n }\n\n topic(name: string): Topic {\n return new SNSTopic(name, this.getClient(), this.tracer);\n }\n\n close(): void {\n this.client?.destroy();\n this.client = null;\n }\n\n private getClient(): SNSClient {\n if (!this.client) {\n this.client = new SNSClient({\n region: this.config.region,\n endpoint: this.config.endpoint,\n credentials: this.config.credentials,\n });\n }\n return this.client;\n }\n}\n","import createDebug from \"debug\";\nimport {\n type SNSClient,\n PublishCommand,\n PublishBatchCommand,\n type MessageAttributeValue,\n type PublishBatchRequestEntry,\n} from \"@aws-sdk/client-sns\";\nimport type { CelerityTracer, CeleritySpan } from \"@celerity-sdk/types\";\nimport type {\n Topic,\n PublishOptions,\n PublishResult,\n BatchPublishEntry,\n BatchPublishResult,\n BatchPublishSuccess,\n BatchPublishFailure,\n} from \"../../types\";\nimport { TopicError } from \"../../errors\";\n\nconst debug = createDebug(\"celerity:topic:sns\");\n\nconst SNS_MAX_BATCH_SIZE = 10;\n\nexport class SNSTopic implements Topic {\n constructor(\n private readonly topicArn: string,\n private readonly client: SNSClient,\n private readonly tracer?: CelerityTracer,\n ) {}\n\n async publish<T = Record<string, unknown>>(\n body: T,\n options?: PublishOptions,\n ): Promise<PublishResult> {\n debug(\"publish %s\", this.topicArn);\n return this.traced(\"celerity.topic.publish\", { \"topic.arn\": this.topicArn }, async () => {\n try {\n const result = await this.client.send(\n new PublishCommand({\n TopicArn: this.topicArn,\n Message: JSON.stringify(body),\n MessageGroupId: options?.groupId,\n MessageDeduplicationId: options?.deduplicationId,\n Subject: options?.subject,\n MessageAttributes: options?.attributes\n ? toSNSAttributes(options.attributes)\n : undefined,\n }),\n );\n return { messageId: result.MessageId! };\n } catch (error) {\n throw new TopicError(\n `Failed to publish message to topic \"${this.topicArn}\"`,\n this.topicArn,\n { cause: error },\n );\n }\n });\n }\n\n async publishBatch<T = Record<string, unknown>>(\n entries: BatchPublishEntry<T>[],\n ): Promise<BatchPublishResult> {\n debug(\"publishBatch %s (%d entries)\", this.topicArn, entries.length);\n return this.traced(\n \"celerity.topic.publish_batch\",\n { \"topic.arn\": this.topicArn, \"topic.message_count\": entries.length },\n async () => {\n const successful: BatchPublishSuccess[] = [];\n const failed: BatchPublishFailure[] = [];\n\n // Auto-chunk into groups of 10 (SNS limit)\n for (let i = 0; i < entries.length; i += SNS_MAX_BATCH_SIZE) {\n const chunk = entries.slice(i, i + SNS_MAX_BATCH_SIZE);\n const snsEntries: PublishBatchRequestEntry[] = chunk.map((entry) => ({\n Id: entry.id,\n Message: JSON.stringify(entry.body),\n MessageGroupId: entry.options?.groupId,\n MessageDeduplicationId: entry.options?.deduplicationId,\n Subject: entry.options?.subject,\n MessageAttributes: entry.options?.attributes\n ? toSNSAttributes(entry.options.attributes)\n : undefined,\n }));\n\n try {\n const result = await this.client.send(\n new PublishBatchCommand({\n TopicArn: this.topicArn,\n PublishBatchRequestEntries: snsEntries,\n }),\n );\n\n for (const s of result.Successful ?? []) {\n successful.push({ id: s.Id!, messageId: s.MessageId! });\n }\n for (const f of result.Failed ?? []) {\n failed.push({ id: f.Id!, code: f.Code!, message: f.Message ?? \"Unknown error\" });\n }\n } catch (error) {\n throw new TopicError(\n `Failed to publish message batch to topic \"${this.topicArn}\"`,\n this.topicArn,\n { cause: error },\n );\n }\n }\n\n return { successful, failed };\n },\n );\n }\n\n private traced<T>(\n name: string,\n attributes: Record<string, string | number | boolean>,\n fn: (span?: CeleritySpan) => Promise<T>,\n ): Promise<T> {\n if (!this.tracer) return fn();\n return this.tracer.withSpan(name, (span) => fn(span), attributes);\n }\n}\n\nfunction toSNSAttributes(attrs: Record<string, string>): Record<string, MessageAttributeValue> {\n const result: Record<string, MessageAttributeValue> = {};\n for (const [key, value] of Object.entries(attrs)) {\n result[key] = { DataType: \"String\", StringValue: value };\n }\n return result;\n}\n","import type { SNSTopicConfig } from \"./types\";\n\n/**\n * Captures SNS configuration from environment variables.\n * This is the only place that reads `process.env` for SNS config.\n */\nexport function captureSNSConfig(): SNSTopicConfig {\n return {\n region: process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION,\n endpoint: process.env.CELERITY_AWS_SNS_ENDPOINT ?? process.env.AWS_ENDPOINT_URL,\n credentials:\n process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY\n ? {\n accessKeyId: process.env.AWS_ACCESS_KEY_ID,\n secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,\n }\n : undefined,\n };\n}\n"],"mappings":"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","names":["SNSClient","createDebug","PublishCommand","PublishBatchCommand","debug","createDebug","SNS_MAX_BATCH_SIZE","SNSTopic","topicArn","client","tracer","publish","body","options","traced","result","send","PublishCommand","TopicArn","Message","JSON","stringify","MessageGroupId","groupId","MessageDeduplicationId","deduplicationId","Subject","subject","MessageAttributes","attributes","toSNSAttributes","undefined","messageId","MessageId","error","TopicError","cause","publishBatch","entries","length","successful","failed","i","chunk","slice","snsEntries","map","entry","Id","id","PublishBatchCommand","PublishBatchRequestEntries","s","Successful","push","f","Failed","code","Code","message","name","fn","withSpan","span","attrs","key","value","Object","DataType","StringValue","captureSNSConfig","region","process","env","AWS_REGION","AWS_DEFAULT_REGION","endpoint","CELERITY_AWS_SNS_ENDPOINT","AWS_ENDPOINT_URL","credentials","AWS_ACCESS_KEY_ID","AWS_SECRET_ACCESS_KEY","accessKeyId","secretAccessKey","undefined","SNSTopicClient","client","config","tracer","captureSNSConfig","topic","name","SNSTopic","getClient","close","destroy","SNSClient","region","endpoint","credentials"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@celerity-sdk/topic",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "description": "Pub/Sub topic abstraction for the Celerity Node SDK (SNS / Pub/Sub / Service Bus Topics)",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -31,13 +31,23 @@
31
31
  "node": ">=22.0.0"
32
32
  },
33
33
  "dependencies": {
34
- "@celerity-sdk/types": "^0.3.1",
35
- "@celerity-sdk/config": "^0.3.1"
34
+ "debug": "^4.4.0",
35
+ "@celerity-sdk/types": "^0.5.0",
36
+ "@celerity-sdk/common": "^0.5.0",
37
+ "@celerity-sdk/config": "^0.5.0"
38
+ },
39
+ "devDependencies": {
40
+ "@aws-sdk/client-sns": "^3.750.0",
41
+ "@aws-sdk/client-sqs": "^3.750.0",
42
+ "ioredis": "^5.4.0",
43
+ "reflect-metadata": "^0.2.0"
36
44
  },
37
45
  "peerDependencies": {
38
46
  "@aws-sdk/client-sns": "^3.0.0",
39
47
  "@google-cloud/pubsub": "^4.0.0",
40
- "@azure/service-bus": "^7.0.0"
48
+ "@azure/service-bus": "^7.0.0",
49
+ "ioredis": "^5.0.0",
50
+ "reflect-metadata": "^0.2.0"
41
51
  },
42
52
  "peerDependenciesMeta": {
43
53
  "@aws-sdk/client-sns": {
@@ -48,6 +58,12 @@
48
58
  },
49
59
  "@azure/service-bus": {
50
60
  "optional": true
61
+ },
62
+ "ioredis": {
63
+ "optional": true
64
+ },
65
+ "reflect-metadata": {
66
+ "optional": true
51
67
  }
52
68
  },
53
69
  "publishConfig": {
package/dist/index.d.cts DELETED
@@ -1,2 +0,0 @@
1
-
2
- export { }