@geekmidas/events 10.0.0-alpha.2 → 10.0.0-alpha.21
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/PgBossConnection-CywKoAZU.cjs +2 -0
- package/dist/PgBossConnection-DjoqT84r.mjs +2 -0
- package/dist/RabbitMQConnection-C9eccBL8.cjs +2 -0
- package/dist/RabbitMQConnection-CAp7VqyT.mjs +2 -0
- package/dist/SNSConnection-BWDC1wAF.cjs +2 -0
- package/dist/SNSConnection-ezQvVrDv.mjs +2 -0
- package/dist/{SQSSubscriber-BMWZ3s5q.mjs → SQSSubscriber-BXLE_1L3.mjs} +73 -7
- package/dist/SQSSubscriber-BXLE_1L3.mjs.map +1 -0
- package/dist/{SQSSubscriber-YXPlg2rm.cjs → SQSSubscriber-DtRUaZB3.cjs} +91 -14
- package/dist/SQSSubscriber-DtRUaZB3.cjs.map +1 -0
- package/dist/basic/index.cjs +7 -8
- package/dist/basic/index.cjs.map +1 -1
- package/dist/basic/index.d.cts +4 -10
- package/dist/basic/index.d.cts.map +1 -1
- package/dist/basic/index.d.mts +4 -10
- package/dist/basic/index.d.mts.map +1 -1
- package/dist/basic/index.mjs +5 -6
- package/dist/basic/index.mjs.map +1 -1
- package/dist/index.cjs +39 -46
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -9
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +5 -9
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +38 -47
- package/dist/index.mjs.map +1 -1
- package/dist/pgboss/index.cjs +98 -21
- package/dist/pgboss/index.cjs.map +1 -1
- package/dist/pgboss/index.d.cts +11 -10
- package/dist/pgboss/index.d.cts.map +1 -1
- package/dist/pgboss/index.d.mts +11 -10
- package/dist/pgboss/index.d.mts.map +1 -1
- package/dist/pgboss/index.mjs +95 -21
- package/dist/pgboss/index.mjs.map +1 -1
- package/dist/rabbitmq/index.cjs +135 -22
- package/dist/rabbitmq/index.cjs.map +1 -1
- package/dist/rabbitmq/index.d.cts +11 -10
- package/dist/rabbitmq/index.d.cts.map +1 -1
- package/dist/rabbitmq/index.d.mts +11 -10
- package/dist/rabbitmq/index.d.mts.map +1 -1
- package/dist/rabbitmq/index.mjs +130 -22
- package/dist/rabbitmq/index.mjs.map +1 -1
- package/dist/{chunk-CsX-DzYB.cjs → rolldown-runtime-C0BPl7ul.cjs} +17 -16
- package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
- package/dist/sns/index.cjs +106 -34
- package/dist/sns/index.cjs.map +1 -1
- package/dist/sns/index.d.cts +14 -11
- package/dist/sns/index.d.cts.map +1 -1
- package/dist/sns/index.d.mts +14 -11
- package/dist/sns/index.d.mts.map +1 -1
- package/dist/sns/index.mjs +88 -18
- package/dist/sns/index.mjs.map +1 -1
- package/dist/sns/snsUrl.cjs +91 -6
- package/dist/sns/snsUrl.cjs.map +1 -0
- package/dist/sns/snsUrl.d.cts +57 -2
- package/dist/sns/snsUrl.d.cts.map +1 -0
- package/dist/sns/snsUrl.d.mts +57 -2
- package/dist/sns/snsUrl.d.mts.map +1 -0
- package/dist/sns/snsUrl.mjs +81 -2
- package/dist/sns/snsUrl.mjs.map +1 -0
- package/dist/sqs/index.cjs +34 -24
- package/dist/sqs/index.cjs.map +1 -1
- package/dist/sqs/index.d.cts +19 -11
- package/dist/sqs/index.d.cts.map +1 -1
- package/dist/sqs/index.d.mts +19 -11
- package/dist/sqs/index.d.mts.map +1 -1
- package/dist/sqs/index.mjs +22 -15
- package/dist/sqs/index.mjs.map +1 -1
- package/dist/sqs/sqsUrl.cjs +92 -6
- package/dist/sqs/sqsUrl.cjs.map +1 -0
- package/dist/sqs/sqsUrl.d.cts +56 -2
- package/dist/sqs/sqsUrl.d.cts.map +1 -0
- package/dist/sqs/sqsUrl.d.mts +56 -2
- package/dist/sqs/sqsUrl.d.mts.map +1 -0
- package/dist/sqs/sqsUrl.mjs +82 -2
- package/dist/sqs/sqsUrl.mjs.map +1 -0
- package/dist/types-BcZjLxVV.cjs +51 -0
- package/dist/types-BcZjLxVV.cjs.map +1 -0
- package/dist/types-Bk5JM6MP.mjs +40 -0
- package/dist/types-Bk5JM6MP.mjs.map +1 -0
- package/dist/types-gGaoT8qc.d.cts +149 -0
- package/dist/types-gGaoT8qc.d.cts.map +1 -0
- package/dist/types-gGaoT8qc.d.mts +149 -0
- package/dist/types-gGaoT8qc.d.mts.map +1 -0
- package/package.json +12 -12
- package/dist/PgBossConnection-23soZ_aM.cjs +0 -80
- package/dist/PgBossConnection-23soZ_aM.cjs.map +0 -1
- package/dist/PgBossConnection-CCXhoNzb.cjs +0 -4
- package/dist/PgBossConnection-DvNbd4Zk.mjs +0 -74
- package/dist/PgBossConnection-DvNbd4Zk.mjs.map +0 -1
- package/dist/PgBossConnection-_gdM40JB.mjs +0 -4
- package/dist/RabbitMQConnection-BKEdCUro.cjs +0 -113
- package/dist/RabbitMQConnection-BKEdCUro.cjs.map +0 -1
- package/dist/RabbitMQConnection-CCOqDDnb.cjs +0 -4
- package/dist/RabbitMQConnection-DJEyM-Bu.mjs +0 -4
- package/dist/RabbitMQConnection-DJgUPc19.mjs +0 -107
- package/dist/RabbitMQConnection-DJgUPc19.mjs.map +0 -1
- package/dist/SNSConnection-B2K86hpz.cjs +0 -75
- package/dist/SNSConnection-B2K86hpz.cjs.map +0 -1
- package/dist/SNSConnection-BVo84FeW.mjs +0 -5
- package/dist/SNSConnection-DIHRjrQF.cjs +0 -5
- package/dist/SNSConnection-v9jjF99w.mjs +0 -69
- package/dist/SNSConnection-v9jjF99w.mjs.map +0 -1
- package/dist/SQSConnection-4tBMkVZE.mjs +0 -69
- package/dist/SQSConnection-4tBMkVZE.mjs.map +0 -1
- package/dist/SQSConnection-BBLAvF-1.cjs +0 -5
- package/dist/SQSConnection-BaC7rGhI.cjs +0 -75
- package/dist/SQSConnection-BaC7rGhI.cjs.map +0 -1
- package/dist/SQSConnection-DbavOq8_.mjs +0 -5
- package/dist/SQSSubscriber-BMWZ3s5q.mjs.map +0 -1
- package/dist/SQSSubscriber-YXPlg2rm.cjs.map +0 -1
- package/dist/chunk-B9dir_RE.mjs +0 -11
- package/dist/snsUrl-ASdc0D1v.d.cts +0 -61
- package/dist/snsUrl-ASdc0D1v.d.cts.map +0 -1
- package/dist/snsUrl-CifYhPAa.mjs +0 -79
- package/dist/snsUrl-CifYhPAa.mjs.map +0 -1
- package/dist/snsUrl-FRbRcwF0.d.mts +0 -61
- package/dist/snsUrl-FRbRcwF0.d.mts.map +0 -1
- package/dist/snsUrl-f2gU3CzK.cjs +0 -114
- package/dist/snsUrl-f2gU3CzK.cjs.map +0 -1
- package/dist/sqsUrl-BV6zS-mi.d.mts +0 -60
- package/dist/sqsUrl-BV6zS-mi.d.mts.map +0 -1
- package/dist/sqsUrl-CbAsBFHI.mjs +0 -80
- package/dist/sqsUrl-CbAsBFHI.mjs.map +0 -1
- package/dist/sqsUrl-CdisN3GU.cjs +0 -115
- package/dist/sqsUrl-CdisN3GU.cjs.map +0 -1
- package/dist/sqsUrl-DZDPHxIk.d.cts +0 -60
- package/dist/sqsUrl-DZDPHxIk.d.cts.map +0 -1
- package/dist/types-BmixGrOD.d.cts +0 -67
- package/dist/types-BmixGrOD.d.cts.map +0 -1
- package/dist/types-Byv8N9ma.cjs +0 -24
- package/dist/types-Byv8N9ma.cjs.map +0 -1
- package/dist/types-CYDt-2RQ.mjs +0 -18
- package/dist/types-CYDt-2RQ.mjs.map +0 -1
- package/dist/types-DycjsYms.d.mts +0 -67
- package/dist/types-DycjsYms.d.mts.map +0 -1
package/dist/sns/index.mjs
CHANGED
|
@@ -1,14 +1,73 @@
|
|
|
1
|
-
import "../types-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import "../sqsUrl-CbAsBFHI.mjs";
|
|
5
|
-
import { SQSConnection } from "../SQSConnection-4tBMkVZE.mjs";
|
|
6
|
-
import { SQSSubscriber } from "../SQSSubscriber-BMWZ3s5q.mjs";
|
|
7
|
-
import { PublishCommand, SubscribeCommand, UnsubscribeCommand } from "@aws-sdk/client-sns";
|
|
1
|
+
import "../types-Bk5JM6MP.mjs";
|
|
2
|
+
import { n as SQSConnection, t as SQSSubscriber } from "../SQSSubscriber-BXLE_1L3.mjs";
|
|
3
|
+
import { parse, t as snsUrl_exports } from "./snsUrl.mjs";
|
|
8
4
|
import { CreateQueueCommand, DeleteQueueCommand, GetQueueAttributesCommand, SQSClient, SetQueueAttributesCommand } from "@aws-sdk/client-sqs";
|
|
9
|
-
|
|
5
|
+
import { PublishCommand, SNSClient, SubscribeCommand, UnsubscribeCommand } from "@aws-sdk/client-sns";
|
|
6
|
+
//#region src/sns/SNSConnection.ts
|
|
7
|
+
var SNSConnection = class SNSConnection {
|
|
8
|
+
type = "sns";
|
|
9
|
+
client;
|
|
10
|
+
connected = false;
|
|
11
|
+
config;
|
|
12
|
+
constructor(config) {
|
|
13
|
+
this.config = config;
|
|
14
|
+
const clientConfig = {
|
|
15
|
+
region: config.region,
|
|
16
|
+
endpoint: config.endpoint,
|
|
17
|
+
credentials: config.credentials
|
|
18
|
+
};
|
|
19
|
+
this.client = new SNSClient(clientConfig);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Create an SNSConnection from a connection string
|
|
23
|
+
* Format: sns://?topicArn=arn:aws:sns:region:account:topic®ion=us-east-1&endpoint=http://localhost:4566
|
|
24
|
+
*/
|
|
25
|
+
static async fromConnectionString(connectionString) {
|
|
26
|
+
const { topicArn, region, endpoint } = parse(connectionString);
|
|
27
|
+
const params = new URL(connectionString).searchParams;
|
|
28
|
+
const config = {
|
|
29
|
+
topicArn,
|
|
30
|
+
region,
|
|
31
|
+
endpoint
|
|
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
|
+
//#endregion
|
|
10
68
|
//#region src/sns/SNSPublisher.ts
|
|
11
69
|
var SNSPublisher = class SNSPublisher {
|
|
70
|
+
connection;
|
|
12
71
|
constructor(connection, _options = {}) {
|
|
13
72
|
this.connection = connection;
|
|
14
73
|
}
|
|
@@ -17,8 +76,8 @@ var SNSPublisher = class SNSPublisher {
|
|
|
17
76
|
* Format: sns://?topicArn=arn:aws:sns:region:account:topic®ion=us-east-1&endpoint=http://localhost:4566
|
|
18
77
|
*/
|
|
19
78
|
static async fromConnectionString(connectionString) {
|
|
20
|
-
const { SNSConnection
|
|
21
|
-
const connection = await SNSConnection
|
|
79
|
+
const { SNSConnection } = await import("../SNSConnection-ezQvVrDv.mjs");
|
|
80
|
+
const connection = await SNSConnection.fromConnectionString(connectionString);
|
|
22
81
|
return new SNSPublisher(connection);
|
|
23
82
|
}
|
|
24
83
|
async publish(messages) {
|
|
@@ -42,7 +101,6 @@ var SNSPublisher = class SNSPublisher {
|
|
|
42
101
|
}
|
|
43
102
|
async close() {}
|
|
44
103
|
};
|
|
45
|
-
|
|
46
104
|
//#endregion
|
|
47
105
|
//#region src/sns/SNSSubscriber.ts
|
|
48
106
|
/**
|
|
@@ -63,6 +121,7 @@ var SNSPublisher = class SNSPublisher {
|
|
|
63
121
|
* Messages are pushed from SNS to SQS, and we receive those pushed messages.
|
|
64
122
|
*/
|
|
65
123
|
var SNSSubscriber = class SNSSubscriber {
|
|
124
|
+
connection;
|
|
66
125
|
sqsClient;
|
|
67
126
|
queueUrl;
|
|
68
127
|
queueArn;
|
|
@@ -89,10 +148,9 @@ var SNSSubscriber = class SNSSubscriber {
|
|
|
89
148
|
* Format: sns://?topicArn=...&queueName=myqueue®ion=us-east-1
|
|
90
149
|
*/
|
|
91
150
|
static async fromConnectionString(connectionString) {
|
|
92
|
-
const
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
const connection = await SNSConnection$1.fromConnectionString(connectionString);
|
|
151
|
+
const params = new URL(connectionString).searchParams;
|
|
152
|
+
const { SNSConnection } = await import("../SNSConnection-ezQvVrDv.mjs");
|
|
153
|
+
const connection = await SNSConnection.fromConnectionString(connectionString);
|
|
96
154
|
const options = {
|
|
97
155
|
queueName: params.get("queueName") || void 0,
|
|
98
156
|
createQueue: params.get("createQueue") !== "false",
|
|
@@ -138,7 +196,7 @@ var SNSSubscriber = class SNSSubscriber {
|
|
|
138
196
|
const createCommand = new CreateQueueCommand({ QueueName: this.options.queueName });
|
|
139
197
|
const response = await this.sqsClient.send(createCommand);
|
|
140
198
|
this.queueUrl = response.QueueUrl;
|
|
141
|
-
} else throw new
|
|
199
|
+
} else throw new SnsQueueMissing(this.options.queueName);
|
|
142
200
|
const attrsCommand = new GetQueueAttributesCommand({
|
|
143
201
|
QueueUrl: this.queueUrl,
|
|
144
202
|
AttributeNames: ["QueueArn"]
|
|
@@ -174,7 +232,19 @@ var SNSSubscriber = class SNSSubscriber {
|
|
|
174
232
|
this.subscriptionArn = response.SubscriptionArn;
|
|
175
233
|
}
|
|
176
234
|
};
|
|
177
|
-
|
|
235
|
+
/**
|
|
236
|
+
* A subscriber asked to use a queue it may not create. The SQS queue behind an
|
|
237
|
+
* SNS subscription has to exist first, or `createQueue` has to allow it.
|
|
238
|
+
*/
|
|
239
|
+
var SnsQueueMissing = class extends Error {
|
|
240
|
+
queueName;
|
|
241
|
+
constructor(queueName) {
|
|
242
|
+
super(`The SNS subscriber's queue${queueName ? ` "${queueName}"` : ""} is not created here: pass createQueue: true, or create the queue first.`);
|
|
243
|
+
this.queueName = queueName;
|
|
244
|
+
this.name = "SnsQueueMissing";
|
|
245
|
+
}
|
|
246
|
+
};
|
|
178
247
|
//#endregion
|
|
179
|
-
export { SNSConnection, SNSPublisher, SNSSubscriber, snsUrl_exports as snsUrl };
|
|
248
|
+
export { SNSConnection, SNSPublisher, SNSSubscriber, SnsQueueMissing, snsUrl_exports as snsUrl };
|
|
249
|
+
|
|
180
250
|
//# sourceMappingURL=index.mjs.map
|
package/dist/sns/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["connection: SNSConnection","_options: SNSPublisherOptions","connectionString: string","messages: TMessage[]","message: TMessage","connection: SNSConnection","options: SNSSubscriberOptions","connectionString: string","messages: TMessage['type'][]","listener: (payload: TMessage) => Promise<void>"],"sources":["../../src/sns/SNSPublisher.ts","../../src/sns/SNSSubscriber.ts"],"sourcesContent":["import { PublishCommand } from '@aws-sdk/client-sns';\nimport type { EventPublisher, PublishableMessage } from '../types';\nimport type { SNSConnection } from './SNSConnection';\n\nexport type SNSPublisherOptions = {};\n\nexport class SNSPublisher<TMessage extends PublishableMessage<string, any>>\n\timplements EventPublisher<TMessage>\n{\n\tconstructor(\n\t\tprivate connection: SNSConnection,\n\t\t_options: SNSPublisherOptions = {},\n\t) {}\n\n\t/**\n\t * Create an SNSPublisher from a connection string\n\t * Format: sns://?topicArn=arn:aws:sns:region:account:topic®ion=us-east-1&endpoint=http://localhost:4566\n\t */\n\tstatic async fromConnectionString<\n\t\tTMessage extends PublishableMessage<string, any>,\n\t>(connectionString: string): Promise<SNSPublisher<TMessage>> {\n\t\tconst { SNSConnection } = await import('./SNSConnection');\n\t\tconst connection =\n\t\t\tawait SNSConnection.fromConnectionString(connectionString);\n\n\t\treturn new SNSPublisher<TMessage>(connection);\n\t}\n\n\tasync publish(messages: TMessage[]): Promise<void> {\n\t\tif (messages.length === 0) return;\n\n\t\tif (!this.connection.isConnected()) {\n\t\t\tawait this.connection.connect();\n\t\t}\n\n\t\t// Publish all messages\n\t\tawait Promise.all(messages.map((message) => this.publishMessage(message)));\n\t}\n\n\tprivate async publishMessage(message: TMessage): Promise<void> {\n\t\tconst command = new PublishCommand({\n\t\t\tTopicArn: this.connection.topicArn,\n\t\t\tMessage: JSON.stringify({\n\t\t\t\ttype: message.type,\n\t\t\t\tpayload: message.payload,\n\t\t\t}),\n\t\t\tMessageAttributes: {\n\t\t\t\ttype: {\n\t\t\t\t\tDataType: 'String',\n\t\t\t\t\tStringValue: message.type,\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\n\t\tawait this.connection.snsClient.send(command);\n\t}\n\n\tasync close(): Promise<void> {\n\t\t// Publisher doesn't own the connection\n\t\t// Connection should be closed by whoever created it\n\t}\n}\n","import { SubscribeCommand, UnsubscribeCommand } from '@aws-sdk/client-sns';\nimport {\n\tCreateQueueCommand,\n\tDeleteQueueCommand,\n\tGetQueueAttributesCommand,\n\tSetQueueAttributesCommand,\n\tSQSClient,\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\tqueueName?: string; // Optional queue name (defaults to auto-generated)\n\tcreateQueue?: boolean; // Auto-create SQS queue (default: true)\n\tdeleteQueueOnClose?: boolean; // Delete queue when subscriber closes (default: false for named queues, true for auto-generated)\n\twaitTimeSeconds?: number; // SQS long polling (default: 20)\n\tmaxMessages?: 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\timplements EventSubscriber<TMessage>\n{\n\tprivate sqsClient: SQSClient;\n\tprivate queueUrl?: string;\n\tprivate queueArn?: string;\n\tprivate subscriptionArn?: string;\n\tprivate sqsSubscriber?: SQSSubscriber<TMessage>;\n\tprivate options: Required<SNSSubscriberOptions>;\n\n\tconstructor(\n\t\tprivate connection: SNSConnection,\n\t\toptions: SNSSubscriberOptions = {},\n\t) {\n\t\tthis.options = {\n\t\t\tqueueName:\n\t\t\t\toptions.queueName ||\n\t\t\t\t`sns-sub-${Date.now()}-${Math.random().toString(36).substring(7)}`,\n\t\t\tcreateQueue: options.createQueue ?? true,\n\t\t\tdeleteQueueOnClose: options.deleteQueueOnClose ?? !options.queueName, // Delete auto-generated queues\n\t\t\twaitTimeSeconds: options.waitTimeSeconds ?? 20,\n\t\t\tmaxMessages: options.maxMessages ?? 10,\n\t\t};\n\n\t\t// Create SQS client with same config as SNS\n\t\tthis.sqsClient = new SQSClient({\n\t\t\tregion: (this.connection as any).config.region,\n\t\t\tendpoint: (this.connection as any).config.endpoint,\n\t\t\tcredentials: (this.connection as any).config.credentials,\n\t\t});\n\t}\n\n\t/**\n\t * Create an SNSSubscriber from a connection string\n\t * Format: sns://?topicArn=...&queueName=myqueue®ion=us-east-1\n\t */\n\tstatic async fromConnectionString<\n\t\tTMessage extends PublishableMessage<string, any>,\n\t>(connectionString: string): Promise<SNSSubscriber<TMessage>> {\n\t\tconst url = new URL(connectionString);\n\t\tconst params = url.searchParams;\n\n\t\tconst { SNSConnection } = await import('./SNSConnection');\n\t\tconst connection =\n\t\t\tawait SNSConnection.fromConnectionString(connectionString);\n\n\t\tconst options: SNSSubscriberOptions = {\n\t\t\tqueueName: params.get('queueName') || undefined,\n\t\t\tcreateQueue: params.get('createQueue') !== 'false',\n\t\t\tdeleteQueueOnClose: params.get('deleteQueueOnClose') === 'true',\n\t\t\twaitTimeSeconds: params.get('waitTimeSeconds')\n\t\t\t\t? Number.parseInt(params.get('waitTimeSeconds')!, 10)\n\t\t\t\t: undefined,\n\t\t};\n\n\t\treturn new SNSSubscriber<TMessage>(connection, options);\n\t}\n\n\tasync subscribe(\n\t\tmessages: TMessage['type'][],\n\t\tlistener: (payload: TMessage) => Promise<void>,\n\t): Promise<void> {\n\t\t// Setup SQS queue and SNS subscription\n\t\tawait this.setupQueue();\n\t\tawait this.subscribeToTopic();\n\n\t\t// Create SQS connection for the subscriber\n\t\tconst sqsConnection = new SQSConnection({\n\t\t\tqueueUrl: this.queueUrl!,\n\t\t\tregion: (this.connection as any).config.region,\n\t\t\tendpoint: (this.connection as any).config.endpoint,\n\t\t\tcredentials: (this.connection as any).config.credentials,\n\t\t});\n\t\tawait sqsConnection.connect();\n\n\t\t// Use SQSSubscriber to receive messages, with topic filtering\n\t\tthis.sqsSubscriber = new SQSSubscriber<TMessage>(sqsConnection, {\n\t\t\twaitTimeSeconds: this.options.waitTimeSeconds,\n\t\t\tmaxMessages: this.options.maxMessages,\n\t\t\texpectedTopicArn: this.connection.topicArn,\n\t\t});\n\n\t\tawait this.sqsSubscriber.subscribe(messages, listener);\n\t}\n\n\t/**\n\t * Stop receiving messages and clean up resources\n\t */\n\tasync stop(): Promise<void> {\n\t\t// Stop SQS subscriber\n\t\tif (this.sqsSubscriber) {\n\t\t\tthis.sqsSubscriber.stop();\n\t\t}\n\n\t\t// Unsubscribe from topic\n\t\tif (this.subscriptionArn) {\n\t\t\ttry {\n\t\t\t\tconst command = new UnsubscribeCommand({\n\t\t\t\t\tSubscriptionArn: this.subscriptionArn,\n\t\t\t\t});\n\t\t\t\tawait this.connection.snsClient.send(command);\n\t\t\t} catch (_error) {}\n\t\t}\n\n\t\t// Delete queue if configured\n\t\tif (this.queueUrl && this.options.deleteQueueOnClose) {\n\t\t\ttry {\n\t\t\t\tconst command = new DeleteQueueCommand({\n\t\t\t\t\tQueueUrl: this.queueUrl,\n\t\t\t\t});\n\t\t\t\tawait this.sqsClient.send(command);\n\t\t\t} catch (_error) {}\n\t\t}\n\n\t\tthis.sqsClient.destroy();\n\t}\n\n\tprivate async setupQueue(): Promise<void> {\n\t\tif (this.options.createQueue) {\n\t\t\t// Create queue\n\t\t\tconst createCommand = new CreateQueueCommand({\n\t\t\t\tQueueName: this.options.queueName,\n\t\t\t});\n\t\t\tconst response = await this.sqsClient.send(createCommand);\n\t\t\tthis.queueUrl = response.QueueUrl!;\n\t\t} else {\n\t\t\tthrow new Error('Queue must exist or createQueue option must be true');\n\t\t}\n\n\t\t// Get queue ARN\n\t\tconst attrsCommand = new GetQueueAttributesCommand({\n\t\t\tQueueUrl: this.queueUrl,\n\t\t\tAttributeNames: ['QueueArn'],\n\t\t});\n\t\tconst attrsResponse = await this.sqsClient.send(attrsCommand);\n\t\tthis.queueArn = attrsResponse.Attributes?.QueueArn!;\n\n\t\t// Set queue policy to allow SNS\n\t\tawait this.setQueuePolicy();\n\t}\n\n\tprivate async setQueuePolicy(): Promise<void> {\n\t\tconst policy = {\n\t\t\tVersion: '2012-10-17',\n\t\t\tStatement: [\n\t\t\t\t{\n\t\t\t\t\tEffect: 'Allow',\n\t\t\t\t\tPrincipal: '*',\n\t\t\t\t\tAction: 'SQS:SendMessage',\n\t\t\t\t\tResource: this.queueArn,\n\t\t\t\t\tCondition: {\n\t\t\t\t\t\tArnEquals: {\n\t\t\t\t\t\t\t'aws:SourceArn': this.connection.topicArn,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\n\t\tconst command = new SetQueueAttributesCommand({\n\t\t\tQueueUrl: this.queueUrl,\n\t\t\tAttributes: {\n\t\t\t\tPolicy: JSON.stringify(policy),\n\t\t\t},\n\t\t});\n\n\t\tawait this.sqsClient.send(command);\n\t}\n\n\tprivate async subscribeToTopic(): Promise<void> {\n\t\tconst command = new SubscribeCommand({\n\t\t\tTopicArn: this.connection.topicArn,\n\t\t\tProtocol: 'sqs',\n\t\t\tEndpoint: this.queueArn,\n\t\t});\n\n\t\tconst response = await this.connection.snsClient.send(command);\n\t\tthis.subscriptionArn = response.SubscriptionArn!;\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["snsUrl.parse"],"sources":["../../src/sns/SNSConnection.ts","../../src/sns/SNSPublisher.ts","../../src/sns/SNSSubscriber.ts"],"sourcesContent":["import { SNSClient, type SNSClientConfig } from '@aws-sdk/client-sns';\nimport type { EventConnection } from '../types';\nimport { EventPublisherType } from '../types';\nimport * as snsUrl from './snsUrl';\n\nexport interface SNSConnectionConfig {\n\ttopicArn: string;\n\tregion?: string;\n\tendpoint?: string; // Custom endpoint (e.g., for LocalStack)\n\tcredentials?: {\n\t\taccessKeyId: string;\n\t\tsecretAccessKey: string;\n\t\tsessionToken?: string;\n\t};\n}\n\nexport class SNSConnection implements EventConnection {\n\treadonly type = EventPublisherType.SNS;\n\tprivate client: SNSClient;\n\tprivate connected = false;\n\tprivate config: SNSConnectionConfig;\n\n\tconstructor(config: SNSConnectionConfig) {\n\t\tthis.config = config;\n\n\t\tconst clientConfig: SNSClientConfig = {\n\t\t\tregion: config.region,\n\t\t\tendpoint: config.endpoint,\n\t\t\tcredentials: config.credentials,\n\t\t};\n\n\t\tthis.client = new SNSClient(clientConfig);\n\t}\n\n\t/**\n\t * Create an SNSConnection from a connection string\n\t * Format: sns://?topicArn=arn:aws:sns:region:account:topic®ion=us-east-1&endpoint=http://localhost:4566\n\t */\n\tstatic async fromConnectionString(\n\t\tconnectionString: string,\n\t): Promise<SNSConnection> {\n\t\t// Through the codec, not a second hand-rolled parse: the deploy target\n\t\t// composes these with `snsUrl.build`, and a string it cannot read back is\n\t\t// exactly the drift one shared module rules out.\n\t\tconst { topicArn, region, endpoint } = snsUrl.parse(connectionString);\n\t\tconst params = new URL(connectionString).searchParams;\n\n\t\tconst config: SNSConnectionConfig = {\n\t\t\ttopicArn,\n\t\t\tregion,\n\t\t\tendpoint,\n\t\t};\n\n\t\t// Credentials are not part of the address — see `snsUrl` — but a caller\n\t\t// may still pin them here, so they are read beside it rather than in it.\n\t\tconst accessKeyId = params.get('accessKeyId');\n\t\tconst secretAccessKey = params.get('secretAccessKey');\n\t\tif (accessKeyId && secretAccessKey) {\n\t\t\tconfig.credentials = {\n\t\t\t\taccessKeyId,\n\t\t\t\tsecretAccessKey,\n\t\t\t\tsessionToken: params.get('sessionToken') || undefined,\n\t\t\t};\n\t\t}\n\n\t\tconst connection = new SNSConnection(config);\n\t\tawait connection.connect();\n\t\treturn connection;\n\t}\n\n\tasync connect(): Promise<void> {\n\t\t// SNS doesn't have a traditional connection, but we mark as connected\n\t\tthis.connected = true;\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.client.destroy();\n\t\tthis.connected = false;\n\t}\n\n\tisConnected(): boolean {\n\t\treturn this.connected;\n\t}\n\n\t/**\n\t * Get the underlying SNS client\n\t */\n\tget snsClient(): SNSClient {\n\t\treturn this.client;\n\t}\n\n\t/**\n\t * Get the topic ARN for this connection\n\t */\n\tget topicArn(): string {\n\t\treturn this.config.topicArn;\n\t}\n}\n","import { PublishCommand } from '@aws-sdk/client-sns';\nimport type { EventPublisher, PublishableMessage } from '../types';\nimport type { SNSConnection } from './SNSConnection';\n\nexport type SNSPublisherOptions = {};\n\nexport class SNSPublisher<TMessage extends PublishableMessage<string, any>>\n\timplements EventPublisher<TMessage>\n{\n\tconstructor(\n\t\tprivate connection: SNSConnection,\n\t\t_options: SNSPublisherOptions = {},\n\t) {}\n\n\t/**\n\t * Create an SNSPublisher from a connection string\n\t * Format: sns://?topicArn=arn:aws:sns:region:account:topic®ion=us-east-1&endpoint=http://localhost:4566\n\t */\n\tstatic async fromConnectionString<\n\t\tTMessage extends PublishableMessage<string, any>,\n\t>(connectionString: string): Promise<SNSPublisher<TMessage>> {\n\t\tconst { SNSConnection } = await import('./SNSConnection');\n\t\tconst connection =\n\t\t\tawait SNSConnection.fromConnectionString(connectionString);\n\n\t\treturn new SNSPublisher<TMessage>(connection);\n\t}\n\n\tasync publish(messages: TMessage[]): Promise<void> {\n\t\tif (messages.length === 0) return;\n\n\t\tif (!this.connection.isConnected()) {\n\t\t\tawait this.connection.connect();\n\t\t}\n\n\t\t// Publish all messages\n\t\tawait Promise.all(messages.map((message) => this.publishMessage(message)));\n\t}\n\n\tprivate async publishMessage(message: TMessage): Promise<void> {\n\t\tconst command = new PublishCommand({\n\t\t\tTopicArn: this.connection.topicArn,\n\t\t\tMessage: JSON.stringify({\n\t\t\t\ttype: message.type,\n\t\t\t\tpayload: message.payload,\n\t\t\t}),\n\t\t\tMessageAttributes: {\n\t\t\t\ttype: {\n\t\t\t\t\tDataType: 'String',\n\t\t\t\t\tStringValue: message.type,\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\n\t\tawait this.connection.snsClient.send(command);\n\t}\n\n\tasync close(): Promise<void> {\n\t\t// Publisher doesn't own the connection\n\t\t// Connection should be closed by whoever created it\n\t}\n}\n","import { SubscribeCommand, UnsubscribeCommand } from '@aws-sdk/client-sns';\nimport {\n\tCreateQueueCommand,\n\tDeleteQueueCommand,\n\tGetQueueAttributesCommand,\n\tSetQueueAttributesCommand,\n\tSQSClient,\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\tqueueName?: string; // Optional queue name (defaults to auto-generated)\n\tcreateQueue?: boolean; // Auto-create SQS queue (default: true)\n\tdeleteQueueOnClose?: boolean; // Delete queue when subscriber closes (default: false for named queues, true for auto-generated)\n\twaitTimeSeconds?: number; // SQS long polling (default: 20)\n\tmaxMessages?: 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\timplements EventSubscriber<TMessage>\n{\n\tprivate sqsClient: SQSClient;\n\tprivate queueUrl?: string;\n\tprivate queueArn?: string;\n\tprivate subscriptionArn?: string;\n\tprivate sqsSubscriber?: SQSSubscriber<TMessage>;\n\tprivate options: Required<SNSSubscriberOptions>;\n\n\tconstructor(\n\t\tprivate connection: SNSConnection,\n\t\toptions: SNSSubscriberOptions = {},\n\t) {\n\t\tthis.options = {\n\t\t\tqueueName:\n\t\t\t\toptions.queueName ||\n\t\t\t\t`sns-sub-${Date.now()}-${Math.random().toString(36).substring(7)}`,\n\t\t\tcreateQueue: options.createQueue ?? true,\n\t\t\tdeleteQueueOnClose: options.deleteQueueOnClose ?? !options.queueName, // Delete auto-generated queues\n\t\t\twaitTimeSeconds: options.waitTimeSeconds ?? 20,\n\t\t\tmaxMessages: options.maxMessages ?? 10,\n\t\t};\n\n\t\t// Create SQS client with same config as SNS\n\t\tthis.sqsClient = new SQSClient({\n\t\t\tregion: (this.connection as any).config.region,\n\t\t\tendpoint: (this.connection as any).config.endpoint,\n\t\t\tcredentials: (this.connection as any).config.credentials,\n\t\t});\n\t}\n\n\t/**\n\t * Create an SNSSubscriber from a connection string\n\t * Format: sns://?topicArn=...&queueName=myqueue®ion=us-east-1\n\t */\n\tstatic async fromConnectionString<\n\t\tTMessage extends PublishableMessage<string, any>,\n\t>(connectionString: string): Promise<SNSSubscriber<TMessage>> {\n\t\tconst url = new URL(connectionString);\n\t\tconst params = url.searchParams;\n\n\t\tconst { SNSConnection } = await import('./SNSConnection');\n\t\tconst connection =\n\t\t\tawait SNSConnection.fromConnectionString(connectionString);\n\n\t\tconst options: SNSSubscriberOptions = {\n\t\t\tqueueName: params.get('queueName') || undefined,\n\t\t\tcreateQueue: params.get('createQueue') !== 'false',\n\t\t\tdeleteQueueOnClose: params.get('deleteQueueOnClose') === 'true',\n\t\t\twaitTimeSeconds: params.get('waitTimeSeconds')\n\t\t\t\t? Number.parseInt(params.get('waitTimeSeconds')!, 10)\n\t\t\t\t: undefined,\n\t\t};\n\n\t\treturn new SNSSubscriber<TMessage>(connection, options);\n\t}\n\n\tasync subscribe(\n\t\tmessages: TMessage['type'][],\n\t\tlistener: (payload: TMessage) => Promise<void>,\n\t): Promise<void> {\n\t\t// Setup SQS queue and SNS subscription\n\t\tawait this.setupQueue();\n\t\tawait this.subscribeToTopic();\n\n\t\t// Create SQS connection for the subscriber\n\t\tconst sqsConnection = new SQSConnection({\n\t\t\tqueueUrl: this.queueUrl!,\n\t\t\tregion: (this.connection as any).config.region,\n\t\t\tendpoint: (this.connection as any).config.endpoint,\n\t\t\tcredentials: (this.connection as any).config.credentials,\n\t\t});\n\t\tawait sqsConnection.connect();\n\n\t\t// Use SQSSubscriber to receive messages, with topic filtering\n\t\tthis.sqsSubscriber = new SQSSubscriber<TMessage>(sqsConnection, {\n\t\t\twaitTimeSeconds: this.options.waitTimeSeconds,\n\t\t\tmaxMessages: this.options.maxMessages,\n\t\t\texpectedTopicArn: this.connection.topicArn,\n\t\t});\n\n\t\tawait this.sqsSubscriber.subscribe(messages, listener);\n\t}\n\n\t/**\n\t * Stop receiving messages and clean up resources\n\t */\n\tasync stop(): Promise<void> {\n\t\t// Stop SQS subscriber\n\t\tif (this.sqsSubscriber) {\n\t\t\tthis.sqsSubscriber.stop();\n\t\t}\n\n\t\t// Unsubscribe from topic\n\t\tif (this.subscriptionArn) {\n\t\t\ttry {\n\t\t\t\tconst command = new UnsubscribeCommand({\n\t\t\t\t\tSubscriptionArn: this.subscriptionArn,\n\t\t\t\t});\n\t\t\t\tawait this.connection.snsClient.send(command);\n\t\t\t} catch (_error) {}\n\t\t}\n\n\t\t// Delete queue if configured\n\t\tif (this.queueUrl && this.options.deleteQueueOnClose) {\n\t\t\ttry {\n\t\t\t\tconst command = new DeleteQueueCommand({\n\t\t\t\t\tQueueUrl: this.queueUrl,\n\t\t\t\t});\n\t\t\t\tawait this.sqsClient.send(command);\n\t\t\t} catch (_error) {}\n\t\t}\n\n\t\tthis.sqsClient.destroy();\n\t}\n\n\tprivate async setupQueue(): Promise<void> {\n\t\tif (this.options.createQueue) {\n\t\t\t// Create queue\n\t\t\tconst createCommand = new CreateQueueCommand({\n\t\t\t\tQueueName: this.options.queueName,\n\t\t\t});\n\t\t\tconst response = await this.sqsClient.send(createCommand);\n\t\t\tthis.queueUrl = response.QueueUrl!;\n\t\t} else {\n\t\t\tthrow new SnsQueueMissing(this.options.queueName);\n\t\t}\n\n\t\t// Get queue ARN\n\t\tconst attrsCommand = new GetQueueAttributesCommand({\n\t\t\tQueueUrl: this.queueUrl,\n\t\t\tAttributeNames: ['QueueArn'],\n\t\t});\n\t\tconst attrsResponse = await this.sqsClient.send(attrsCommand);\n\t\tthis.queueArn = attrsResponse.Attributes?.QueueArn!;\n\n\t\t// Set queue policy to allow SNS\n\t\tawait this.setQueuePolicy();\n\t}\n\n\tprivate async setQueuePolicy(): Promise<void> {\n\t\tconst policy = {\n\t\t\tVersion: '2012-10-17',\n\t\t\tStatement: [\n\t\t\t\t{\n\t\t\t\t\tEffect: 'Allow',\n\t\t\t\t\tPrincipal: '*',\n\t\t\t\t\tAction: 'SQS:SendMessage',\n\t\t\t\t\tResource: this.queueArn,\n\t\t\t\t\tCondition: {\n\t\t\t\t\t\tArnEquals: {\n\t\t\t\t\t\t\t'aws:SourceArn': this.connection.topicArn,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\n\t\tconst command = new SetQueueAttributesCommand({\n\t\t\tQueueUrl: this.queueUrl,\n\t\t\tAttributes: {\n\t\t\t\tPolicy: JSON.stringify(policy),\n\t\t\t},\n\t\t});\n\n\t\tawait this.sqsClient.send(command);\n\t}\n\n\tprivate async subscribeToTopic(): Promise<void> {\n\t\tconst command = new SubscribeCommand({\n\t\t\tTopicArn: this.connection.topicArn,\n\t\t\tProtocol: 'sqs',\n\t\t\tEndpoint: this.queueArn,\n\t\t});\n\n\t\tconst response = await this.connection.snsClient.send(command);\n\t\tthis.subscriptionArn = response.SubscriptionArn!;\n\t}\n}\n\n/**\n * A subscriber asked to use a queue it may not create. The SQS queue behind an\n * SNS subscription has to exist first, or `createQueue` has to allow it.\n */\nexport class SnsQueueMissing extends Error {\n\tconstructor(readonly queueName: string | undefined) {\n\t\tsuper(\n\t\t\t`The SNS subscriber's queue${queueName ? ` \"${queueName}\"` : ''} is not created here: pass createQueue: true, or create the queue first.`,\n\t\t);\n\t\tthis.name = 'SnsQueueMissing';\n\t}\n}\n"],"mappings":"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"}
|
package/dist/sns/snsUrl.cjs
CHANGED
|
@@ -1,7 +1,92 @@
|
|
|
1
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/sns/snsUrl.ts
|
|
3
|
+
var snsUrl_exports = /* @__PURE__ */ require("../rolldown-runtime-C0BPl7ul.cjs").__exportAll({
|
|
4
|
+
MalformedTopicUrl: () => MalformedTopicUrl,
|
|
5
|
+
MissingTopicArn: () => MissingTopicArn,
|
|
6
|
+
UnexpectedTopicScheme: () => UnexpectedTopicScheme,
|
|
7
|
+
build: () => build,
|
|
8
|
+
parse: () => parse
|
|
9
|
+
});
|
|
10
|
+
const SCHEME = "sns:";
|
|
11
|
+
/**
|
|
12
|
+
* Compose an address into a connection string.
|
|
13
|
+
*
|
|
14
|
+
* Credentials never appear, for the same reason they never appear in an
|
|
15
|
+
* `s3://` URL: the SDK resolves them from its own chain.
|
|
16
|
+
*/
|
|
17
|
+
function build(address) {
|
|
18
|
+
const { topicArn, region, endpoint, queueName } = address;
|
|
19
|
+
if (!topicArn) throw new MissingTopicArn("");
|
|
20
|
+
const url = new URL(`${SCHEME}//`);
|
|
21
|
+
url.searchParams.set("topicArn", topicArn);
|
|
22
|
+
if (region) url.searchParams.set("region", region);
|
|
23
|
+
if (endpoint) url.searchParams.set("endpoint", endpoint);
|
|
24
|
+
if (queueName) url.searchParams.set("queueName", queueName);
|
|
25
|
+
return url.toString();
|
|
26
|
+
}
|
|
27
|
+
/** Parse a connection string back into an address. */
|
|
28
|
+
function parse(connectionString) {
|
|
29
|
+
let parsed;
|
|
30
|
+
try {
|
|
31
|
+
parsed = new URL(connectionString);
|
|
32
|
+
} catch {
|
|
33
|
+
throw new MalformedTopicUrl(connectionString);
|
|
34
|
+
}
|
|
35
|
+
if (parsed.protocol !== SCHEME) throw new UnexpectedTopicScheme(connectionString, SCHEME, parsed.protocol);
|
|
36
|
+
const topicArn = parsed.searchParams.get("topicArn");
|
|
37
|
+
if (!topicArn) throw new MissingTopicArn(connectionString);
|
|
38
|
+
const region = parsed.searchParams.get("region") ?? void 0;
|
|
39
|
+
const endpoint = parsed.searchParams.get("endpoint") ?? void 0;
|
|
40
|
+
const queueName = parsed.searchParams.get("queueName") ?? void 0;
|
|
41
|
+
return {
|
|
42
|
+
topicArn,
|
|
43
|
+
...region ? { region } : {},
|
|
44
|
+
...endpoint ? { endpoint } : {},
|
|
45
|
+
...queueName ? { queueName } : {}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/** The string is not a URL at all. */
|
|
49
|
+
var MalformedTopicUrl = class extends Error {
|
|
50
|
+
url;
|
|
51
|
+
constructor(url) {
|
|
52
|
+
super(`'${url}' is not a valid connection string.`);
|
|
53
|
+
this.url = url;
|
|
54
|
+
this.name = "MalformedTopicUrl";
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
/** The string is a URL, but not an `sns://` one. */
|
|
58
|
+
var UnexpectedTopicScheme = class extends Error {
|
|
59
|
+
url;
|
|
60
|
+
expected;
|
|
61
|
+
actual;
|
|
62
|
+
constructor(url, expected, actual) {
|
|
63
|
+
super(`Expected a '${expected}//' connection string and got '${actual}//' in '${url}'.`);
|
|
64
|
+
this.url = url;
|
|
65
|
+
this.expected = expected;
|
|
66
|
+
this.actual = actual;
|
|
67
|
+
this.name = "UnexpectedTopicScheme";
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
/** An `sns://` string with no topic names nothing. */
|
|
71
|
+
var MissingTopicArn = class extends Error {
|
|
72
|
+
url;
|
|
73
|
+
constructor(url) {
|
|
74
|
+
super(url ? `'${url}' names no topic: an sns:// connection string needs ?topicArn=.` : "An sns:// connection string needs a topicArn.");
|
|
75
|
+
this.url = url;
|
|
76
|
+
this.name = "MissingTopicArn";
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
//#endregion
|
|
80
|
+
exports.MalformedTopicUrl = MalformedTopicUrl;
|
|
81
|
+
exports.MissingTopicArn = MissingTopicArn;
|
|
82
|
+
exports.UnexpectedTopicScheme = UnexpectedTopicScheme;
|
|
83
|
+
exports.build = build;
|
|
84
|
+
exports.parse = parse;
|
|
85
|
+
Object.defineProperty(exports, "snsUrl_exports", {
|
|
86
|
+
enumerable: true,
|
|
87
|
+
get: function() {
|
|
88
|
+
return snsUrl_exports;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
2
91
|
|
|
3
|
-
|
|
4
|
-
exports.MissingTopicArn = require_snsUrl.MissingTopicArn;
|
|
5
|
-
exports.UnexpectedTopicScheme = require_snsUrl.UnexpectedTopicScheme;
|
|
6
|
-
exports.build = require_snsUrl.build;
|
|
7
|
-
exports.parse = require_snsUrl.parse;
|
|
92
|
+
//# sourceMappingURL=snsUrl.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snsUrl.cjs","names":[],"sources":["../../src/sns/snsUrl.ts"],"sourcesContent":["/**\n * The `sns://` connection-string codec — how a topic is addressed as one string.\n *\n * The twin of `sqsUrl`, and separate from it for the same reason `gs://` would\n * be separate from `s3://`: a topic ARN and a queue URL are different\n * vocabularies, and a shared codec would have to contain both. What they share\n * is only the rule that a construct provides one string.\n *\n * Both directions live here so they cannot drift: `parse(build(x))` is `x`.\n */\n\n/** What an SNS connection string addresses. */\nexport interface SnsAddress {\n\ttopicArn: string;\n\t/** Read off the topic, never inherited: a topic may live in another region. */\n\tregion?: string;\n\t/** Set for SNS-compatible backends such as LocalStack. */\n\tendpoint?: string;\n\t/**\n\t * The queue a subscriber drains.\n\t *\n\t * Present only on the subscriber's string: fan-out delivers to a queue per\n\t * subscriber, so the publisher's string names the topic and nothing else.\n\t */\n\tqueueName?: string;\n}\n\nconst SCHEME = 'sns:';\n\n/**\n * Compose an address into a connection string.\n *\n * Credentials never appear, for the same reason they never appear in an\n * `s3://` URL: the SDK resolves them from its own chain.\n */\nexport function build(address: SnsAddress): string {\n\tconst { topicArn, region, endpoint, queueName } = address;\n\tif (!topicArn) throw new MissingTopicArn('');\n\n\tconst url = new URL(`${SCHEME}//`);\n\turl.searchParams.set('topicArn', topicArn);\n\tif (region) url.searchParams.set('region', region);\n\tif (endpoint) url.searchParams.set('endpoint', endpoint);\n\tif (queueName) url.searchParams.set('queueName', queueName);\n\n\treturn url.toString();\n}\n\n/** Parse a connection string back into an address. */\nexport function parse(connectionString: string): SnsAddress {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(connectionString);\n\t} catch {\n\t\tthrow new MalformedTopicUrl(connectionString);\n\t}\n\n\tif (parsed.protocol !== SCHEME) {\n\t\tthrow new UnexpectedTopicScheme(connectionString, SCHEME, parsed.protocol);\n\t}\n\n\tconst topicArn = parsed.searchParams.get('topicArn');\n\tif (!topicArn) throw new MissingTopicArn(connectionString);\n\n\tconst region = parsed.searchParams.get('region') ?? undefined;\n\tconst endpoint = parsed.searchParams.get('endpoint') ?? undefined;\n\tconst queueName = parsed.searchParams.get('queueName') ?? undefined;\n\n\treturn {\n\t\ttopicArn,\n\t\t...(region ? { region } : {}),\n\t\t...(endpoint ? { endpoint } : {}),\n\t\t...(queueName ? { queueName } : {}),\n\t};\n}\n\n/** The string is not a URL at all. */\nexport class MalformedTopicUrl extends Error {\n\tconstructor(readonly url: string) {\n\t\tsuper(`'${url}' is not a valid connection string.`);\n\t\tthis.name = 'MalformedTopicUrl';\n\t}\n}\n\n/** The string is a URL, but not an `sns://` one. */\nexport class UnexpectedTopicScheme extends Error {\n\tconstructor(\n\t\treadonly url: string,\n\t\treadonly expected: string,\n\t\treadonly actual: string,\n\t) {\n\t\tsuper(\n\t\t\t`Expected a '${expected}//' connection string and got '${actual}//' in '${url}'.`,\n\t\t);\n\t\tthis.name = 'UnexpectedTopicScheme';\n\t}\n}\n\n/** An `sns://` string with no topic names nothing. */\nexport class MissingTopicArn extends Error {\n\tconstructor(readonly url: string) {\n\t\tsuper(\n\t\t\turl\n\t\t\t\t? `'${url}' names no topic: an sns:// connection string needs ?topicArn=.`\n\t\t\t\t: 'An sns:// connection string needs a topicArn.',\n\t\t);\n\t\tthis.name = 'MissingTopicArn';\n\t}\n}\n"],"mappings":";;;;;;;;;AA2BA,MAAM,SAAS;;;;;;;AAQf,SAAgB,MAAM,SAA6B;CAClD,MAAM,EAAE,UAAU,QAAQ,UAAU,cAAc;CAClD,IAAI,CAAC,UAAU,MAAM,IAAI,gBAAgB,EAAE;CAE3C,MAAM,MAAM,IAAI,IAAI,GAAG,OAAO,GAAG;CACjC,IAAI,aAAa,IAAI,YAAY,QAAQ;CACzC,IAAI,QAAQ,IAAI,aAAa,IAAI,UAAU,MAAM;CACjD,IAAI,UAAU,IAAI,aAAa,IAAI,YAAY,QAAQ;CACvD,IAAI,WAAW,IAAI,aAAa,IAAI,aAAa,SAAS;CAE1D,OAAO,IAAI,SAAS;AACrB;;AAGA,SAAgB,MAAM,kBAAsC;CAC3D,IAAI;CACJ,IAAI;EACH,SAAS,IAAI,IAAI,gBAAgB;CAClC,QAAQ;EACP,MAAM,IAAI,kBAAkB,gBAAgB;CAC7C;CAEA,IAAI,OAAO,aAAa,QACvB,MAAM,IAAI,sBAAsB,kBAAkB,QAAQ,OAAO,QAAQ;CAG1E,MAAM,WAAW,OAAO,aAAa,IAAI,UAAU;CACnD,IAAI,CAAC,UAAU,MAAM,IAAI,gBAAgB,gBAAgB;CAEzD,MAAM,SAAS,OAAO,aAAa,IAAI,QAAQ,KAAK,KAAA;CACpD,MAAM,WAAW,OAAO,aAAa,IAAI,UAAU,KAAK,KAAA;CACxD,MAAM,YAAY,OAAO,aAAa,IAAI,WAAW,KAAK,KAAA;CAE1D,OAAO;EACN;EACA,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;EAC3B,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;EAC/B,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;CAClC;AACD;;AAGA,IAAa,oBAAb,cAAuC,MAAM;CACvB;CAArB,YAAY,KAAsB;EACjC,MAAM,IAAI,IAAI,oCAAoC;EAD9B,KAAA,MAAA;EAEpB,KAAK,OAAO;CACb;AACD;;AAGA,IAAa,wBAAb,cAA2C,MAAM;CAEtC;CACA;CACA;CAHV,YACC,KACA,UACA,QACC;EACD,MACC,eAAe,SAAS,iCAAiC,OAAO,UAAU,IAAI,GAC/E;EANS,KAAA,MAAA;EACA,KAAA,WAAA;EACA,KAAA,SAAA;EAKT,KAAK,OAAO;CACb;AACD;;AAGA,IAAa,kBAAb,cAAqC,MAAM;CACrB;CAArB,YAAY,KAAsB;EACjC,MACC,MACG,IAAI,IAAI,mEACR,+CACJ;EALoB,KAAA,MAAA;EAMpB,KAAK,OAAO;CACb;AACD"}
|
package/dist/sns/snsUrl.d.cts
CHANGED
|
@@ -1,2 +1,57 @@
|
|
|
1
|
-
|
|
2
|
-
export { MalformedTopicUrl, MissingTopicArn, SnsAddress, UnexpectedTopicScheme, build, parse };
|
|
1
|
+
declare namespace snsUrl_d_exports {
|
|
2
|
+
export { MalformedTopicUrl, MissingTopicArn, SnsAddress, UnexpectedTopicScheme, build, parse };
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* The `sns://` connection-string codec — how a topic is addressed as one string.
|
|
6
|
+
*
|
|
7
|
+
* The twin of `sqsUrl`, and separate from it for the same reason `gs://` would
|
|
8
|
+
* be separate from `s3://`: a topic ARN and a queue URL are different
|
|
9
|
+
* vocabularies, and a shared codec would have to contain both. What they share
|
|
10
|
+
* is only the rule that a construct provides one string.
|
|
11
|
+
*
|
|
12
|
+
* Both directions live here so they cannot drift: `parse(build(x))` is `x`.
|
|
13
|
+
*/
|
|
14
|
+
/** What an SNS connection string addresses. */
|
|
15
|
+
export interface SnsAddress {
|
|
16
|
+
topicArn: string;
|
|
17
|
+
/** Read off the topic, never inherited: a topic may live in another region. */
|
|
18
|
+
region?: string;
|
|
19
|
+
/** Set for SNS-compatible backends such as LocalStack. */
|
|
20
|
+
endpoint?: string;
|
|
21
|
+
/**
|
|
22
|
+
* The queue a subscriber drains.
|
|
23
|
+
*
|
|
24
|
+
* Present only on the subscriber's string: fan-out delivers to a queue per
|
|
25
|
+
* subscriber, so the publisher's string names the topic and nothing else.
|
|
26
|
+
*/
|
|
27
|
+
queueName?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Compose an address into a connection string.
|
|
31
|
+
*
|
|
32
|
+
* Credentials never appear, for the same reason they never appear in an
|
|
33
|
+
* `s3://` URL: the SDK resolves them from its own chain.
|
|
34
|
+
*/
|
|
35
|
+
export declare function build(address: SnsAddress): string;
|
|
36
|
+
/** Parse a connection string back into an address. */
|
|
37
|
+
export declare function parse(connectionString: string): SnsAddress;
|
|
38
|
+
/** The string is not a URL at all. */
|
|
39
|
+
export declare class MalformedTopicUrl extends Error {
|
|
40
|
+
readonly url: string;
|
|
41
|
+
constructor(url: string);
|
|
42
|
+
}
|
|
43
|
+
/** The string is a URL, but not an `sns://` one. */
|
|
44
|
+
export declare class UnexpectedTopicScheme extends Error {
|
|
45
|
+
readonly url: string;
|
|
46
|
+
readonly expected: string;
|
|
47
|
+
readonly actual: string;
|
|
48
|
+
constructor(url: string, expected: string, actual: string);
|
|
49
|
+
}
|
|
50
|
+
/** An `sns://` string with no topic names nothing. */
|
|
51
|
+
export declare class MissingTopicArn extends Error {
|
|
52
|
+
readonly url: string;
|
|
53
|
+
constructor(url: string);
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { snsUrl_d_exports as t };
|
|
57
|
+
//# sourceMappingURL=snsUrl.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snsUrl.d.cts","names":[],"sources":["../../src/sns/snsUrl.ts"],"mappings":";;;;;;;;;;;;;;iBAYiB;EAChB;;EAEA;;EAEA;;;;;;;EAOA;;;;;;;;wBAWe,MAAM,SAAS;;wBAcf,MAAM,2BAA2B;;qBA4BpC,0BAA0B;WACjB;EAArB,YAAqB;;;qBAOT,8BAA8B;WAEhC;WACA;WACA;EAHV,YACU,aACA,kBACA;;;qBAUE,wBAAwB;WACf;EAArB,YAAqB"}
|
package/dist/sns/snsUrl.d.mts
CHANGED
|
@@ -1,2 +1,57 @@
|
|
|
1
|
-
|
|
2
|
-
export { MalformedTopicUrl, MissingTopicArn, SnsAddress, UnexpectedTopicScheme, build, parse };
|
|
1
|
+
declare namespace snsUrl_d_exports {
|
|
2
|
+
export { MalformedTopicUrl, MissingTopicArn, SnsAddress, UnexpectedTopicScheme, build, parse };
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* The `sns://` connection-string codec — how a topic is addressed as one string.
|
|
6
|
+
*
|
|
7
|
+
* The twin of `sqsUrl`, and separate from it for the same reason `gs://` would
|
|
8
|
+
* be separate from `s3://`: a topic ARN and a queue URL are different
|
|
9
|
+
* vocabularies, and a shared codec would have to contain both. What they share
|
|
10
|
+
* is only the rule that a construct provides one string.
|
|
11
|
+
*
|
|
12
|
+
* Both directions live here so they cannot drift: `parse(build(x))` is `x`.
|
|
13
|
+
*/
|
|
14
|
+
/** What an SNS connection string addresses. */
|
|
15
|
+
export interface SnsAddress {
|
|
16
|
+
topicArn: string;
|
|
17
|
+
/** Read off the topic, never inherited: a topic may live in another region. */
|
|
18
|
+
region?: string;
|
|
19
|
+
/** Set for SNS-compatible backends such as LocalStack. */
|
|
20
|
+
endpoint?: string;
|
|
21
|
+
/**
|
|
22
|
+
* The queue a subscriber drains.
|
|
23
|
+
*
|
|
24
|
+
* Present only on the subscriber's string: fan-out delivers to a queue per
|
|
25
|
+
* subscriber, so the publisher's string names the topic and nothing else.
|
|
26
|
+
*/
|
|
27
|
+
queueName?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Compose an address into a connection string.
|
|
31
|
+
*
|
|
32
|
+
* Credentials never appear, for the same reason they never appear in an
|
|
33
|
+
* `s3://` URL: the SDK resolves them from its own chain.
|
|
34
|
+
*/
|
|
35
|
+
export declare function build(address: SnsAddress): string;
|
|
36
|
+
/** Parse a connection string back into an address. */
|
|
37
|
+
export declare function parse(connectionString: string): SnsAddress;
|
|
38
|
+
/** The string is not a URL at all. */
|
|
39
|
+
export declare class MalformedTopicUrl extends Error {
|
|
40
|
+
readonly url: string;
|
|
41
|
+
constructor(url: string);
|
|
42
|
+
}
|
|
43
|
+
/** The string is a URL, but not an `sns://` one. */
|
|
44
|
+
export declare class UnexpectedTopicScheme extends Error {
|
|
45
|
+
readonly url: string;
|
|
46
|
+
readonly expected: string;
|
|
47
|
+
readonly actual: string;
|
|
48
|
+
constructor(url: string, expected: string, actual: string);
|
|
49
|
+
}
|
|
50
|
+
/** An `sns://` string with no topic names nothing. */
|
|
51
|
+
export declare class MissingTopicArn extends Error {
|
|
52
|
+
readonly url: string;
|
|
53
|
+
constructor(url: string);
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { snsUrl_d_exports as t };
|
|
57
|
+
//# sourceMappingURL=snsUrl.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snsUrl.d.mts","names":[],"sources":["../../src/sns/snsUrl.ts"],"mappings":";;;;;;;;;;;;;;iBAYiB;EAChB;;EAEA;;EAEA;;;;;;;EAOA;;;;;;;;wBAWe,MAAM,SAAS;;wBAcf,MAAM,2BAA2B;;qBA4BpC,0BAA0B;WACjB;EAArB,YAAqB;;;qBAOT,8BAA8B;WAEhC;WACA;WACA;EAHV,YACU,aACA,kBACA;;;qBAUE,wBAAwB;WACf;EAArB,YAAqB"}
|
package/dist/sns/snsUrl.mjs
CHANGED
|
@@ -1,3 +1,82 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { t as __exportAll } from "../rolldown-runtime-D7D4PA-g.mjs";
|
|
2
|
+
//#region src/sns/snsUrl.ts
|
|
3
|
+
var snsUrl_exports = /* @__PURE__ */ __exportAll({
|
|
4
|
+
MalformedTopicUrl: () => MalformedTopicUrl,
|
|
5
|
+
MissingTopicArn: () => MissingTopicArn,
|
|
6
|
+
UnexpectedTopicScheme: () => UnexpectedTopicScheme,
|
|
7
|
+
build: () => build,
|
|
8
|
+
parse: () => parse
|
|
9
|
+
});
|
|
10
|
+
const SCHEME = "sns:";
|
|
11
|
+
/**
|
|
12
|
+
* Compose an address into a connection string.
|
|
13
|
+
*
|
|
14
|
+
* Credentials never appear, for the same reason they never appear in an
|
|
15
|
+
* `s3://` URL: the SDK resolves them from its own chain.
|
|
16
|
+
*/
|
|
17
|
+
function build(address) {
|
|
18
|
+
const { topicArn, region, endpoint, queueName } = address;
|
|
19
|
+
if (!topicArn) throw new MissingTopicArn("");
|
|
20
|
+
const url = new URL(`${SCHEME}//`);
|
|
21
|
+
url.searchParams.set("topicArn", topicArn);
|
|
22
|
+
if (region) url.searchParams.set("region", region);
|
|
23
|
+
if (endpoint) url.searchParams.set("endpoint", endpoint);
|
|
24
|
+
if (queueName) url.searchParams.set("queueName", queueName);
|
|
25
|
+
return url.toString();
|
|
26
|
+
}
|
|
27
|
+
/** Parse a connection string back into an address. */
|
|
28
|
+
function parse(connectionString) {
|
|
29
|
+
let parsed;
|
|
30
|
+
try {
|
|
31
|
+
parsed = new URL(connectionString);
|
|
32
|
+
} catch {
|
|
33
|
+
throw new MalformedTopicUrl(connectionString);
|
|
34
|
+
}
|
|
35
|
+
if (parsed.protocol !== SCHEME) throw new UnexpectedTopicScheme(connectionString, SCHEME, parsed.protocol);
|
|
36
|
+
const topicArn = parsed.searchParams.get("topicArn");
|
|
37
|
+
if (!topicArn) throw new MissingTopicArn(connectionString);
|
|
38
|
+
const region = parsed.searchParams.get("region") ?? void 0;
|
|
39
|
+
const endpoint = parsed.searchParams.get("endpoint") ?? void 0;
|
|
40
|
+
const queueName = parsed.searchParams.get("queueName") ?? void 0;
|
|
41
|
+
return {
|
|
42
|
+
topicArn,
|
|
43
|
+
...region ? { region } : {},
|
|
44
|
+
...endpoint ? { endpoint } : {},
|
|
45
|
+
...queueName ? { queueName } : {}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/** The string is not a URL at all. */
|
|
49
|
+
var MalformedTopicUrl = class extends Error {
|
|
50
|
+
url;
|
|
51
|
+
constructor(url) {
|
|
52
|
+
super(`'${url}' is not a valid connection string.`);
|
|
53
|
+
this.url = url;
|
|
54
|
+
this.name = "MalformedTopicUrl";
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
/** The string is a URL, but not an `sns://` one. */
|
|
58
|
+
var UnexpectedTopicScheme = class extends Error {
|
|
59
|
+
url;
|
|
60
|
+
expected;
|
|
61
|
+
actual;
|
|
62
|
+
constructor(url, expected, actual) {
|
|
63
|
+
super(`Expected a '${expected}//' connection string and got '${actual}//' in '${url}'.`);
|
|
64
|
+
this.url = url;
|
|
65
|
+
this.expected = expected;
|
|
66
|
+
this.actual = actual;
|
|
67
|
+
this.name = "UnexpectedTopicScheme";
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
/** An `sns://` string with no topic names nothing. */
|
|
71
|
+
var MissingTopicArn = class extends Error {
|
|
72
|
+
url;
|
|
73
|
+
constructor(url) {
|
|
74
|
+
super(url ? `'${url}' names no topic: an sns:// connection string needs ?topicArn=.` : "An sns:// connection string needs a topicArn.");
|
|
75
|
+
this.url = url;
|
|
76
|
+
this.name = "MissingTopicArn";
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
//#endregion
|
|
80
|
+
export { MalformedTopicUrl, MissingTopicArn, UnexpectedTopicScheme, build, parse, snsUrl_exports as t };
|
|
2
81
|
|
|
3
|
-
|
|
82
|
+
//# sourceMappingURL=snsUrl.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snsUrl.mjs","names":[],"sources":["../../src/sns/snsUrl.ts"],"sourcesContent":["/**\n * The `sns://` connection-string codec — how a topic is addressed as one string.\n *\n * The twin of `sqsUrl`, and separate from it for the same reason `gs://` would\n * be separate from `s3://`: a topic ARN and a queue URL are different\n * vocabularies, and a shared codec would have to contain both. What they share\n * is only the rule that a construct provides one string.\n *\n * Both directions live here so they cannot drift: `parse(build(x))` is `x`.\n */\n\n/** What an SNS connection string addresses. */\nexport interface SnsAddress {\n\ttopicArn: string;\n\t/** Read off the topic, never inherited: a topic may live in another region. */\n\tregion?: string;\n\t/** Set for SNS-compatible backends such as LocalStack. */\n\tendpoint?: string;\n\t/**\n\t * The queue a subscriber drains.\n\t *\n\t * Present only on the subscriber's string: fan-out delivers to a queue per\n\t * subscriber, so the publisher's string names the topic and nothing else.\n\t */\n\tqueueName?: string;\n}\n\nconst SCHEME = 'sns:';\n\n/**\n * Compose an address into a connection string.\n *\n * Credentials never appear, for the same reason they never appear in an\n * `s3://` URL: the SDK resolves them from its own chain.\n */\nexport function build(address: SnsAddress): string {\n\tconst { topicArn, region, endpoint, queueName } = address;\n\tif (!topicArn) throw new MissingTopicArn('');\n\n\tconst url = new URL(`${SCHEME}//`);\n\turl.searchParams.set('topicArn', topicArn);\n\tif (region) url.searchParams.set('region', region);\n\tif (endpoint) url.searchParams.set('endpoint', endpoint);\n\tif (queueName) url.searchParams.set('queueName', queueName);\n\n\treturn url.toString();\n}\n\n/** Parse a connection string back into an address. */\nexport function parse(connectionString: string): SnsAddress {\n\tlet parsed: URL;\n\ttry {\n\t\tparsed = new URL(connectionString);\n\t} catch {\n\t\tthrow new MalformedTopicUrl(connectionString);\n\t}\n\n\tif (parsed.protocol !== SCHEME) {\n\t\tthrow new UnexpectedTopicScheme(connectionString, SCHEME, parsed.protocol);\n\t}\n\n\tconst topicArn = parsed.searchParams.get('topicArn');\n\tif (!topicArn) throw new MissingTopicArn(connectionString);\n\n\tconst region = parsed.searchParams.get('region') ?? undefined;\n\tconst endpoint = parsed.searchParams.get('endpoint') ?? undefined;\n\tconst queueName = parsed.searchParams.get('queueName') ?? undefined;\n\n\treturn {\n\t\ttopicArn,\n\t\t...(region ? { region } : {}),\n\t\t...(endpoint ? { endpoint } : {}),\n\t\t...(queueName ? { queueName } : {}),\n\t};\n}\n\n/** The string is not a URL at all. */\nexport class MalformedTopicUrl extends Error {\n\tconstructor(readonly url: string) {\n\t\tsuper(`'${url}' is not a valid connection string.`);\n\t\tthis.name = 'MalformedTopicUrl';\n\t}\n}\n\n/** The string is a URL, but not an `sns://` one. */\nexport class UnexpectedTopicScheme extends Error {\n\tconstructor(\n\t\treadonly url: string,\n\t\treadonly expected: string,\n\t\treadonly actual: string,\n\t) {\n\t\tsuper(\n\t\t\t`Expected a '${expected}//' connection string and got '${actual}//' in '${url}'.`,\n\t\t);\n\t\tthis.name = 'UnexpectedTopicScheme';\n\t}\n}\n\n/** An `sns://` string with no topic names nothing. */\nexport class MissingTopicArn extends Error {\n\tconstructor(readonly url: string) {\n\t\tsuper(\n\t\t\turl\n\t\t\t\t? `'${url}' names no topic: an sns:// connection string needs ?topicArn=.`\n\t\t\t\t: 'An sns:// connection string needs a topicArn.',\n\t\t);\n\t\tthis.name = 'MissingTopicArn';\n\t}\n}\n"],"mappings":";;;;;;;;;AA2BA,MAAM,SAAS;;;;;;;AAQf,SAAgB,MAAM,SAA6B;CAClD,MAAM,EAAE,UAAU,QAAQ,UAAU,cAAc;CAClD,IAAI,CAAC,UAAU,MAAM,IAAI,gBAAgB,EAAE;CAE3C,MAAM,MAAM,IAAI,IAAI,GAAG,OAAO,GAAG;CACjC,IAAI,aAAa,IAAI,YAAY,QAAQ;CACzC,IAAI,QAAQ,IAAI,aAAa,IAAI,UAAU,MAAM;CACjD,IAAI,UAAU,IAAI,aAAa,IAAI,YAAY,QAAQ;CACvD,IAAI,WAAW,IAAI,aAAa,IAAI,aAAa,SAAS;CAE1D,OAAO,IAAI,SAAS;AACrB;;AAGA,SAAgB,MAAM,kBAAsC;CAC3D,IAAI;CACJ,IAAI;EACH,SAAS,IAAI,IAAI,gBAAgB;CAClC,QAAQ;EACP,MAAM,IAAI,kBAAkB,gBAAgB;CAC7C;CAEA,IAAI,OAAO,aAAa,QACvB,MAAM,IAAI,sBAAsB,kBAAkB,QAAQ,OAAO,QAAQ;CAG1E,MAAM,WAAW,OAAO,aAAa,IAAI,UAAU;CACnD,IAAI,CAAC,UAAU,MAAM,IAAI,gBAAgB,gBAAgB;CAEzD,MAAM,SAAS,OAAO,aAAa,IAAI,QAAQ,KAAK,KAAA;CACpD,MAAM,WAAW,OAAO,aAAa,IAAI,UAAU,KAAK,KAAA;CACxD,MAAM,YAAY,OAAO,aAAa,IAAI,WAAW,KAAK,KAAA;CAE1D,OAAO;EACN;EACA,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;EAC3B,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;EAC/B,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;CAClC;AACD;;AAGA,IAAa,oBAAb,cAAuC,MAAM;CACvB;CAArB,YAAY,KAAsB;EACjC,MAAM,IAAI,IAAI,oCAAoC;EAD9B,KAAA,MAAA;EAEpB,KAAK,OAAO;CACb;AACD;;AAGA,IAAa,wBAAb,cAA2C,MAAM;CAEtC;CACA;CACA;CAHV,YACC,KACA,UACA,QACC;EACD,MACC,eAAe,SAAS,iCAAiC,OAAO,UAAU,IAAI,GAC/E;EANS,KAAA,MAAA;EACA,KAAA,WAAA;EACA,KAAA,SAAA;EAKT,KAAK,OAAO;CACb;AACD;;AAGA,IAAa,kBAAb,cAAqC,MAAM;CACrB;CAArB,YAAY,KAAsB;EACjC,MACC,MACG,IAAI,IAAI,mEACR,+CACJ;EALoB,KAAA,MAAA;EAMpB,KAAK,OAAO;CACb;AACD"}
|
package/dist/sqs/index.cjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
require(
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_rolldown_runtime = require("../rolldown-runtime-C0BPl7ul.cjs");
|
|
3
|
+
const require_sqs_sqsUrl = require("./sqsUrl.cjs");
|
|
4
|
+
const require_SQSSubscriber = require("../SQSSubscriber-DtRUaZB3.cjs");
|
|
5
|
+
let _aws_sdk_client_sqs = require("@aws-sdk/client-sqs");
|
|
6
|
+
let lodash_chunk = require("lodash.chunk");
|
|
7
|
+
lodash_chunk = require_rolldown_runtime.__toESM(lodash_chunk, 1);
|
|
9
8
|
//#region src/sqs/SQSPublisher.ts
|
|
10
9
|
var SQSPublisher = class SQSPublisher {
|
|
10
|
+
connection;
|
|
11
11
|
options;
|
|
12
12
|
constructor(connection, options = {}) {
|
|
13
13
|
this.connection = connection;
|
|
@@ -18,10 +18,9 @@ var SQSPublisher = class SQSPublisher {
|
|
|
18
18
|
* Format: sqs://?queueUrl=https://sqs.region.amazonaws.com/accountId/queueName®ion=us-east-1&endpoint=http://localhost:4566&maxBatchSize=10
|
|
19
19
|
*/
|
|
20
20
|
static async fromConnectionString(connectionString) {
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const connection = await SQSConnection$1.fromConnectionString(connectionString);
|
|
21
|
+
const params = new URL(connectionString).searchParams;
|
|
22
|
+
const { SQSConnection } = await Promise.resolve().then(() => require("../SQSSubscriber-DtRUaZB3.cjs")).then((n) => n.SQSConnection_exports);
|
|
23
|
+
const connection = await SQSConnection.fromConnectionString(connectionString);
|
|
25
24
|
const options = { maxBatchSize: params.get("maxBatchSize") ? Number.parseInt(params.get("maxBatchSize"), 10) : void 0 };
|
|
26
25
|
return new SQSPublisher(connection, options);
|
|
27
26
|
}
|
|
@@ -47,24 +46,35 @@ var SQSPublisher = class SQSPublisher {
|
|
|
47
46
|
QueueUrl: this.connection.queueUrl,
|
|
48
47
|
Entries: entries
|
|
49
48
|
};
|
|
50
|
-
const command = new
|
|
49
|
+
const command = new _aws_sdk_client_sqs.SendMessageBatchCommand(input);
|
|
51
50
|
const response = await this.connection.sqsClient.send(command);
|
|
52
|
-
if (response.Failed && response.Failed.length > 0) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
if (response.Failed && response.Failed.length > 0) throw new SqsBatchPartlyFailed(response.Failed.map((f) => ({
|
|
52
|
+
id: f.Id,
|
|
53
|
+
code: f.Code,
|
|
54
|
+
message: f.Message
|
|
55
|
+
})));
|
|
56
56
|
}
|
|
57
57
|
async close() {}
|
|
58
58
|
};
|
|
59
|
-
|
|
59
|
+
/** SQS accepted the batch but refused some of its messages; the rest were sent. */
|
|
60
|
+
var SqsBatchPartlyFailed = class extends Error {
|
|
61
|
+
failed;
|
|
62
|
+
constructor(failed) {
|
|
63
|
+
super(`Failed to send ${failed.length} messages: ${failed.map((f) => `${f.id}: ${f.code} - ${f.message}`).join(", ")}. The others in the batch were sent; retry only these.`);
|
|
64
|
+
this.failed = failed;
|
|
65
|
+
this.name = "SqsBatchPartlyFailed";
|
|
66
|
+
}
|
|
67
|
+
};
|
|
60
68
|
//#endregion
|
|
61
|
-
exports.SQSConnection =
|
|
69
|
+
exports.SQSConnection = require_SQSSubscriber.SQSConnection;
|
|
62
70
|
exports.SQSPublisher = SQSPublisher;
|
|
63
71
|
exports.SQSSubscriber = require_SQSSubscriber.SQSSubscriber;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
exports.SqsBatchPartlyFailed = SqsBatchPartlyFailed;
|
|
73
|
+
Object.defineProperty(exports, "sqsUrl", {
|
|
74
|
+
enumerable: true,
|
|
75
|
+
get: function() {
|
|
76
|
+
return require_sqs_sqsUrl.sqsUrl_exports;
|
|
77
|
+
}
|
|
69
78
|
});
|
|
79
|
+
|
|
70
80
|
//# sourceMappingURL=index.cjs.map
|