@geekmidas/events 0.0.1
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/README.md +473 -0
- package/dist/BasicConnection-BNi6_olg.mjs +42 -0
- package/dist/BasicConnection-BNi6_olg.mjs.map +1 -0
- package/dist/BasicConnection-C4_Y0nIj.d.mts +26 -0
- package/dist/BasicConnection-CddnULuT.d.cts +26 -0
- package/dist/BasicConnection-CzfMubv_.cjs +48 -0
- package/dist/BasicConnection-CzfMubv_.cjs.map +1 -0
- package/dist/BasicPublisher-BzfzHIfb.cjs +20 -0
- package/dist/BasicPublisher-BzfzHIfb.cjs.map +1 -0
- package/dist/BasicPublisher-Cg3SxIVR.mjs +14 -0
- package/dist/BasicPublisher-Cg3SxIVR.mjs.map +1 -0
- package/dist/BasicPublisher-DCBxaTwC.d.mts +12 -0
- package/dist/BasicPublisher-V5hELHG9.d.cts +12 -0
- package/dist/BasicSubscriber-BB3aKeph.d.mts +12 -0
- package/dist/BasicSubscriber-BEv5N21f.mjs +18 -0
- package/dist/BasicSubscriber-BEv5N21f.mjs.map +1 -0
- package/dist/BasicSubscriber-DOwgFw5j.d.cts +12 -0
- package/dist/BasicSubscriber-DyTKOixe.cjs +24 -0
- package/dist/BasicSubscriber-DyTKOixe.cjs.map +1 -0
- package/dist/EventConnection-ClLMoIUU.mjs +36 -0
- package/dist/EventConnection-ClLMoIUU.mjs.map +1 -0
- package/dist/EventConnection-DZhn1Msl.d.cts +13 -0
- package/dist/EventConnection-DeXfLGom.d.mts +13 -0
- package/dist/EventConnection-F_N81SXu.cjs +41 -0
- package/dist/EventConnection-F_N81SXu.cjs.map +1 -0
- package/dist/EventConnection.cjs +5 -0
- package/dist/EventConnection.d.cts +3 -0
- package/dist/EventConnection.d.mts +3 -0
- package/dist/EventConnection.mjs +4 -0
- package/dist/Publisher-C3m8JFXm.d.mts +19 -0
- package/dist/Publisher-DS0aOh8r.mjs +65 -0
- package/dist/Publisher-DS0aOh8r.mjs.map +1 -0
- package/dist/Publisher-ceu6OxCj.cjs +70 -0
- package/dist/Publisher-ceu6OxCj.cjs.map +1 -0
- package/dist/Publisher-nXNVjL0e.d.cts +19 -0
- package/dist/Publisher.cjs +4 -0
- package/dist/Publisher.d.cts +3 -0
- package/dist/Publisher.d.mts +3 -0
- package/dist/Publisher.mjs +4 -0
- package/dist/RabbitMQConnection-7cWp_-_Q.d.cts +43 -0
- package/dist/RabbitMQConnection-BN_GybOv.cjs +113 -0
- package/dist/RabbitMQConnection-BN_GybOv.cjs.map +1 -0
- package/dist/RabbitMQConnection-C2HC7J7K.d.mts +43 -0
- package/dist/RabbitMQConnection-eVOVS4Dl.mjs +107 -0
- package/dist/RabbitMQConnection-eVOVS4Dl.mjs.map +1 -0
- package/dist/RabbitMQPublisher-BZX0edgL.mjs +39 -0
- package/dist/RabbitMQPublisher-BZX0edgL.mjs.map +1 -0
- package/dist/RabbitMQPublisher-CSCn6gMA.cjs +45 -0
- package/dist/RabbitMQPublisher-CSCn6gMA.cjs.map +1 -0
- package/dist/RabbitMQPublisher-CpcbgrXj.d.cts +23 -0
- package/dist/RabbitMQPublisher-DDZi15Ro.d.mts +23 -0
- package/dist/RabbitMQSubscriber-B5I-hBaT.mjs +57 -0
- package/dist/RabbitMQSubscriber-B5I-hBaT.mjs.map +1 -0
- package/dist/RabbitMQSubscriber-BJ9PTGny.d.cts +25 -0
- package/dist/RabbitMQSubscriber-CIvIw8MG.d.mts +25 -0
- package/dist/RabbitMQSubscriber-Cj7qLIi6.cjs +63 -0
- package/dist/RabbitMQSubscriber-Cj7qLIi6.cjs.map +1 -0
- package/dist/SNSConnection-CAImaMM2.d.mts +40 -0
- package/dist/SNSConnection-Cqbr7-Ho.d.cts +40 -0
- package/dist/SNSConnection-D7wCf9Si.mjs +70 -0
- package/dist/SNSConnection-D7wCf9Si.mjs.map +1 -0
- package/dist/SNSConnection-DVsC_pbB.cjs +76 -0
- package/dist/SNSConnection-DVsC_pbB.cjs.map +1 -0
- package/dist/SNSPublisher-BZ6N3JI9.cjs +48 -0
- package/dist/SNSPublisher-BZ6N3JI9.cjs.map +1 -0
- package/dist/SNSPublisher-BfWjzNiB.mjs +42 -0
- package/dist/SNSPublisher-BfWjzNiB.mjs.map +1 -0
- package/dist/SNSPublisher-Dkhb4LU-.d.mts +21 -0
- package/dist/SNSPublisher-RVZFa7kL.d.cts +21 -0
- package/dist/SNSSubscriber-B31JmkAE.d.mts +54 -0
- package/dist/SNSSubscriber-C9YJWa7m.mjs +143 -0
- package/dist/SNSSubscriber-C9YJWa7m.mjs.map +1 -0
- package/dist/SNSSubscriber-UE0ia4XM.cjs +149 -0
- package/dist/SNSSubscriber-UE0ia4XM.cjs.map +1 -0
- package/dist/SNSSubscriber-k2UwKUxu.d.cts +54 -0
- package/dist/SQSConnection-BwNjUPr4.cjs +76 -0
- package/dist/SQSConnection-BwNjUPr4.cjs.map +1 -0
- package/dist/SQSConnection-C5WFqZW7.d.mts +40 -0
- package/dist/SQSConnection-Eleqqre3.mjs +70 -0
- package/dist/SQSConnection-Eleqqre3.mjs.map +1 -0
- package/dist/SQSConnection-geav2Rsn.d.cts +40 -0
- package/dist/SQSPublisher-CdsayOLV.d.mts +23 -0
- package/dist/SQSPublisher-DG9o4ME3.mjs +57 -0
- package/dist/SQSPublisher-DG9o4ME3.mjs.map +1 -0
- package/dist/SQSPublisher-Dq5353oZ.cjs +63 -0
- package/dist/SQSPublisher-Dq5353oZ.cjs.map +1 -0
- package/dist/SQSPublisher-Utb_FTe5.d.cts +23 -0
- package/dist/SQSSubscriber-B6iL1EnX.d.cts +43 -0
- package/dist/SQSSubscriber-CD66P7hH.mjs +121 -0
- package/dist/SQSSubscriber-CD66P7hH.mjs.map +1 -0
- package/dist/SQSSubscriber-DBeE4XAR.d.mts +43 -0
- package/dist/SQSSubscriber-DZDNgLE5.cjs +127 -0
- package/dist/SQSSubscriber-DZDNgLE5.cjs.map +1 -0
- package/dist/Subscriber-Bd9hb_jp.mjs +74 -0
- package/dist/Subscriber-Bd9hb_jp.mjs.map +1 -0
- package/dist/Subscriber-Cff9EIpv.d.mts +19 -0
- package/dist/Subscriber-CpAwcUzb.d.cts +19 -0
- package/dist/Subscriber-saVOWuMq.cjs +79 -0
- package/dist/Subscriber-saVOWuMq.cjs.map +1 -0
- package/dist/Subscriber.cjs +4 -0
- package/dist/Subscriber.d.cts +3 -0
- package/dist/Subscriber.d.mts +3 -0
- package/dist/Subscriber.mjs +4 -0
- package/dist/basic/BasicConnection.cjs +4 -0
- package/dist/basic/BasicConnection.d.cts +3 -0
- package/dist/basic/BasicConnection.d.mts +3 -0
- package/dist/basic/BasicConnection.mjs +4 -0
- package/dist/basic/BasicPublisher.cjs +3 -0
- package/dist/basic/BasicPublisher.d.cts +4 -0
- package/dist/basic/BasicPublisher.d.mts +4 -0
- package/dist/basic/BasicPublisher.mjs +3 -0
- package/dist/basic/BasicSubscriber.cjs +3 -0
- package/dist/basic/BasicSubscriber.d.cts +4 -0
- package/dist/basic/BasicSubscriber.d.mts +4 -0
- package/dist/basic/BasicSubscriber.mjs +3 -0
- package/dist/basic/index.cjs +8 -0
- package/dist/basic/index.d.cts +5 -0
- package/dist/basic/index.d.mts +5 -0
- package/dist/basic/index.mjs +6 -0
- package/dist/chunk-CUT6urMc.cjs +30 -0
- package/dist/index.cjs +9 -0
- package/dist/index.d.cts +5 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.mjs +6 -0
- package/dist/rabbitmq/RabbitMQConnection.cjs +4 -0
- package/dist/rabbitmq/RabbitMQConnection.d.cts +3 -0
- package/dist/rabbitmq/RabbitMQConnection.d.mts +3 -0
- package/dist/rabbitmq/RabbitMQConnection.mjs +4 -0
- package/dist/rabbitmq/RabbitMQPublisher.cjs +3 -0
- package/dist/rabbitmq/RabbitMQPublisher.d.cts +4 -0
- package/dist/rabbitmq/RabbitMQPublisher.d.mts +4 -0
- package/dist/rabbitmq/RabbitMQPublisher.mjs +3 -0
- package/dist/rabbitmq/RabbitMQSubscriber.cjs +3 -0
- package/dist/rabbitmq/RabbitMQSubscriber.d.cts +4 -0
- package/dist/rabbitmq/RabbitMQSubscriber.d.mts +4 -0
- package/dist/rabbitmq/RabbitMQSubscriber.mjs +3 -0
- package/dist/rabbitmq/index.cjs +8 -0
- package/dist/rabbitmq/index.d.cts +5 -0
- package/dist/rabbitmq/index.d.mts +5 -0
- package/dist/rabbitmq/index.mjs +6 -0
- package/dist/sns/SNSConnection.cjs +4 -0
- package/dist/sns/SNSConnection.d.cts +3 -0
- package/dist/sns/SNSConnection.d.mts +3 -0
- package/dist/sns/SNSConnection.mjs +4 -0
- package/dist/sns/SNSPublisher.cjs +3 -0
- package/dist/sns/SNSPublisher.d.cts +4 -0
- package/dist/sns/SNSPublisher.d.mts +4 -0
- package/dist/sns/SNSPublisher.mjs +3 -0
- package/dist/sns/SNSSubscriber.cjs +6 -0
- package/dist/sns/SNSSubscriber.d.cts +4 -0
- package/dist/sns/SNSSubscriber.d.mts +4 -0
- package/dist/sns/SNSSubscriber.mjs +6 -0
- package/dist/sns/index.cjs +10 -0
- package/dist/sns/index.d.cts +5 -0
- package/dist/sns/index.d.mts +5 -0
- package/dist/sns/index.mjs +8 -0
- package/dist/sqs/SQSConnection.cjs +4 -0
- package/dist/sqs/SQSConnection.d.cts +3 -0
- package/dist/sqs/SQSConnection.d.mts +3 -0
- package/dist/sqs/SQSConnection.mjs +4 -0
- package/dist/sqs/SQSPublisher.cjs +3 -0
- package/dist/sqs/SQSPublisher.d.cts +4 -0
- package/dist/sqs/SQSPublisher.d.mts +4 -0
- package/dist/sqs/SQSPublisher.mjs +3 -0
- package/dist/sqs/SQSSubscriber.cjs +3 -0
- package/dist/sqs/SQSSubscriber.d.cts +4 -0
- package/dist/sqs/SQSSubscriber.d.mts +4 -0
- package/dist/sqs/SQSSubscriber.mjs +3 -0
- package/dist/sqs/index.cjs +8 -0
- package/dist/sqs/index.d.cts +5 -0
- package/dist/sqs/index.d.mts +5 -0
- package/dist/sqs/index.mjs +6 -0
- package/dist/types-B63qHVOG.mjs +17 -0
- package/dist/types-B63qHVOG.mjs.map +1 -0
- package/dist/types-CvSMEO5z.cjs +23 -0
- package/dist/types-CvSMEO5z.cjs.map +1 -0
- package/dist/types-D0g-o6wX.d.mts +65 -0
- package/dist/types-DEGUg5BA.d.cts +65 -0
- package/dist/types.cjs +3 -0
- package/dist/types.d.cts +2 -0
- package/dist/types.d.mts +2 -0
- package/dist/types.mjs +3 -0
- package/package.json +49 -0
- package/src/EventConnection.ts +39 -0
- package/src/Publisher.ts +87 -0
- package/src/Subscriber.ts +102 -0
- package/src/__tests__/Subscriber.spec.ts +41 -0
- package/src/basic/BasicConnection.ts +47 -0
- package/src/basic/BasicPublisher.ts +15 -0
- package/src/basic/BasicSubscriber.ts +24 -0
- package/src/basic/__tests__/BasicSubscriber.spec.ts +166 -0
- package/src/basic/index.ts +3 -0
- package/src/index.ts +25 -0
- package/src/rabbitmq/RabbitMQConnection.ts +148 -0
- package/src/rabbitmq/RabbitMQPublisher.ts +67 -0
- package/src/rabbitmq/RabbitMQSubscriber.ts +113 -0
- package/src/rabbitmq/__tests__/RabbitMQPublisher.spec.ts +378 -0
- package/src/rabbitmq/__tests__/RabbitMQSubscriber.spec.ts +292 -0
- package/src/rabbitmq/index.ts +6 -0
- package/src/sns/SNSConnection.ts +98 -0
- package/src/sns/SNSPublisher.ts +64 -0
- package/src/sns/SNSSubscriber.ts +222 -0
- package/src/sns/__tests__/SNS-SQS-Integration.spec.ts +389 -0
- package/src/sns/index.ts +6 -0
- package/src/sqs/SQSConnection.ts +97 -0
- package/src/sqs/SQSPublisher.ts +105 -0
- package/src/sqs/SQSSubscriber.ts +189 -0
- package/src/sqs/__tests__/SQSPublisher.spec.ts +189 -0
- package/src/sqs/index.ts +6 -0
- package/src/types.ts +76 -0
- package/tsdown.config.ts +5 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { EventPublisherType } from "./types-B63qHVOG.mjs";
|
|
2
|
+
import { SNSClient } from "@aws-sdk/client-sns";
|
|
3
|
+
|
|
4
|
+
//#region src/sns/SNSConnection.ts
|
|
5
|
+
var SNSConnection = class SNSConnection {
|
|
6
|
+
type = EventPublisherType.SNS;
|
|
7
|
+
client;
|
|
8
|
+
connected = false;
|
|
9
|
+
config;
|
|
10
|
+
constructor(config) {
|
|
11
|
+
this.config = config;
|
|
12
|
+
const clientConfig = {
|
|
13
|
+
region: config.region,
|
|
14
|
+
endpoint: config.endpoint,
|
|
15
|
+
credentials: config.credentials
|
|
16
|
+
};
|
|
17
|
+
this.client = new SNSClient(clientConfig);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Create an SNSConnection from a connection string
|
|
21
|
+
* Format: sns://?topicArn=arn:aws:sns:region:account:topic®ion=us-east-1&endpoint=http://localhost:4566
|
|
22
|
+
*/
|
|
23
|
+
static async fromConnectionString(connectionString) {
|
|
24
|
+
const url = new URL(connectionString);
|
|
25
|
+
const params = url.searchParams;
|
|
26
|
+
const topicArn = params.get("topicArn");
|
|
27
|
+
if (!topicArn) throw new Error("topicArn parameter is required in connection string");
|
|
28
|
+
const config = {
|
|
29
|
+
topicArn,
|
|
30
|
+
region: params.get("region") || void 0,
|
|
31
|
+
endpoint: params.get("endpoint") || void 0
|
|
32
|
+
};
|
|
33
|
+
const accessKeyId = params.get("accessKeyId");
|
|
34
|
+
const secretAccessKey = params.get("secretAccessKey");
|
|
35
|
+
if (accessKeyId && secretAccessKey) config.credentials = {
|
|
36
|
+
accessKeyId,
|
|
37
|
+
secretAccessKey,
|
|
38
|
+
sessionToken: params.get("sessionToken") || void 0
|
|
39
|
+
};
|
|
40
|
+
const connection = new SNSConnection(config);
|
|
41
|
+
await connection.connect();
|
|
42
|
+
return connection;
|
|
43
|
+
}
|
|
44
|
+
async connect() {
|
|
45
|
+
this.connected = true;
|
|
46
|
+
}
|
|
47
|
+
async close() {
|
|
48
|
+
this.client.destroy();
|
|
49
|
+
this.connected = false;
|
|
50
|
+
}
|
|
51
|
+
isConnected() {
|
|
52
|
+
return this.connected;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get the underlying SNS client
|
|
56
|
+
*/
|
|
57
|
+
get snsClient() {
|
|
58
|
+
return this.client;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get the topic ARN for this connection
|
|
62
|
+
*/
|
|
63
|
+
get topicArn() {
|
|
64
|
+
return this.config.topicArn;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
//#endregion
|
|
69
|
+
export { SNSConnection };
|
|
70
|
+
//# sourceMappingURL=SNSConnection-D7wCf9Si.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SNSConnection-D7wCf9Si.mjs","names":["config: SNSConnectionConfig","clientConfig: SNSClientConfig","connectionString: string"],"sources":["../src/sns/SNSConnection.ts"],"sourcesContent":["import { SNSClient, type SNSClientConfig } from '@aws-sdk/client-sns';\nimport type { EventConnection } from '../types';\nimport { EventPublisherType } from '../types';\n\nexport interface SNSConnectionConfig {\n topicArn: string;\n region?: string;\n endpoint?: string; // Custom endpoint (e.g., for LocalStack)\n credentials?: {\n accessKeyId: string;\n secretAccessKey: string;\n sessionToken?: string;\n };\n}\n\nexport class SNSConnection implements EventConnection {\n readonly type = EventPublisherType.SNS;\n private client: SNSClient;\n private connected = false;\n private config: SNSConnectionConfig;\n\n constructor(config: SNSConnectionConfig) {\n this.config = config;\n\n const clientConfig: SNSClientConfig = {\n region: config.region,\n endpoint: config.endpoint,\n credentials: config.credentials,\n };\n\n this.client = new SNSClient(clientConfig);\n }\n\n /**\n * Create an SNSConnection from a connection string\n * Format: sns://?topicArn=arn:aws:sns:region:account:topic®ion=us-east-1&endpoint=http://localhost:4566\n */\n static async fromConnectionString(\n connectionString: string,\n ): Promise<SNSConnection> {\n const url = new URL(connectionString);\n const params = url.searchParams;\n\n const topicArn = params.get('topicArn');\n if (!topicArn) {\n throw new Error('topicArn parameter is required in connection string');\n }\n\n const config: SNSConnectionConfig = {\n topicArn,\n region: params.get('region') || undefined,\n endpoint: params.get('endpoint') || undefined,\n };\n\n // Parse credentials if provided\n const accessKeyId = params.get('accessKeyId');\n const secretAccessKey = params.get('secretAccessKey');\n if (accessKeyId && secretAccessKey) {\n config.credentials = {\n accessKeyId,\n secretAccessKey,\n sessionToken: params.get('sessionToken') || undefined,\n };\n }\n\n const connection = new SNSConnection(config);\n await connection.connect();\n return connection;\n }\n\n async connect(): Promise<void> {\n // SNS doesn't have a traditional connection, but we mark as connected\n this.connected = true;\n }\n\n async close(): Promise<void> {\n this.client.destroy();\n this.connected = false;\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n /**\n * Get the underlying SNS client\n */\n get snsClient(): SNSClient {\n return this.client;\n }\n\n /**\n * Get the topic ARN for this connection\n */\n get topicArn(): string {\n return this.config.topicArn;\n }\n}\n"],"mappings":";;;;AAeA,IAAa,gBAAb,MAAa,cAAyC;CACpD,AAAS,OAAO,mBAAmB;CACnC,AAAQ;CACR,AAAQ,YAAY;CACpB,AAAQ;CAER,YAAYA,QAA6B;AACvC,OAAK,SAAS;EAEd,MAAMC,eAAgC;GACpC,QAAQ,OAAO;GACf,UAAU,OAAO;GACjB,aAAa,OAAO;EACrB;AAED,OAAK,SAAS,IAAI,UAAU;CAC7B;;;;;CAMD,aAAa,qBACXC,kBACwB;EACxB,MAAM,MAAM,IAAI,IAAI;EACpB,MAAM,SAAS,IAAI;EAEnB,MAAM,WAAW,OAAO,IAAI,WAAW;AACvC,OAAK,SACH,OAAM,IAAI,MAAM;EAGlB,MAAMF,SAA8B;GAClC;GACA,QAAQ,OAAO,IAAI,SAAS;GAC5B,UAAU,OAAO,IAAI,WAAW;EACjC;EAGD,MAAM,cAAc,OAAO,IAAI,cAAc;EAC7C,MAAM,kBAAkB,OAAO,IAAI,kBAAkB;AACrD,MAAI,eAAe,gBACjB,QAAO,cAAc;GACnB;GACA;GACA,cAAc,OAAO,IAAI,eAAe;EACzC;EAGH,MAAM,aAAa,IAAI,cAAc;AACrC,QAAM,WAAW,SAAS;AAC1B,SAAO;CACR;CAED,MAAM,UAAyB;AAE7B,OAAK,YAAY;CAClB;CAED,MAAM,QAAuB;AAC3B,OAAK,OAAO,SAAS;AACrB,OAAK,YAAY;CAClB;CAED,cAAuB;AACrB,SAAO,KAAK;CACb;;;;CAKD,IAAI,YAAuB;AACzB,SAAO,KAAK;CACb;;;;CAKD,IAAI,WAAmB;AACrB,SAAO,KAAK,OAAO;CACpB;AACF"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
const require_chunk = require('./chunk-CUT6urMc.cjs');
|
|
2
|
+
const require_types = require('./types-CvSMEO5z.cjs');
|
|
3
|
+
const __aws_sdk_client_sns = require_chunk.__toESM(require("@aws-sdk/client-sns"));
|
|
4
|
+
|
|
5
|
+
//#region src/sns/SNSConnection.ts
|
|
6
|
+
var SNSConnection = class SNSConnection {
|
|
7
|
+
type = require_types.EventPublisherType.SNS;
|
|
8
|
+
client;
|
|
9
|
+
connected = false;
|
|
10
|
+
config;
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.config = config;
|
|
13
|
+
const clientConfig = {
|
|
14
|
+
region: config.region,
|
|
15
|
+
endpoint: config.endpoint,
|
|
16
|
+
credentials: config.credentials
|
|
17
|
+
};
|
|
18
|
+
this.client = new __aws_sdk_client_sns.SNSClient(clientConfig);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create an SNSConnection from a connection string
|
|
22
|
+
* Format: sns://?topicArn=arn:aws:sns:region:account:topic®ion=us-east-1&endpoint=http://localhost:4566
|
|
23
|
+
*/
|
|
24
|
+
static async fromConnectionString(connectionString) {
|
|
25
|
+
const url = new URL(connectionString);
|
|
26
|
+
const params = url.searchParams;
|
|
27
|
+
const topicArn = params.get("topicArn");
|
|
28
|
+
if (!topicArn) throw new Error("topicArn parameter is required in connection string");
|
|
29
|
+
const config = {
|
|
30
|
+
topicArn,
|
|
31
|
+
region: params.get("region") || void 0,
|
|
32
|
+
endpoint: params.get("endpoint") || void 0
|
|
33
|
+
};
|
|
34
|
+
const accessKeyId = params.get("accessKeyId");
|
|
35
|
+
const secretAccessKey = params.get("secretAccessKey");
|
|
36
|
+
if (accessKeyId && secretAccessKey) config.credentials = {
|
|
37
|
+
accessKeyId,
|
|
38
|
+
secretAccessKey,
|
|
39
|
+
sessionToken: params.get("sessionToken") || void 0
|
|
40
|
+
};
|
|
41
|
+
const connection = new SNSConnection(config);
|
|
42
|
+
await connection.connect();
|
|
43
|
+
return connection;
|
|
44
|
+
}
|
|
45
|
+
async connect() {
|
|
46
|
+
this.connected = true;
|
|
47
|
+
}
|
|
48
|
+
async close() {
|
|
49
|
+
this.client.destroy();
|
|
50
|
+
this.connected = false;
|
|
51
|
+
}
|
|
52
|
+
isConnected() {
|
|
53
|
+
return this.connected;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get the underlying SNS client
|
|
57
|
+
*/
|
|
58
|
+
get snsClient() {
|
|
59
|
+
return this.client;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get the topic ARN for this connection
|
|
63
|
+
*/
|
|
64
|
+
get topicArn() {
|
|
65
|
+
return this.config.topicArn;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
//#endregion
|
|
70
|
+
Object.defineProperty(exports, 'SNSConnection', {
|
|
71
|
+
enumerable: true,
|
|
72
|
+
get: function () {
|
|
73
|
+
return SNSConnection;
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=SNSConnection-DVsC_pbB.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SNSConnection-DVsC_pbB.cjs","names":["EventPublisherType","config: SNSConnectionConfig","clientConfig: SNSClientConfig","SNSClient","connectionString: string"],"sources":["../src/sns/SNSConnection.ts"],"sourcesContent":["import { SNSClient, type SNSClientConfig } from '@aws-sdk/client-sns';\nimport type { EventConnection } from '../types';\nimport { EventPublisherType } from '../types';\n\nexport interface SNSConnectionConfig {\n topicArn: string;\n region?: string;\n endpoint?: string; // Custom endpoint (e.g., for LocalStack)\n credentials?: {\n accessKeyId: string;\n secretAccessKey: string;\n sessionToken?: string;\n };\n}\n\nexport class SNSConnection implements EventConnection {\n readonly type = EventPublisherType.SNS;\n private client: SNSClient;\n private connected = false;\n private config: SNSConnectionConfig;\n\n constructor(config: SNSConnectionConfig) {\n this.config = config;\n\n const clientConfig: SNSClientConfig = {\n region: config.region,\n endpoint: config.endpoint,\n credentials: config.credentials,\n };\n\n this.client = new SNSClient(clientConfig);\n }\n\n /**\n * Create an SNSConnection from a connection string\n * Format: sns://?topicArn=arn:aws:sns:region:account:topic®ion=us-east-1&endpoint=http://localhost:4566\n */\n static async fromConnectionString(\n connectionString: string,\n ): Promise<SNSConnection> {\n const url = new URL(connectionString);\n const params = url.searchParams;\n\n const topicArn = params.get('topicArn');\n if (!topicArn) {\n throw new Error('topicArn parameter is required in connection string');\n }\n\n const config: SNSConnectionConfig = {\n topicArn,\n region: params.get('region') || undefined,\n endpoint: params.get('endpoint') || undefined,\n };\n\n // Parse credentials if provided\n const accessKeyId = params.get('accessKeyId');\n const secretAccessKey = params.get('secretAccessKey');\n if (accessKeyId && secretAccessKey) {\n config.credentials = {\n accessKeyId,\n secretAccessKey,\n sessionToken: params.get('sessionToken') || undefined,\n };\n }\n\n const connection = new SNSConnection(config);\n await connection.connect();\n return connection;\n }\n\n async connect(): Promise<void> {\n // SNS doesn't have a traditional connection, but we mark as connected\n this.connected = true;\n }\n\n async close(): Promise<void> {\n this.client.destroy();\n this.connected = false;\n }\n\n isConnected(): boolean {\n return this.connected;\n }\n\n /**\n * Get the underlying SNS client\n */\n get snsClient(): SNSClient {\n return this.client;\n }\n\n /**\n * Get the topic ARN for this connection\n */\n get topicArn(): string {\n return this.config.topicArn;\n }\n}\n"],"mappings":";;;;;AAeA,IAAa,gBAAb,MAAa,cAAyC;CACpD,AAAS,OAAOA,iCAAmB;CACnC,AAAQ;CACR,AAAQ,YAAY;CACpB,AAAQ;CAER,YAAYC,QAA6B;AACvC,OAAK,SAAS;EAEd,MAAMC,eAAgC;GACpC,QAAQ,OAAO;GACf,UAAU,OAAO;GACjB,aAAa,OAAO;EACrB;AAED,OAAK,SAAS,IAAIC,+BAAU;CAC7B;;;;;CAMD,aAAa,qBACXC,kBACwB;EACxB,MAAM,MAAM,IAAI,IAAI;EACpB,MAAM,SAAS,IAAI;EAEnB,MAAM,WAAW,OAAO,IAAI,WAAW;AACvC,OAAK,SACH,OAAM,IAAI,MAAM;EAGlB,MAAMH,SAA8B;GAClC;GACA,QAAQ,OAAO,IAAI,SAAS;GAC5B,UAAU,OAAO,IAAI,WAAW;EACjC;EAGD,MAAM,cAAc,OAAO,IAAI,cAAc;EAC7C,MAAM,kBAAkB,OAAO,IAAI,kBAAkB;AACrD,MAAI,eAAe,gBACjB,QAAO,cAAc;GACnB;GACA;GACA,cAAc,OAAO,IAAI,eAAe;EACzC;EAGH,MAAM,aAAa,IAAI,cAAc;AACrC,QAAM,WAAW,SAAS;AAC1B,SAAO;CACR;CAED,MAAM,UAAyB;AAE7B,OAAK,YAAY;CAClB;CAED,MAAM,QAAuB;AAC3B,OAAK,OAAO,SAAS;AACrB,OAAK,YAAY;CAClB;CAED,cAAuB;AACrB,SAAO,KAAK;CACb;;;;CAKD,IAAI,YAAuB;AACzB,SAAO,KAAK;CACb;;;;CAKD,IAAI,WAAmB;AACrB,SAAO,KAAK,OAAO;CACpB;AACF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const require_chunk = require('./chunk-CUT6urMc.cjs');
|
|
2
|
+
const __aws_sdk_client_sns = require_chunk.__toESM(require("@aws-sdk/client-sns"));
|
|
3
|
+
|
|
4
|
+
//#region src/sns/SNSPublisher.ts
|
|
5
|
+
var SNSPublisher = class SNSPublisher {
|
|
6
|
+
constructor(connection, options = {}) {
|
|
7
|
+
this.connection = connection;
|
|
8
|
+
this.options = options;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Create an SNSPublisher from a connection string
|
|
12
|
+
* Format: sns://?topicArn=arn:aws:sns:region:account:topic®ion=us-east-1&endpoint=http://localhost:4566
|
|
13
|
+
*/
|
|
14
|
+
static async fromConnectionString(connectionString) {
|
|
15
|
+
const { SNSConnection } = await Promise.resolve().then(() => require("./sns/SNSConnection.cjs"));
|
|
16
|
+
const connection = await SNSConnection.fromConnectionString(connectionString);
|
|
17
|
+
return new SNSPublisher(connection);
|
|
18
|
+
}
|
|
19
|
+
async publish(messages) {
|
|
20
|
+
if (messages.length === 0) return;
|
|
21
|
+
if (!this.connection.isConnected()) await this.connection.connect();
|
|
22
|
+
await Promise.all(messages.map((message) => this.publishMessage(message)));
|
|
23
|
+
}
|
|
24
|
+
async publishMessage(message) {
|
|
25
|
+
const command = new __aws_sdk_client_sns.PublishCommand({
|
|
26
|
+
TopicArn: this.connection.topicArn,
|
|
27
|
+
Message: JSON.stringify({
|
|
28
|
+
type: message.type,
|
|
29
|
+
payload: message.payload
|
|
30
|
+
}),
|
|
31
|
+
MessageAttributes: { type: {
|
|
32
|
+
DataType: "String",
|
|
33
|
+
StringValue: message.type
|
|
34
|
+
} }
|
|
35
|
+
});
|
|
36
|
+
await this.connection.snsClient.send(command);
|
|
37
|
+
}
|
|
38
|
+
async close() {}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
//#endregion
|
|
42
|
+
Object.defineProperty(exports, 'SNSPublisher', {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
get: function () {
|
|
45
|
+
return SNSPublisher;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
//# sourceMappingURL=SNSPublisher-BZ6N3JI9.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SNSPublisher-BZ6N3JI9.cjs","names":["connection: SNSConnection","options: SNSPublisherOptions","connectionString: string","messages: TMessage[]","message: TMessage","PublishCommand"],"sources":["../src/sns/SNSPublisher.ts"],"sourcesContent":["import { PublishCommand } from '@aws-sdk/client-sns';\nimport type { EventPublisher, PublishableMessage } from '../types';\nimport type { SNSConnection } from './SNSConnection';\n\nexport interface SNSPublisherOptions {\n // Optional publisher-specific options\n}\n\nexport class SNSPublisher<TMessage extends PublishableMessage<string, any>>\n implements EventPublisher<TMessage>\n{\n constructor(\n private connection: SNSConnection,\n private options: SNSPublisherOptions = {},\n ) {}\n\n /**\n * Create an SNSPublisher from a connection string\n * Format: sns://?topicArn=arn:aws:sns:region:account:topic®ion=us-east-1&endpoint=http://localhost:4566\n */\n static async fromConnectionString<\n TMessage extends PublishableMessage<string, any>,\n >(connectionString: string): Promise<SNSPublisher<TMessage>> {\n const { SNSConnection } = await import('./SNSConnection');\n const connection =\n await SNSConnection.fromConnectionString(connectionString);\n\n return new SNSPublisher<TMessage>(connection);\n }\n\n async publish(messages: TMessage[]): Promise<void> {\n if (messages.length === 0) return;\n\n if (!this.connection.isConnected()) {\n await this.connection.connect();\n }\n\n // Publish all messages\n await Promise.all(messages.map((message) => this.publishMessage(message)));\n }\n\n private async publishMessage(message: TMessage): Promise<void> {\n const command = new PublishCommand({\n TopicArn: this.connection.topicArn,\n Message: JSON.stringify({\n type: message.type,\n payload: message.payload,\n }),\n MessageAttributes: {\n type: {\n DataType: 'String',\n StringValue: message.type,\n },\n },\n });\n\n await this.connection.snsClient.send(command);\n }\n\n async close(): Promise<void> {\n // Publisher doesn't own the connection\n // Connection should be closed by whoever created it\n }\n}\n"],"mappings":";;;;AAQA,IAAa,eAAb,MAAa,aAEb;CACE,YACUA,YACAC,UAA+B,CAAE,GACzC;EAFQ;EACA;CACN;;;;;CAMJ,aAAa,qBAEXC,kBAA2D;EAC3D,MAAM,EAAE,eAAe,GAAG,2CAAM;EAChC,MAAM,aACJ,MAAM,cAAc,qBAAqB,iBAAiB;AAE5D,SAAO,IAAI,aAAuB;CACnC;CAED,MAAM,QAAQC,UAAqC;AACjD,MAAI,SAAS,WAAW,EAAG;AAE3B,OAAK,KAAK,WAAW,aAAa,CAChC,OAAM,KAAK,WAAW,SAAS;AAIjC,QAAM,QAAQ,IAAI,SAAS,IAAI,CAAC,YAAY,KAAK,eAAe,QAAQ,CAAC,CAAC;CAC3E;CAED,MAAc,eAAeC,SAAkC;EAC7D,MAAM,UAAU,IAAIC,oCAAe;GACjC,UAAU,KAAK,WAAW;GAC1B,SAAS,KAAK,UAAU;IACtB,MAAM,QAAQ;IACd,SAAS,QAAQ;GAClB,EAAC;GACF,mBAAmB,EACjB,MAAM;IACJ,UAAU;IACV,aAAa,QAAQ;GACtB,EACF;EACF;AAED,QAAM,KAAK,WAAW,UAAU,KAAK,QAAQ;CAC9C;CAED,MAAM,QAAuB,CAG5B;AACF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { PublishCommand } from "@aws-sdk/client-sns";
|
|
2
|
+
|
|
3
|
+
//#region src/sns/SNSPublisher.ts
|
|
4
|
+
var SNSPublisher = class SNSPublisher {
|
|
5
|
+
constructor(connection, options = {}) {
|
|
6
|
+
this.connection = connection;
|
|
7
|
+
this.options = options;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Create an SNSPublisher from a connection string
|
|
11
|
+
* Format: sns://?topicArn=arn:aws:sns:region:account:topic®ion=us-east-1&endpoint=http://localhost:4566
|
|
12
|
+
*/
|
|
13
|
+
static async fromConnectionString(connectionString) {
|
|
14
|
+
const { SNSConnection } = await import("./sns/SNSConnection.mjs");
|
|
15
|
+
const connection = await SNSConnection.fromConnectionString(connectionString);
|
|
16
|
+
return new SNSPublisher(connection);
|
|
17
|
+
}
|
|
18
|
+
async publish(messages) {
|
|
19
|
+
if (messages.length === 0) return;
|
|
20
|
+
if (!this.connection.isConnected()) await this.connection.connect();
|
|
21
|
+
await Promise.all(messages.map((message) => this.publishMessage(message)));
|
|
22
|
+
}
|
|
23
|
+
async publishMessage(message) {
|
|
24
|
+
const command = new PublishCommand({
|
|
25
|
+
TopicArn: this.connection.topicArn,
|
|
26
|
+
Message: JSON.stringify({
|
|
27
|
+
type: message.type,
|
|
28
|
+
payload: message.payload
|
|
29
|
+
}),
|
|
30
|
+
MessageAttributes: { type: {
|
|
31
|
+
DataType: "String",
|
|
32
|
+
StringValue: message.type
|
|
33
|
+
} }
|
|
34
|
+
});
|
|
35
|
+
await this.connection.snsClient.send(command);
|
|
36
|
+
}
|
|
37
|
+
async close() {}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
export { SNSPublisher };
|
|
42
|
+
//# sourceMappingURL=SNSPublisher-BfWjzNiB.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SNSPublisher-BfWjzNiB.mjs","names":["connection: SNSConnection","options: SNSPublisherOptions","connectionString: string","messages: TMessage[]","message: TMessage"],"sources":["../src/sns/SNSPublisher.ts"],"sourcesContent":["import { PublishCommand } from '@aws-sdk/client-sns';\nimport type { EventPublisher, PublishableMessage } from '../types';\nimport type { SNSConnection } from './SNSConnection';\n\nexport interface SNSPublisherOptions {\n // Optional publisher-specific options\n}\n\nexport class SNSPublisher<TMessage extends PublishableMessage<string, any>>\n implements EventPublisher<TMessage>\n{\n constructor(\n private connection: SNSConnection,\n private options: SNSPublisherOptions = {},\n ) {}\n\n /**\n * Create an SNSPublisher from a connection string\n * Format: sns://?topicArn=arn:aws:sns:region:account:topic®ion=us-east-1&endpoint=http://localhost:4566\n */\n static async fromConnectionString<\n TMessage extends PublishableMessage<string, any>,\n >(connectionString: string): Promise<SNSPublisher<TMessage>> {\n const { SNSConnection } = await import('./SNSConnection');\n const connection =\n await SNSConnection.fromConnectionString(connectionString);\n\n return new SNSPublisher<TMessage>(connection);\n }\n\n async publish(messages: TMessage[]): Promise<void> {\n if (messages.length === 0) return;\n\n if (!this.connection.isConnected()) {\n await this.connection.connect();\n }\n\n // Publish all messages\n await Promise.all(messages.map((message) => this.publishMessage(message)));\n }\n\n private async publishMessage(message: TMessage): Promise<void> {\n const command = new PublishCommand({\n TopicArn: this.connection.topicArn,\n Message: JSON.stringify({\n type: message.type,\n payload: message.payload,\n }),\n MessageAttributes: {\n type: {\n DataType: 'String',\n StringValue: message.type,\n },\n },\n });\n\n await this.connection.snsClient.send(command);\n }\n\n async close(): Promise<void> {\n // Publisher doesn't own the connection\n // Connection should be closed by whoever created it\n }\n}\n"],"mappings":";;;AAQA,IAAa,eAAb,MAAa,aAEb;CACE,YACUA,YACAC,UAA+B,CAAE,GACzC;EAFQ;EACA;CACN;;;;;CAMJ,aAAa,qBAEXC,kBAA2D;EAC3D,MAAM,EAAE,eAAe,GAAG,MAAM,OAAO;EACvC,MAAM,aACJ,MAAM,cAAc,qBAAqB,iBAAiB;AAE5D,SAAO,IAAI,aAAuB;CACnC;CAED,MAAM,QAAQC,UAAqC;AACjD,MAAI,SAAS,WAAW,EAAG;AAE3B,OAAK,KAAK,WAAW,aAAa,CAChC,OAAM,KAAK,WAAW,SAAS;AAIjC,QAAM,QAAQ,IAAI,SAAS,IAAI,CAAC,YAAY,KAAK,eAAe,QAAQ,CAAC,CAAC;CAC3E;CAED,MAAc,eAAeC,SAAkC;EAC7D,MAAM,UAAU,IAAI,eAAe;GACjC,UAAU,KAAK,WAAW;GAC1B,SAAS,KAAK,UAAU;IACtB,MAAM,QAAQ;IACd,SAAS,QAAQ;GAClB,EAAC;GACF,mBAAmB,EACjB,MAAM;IACJ,UAAU;IACV,aAAa,QAAQ;GACtB,EACF;EACF;AAED,QAAM,KAAK,WAAW,UAAU,KAAK,QAAQ;CAC9C;CAED,MAAM,QAAuB,CAG5B;AACF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { EventPublisher, PublishableMessage } from "./types-D0g-o6wX.mjs";
|
|
2
|
+
import { SNSConnection } from "./SNSConnection-CAImaMM2.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/sns/SNSPublisher.d.ts
|
|
5
|
+
interface SNSPublisherOptions {}
|
|
6
|
+
declare class SNSPublisher<TMessage extends PublishableMessage<string, any>> implements EventPublisher<TMessage> {
|
|
7
|
+
private connection;
|
|
8
|
+
private options;
|
|
9
|
+
constructor(connection: SNSConnection, options?: SNSPublisherOptions);
|
|
10
|
+
/**
|
|
11
|
+
* Create an SNSPublisher from a connection string
|
|
12
|
+
* Format: sns://?topicArn=arn:aws:sns:region:account:topic®ion=us-east-1&endpoint=http://localhost:4566
|
|
13
|
+
*/
|
|
14
|
+
static fromConnectionString<TMessage extends PublishableMessage<string, any>>(connectionString: string): Promise<SNSPublisher<TMessage>>;
|
|
15
|
+
publish(messages: TMessage[]): Promise<void>;
|
|
16
|
+
private publishMessage;
|
|
17
|
+
close(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { SNSPublisher, SNSPublisherOptions };
|
|
21
|
+
//# sourceMappingURL=SNSPublisher-Dkhb4LU-.d.mts.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { EventPublisher, PublishableMessage } from "./types-DEGUg5BA.cjs";
|
|
2
|
+
import { SNSConnection } from "./SNSConnection-Cqbr7-Ho.cjs";
|
|
3
|
+
|
|
4
|
+
//#region src/sns/SNSPublisher.d.ts
|
|
5
|
+
interface SNSPublisherOptions {}
|
|
6
|
+
declare class SNSPublisher<TMessage extends PublishableMessage<string, any>> implements EventPublisher<TMessage> {
|
|
7
|
+
private connection;
|
|
8
|
+
private options;
|
|
9
|
+
constructor(connection: SNSConnection, options?: SNSPublisherOptions);
|
|
10
|
+
/**
|
|
11
|
+
* Create an SNSPublisher from a connection string
|
|
12
|
+
* Format: sns://?topicArn=arn:aws:sns:region:account:topic®ion=us-east-1&endpoint=http://localhost:4566
|
|
13
|
+
*/
|
|
14
|
+
static fromConnectionString<TMessage extends PublishableMessage<string, any>>(connectionString: string): Promise<SNSPublisher<TMessage>>;
|
|
15
|
+
publish(messages: TMessage[]): Promise<void>;
|
|
16
|
+
private publishMessage;
|
|
17
|
+
close(): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { SNSPublisher, SNSPublisherOptions };
|
|
21
|
+
//# sourceMappingURL=SNSPublisher-RVZFa7kL.d.cts.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { EventSubscriber, PublishableMessage } from "./types-D0g-o6wX.mjs";
|
|
2
|
+
import { SNSConnection } from "./SNSConnection-CAImaMM2.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/sns/SNSSubscriber.d.ts
|
|
5
|
+
interface SNSSubscriberOptions {
|
|
6
|
+
queueName?: string;
|
|
7
|
+
createQueue?: boolean;
|
|
8
|
+
deleteQueueOnClose?: boolean;
|
|
9
|
+
waitTimeSeconds?: number;
|
|
10
|
+
maxMessages?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* SNS Subscriber - receives push-based messages from SNS via SQS queue
|
|
14
|
+
*
|
|
15
|
+
* Architecture:
|
|
16
|
+
* SNS Topic → (push) → SQS Queue → Subscriber
|
|
17
|
+
*
|
|
18
|
+
* This subscriber automatically:
|
|
19
|
+
* 1. Creates an SQS queue (or uses existing one)
|
|
20
|
+
* 2. Subscribes the queue to the SNS topic
|
|
21
|
+
* 3. Receives messages pushed from SNS to the queue
|
|
22
|
+
* 4. Filters messages by topic ARN and message type
|
|
23
|
+
* 5. Processes and acknowledges messages
|
|
24
|
+
*
|
|
25
|
+
* Note: While SQS long-polling is used internally to receive messages,
|
|
26
|
+
* this is an implementation detail of the SNS push delivery mechanism.
|
|
27
|
+
* Messages are pushed from SNS to SQS, and we receive those pushed messages.
|
|
28
|
+
*/
|
|
29
|
+
declare class SNSSubscriber<TMessage extends PublishableMessage<string, any>> implements EventSubscriber<TMessage> {
|
|
30
|
+
private connection;
|
|
31
|
+
private sqsClient;
|
|
32
|
+
private queueUrl?;
|
|
33
|
+
private queueArn?;
|
|
34
|
+
private subscriptionArn?;
|
|
35
|
+
private sqsSubscriber?;
|
|
36
|
+
private options;
|
|
37
|
+
constructor(connection: SNSConnection, options?: SNSSubscriberOptions);
|
|
38
|
+
/**
|
|
39
|
+
* Create an SNSSubscriber from a connection string
|
|
40
|
+
* Format: sns://?topicArn=...&queueName=myqueue®ion=us-east-1
|
|
41
|
+
*/
|
|
42
|
+
static fromConnectionString<TMessage extends PublishableMessage<string, any>>(connectionString: string): Promise<SNSSubscriber<TMessage>>;
|
|
43
|
+
subscribe(messages: TMessage['type'][], listener: (payload: TMessage) => Promise<void>): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Stop receiving messages and clean up resources
|
|
46
|
+
*/
|
|
47
|
+
stop(): Promise<void>;
|
|
48
|
+
private setupQueue;
|
|
49
|
+
private setQueuePolicy;
|
|
50
|
+
private subscribeToTopic;
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
export { SNSSubscriber, SNSSubscriberOptions };
|
|
54
|
+
//# sourceMappingURL=SNSSubscriber-B31JmkAE.d.mts.map
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { SQSConnection } from "./SQSConnection-Eleqqre3.mjs";
|
|
2
|
+
import { SQSSubscriber } from "./SQSSubscriber-CD66P7hH.mjs";
|
|
3
|
+
import { SubscribeCommand, UnsubscribeCommand } from "@aws-sdk/client-sns";
|
|
4
|
+
import { CreateQueueCommand, DeleteQueueCommand, GetQueueAttributesCommand, SQSClient, SetQueueAttributesCommand } from "@aws-sdk/client-sqs";
|
|
5
|
+
|
|
6
|
+
//#region src/sns/SNSSubscriber.ts
|
|
7
|
+
/**
|
|
8
|
+
* SNS Subscriber - receives push-based messages from SNS via SQS queue
|
|
9
|
+
*
|
|
10
|
+
* Architecture:
|
|
11
|
+
* SNS Topic → (push) → SQS Queue → Subscriber
|
|
12
|
+
*
|
|
13
|
+
* This subscriber automatically:
|
|
14
|
+
* 1. Creates an SQS queue (or uses existing one)
|
|
15
|
+
* 2. Subscribes the queue to the SNS topic
|
|
16
|
+
* 3. Receives messages pushed from SNS to the queue
|
|
17
|
+
* 4. Filters messages by topic ARN and message type
|
|
18
|
+
* 5. Processes and acknowledges messages
|
|
19
|
+
*
|
|
20
|
+
* Note: While SQS long-polling is used internally to receive messages,
|
|
21
|
+
* this is an implementation detail of the SNS push delivery mechanism.
|
|
22
|
+
* Messages are pushed from SNS to SQS, and we receive those pushed messages.
|
|
23
|
+
*/
|
|
24
|
+
var SNSSubscriber = class SNSSubscriber {
|
|
25
|
+
sqsClient;
|
|
26
|
+
queueUrl;
|
|
27
|
+
queueArn;
|
|
28
|
+
subscriptionArn;
|
|
29
|
+
sqsSubscriber;
|
|
30
|
+
options;
|
|
31
|
+
constructor(connection, options = {}) {
|
|
32
|
+
this.connection = connection;
|
|
33
|
+
this.options = {
|
|
34
|
+
queueName: options.queueName || `sns-sub-${Date.now()}-${Math.random().toString(36).substring(7)}`,
|
|
35
|
+
createQueue: options.createQueue ?? true,
|
|
36
|
+
deleteQueueOnClose: options.deleteQueueOnClose ?? !options.queueName,
|
|
37
|
+
waitTimeSeconds: options.waitTimeSeconds ?? 20,
|
|
38
|
+
maxMessages: options.maxMessages ?? 10
|
|
39
|
+
};
|
|
40
|
+
this.sqsClient = new SQSClient({
|
|
41
|
+
region: this.connection.config.region,
|
|
42
|
+
endpoint: this.connection.config.endpoint,
|
|
43
|
+
credentials: this.connection.config.credentials
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Create an SNSSubscriber from a connection string
|
|
48
|
+
* Format: sns://?topicArn=...&queueName=myqueue®ion=us-east-1
|
|
49
|
+
*/
|
|
50
|
+
static async fromConnectionString(connectionString) {
|
|
51
|
+
const url = new URL(connectionString);
|
|
52
|
+
const params = url.searchParams;
|
|
53
|
+
const { SNSConnection } = await import("./sns/SNSConnection.mjs");
|
|
54
|
+
const connection = await SNSConnection.fromConnectionString(connectionString);
|
|
55
|
+
const options = {
|
|
56
|
+
queueName: params.get("queueName") || void 0,
|
|
57
|
+
createQueue: params.get("createQueue") !== "false",
|
|
58
|
+
deleteQueueOnClose: params.get("deleteQueueOnClose") === "true",
|
|
59
|
+
waitTimeSeconds: params.get("waitTimeSeconds") ? Number.parseInt(params.get("waitTimeSeconds"), 10) : void 0
|
|
60
|
+
};
|
|
61
|
+
return new SNSSubscriber(connection, options);
|
|
62
|
+
}
|
|
63
|
+
async subscribe(messages, listener) {
|
|
64
|
+
await this.setupQueue();
|
|
65
|
+
await this.subscribeToTopic();
|
|
66
|
+
const sqsConnection = new SQSConnection({
|
|
67
|
+
queueUrl: this.queueUrl,
|
|
68
|
+
region: this.connection.config.region,
|
|
69
|
+
endpoint: this.connection.config.endpoint,
|
|
70
|
+
credentials: this.connection.config.credentials
|
|
71
|
+
});
|
|
72
|
+
await sqsConnection.connect();
|
|
73
|
+
this.sqsSubscriber = new SQSSubscriber(sqsConnection, {
|
|
74
|
+
waitTimeSeconds: this.options.waitTimeSeconds,
|
|
75
|
+
maxMessages: this.options.maxMessages,
|
|
76
|
+
expectedTopicArn: this.connection.topicArn
|
|
77
|
+
});
|
|
78
|
+
await this.sqsSubscriber.subscribe(messages, listener);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Stop receiving messages and clean up resources
|
|
82
|
+
*/
|
|
83
|
+
async stop() {
|
|
84
|
+
if (this.sqsSubscriber) this.sqsSubscriber.stop();
|
|
85
|
+
if (this.subscriptionArn) try {
|
|
86
|
+
const command = new UnsubscribeCommand({ SubscriptionArn: this.subscriptionArn });
|
|
87
|
+
await this.connection.snsClient.send(command);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error("Error unsubscribing:", error);
|
|
90
|
+
}
|
|
91
|
+
if (this.queueUrl && this.options.deleteQueueOnClose) try {
|
|
92
|
+
const command = new DeleteQueueCommand({ QueueUrl: this.queueUrl });
|
|
93
|
+
await this.sqsClient.send(command);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.error("Error deleting queue:", error);
|
|
96
|
+
}
|
|
97
|
+
this.sqsClient.destroy();
|
|
98
|
+
}
|
|
99
|
+
async setupQueue() {
|
|
100
|
+
if (this.options.createQueue) {
|
|
101
|
+
const createCommand = new CreateQueueCommand({ QueueName: this.options.queueName });
|
|
102
|
+
const response = await this.sqsClient.send(createCommand);
|
|
103
|
+
this.queueUrl = response.QueueUrl;
|
|
104
|
+
} else throw new Error("Queue must exist or createQueue option must be true");
|
|
105
|
+
const attrsCommand = new GetQueueAttributesCommand({
|
|
106
|
+
QueueUrl: this.queueUrl,
|
|
107
|
+
AttributeNames: ["QueueArn"]
|
|
108
|
+
});
|
|
109
|
+
const attrsResponse = await this.sqsClient.send(attrsCommand);
|
|
110
|
+
this.queueArn = attrsResponse.Attributes?.QueueArn;
|
|
111
|
+
await this.setQueuePolicy();
|
|
112
|
+
}
|
|
113
|
+
async setQueuePolicy() {
|
|
114
|
+
const policy = {
|
|
115
|
+
Version: "2012-10-17",
|
|
116
|
+
Statement: [{
|
|
117
|
+
Effect: "Allow",
|
|
118
|
+
Principal: "*",
|
|
119
|
+
Action: "SQS:SendMessage",
|
|
120
|
+
Resource: this.queueArn,
|
|
121
|
+
Condition: { ArnEquals: { "aws:SourceArn": this.connection.topicArn } }
|
|
122
|
+
}]
|
|
123
|
+
};
|
|
124
|
+
const command = new SetQueueAttributesCommand({
|
|
125
|
+
QueueUrl: this.queueUrl,
|
|
126
|
+
Attributes: { Policy: JSON.stringify(policy) }
|
|
127
|
+
});
|
|
128
|
+
await this.sqsClient.send(command);
|
|
129
|
+
}
|
|
130
|
+
async subscribeToTopic() {
|
|
131
|
+
const command = new SubscribeCommand({
|
|
132
|
+
TopicArn: this.connection.topicArn,
|
|
133
|
+
Protocol: "sqs",
|
|
134
|
+
Endpoint: this.queueArn
|
|
135
|
+
});
|
|
136
|
+
const response = await this.connection.snsClient.send(command);
|
|
137
|
+
this.subscriptionArn = response.SubscriptionArn;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
//#endregion
|
|
142
|
+
export { SNSSubscriber };
|
|
143
|
+
//# sourceMappingURL=SNSSubscriber-C9YJWa7m.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SNSSubscriber-C9YJWa7m.mjs","names":["connection: SNSConnection","options: SNSSubscriberOptions","connectionString: string","messages: TMessage['type'][]","listener: (payload: TMessage) => Promise<void>"],"sources":["../src/sns/SNSSubscriber.ts"],"sourcesContent":["import { SubscribeCommand, UnsubscribeCommand } from '@aws-sdk/client-sns';\nimport {\n CreateQueueCommand,\n DeleteQueueCommand,\n GetQueueAttributesCommand,\n SQSClient,\n SetQueueAttributesCommand,\n} from '@aws-sdk/client-sqs';\nimport { SQSConnection } from '../sqs/SQSConnection';\nimport { SQSSubscriber } from '../sqs/SQSSubscriber';\nimport type { EventSubscriber, PublishableMessage } from '../types';\nimport type { SNSConnection } from './SNSConnection';\n\nexport interface SNSSubscriberOptions {\n queueName?: string; // Optional queue name (defaults to auto-generated)\n createQueue?: boolean; // Auto-create SQS queue (default: true)\n deleteQueueOnClose?: boolean; // Delete queue when subscriber closes (default: false for named queues, true for auto-generated)\n waitTimeSeconds?: number; // SQS long polling (default: 20)\n maxMessages?: number; // Max messages per poll (default: 10)\n}\n\n/**\n * SNS Subscriber - receives push-based messages from SNS via SQS queue\n *\n * Architecture:\n * SNS Topic → (push) → SQS Queue → Subscriber\n *\n * This subscriber automatically:\n * 1. Creates an SQS queue (or uses existing one)\n * 2. Subscribes the queue to the SNS topic\n * 3. Receives messages pushed from SNS to the queue\n * 4. Filters messages by topic ARN and message type\n * 5. Processes and acknowledges messages\n *\n * Note: While SQS long-polling is used internally to receive messages,\n * this is an implementation detail of the SNS push delivery mechanism.\n * Messages are pushed from SNS to SQS, and we receive those pushed messages.\n */\nexport class SNSSubscriber<TMessage extends PublishableMessage<string, any>>\n implements EventSubscriber<TMessage>\n{\n private sqsClient: SQSClient;\n private queueUrl?: string;\n private queueArn?: string;\n private subscriptionArn?: string;\n private sqsSubscriber?: SQSSubscriber<TMessage>;\n private options: Required<SNSSubscriberOptions>;\n\n constructor(\n private connection: SNSConnection,\n options: SNSSubscriberOptions = {},\n ) {\n this.options = {\n queueName:\n options.queueName ||\n `sns-sub-${Date.now()}-${Math.random().toString(36).substring(7)}`,\n createQueue: options.createQueue ?? true,\n deleteQueueOnClose: options.deleteQueueOnClose ?? !options.queueName, // Delete auto-generated queues\n waitTimeSeconds: options.waitTimeSeconds ?? 20,\n maxMessages: options.maxMessages ?? 10,\n };\n\n // Create SQS client with same config as SNS\n this.sqsClient = new SQSClient({\n region: (this.connection as any).config.region,\n endpoint: (this.connection as any).config.endpoint,\n credentials: (this.connection as any).config.credentials,\n });\n }\n\n /**\n * Create an SNSSubscriber from a connection string\n * Format: sns://?topicArn=...&queueName=myqueue®ion=us-east-1\n */\n static async fromConnectionString<\n TMessage extends PublishableMessage<string, any>,\n >(connectionString: string): Promise<SNSSubscriber<TMessage>> {\n const url = new URL(connectionString);\n const params = url.searchParams;\n\n const { SNSConnection } = await import('./SNSConnection');\n const connection =\n await SNSConnection.fromConnectionString(connectionString);\n\n const options: SNSSubscriberOptions = {\n queueName: params.get('queueName') || undefined,\n createQueue: params.get('createQueue') !== 'false',\n deleteQueueOnClose: params.get('deleteQueueOnClose') === 'true',\n waitTimeSeconds: params.get('waitTimeSeconds')\n ? Number.parseInt(params.get('waitTimeSeconds')!, 10)\n : undefined,\n };\n\n return new SNSSubscriber<TMessage>(connection, options);\n }\n\n async subscribe(\n messages: TMessage['type'][],\n listener: (payload: TMessage) => Promise<void>,\n ): Promise<void> {\n // Setup SQS queue and SNS subscription\n await this.setupQueue();\n await this.subscribeToTopic();\n\n // Create SQS connection for the subscriber\n const sqsConnection = new SQSConnection({\n queueUrl: this.queueUrl!,\n region: (this.connection as any).config.region,\n endpoint: (this.connection as any).config.endpoint,\n credentials: (this.connection as any).config.credentials,\n });\n await sqsConnection.connect();\n\n // Use SQSSubscriber to receive messages, with topic filtering\n this.sqsSubscriber = new SQSSubscriber<TMessage>(sqsConnection, {\n waitTimeSeconds: this.options.waitTimeSeconds,\n maxMessages: this.options.maxMessages,\n expectedTopicArn: this.connection.topicArn,\n });\n\n await this.sqsSubscriber.subscribe(messages, listener);\n }\n\n /**\n * Stop receiving messages and clean up resources\n */\n async stop(): Promise<void> {\n // Stop SQS subscriber\n if (this.sqsSubscriber) {\n this.sqsSubscriber.stop();\n }\n\n // Unsubscribe from topic\n if (this.subscriptionArn) {\n try {\n const command = new UnsubscribeCommand({\n SubscriptionArn: this.subscriptionArn,\n });\n await this.connection.snsClient.send(command);\n } catch (error) {\n console.error('Error unsubscribing:', error);\n }\n }\n\n // Delete queue if configured\n if (this.queueUrl && this.options.deleteQueueOnClose) {\n try {\n const command = new DeleteQueueCommand({\n QueueUrl: this.queueUrl,\n });\n await this.sqsClient.send(command);\n } catch (error) {\n console.error('Error deleting queue:', error);\n }\n }\n\n this.sqsClient.destroy();\n }\n\n private async setupQueue(): Promise<void> {\n if (this.options.createQueue) {\n // Create queue\n const createCommand = new CreateQueueCommand({\n QueueName: this.options.queueName,\n });\n const response = await this.sqsClient.send(createCommand);\n this.queueUrl = response.QueueUrl!;\n } else {\n throw new Error('Queue must exist or createQueue option must be true');\n }\n\n // Get queue ARN\n const attrsCommand = new GetQueueAttributesCommand({\n QueueUrl: this.queueUrl,\n AttributeNames: ['QueueArn'],\n });\n const attrsResponse = await this.sqsClient.send(attrsCommand);\n this.queueArn = attrsResponse.Attributes?.QueueArn!;\n\n // Set queue policy to allow SNS\n await this.setQueuePolicy();\n }\n\n private async setQueuePolicy(): Promise<void> {\n const policy = {\n Version: '2012-10-17',\n Statement: [\n {\n Effect: 'Allow',\n Principal: '*',\n Action: 'SQS:SendMessage',\n Resource: this.queueArn,\n Condition: {\n ArnEquals: {\n 'aws:SourceArn': this.connection.topicArn,\n },\n },\n },\n ],\n };\n\n const command = new SetQueueAttributesCommand({\n QueueUrl: this.queueUrl,\n Attributes: {\n Policy: JSON.stringify(policy),\n },\n });\n\n await this.sqsClient.send(command);\n }\n\n private async subscribeToTopic(): Promise<void> {\n const command = new SubscribeCommand({\n TopicArn: this.connection.topicArn,\n Protocol: 'sqs',\n Endpoint: this.queueArn,\n });\n\n const response = await this.connection.snsClient.send(command);\n this.subscriptionArn = response.SubscriptionArn!;\n }\n}\n"],"mappings":"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"}
|