@blokjs/trigger-pubsub 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,257 @@
1
+ "use strict";
2
+ /**
3
+ * AWSSNSAdapter - AWS SNS/SQS adapter for PubSubTrigger
4
+ *
5
+ * Uses AWS SDK v3 for SNS/SQS connectivity.
6
+ * SNS topics deliver to SQS queues, which this adapter polls.
7
+ *
8
+ * Requires: npm install @aws-sdk/client-sns @aws-sdk/client-sqs
9
+ *
10
+ * Environment variables:
11
+ * - AWS_REGION: AWS region (default: us-east-1)
12
+ * - AWS_ACCESS_KEY_ID: AWS access key (optional if using IAM roles)
13
+ * - AWS_SECRET_ACCESS_KEY: AWS secret key (optional if using IAM roles)
14
+ * - SQS_WAIT_TIME_SECONDS: Long polling wait time (default: 20)
15
+ * - SQS_MAX_MESSAGES: Max messages per receive (default: 10)
16
+ */
17
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ var desc = Object.getOwnPropertyDescriptor(m, k);
20
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
21
+ desc = { enumerable: true, get: function() { return m[k]; } };
22
+ }
23
+ Object.defineProperty(o, k2, desc);
24
+ }) : (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ o[k2] = m[k];
27
+ }));
28
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
29
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
30
+ }) : function(o, v) {
31
+ o["default"] = v;
32
+ });
33
+ var __importStar = (this && this.__importStar) || (function () {
34
+ var ownKeys = function(o) {
35
+ ownKeys = Object.getOwnPropertyNames || function (o) {
36
+ var ar = [];
37
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
38
+ return ar;
39
+ };
40
+ return ownKeys(o);
41
+ };
42
+ return function (mod) {
43
+ if (mod && mod.__esModule) return mod;
44
+ var result = {};
45
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
46
+ __setModuleDefault(result, mod);
47
+ return result;
48
+ };
49
+ })();
50
+ Object.defineProperty(exports, "__esModule", { value: true });
51
+ exports.AWSSNSAdapter = void 0;
52
+ const uuid_1 = require("uuid");
53
+ /**
54
+ * AWSSNSAdapter - AWS SNS implementation using SQS subscriptions
55
+ */
56
+ class AWSSNSAdapter {
57
+ provider = "aws";
58
+ sqsClient;
59
+ connected = false;
60
+ config;
61
+ pollingIntervals = new Map();
62
+ shouldStop = false;
63
+ constructor(config) {
64
+ this.config = {
65
+ region: config?.region || process.env.AWS_REGION || "us-east-1",
66
+ waitTimeSeconds: config?.waitTimeSeconds ?? Number.parseInt(process.env.SQS_WAIT_TIME_SECONDS || "20", 10),
67
+ maxNumberOfMessages: config?.maxNumberOfMessages ?? Number.parseInt(process.env.SQS_MAX_MESSAGES || "10", 10),
68
+ };
69
+ }
70
+ /**
71
+ * Connect to AWS
72
+ */
73
+ async connect() {
74
+ if (this.connected)
75
+ return;
76
+ try {
77
+ // Dynamic import of AWS SDK
78
+ const { SQSClient } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-sqs")));
79
+ this.sqsClient = new SQSClient({
80
+ region: this.config.region,
81
+ });
82
+ this.connected = true;
83
+ this.shouldStop = false;
84
+ console.log(`[AWSSNSAdapter] Connected to AWS SNS/SQS: ${this.config.region}`);
85
+ }
86
+ catch (error) {
87
+ throw new Error(`Failed to connect to AWS: ${error.message}. ` +
88
+ `Make sure @aws-sdk/client-sqs is installed: npm install @aws-sdk/client-sqs`);
89
+ }
90
+ }
91
+ /**
92
+ * Disconnect from AWS
93
+ */
94
+ async disconnect() {
95
+ if (!this.connected)
96
+ return;
97
+ this.shouldStop = true;
98
+ // Clear all polling intervals
99
+ for (const [queueUrl, interval] of this.pollingIntervals) {
100
+ clearTimeout(interval);
101
+ }
102
+ this.pollingIntervals.clear();
103
+ this.connected = false;
104
+ console.log("[AWSSNSAdapter] Disconnected from AWS SNS/SQS");
105
+ }
106
+ /**
107
+ * Subscribe to an SNS topic via SQS queue
108
+ * Note: The SQS queue should be pre-configured as an SNS subscription
109
+ */
110
+ async subscribe(config, handler) {
111
+ if (!this.connected) {
112
+ throw new Error("Not connected to AWS. Call connect() first.");
113
+ }
114
+ // In AWS, subscription is the SQS queue URL that's subscribed to the SNS topic
115
+ const queueUrl = config.subscription;
116
+ // Start polling the SQS queue
117
+ this.poll(queueUrl, config, handler);
118
+ console.log(`[AWSSNSAdapter] Subscribed to queue: ${queueUrl} (topic: ${config.topic})`);
119
+ }
120
+ /**
121
+ * Poll SQS queue for messages (long polling)
122
+ */
123
+ async poll(queueUrl, config, handler) {
124
+ if (this.shouldStop)
125
+ return;
126
+ try {
127
+ const { ReceiveMessageCommand, DeleteMessageCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-sqs")));
128
+ const command = new ReceiveMessageCommand({
129
+ QueueUrl: queueUrl,
130
+ MaxNumberOfMessages: config.maxMessages || this.config.maxNumberOfMessages,
131
+ WaitTimeSeconds: this.config.waitTimeSeconds,
132
+ MessageAttributeNames: ["All"],
133
+ AttributeNames: ["All"],
134
+ });
135
+ const response = await this.sqsClient.send(command);
136
+ if (response.Messages && response.Messages.length > 0) {
137
+ for (const msg of response.Messages) {
138
+ // Parse SNS message wrapper
139
+ let snsMessage;
140
+ let body;
141
+ try {
142
+ snsMessage = JSON.parse(msg.Body || "{}");
143
+ // SNS wraps the actual message in a "Message" field
144
+ if (snsMessage.Type === "Notification" && snsMessage.Message) {
145
+ try {
146
+ body = JSON.parse(snsMessage.Message);
147
+ }
148
+ catch {
149
+ body = snsMessage.Message;
150
+ }
151
+ }
152
+ else {
153
+ body = snsMessage;
154
+ }
155
+ }
156
+ catch {
157
+ body = msg.Body;
158
+ snsMessage = {};
159
+ }
160
+ // Extract attributes from both SQS and SNS
161
+ const attributes = {};
162
+ // SQS message attributes
163
+ if (msg.MessageAttributes) {
164
+ for (const [key, attr] of Object.entries(msg.MessageAttributes)) {
165
+ attributes[key] = attr.StringValue || "";
166
+ }
167
+ }
168
+ // SNS message attributes (if present)
169
+ if (snsMessage.MessageAttributes) {
170
+ for (const [key, attr] of Object.entries(snsMessage.MessageAttributes)) {
171
+ attributes[`sns_${key}`] = attr.Value || "";
172
+ }
173
+ }
174
+ // Create pub/sub message
175
+ const pubsubMessage = {
176
+ id: snsMessage.MessageId || msg.MessageId || (0, uuid_1.v4)(),
177
+ body,
178
+ attributes,
179
+ raw: msg,
180
+ topic: snsMessage.TopicArn || config.topic,
181
+ subscription: queueUrl,
182
+ publishTime: snsMessage.Timestamp ? new Date(snsMessage.Timestamp) : new Date(),
183
+ ack: async () => {
184
+ const deleteCommand = new DeleteMessageCommand({
185
+ QueueUrl: queueUrl,
186
+ ReceiptHandle: msg.ReceiptHandle,
187
+ });
188
+ await this.sqsClient.send(deleteCommand);
189
+ },
190
+ nack: async () => {
191
+ // Let the visibility timeout expire to return the message
192
+ // Or change visibility to 0 for immediate retry
193
+ const { ChangeMessageVisibilityCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-sqs")));
194
+ const changeCommand = new ChangeMessageVisibilityCommand({
195
+ QueueUrl: queueUrl,
196
+ ReceiptHandle: msg.ReceiptHandle,
197
+ VisibilityTimeout: 0,
198
+ });
199
+ await this.sqsClient.send(changeCommand);
200
+ },
201
+ };
202
+ // Process message
203
+ try {
204
+ await handler(pubsubMessage);
205
+ }
206
+ catch (error) {
207
+ console.error(`[AWSSNSAdapter] Error processing message: ${error.message}`);
208
+ }
209
+ }
210
+ }
211
+ }
212
+ catch (error) {
213
+ console.error(`[AWSSNSAdapter] Polling error: ${error.message}`);
214
+ }
215
+ // Continue polling unless stopped
216
+ if (!this.shouldStop) {
217
+ const timeout = setTimeout(() => this.poll(queueUrl, config, handler), 0);
218
+ this.pollingIntervals.set(queueUrl, timeout);
219
+ }
220
+ }
221
+ /**
222
+ * Unsubscribe from a queue (stops polling)
223
+ */
224
+ async unsubscribe(queueUrl) {
225
+ const interval = this.pollingIntervals.get(queueUrl);
226
+ if (interval) {
227
+ clearTimeout(interval);
228
+ this.pollingIntervals.delete(queueUrl);
229
+ console.log(`[AWSSNSAdapter] Unsubscribed from queue: ${queueUrl}`);
230
+ }
231
+ }
232
+ /**
233
+ * Check if connected to AWS
234
+ */
235
+ isConnected() {
236
+ return this.connected;
237
+ }
238
+ /**
239
+ * Health check - verify AWS connectivity
240
+ */
241
+ async healthCheck() {
242
+ if (!this.connected)
243
+ return false;
244
+ try {
245
+ const { ListQueuesCommand } = await Promise.resolve().then(() => __importStar(require("@aws-sdk/client-sqs")));
246
+ const command = new ListQueuesCommand({ MaxResults: 1 });
247
+ await this.sqsClient.send(command);
248
+ return true;
249
+ }
250
+ catch {
251
+ return false;
252
+ }
253
+ }
254
+ }
255
+ exports.AWSSNSAdapter = AWSSNSAdapter;
256
+ exports.default = AWSSNSAdapter;
257
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQVdTU05TQWRhcHRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hZGFwdGVycy9BV1NTTlNBZGFwdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7Ozs7R0FjRzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBR0gsK0JBQWtDO0FBWWxDOztHQUVHO0FBQ0gsTUFBYSxhQUFhO0lBQ2hCLFFBQVEsR0FBRyxLQUFjLENBQUM7SUFFM0IsU0FBUyxDQUFNO0lBQ2YsU0FBUyxHQUFHLEtBQUssQ0FBQztJQUNsQixNQUFNLENBQWU7SUFDckIsZ0JBQWdCLEdBQWdDLElBQUksR0FBRyxFQUFFLENBQUM7SUFDMUQsVUFBVSxHQUFHLEtBQUssQ0FBQztJQUUzQixZQUFZLE1BQThCO1FBQ3pDLElBQUksQ0FBQyxNQUFNLEdBQUc7WUFDYixNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsSUFBSSxXQUFXO1lBQy9ELGVBQWUsRUFBRSxNQUFNLEVBQUUsZUFBZSxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxxQkFBcUIsSUFBSSxJQUFJLEVBQUUsRUFBRSxDQUFDO1lBQzFHLG1CQUFtQixFQUFFLE1BQU0sRUFBRSxtQkFBbUIsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLElBQUksSUFBSSxFQUFFLEVBQUUsQ0FBQztTQUM3RyxDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLE9BQU87UUFDWixJQUFJLElBQUksQ0FBQyxTQUFTO1lBQUUsT0FBTztRQUUzQixJQUFJLENBQUM7WUFDSiw0QkFBNEI7WUFDNUIsTUFBTSxFQUFFLFNBQVMsRUFBRSxHQUFHLHdEQUFhLHFCQUFxQixHQUFDLENBQUM7WUFFMUQsSUFBSSxDQUFDLFNBQVMsR0FB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RSxDQUFDO0lBQ0YsQ0FBQztJQUVEOztPQUVHO0lBQ0gsV0FBVztRQUNWLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQztJQUN2QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsV0FBVztRQUNoQixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVM7WUFBRSxPQUFPLEtBQUssQ0FBQztRQUVsQyxJQUFJLENBQUM7WUFDSixNQUFNLEVBQUUsaUJBQWlCLEVBQUUsR0FBRyx3REFBYSxxQkFBcUIsR0FBQyxDQUFDO1lBQ2xFLE1BQU0sT0FBTyxHQUFHLElBQUksaUJBQWlCLENBQUMsRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN6RCxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQ25DLE9BQU8sSUFBSSxDQUFDO1FBQ2IsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNSLE9BQU8sS0FBSyxDQUFDO1FBQ2QsQ0FBQztJQUNGLENBQUM7Q0FDRDtBQS9ORCxzQ0ErTkM7QUFFRCxrQkFBZSxhQUFhLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEFXU1NOU0FkYXB0ZXIgLSBBV1MgU05TL1NRUyBhZGFwdGVyIGZvciBQdWJTdWJUcmlnZ2VyXG4gKlxuICogVXNlcyBBV1MgU0RLIHYzIGZvciBTTlMvU1FTIGNvbm5lY3Rpdml0eS5cbiAqIFNOUyB0b3BpY3MgZGVsaXZlciB0byBTUVMgcXVldWVzLCB3aGljaCB0aGlzIGFkYXB0ZXIgcG9sbHMuXG4gKlxuICogUmVxdWlyZXM6IG5wbSBpbnN0YWxsIEBhd3Mtc2RrL2NsaWVudC1zbnMgQGF3cy1zZGsvY2xpZW50LXNxc1xuICpcbiAqIEVudmlyb25tZW50IHZhcmlhYmxlczpcbiAqIC0gQVdTX1JFR0lPTjogQVdTIHJlZ2lvbiAoZGVmYXVsdDogdXMtZWFzdC0xKVxuICogLSBBV1NfQUNDRVNTX0tFWV9JRDogQVdTIGFjY2VzcyBrZXkgKG9wdGlvbmFsIGlmIHVzaW5nIElBTSByb2xlcylcbiAqIC0gQVdTX1NFQ1JFVF9BQ0NFU1NfS0VZOiBBV1Mgc2VjcmV0IGtleSAob3B0aW9uYWwgaWYgdXNpbmcgSUFNIHJvbGVzKVxuICogLSBTUVNfV0FJVF9USU1FX1NFQ09ORFM6IExvbmcgcG9sbGluZyB3YWl0IHRpbWUgKGRlZmF1bHQ6IDIwKVxuICogLSBTUVNfTUFYX01FU1NBR0VTOiBNYXggbWVzc2FnZXMgcGVyIHJlY2VpdmUgKGRlZmF1bHQ6IDEwKVxuICovXG5cbmltcG9ydCB0eXBlIHsgUHViU3ViVHJpZ2dlck9wdHMgfSBmcm9tIFwiQGJsb2svaGVscGVyXCI7XG5pbXBvcnQgeyB2NCBhcyB1dWlkIH0gZnJvbSBcInV1aWRcIjtcbmltcG9ydCB0eXBlIHsgUHViU3ViQWRhcHRlciwgUHViU3ViTWVzc2FnZSB9IGZyb20gXCIuLi9QdWJTdWJUcmlnZ2VyXCI7XG5cbi8qKlxuICogQVdTIFNOUy9TUVMgY29uZmlndXJhdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIEFXU1NOU0NvbmZpZyB7XG5cdHJlZ2lvbjogc3RyaW5nO1xuXHR3YWl0VGltZVNlY29uZHM/OiBudW1iZXI7XG5cdG1heE51bWJlck9mTWVzc2FnZXM/OiBudW1iZXI7XG59XG5cbi8qKlxuICogQVdTU05TQWRhcHRlciAtIEFXUyBTTlMgaW1wbGVtZW50YXRpb24gdXNpbmcgU1FTIHN1YnNjcmlwdGlvbnNcbiAqL1xuZXhwb3J0IGNsYXNzIEFXU1NOU0FkYXB0ZXIgaW1wbGVtZW50cyBQdWJTdWJBZGFwdGVyIHtcblx0cmVhZG9ubHkgcHJvdmlkZXIgPSBcImF3c1wiIGFzIGNvbnN0O1xuXG5cdHByaXZhdGUgc3FzQ2xpZW50OiBhbnk7XG5cdHByaXZhdGUgY29ubmVjdGVkID0gZmFsc2U7XG5cdHByaXZhdGUgY29uZmlnOiBBV1NTTlNDb25maWc7XG5cdHByaXZhdGUgcG9sbGluZ0ludGVydmFsczogTWFwPHN0cmluZywgTm9kZUpTLlRpbWVvdXQ+ID0gbmV3IE1hcCgpO1xuXHRwcml2YXRlIHNob3VsZFN0b3AgPSBmYWxzZTtcblxuXHRjb25zdHJ1Y3Rvcihjb25maWc/OiBQYXJ0aWFsPEFXU1NOU0NvbmZpZz4pIHtcblx0XHR0aGlzLmNvbmZpZyA9IHtcblx0XHRcdHJlZ2lvbjogY29uZmlnPy5yZWdpb24gfHwgcHJvY2Vzcy5lbnYuQVdTX1JFR0lPTiB8fCBcInVzLWVhc3QtMVwiLFxuXHRcdFx0d2FpdFRpbWVTZWNvbmRzOiBjb25maWc/LndhaXRUaW1lU2Vjb25kcyA/PyBOdW1iZXIucGFyc2VJbnQocHJvY2Vzcy5lbnYuU1FTX1dBSVRfVElNRV9TRUNPTkRTIHx8IFwiMjBcIiwgMTApLFxuXHRcdFx0bWF4TnVtYmVyT2ZNZXNzYWdlczogY29uZmlnPy5tYXhOdW1iZXJPZk1lc3NhZ2VzID8/IE51bWJlci5wYXJzZUludChwcm9jZXNzLmVudi5TUVNfTUFYX01FU1NBR0VTIHx8IFwiMTBcIiwgMTApLFxuXHRcdH07XG5cdH1cblxuXHQvKipcblx0ICogQ29ubmVjdCB0byBBV1Ncblx0ICovXG5cdGFzeW5jIGNvbm5lY3QoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0aWYgKHRoaXMuY29ubmVjdGVkKSByZXR1cm47XG5cblx0XHR0cnkge1xuXHRcdFx0Ly8gRHluYW1pYyBpbXBvcnQgb2YgQVdTIFNES1xuXHRcdFx0Y29uc3QgeyBTUVNDbGllbnQgfSA9IGF3YWl0IGltcG9ydChcIkBhd3Mtc2RrL2NsaWVudC1zcXNcIik7XG5cblx0XHRcdHRoaXMuc3FzQ2xpZW50ID0gbmV3IFNRU0NsaWVudCh7XG5cdFx0XHRcdHJlZ2lvbjogdGhpcy5jb25maWcucmVnaW9uLFxuXHRcdFx0fSk7XG5cblx0XHRcdHRoaXMuY29ubmVjdGVkID0gdHJ1ZTtcblx0XHRcdHRoaXMuc2hvdWxkU3RvcCA9IGZhbHNlO1xuXHRcdFx0Y29uc29sZS5sb2coYFtBV1NTTlNBZGFwdGVyXSBDb25uZWN0ZWQgdG8gQVdTIFNOUy9TUVM6ICR7dGhpcy5jb25maWcucmVnaW9ufWApO1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXG5cdFx0XHRcdGBGYWlsZWQgdG8gY29ubmVjdCB0byBBV1M6ICR7KGVycm9yIGFzIEVycm9yKS5tZXNzYWdlfS4gYCArXG5cdFx0XHRcdFx0YE1ha2Ugc3VyZSBAYXdzLXNkay9jbGllbnQtc3FzIGlzIGluc3RhbGxlZDogbnBtIGluc3RhbGwgQGF3cy1zZGsvY2xpZW50LXNxc2AsXG5cdFx0XHQpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNjb25uZWN0IGZyb20gQVdTXG5cdCAqL1xuXHRhc3luYyBkaXNjb25uZWN0KCk6IFByb21pc2U8dm9pZD4ge1xuXHRcdGlmICghdGhpcy5jb25uZWN0ZWQpIHJldHVybjtcblxuXHRcdHRoaXMuc2hvdWxkU3RvcCA9IHRydWU7XG5cblx0XHQvLyBDbGVhciBhbGwgcG9sbGluZyBpbnRlcnZhbHNcblx0XHRmb3IgKGNvbnN0IFtxdWV1ZVVybCwgaW50ZXJ2YWxdIG9mIHRoaXMucG9sbGluZ0ludGVydmFscykge1xuXHRcdFx0Y2xlYXJUaW1lb3V0KGludGVydmFsKTtcblx0XHR9XG5cdFx0dGhpcy5wb2xsaW5nSW50ZXJ2YWxzLmNsZWFyKCk7XG5cblx0XHR0aGlzLmNvbm5lY3RlZCA9IGZhbHNlO1xuXHRcdGNvbnNvbGUubG9nKFwiW0FXU1NOU0FkYXB0ZXJdIERpc2Nvbm5lY3RlZCBmcm9tIEFXUyBTTlMvU1FTXCIpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFN1YnNjcmliZSB0byBhbiBTTlMgdG9waWMgdmlhIFNRUyBxdWV1ZVxuXHQgKiBOb3RlOiBUaGUgU1FTIHF1ZXVlIHNob3VsZCBiZSBwcmUtY29uZmlndXJlZCBhcyBhbiBTTlMgc3Vic2NyaXB0aW9uXG5cdCAqL1xuXHRhc3luYyBzdWJzY3JpYmUoY29uZmlnOiBQdWJTdWJUcmlnZ2VyT3B0cywgaGFuZGxlcjogKG1lc3NhZ2U6IFB1YlN1Yk1lc3NhZ2UpID0+IFByb21pc2U8dm9pZD4pOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRpZiAoIXRoaXMuY29ubmVjdGVkKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJOb3QgY29ubmVjdGVkIHRvIEFXUy4gQ2FsbCBjb25uZWN0KCkgZmlyc3QuXCIpO1xuXHRcdH1cblxuXHRcdC8vIEluIEFXUywgc3Vic2NyaXB0aW9uIGlzIHRoZSBTUVMgcXVldWUgVVJMIHRoYXQncyBzdWJzY3JpYmVkIHRvIHRoZSBTTlMgdG9waWNcblx0XHRjb25zdCBxdWV1ZVVybCA9IGNvbmZpZy5zdWJzY3JpcHRpb247XG5cblx0XHQvLyBTdGFydCBwb2xsaW5nIHRoZSBTUVMgcXVldWVcblx0XHR0aGlzLnBvbGwocXVldWVVcmwsIGNvbmZpZywgaGFuZGxlcik7XG5cblx0XHRjb25zb2xlLmxvZyhgW0FXU1NOU0FkYXB0ZXJdIFN1YnNjcmliZWQgdG8gcXVldWU6ICR7cXVldWVVcmx9ICh0b3BpYzogJHtjb25maWcudG9waWN9KWApO1xuXHR9XG5cblx0LyoqXG5cdCAqIFBvbGwgU1FTIHF1ZXVlIGZvciBtZXNzYWdlcyAobG9uZyBwb2xsaW5nKVxuXHQgKi9cblx0cHJpdmF0ZSBhc3luYyBwb2xsKFxuXHRcdHF1ZXVlVXJsOiBzdHJpbmcsXG5cdFx0Y29uZmlnOiBQdWJTdWJUcmlnZ2VyT3B0cyxcblx0XHRoYW5kbGVyOiAobWVzc2FnZTogUHViU3ViTWVzc2FnZSkgPT4gUHJvbWlzZTx2b2lkPixcblx0KTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0aWYgKHRoaXMuc2hvdWxkU3RvcCkgcmV0dXJuO1xuXG5cdFx0dHJ5IHtcblx0XHRcdGNvbnN0IHsgUmVjZWl2ZU1lc3NhZ2VDb21tYW5kLCBEZWxldGVNZXNzYWdlQ29tbWFuZCB9ID0gYXdhaXQgaW1wb3J0KFwiQGF3cy1zZGsvY2xpZW50LXNxc1wiKTtcblxuXHRcdFx0Y29uc3QgY29tbWFuZCA9IG5ldyBSZWNlaXZlTWVzc2FnZUNvbW1hbmQoe1xuXHRcdFx0XHRRdWV1ZVVybDogcXVldWVVcmwsXG5cdFx0XHRcdE1heE51bWJlck9mTWVzc2FnZXM6IGNvbmZpZy5tYXhNZXNzYWdlcyB8fCB0aGlzLmNvbmZpZy5tYXhOdW1iZXJPZk1lc3NhZ2VzLFxuXHRcdFx0XHRXYWl0VGltZVNlY29uZHM6IHRoaXMuY29uZmlnLndhaXRUaW1lU2Vjb25kcyxcblx0XHRcdFx0TWVzc2FnZUF0dHJpYnV0ZU5hbWVzOiBbXCJBbGxcIl0sXG5cdFx0XHRcdEF0dHJpYnV0ZU5hbWVzOiBbXCJBbGxcIl0sXG5cdFx0XHR9KTtcblxuXHRcdFx0Y29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLnNxc0NsaWVudC5zZW5kKGNvbW1hbmQpO1xuXG5cdFx0XHRpZiAocmVzcG9uc2UuTWVzc2FnZXMgJiYgcmVzcG9uc2UuTWVzc2FnZXMubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRmb3IgKGNvbnN0IG1zZyBvZiByZXNwb25zZS5NZXNzYWdlcykge1xuXHRcdFx0XHRcdC8vIFBhcnNlIFNOUyBtZXNzYWdlIHdyYXBwZXJcblx0XHRcdFx0XHRsZXQgc25zTWVzc2FnZTogYW55O1xuXHRcdFx0XHRcdGxldCBib2R5OiB1bmtub3duO1xuXG5cdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdHNuc01lc3NhZ2UgPSBKU09OLnBhcnNlKG1zZy5Cb2R5IHx8IFwie31cIik7XG5cdFx0XHRcdFx0XHQvLyBTTlMgd3JhcHMgdGhlIGFjdHVhbCBtZXNzYWdlIGluIGEgXCJNZXNzYWdlXCIgZmllbGRcblx0XHRcdFx0XHRcdGlmIChzbnNNZXNzYWdlLlR5cGUgPT09IFwiTm90aWZpY2F0aW9uXCIgJiYgc25zTWVzc2FnZS5NZXNzYWdlKSB7XG5cdFx0XHRcdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0XHRcdFx0Ym9keSA9IEpTT04ucGFyc2Uoc25zTWVzc2FnZS5NZXNzYWdlKTtcblx0XHRcdFx0XHRcdFx0fSBjYXRjaCB7XG5cdFx0XHRcdFx0XHRcdFx0Ym9keSA9IHNuc01lc3NhZ2UuTWVzc2FnZTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0Ym9keSA9IHNuc01lc3NhZ2U7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSBjYXRjaCB7XG5cdFx0XHRcdFx0XHRib2R5ID0gbXNnLkJvZHk7XG5cdFx0XHRcdFx0XHRzbnNNZXNzYWdlID0ge307XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gRXh0cmFjdCBhdHRyaWJ1dGVzIGZyb20gYm90aCBTUVMgYW5kIFNOU1xuXHRcdFx0XHRcdGNvbnN0IGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblxuXHRcdFx0XHRcdC8vIFNRUyBtZXNzYWdlIGF0dHJpYnV0ZXNcblx0XHRcdFx0XHRpZiAobXNnLk1lc3NhZ2VBdHRyaWJ1dGVzKSB7XG5cdFx0XHRcdFx0XHRmb3IgKGNvbnN0IFtrZXksIGF0dHJdIG9mIE9iamVjdC5lbnRyaWVzKG1zZy5NZXNzYWdlQXR0cmlidXRlcykpIHtcblx0XHRcdFx0XHRcdFx0YXR0cmlidXRlc1trZXldID0gKGF0dHIgYXMgYW55KS5TdHJpbmdWYWx1ZSB8fCBcIlwiO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIFNOUyBtZXNzYWdlIGF0dHJpYnV0ZXMgKGlmIHByZXNlbnQpXG5cdFx0XHRcdFx0aWYgKHNuc01lc3NhZ2UuTWVzc2FnZUF0dHJpYnV0ZXMpIHtcblx0XHRcdFx0XHRcdGZvciAoY29uc3QgW2tleSwgYXR0cl0gb2YgT2JqZWN0LmVudHJpZXMoc25zTWVzc2FnZS5NZXNzYWdlQXR0cmlidXRlcykpIHtcblx0XHRcdFx0XHRcdFx0YXR0cmlidXRlc1tgc25zXyR7a2V5fWBdID0gKGF0dHIgYXMgYW55KS5WYWx1ZSB8fCBcIlwiO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIENyZWF0ZSBwdWIvc3ViIG1lc3NhZ2Vcblx0XHRcdFx0XHRjb25zdCBwdWJzdWJNZXNzYWdlOiBQdWJTdWJNZXNzYWdlID0ge1xuXHRcdFx0XHRcdFx0aWQ6IHNuc01lc3NhZ2UuTWVzc2FnZUlkIHx8IG1zZy5NZXNzYWdlSWQgfHwgdXVpZCgpLFxuXHRcdFx0XHRcdFx0Ym9keSxcblx0XHRcdFx0XHRcdGF0dHJpYnV0ZXMsXG5cdFx0XHRcdFx0XHRyYXc6IG1zZyxcblx0XHRcdFx0XHRcdHRvcGljOiBzbnNNZXNzYWdlLlRvcGljQXJuIHx8IGNvbmZpZy50b3BpYyxcblx0XHRcdFx0XHRcdHN1YnNjcmlwdGlvbjogcXVldWVVcmwsXG5cdFx0XHRcdFx0XHRwdWJsaXNoVGltZTogc25zTWVzc2FnZS5UaW1lc3RhbXAgPyBuZXcgRGF0ZShzbnNNZXNzYWdlLlRpbWVzdGFtcCkgOiBuZXcgRGF0ZSgpLFxuXHRcdFx0XHRcdFx0YWNrOiBhc3luYyAoKSA9PiB7XG5cdFx0XHRcdFx0XHRcdGNvbnN0IGRlbGV0ZUNvbW1hbmQgPSBuZXcgRGVsZXRlTWVzc2FnZUNvbW1hbmQoe1xuXHRcdFx0XHRcdFx0XHRcdFF1ZXVlVXJsOiBxdWV1ZVVybCxcblx0XHRcdFx0XHRcdFx0XHRSZWNlaXB0SGFuZGxlOiBtc2cuUmVjZWlwdEhhbmRsZSxcblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMuc3FzQ2xpZW50LnNlbmQoZGVsZXRlQ29tbWFuZCk7XG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdFx0bmFjazogYXN5bmMgKCkgPT4ge1xuXHRcdFx0XHRcdFx0XHQvLyBMZXQgdGhlIHZpc2liaWxpdHkgdGltZW91dCBleHBpcmUgdG8gcmV0dXJuIHRoZSBtZXNzYWdlXG5cdFx0XHRcdFx0XHRcdC8vIE9yIGNoYW5nZSB2aXNpYmlsaXR5IHRvIDAgZm9yIGltbWVkaWF0ZSByZXRyeVxuXHRcdFx0XHRcdFx0XHRjb25zdCB7IENoYW5nZU1lc3NhZ2VWaXNpYmlsaXR5Q29tbWFuZCB9ID0gYXdhaXQgaW1wb3J0KFwiQGF3cy1zZGsvY2xpZW50LXNxc1wiKTtcblx0XHRcdFx0XHRcdFx0Y29uc3QgY2hhbmdlQ29tbWFuZCA9IG5ldyBDaGFuZ2VNZXNzYWdlVmlzaWJpbGl0eUNvbW1hbmQoe1xuXHRcdFx0XHRcdFx0XHRcdFF1ZXVlVXJsOiBxdWV1ZVVybCxcblx0XHRcdFx0XHRcdFx0XHRSZWNlaXB0SGFuZGxlOiBtc2cuUmVjZWlwdEhhbmRsZSxcblx0XHRcdFx0XHRcdFx0XHRWaXNpYmlsaXR5VGltZW91dDogMCxcblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHRcdGF3YWl0IHRoaXMuc3FzQ2xpZW50LnNlbmQoY2hhbmdlQ29tbWFuZCk7XG5cdFx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHQvLyBQcm9jZXNzIG1lc3NhZ2Vcblx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0YXdhaXQgaGFuZGxlcihwdWJzdWJNZXNzYWdlKTtcblx0XHRcdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRcdFx0Y29uc29sZS5lcnJvcihgW0FXU1NOU0FkYXB0ZXJdIEVycm9yIHByb2Nlc3NpbmcgbWVzc2FnZTogJHsoZXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2V9YCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSBjYXRjaCAoZXJyb3IpIHtcblx0XHRcdGNvbnNvbGUuZXJyb3IoYFtBV1NTTlNBZGFwdGVyXSBQb2xsaW5nIGVycm9yOiAkeyhlcnJvciBhcyBFcnJvcikubWVzc2FnZX1gKTtcblx0XHR9XG5cblx0XHQvLyBDb250aW51ZSBwb2xsaW5nIHVubGVzcyBzdG9wcGVkXG5cdFx0aWYgKCF0aGlzLnNob3VsZFN0b3ApIHtcblx0XHRcdGNvbnN0IHRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHRoaXMucG9sbChxdWV1ZVVybCwgY29uZmlnLCBoYW5kbGVyKSwgMCk7XG5cdFx0XHR0aGlzLnBvbGxpbmdJbnRlcnZhbHMuc2V0KHF1ZXVlVXJsLCB0aW1lb3V0KTtcblx0XHR9XG5cdH1cblxuXHQvKipcblx0ICogVW5zdWJzY3JpYmUgZnJvbSBhIHF1ZXVlIChzdG9wcyBwb2xsaW5nKVxuXHQgKi9cblx0YXN5bmMgdW5zdWJzY3JpYmUocXVldWVVcmw6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuXHRcdGNvbnN0IGludGVydmFsID0gdGhpcy5wb2xsaW5nSW50ZXJ2YWxzLmdldChxdWV1ZVVybCk7XG5cdFx0aWYgKGludGVydmFsKSB7XG5cdFx0XHRjbGVhclRpbWVvdXQoaW50ZXJ2YWwpO1xuXHRcdFx0dGhpcy5wb2xsaW5nSW50ZXJ2YWxzLmRlbGV0ZShxdWV1ZVVybCk7XG5cdFx0XHRjb25zb2xlLmxvZyhgW0FXU1NOU0FkYXB0ZXJdIFVuc3Vic2NyaWJlZCBmcm9tIHF1ZXVlOiAke3F1ZXVlVXJsfWApO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVjayBpZiBjb25uZWN0ZWQgdG8gQVdTXG5cdCAqL1xuXHRpc0Nvbm5lY3RlZCgpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy5jb25uZWN0ZWQ7XG5cdH1cblxuXHQvKipcblx0ICogSGVhbHRoIGNoZWNrIC0gdmVyaWZ5IEFXUyBjb25uZWN0aXZpdHlcblx0ICovXG5cdGFzeW5jIGhlYWx0aENoZWNrKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuXHRcdGlmICghdGhpcy5jb25uZWN0ZWQpIHJldHVybiBmYWxzZTtcblxuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCB7IExpc3RRdWV1ZXNDb21tYW5kIH0gPSBhd2FpdCBpbXBvcnQoXCJAYXdzLXNkay9jbGllbnQtc3FzXCIpO1xuXHRcdFx0Y29uc3QgY29tbWFuZCA9IG5ldyBMaXN0UXVldWVzQ29tbWFuZCh7IE1heFJlc3VsdHM6IDEgfSk7XG5cdFx0XHRhd2FpdCB0aGlzLnNxc0NsaWVudC5zZW5kKGNvbW1hbmQpO1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fSBjYXRjaCB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEFXU1NOU0FkYXB0ZXI7XG4iXX0=
@@ -0,0 +1,55 @@
1
+ /**
2
+ * AzureServiceBusAdapter - Azure Service Bus adapter for PubSubTrigger
3
+ *
4
+ * Uses @azure/service-bus for Azure Service Bus connectivity.
5
+ * Requires: npm install @azure/service-bus
6
+ *
7
+ * Environment variables:
8
+ * - AZURE_SERVICE_BUS_CONNECTION_STRING: Azure Service Bus connection string
9
+ * - AZURE_SERVICE_BUS_FULLY_QUALIFIED_NAMESPACE: Fully qualified namespace (if using DefaultAzureCredential)
10
+ */
11
+ import type { PubSubTriggerOpts } from "@blok/helper";
12
+ import type { PubSubAdapter, PubSubMessage } from "../PubSubTrigger";
13
+ /**
14
+ * Azure Service Bus configuration
15
+ */
16
+ export interface AzureServiceBusConfig {
17
+ connectionString?: string;
18
+ fullyQualifiedNamespace?: string;
19
+ }
20
+ /**
21
+ * AzureServiceBusAdapter - Azure Service Bus implementation
22
+ */
23
+ export declare class AzureServiceBusAdapter implements PubSubAdapter {
24
+ readonly provider: "azure";
25
+ private client;
26
+ private receivers;
27
+ private connected;
28
+ private config;
29
+ constructor(config?: AzureServiceBusConfig);
30
+ /**
31
+ * Connect to Azure Service Bus
32
+ */
33
+ connect(): Promise<void>;
34
+ /**
35
+ * Disconnect from Azure Service Bus
36
+ */
37
+ disconnect(): Promise<void>;
38
+ /**
39
+ * Subscribe to an Azure Service Bus topic/subscription or queue
40
+ */
41
+ subscribe(config: PubSubTriggerOpts, handler: (message: PubSubMessage) => Promise<void>): Promise<void>;
42
+ /**
43
+ * Unsubscribe from Azure Service Bus
44
+ */
45
+ unsubscribe(subscriptionKey: string): Promise<void>;
46
+ /**
47
+ * Check if connected to Azure Service Bus
48
+ */
49
+ isConnected(): boolean;
50
+ /**
51
+ * Health check - verify Azure Service Bus connectivity
52
+ */
53
+ healthCheck(): Promise<boolean>;
54
+ }
55
+ export default AzureServiceBusAdapter;
@@ -0,0 +1,229 @@
1
+ "use strict";
2
+ /**
3
+ * AzureServiceBusAdapter - Azure Service Bus adapter for PubSubTrigger
4
+ *
5
+ * Uses @azure/service-bus for Azure Service Bus connectivity.
6
+ * Requires: npm install @azure/service-bus
7
+ *
8
+ * Environment variables:
9
+ * - AZURE_SERVICE_BUS_CONNECTION_STRING: Azure Service Bus connection string
10
+ * - AZURE_SERVICE_BUS_FULLY_QUALIFIED_NAMESPACE: Fully qualified namespace (if using DefaultAzureCredential)
11
+ */
12
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ var desc = Object.getOwnPropertyDescriptor(m, k);
15
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
16
+ desc = { enumerable: true, get: function() { return m[k]; } };
17
+ }
18
+ Object.defineProperty(o, k2, desc);
19
+ }) : (function(o, m, k, k2) {
20
+ if (k2 === undefined) k2 = k;
21
+ o[k2] = m[k];
22
+ }));
23
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
24
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
25
+ }) : function(o, v) {
26
+ o["default"] = v;
27
+ });
28
+ var __importStar = (this && this.__importStar) || (function () {
29
+ var ownKeys = function(o) {
30
+ ownKeys = Object.getOwnPropertyNames || function (o) {
31
+ var ar = [];
32
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
33
+ return ar;
34
+ };
35
+ return ownKeys(o);
36
+ };
37
+ return function (mod) {
38
+ if (mod && mod.__esModule) return mod;
39
+ var result = {};
40
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
41
+ __setModuleDefault(result, mod);
42
+ return result;
43
+ };
44
+ })();
45
+ Object.defineProperty(exports, "__esModule", { value: true });
46
+ exports.AzureServiceBusAdapter = void 0;
47
+ const uuid_1 = require("uuid");
48
+ /**
49
+ * AzureServiceBusAdapter - Azure Service Bus implementation
50
+ */
51
+ class AzureServiceBusAdapter {
52
+ provider = "azure";
53
+ client;
54
+ receivers = new Map();
55
+ connected = false;
56
+ config;
57
+ constructor(config) {
58
+ this.config = {
59
+ connectionString: config?.connectionString || process.env.AZURE_SERVICE_BUS_CONNECTION_STRING,
60
+ fullyQualifiedNamespace: config?.fullyQualifiedNamespace || process.env.AZURE_SERVICE_BUS_FULLY_QUALIFIED_NAMESPACE,
61
+ };
62
+ }
63
+ /**
64
+ * Connect to Azure Service Bus
65
+ */
66
+ async connect() {
67
+ if (this.connected)
68
+ return;
69
+ try {
70
+ // Dynamic import of @azure/service-bus
71
+ const { ServiceBusClient } = await Promise.resolve().then(() => __importStar(require("@azure/service-bus")));
72
+ if (this.config.connectionString) {
73
+ this.client = new ServiceBusClient(this.config.connectionString);
74
+ }
75
+ else if (this.config.fullyQualifiedNamespace) {
76
+ // Would need @azure/identity for DefaultAzureCredential
77
+ throw new Error("Managed identity authentication requires @azure/identity package");
78
+ }
79
+ else {
80
+ throw new Error("Either connectionString or fullyQualifiedNamespace is required");
81
+ }
82
+ this.connected = true;
83
+ console.log("[AzureServiceBusAdapter] Connected to Azure Service Bus");
84
+ }
85
+ catch (error) {
86
+ throw new Error(`Failed to connect to Azure Service Bus: ${error.message}. ` +
87
+ `Make sure @azure/service-bus is installed: npm install @azure/service-bus`);
88
+ }
89
+ }
90
+ /**
91
+ * Disconnect from Azure Service Bus
92
+ */
93
+ async disconnect() {
94
+ if (!this.connected)
95
+ return;
96
+ try {
97
+ // Close all receivers
98
+ for (const [name, receiver] of this.receivers) {
99
+ await receiver.close();
100
+ }
101
+ this.receivers.clear();
102
+ await this.client.close();
103
+ this.connected = false;
104
+ console.log("[AzureServiceBusAdapter] Disconnected from Azure Service Bus");
105
+ }
106
+ catch (error) {
107
+ console.error(`[AzureServiceBusAdapter] Error disconnecting: ${error.message}`);
108
+ }
109
+ }
110
+ /**
111
+ * Subscribe to an Azure Service Bus topic/subscription or queue
112
+ */
113
+ async subscribe(config, handler) {
114
+ if (!this.connected) {
115
+ throw new Error("Not connected to Azure Service Bus. Call connect() first.");
116
+ }
117
+ let receiver;
118
+ // Determine if this is a topic subscription or a queue
119
+ if (config.subscription && config.topic) {
120
+ // Topic with subscription
121
+ receiver = this.client.createReceiver(config.topic, config.subscription, {
122
+ receiveMode: config.ack !== false ? "peekLock" : "receiveAndDelete",
123
+ });
124
+ }
125
+ else {
126
+ // Queue
127
+ receiver = this.client.createReceiver(config.subscription || config.topic, {
128
+ receiveMode: config.ack !== false ? "peekLock" : "receiveAndDelete",
129
+ });
130
+ }
131
+ const subscriptionKey = `${config.topic}/${config.subscription}`;
132
+ // Message handler
133
+ const processMessage = async (sbMessage) => {
134
+ // Parse message body
135
+ let body;
136
+ try {
137
+ if (typeof sbMessage.body === "string") {
138
+ body = JSON.parse(sbMessage.body);
139
+ }
140
+ else {
141
+ body = sbMessage.body;
142
+ }
143
+ }
144
+ catch {
145
+ body = sbMessage.body;
146
+ }
147
+ // Extract application properties as attributes
148
+ const attributes = {};
149
+ if (sbMessage.applicationProperties) {
150
+ for (const [key, value] of Object.entries(sbMessage.applicationProperties)) {
151
+ attributes[key] = String(value);
152
+ }
153
+ }
154
+ // Create pub/sub message
155
+ const pubsubMessage = {
156
+ id: sbMessage.messageId || (0, uuid_1.v4)(),
157
+ body,
158
+ attributes,
159
+ raw: sbMessage,
160
+ topic: config.topic,
161
+ subscription: config.subscription,
162
+ publishTime: sbMessage.enqueuedTimeUtc ? new Date(sbMessage.enqueuedTimeUtc) : new Date(),
163
+ ack: async () => {
164
+ await receiver.completeMessage(sbMessage);
165
+ },
166
+ nack: async () => {
167
+ await receiver.abandonMessage(sbMessage);
168
+ },
169
+ };
170
+ // Process message
171
+ try {
172
+ await handler(pubsubMessage);
173
+ }
174
+ catch (error) {
175
+ console.error(`[AzureServiceBusAdapter] Error processing message: ${error.message}`);
176
+ }
177
+ };
178
+ // Error handler
179
+ const processError = async (error) => {
180
+ console.error(`[AzureServiceBusAdapter] Error: ${error.message}`);
181
+ };
182
+ // Subscribe to messages
183
+ receiver.subscribe({
184
+ processMessage,
185
+ processError,
186
+ });
187
+ this.receivers.set(subscriptionKey, receiver);
188
+ console.log(`[AzureServiceBusAdapter] Subscribed to: ${subscriptionKey}`);
189
+ }
190
+ /**
191
+ * Unsubscribe from Azure Service Bus
192
+ */
193
+ async unsubscribe(subscriptionKey) {
194
+ const receiver = this.receivers.get(subscriptionKey);
195
+ if (receiver) {
196
+ await receiver.close();
197
+ this.receivers.delete(subscriptionKey);
198
+ console.log(`[AzureServiceBusAdapter] Unsubscribed from: ${subscriptionKey}`);
199
+ }
200
+ }
201
+ /**
202
+ * Check if connected to Azure Service Bus
203
+ */
204
+ isConnected() {
205
+ return this.connected;
206
+ }
207
+ /**
208
+ * Health check - verify Azure Service Bus connectivity
209
+ */
210
+ async healthCheck() {
211
+ if (!this.connected)
212
+ return false;
213
+ try {
214
+ // Create a temporary receiver to test connectivity
215
+ const testReceiver = this.client.createReceiver("$default", {
216
+ receiveMode: "peekLock",
217
+ });
218
+ await testReceiver.close();
219
+ return true;
220
+ }
221
+ catch {
222
+ // Queue might not exist but connection is healthy if we got here
223
+ return this.connected;
224
+ }
225
+ }
226
+ }
227
+ exports.AzureServiceBusAdapter = AzureServiceBusAdapter;
228
+ exports.default = AzureServiceBusAdapter;
229
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQXp1cmVTZXJ2aWNlQnVzQWRhcHRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hZGFwdGVycy9BenVyZVNlcnZpY2VCdXNBZGFwdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7O0dBU0c7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUdILCtCQUFrQztBQVdsQzs7R0FFRztBQUNILE1BQWEsc0JBQXNCO0lBQ3pCLFFBQVEsR0FBRyxPQUFnQixDQUFDO0lBRTdCLE1BQU0sQ0FBTTtJQUNaLFNBQVMsR0FBcUIsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUN4QyxTQUFTLEdBQUcsS0FBSyxDQUFDO0lBQ2xCLE1BQU0sQ0FBd0I7SUFFdEMsWUFBWSxNQUE4QjtRQUN6QyxJQUFJLENBQUMsTUFBTSxHQUFHO1lBQ2IsZ0JBQWdCLEVBQUUsTUFBTSxFQUFFLGdCQUFnQixJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUNBQW1DO1lBQzdGLHVCQUF1QixFQUN0QixNQUFNLEVBQUUsdUJBQXVCLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQywyQ0FBMkM7U0FDM0YsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxPQUFPO1FBQ1osSUFBSSxJQUFJLENBQUMsU0FBUztZQUFFLE9BQU87UUFFM0IsSUFBSSxDQUFDO1lBQ0osdUNBQXVDO1lBQ3ZDLE1BQU0sRUFBRSxnQkFBZ0IsRUFBRSxHQUFHLHdEQUFhLG9CQUFvQixHQUFDLENBQUM7WUFFaEUsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGdCQUFnQixFQUFFLENBQUM7Z0JBQ2xDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7WUFDbEUsQ0FBQztpQkFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztn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LENBQUMsV0FBVztRQUNoQixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVM7WUFBRSxPQUFPLEtBQUssQ0FBQztRQUVsQyxJQUFJLENBQUM7WUFDSixtREFBbUQ7WUFDbkQsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsVUFBVSxFQUFFO2dCQUMzRCxXQUFXLEVBQUUsVUFBVTthQUN2QixDQUFDLENBQUM7WUFDSCxNQUFNLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUMzQixPQUFPLElBQUksQ0FBQztRQUNiLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUixpRUFBaUU7WUFDakUsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDO1FBQ3ZCLENBQUM7SUFDRixDQUFDO0NBQ0Q7QUEvTEQsd0RBK0xDO0FBRUQsa0JBQWUsc0JBQXNCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEF6dXJlU2VydmljZUJ1c0FkYXB0ZXIgLSBBenVyZSBTZXJ2aWNlIEJ1cyBhZGFwdGVyIGZvciBQdWJTdWJUcmlnZ2VyXG4gKlxuICogVXNlcyBAYXp1cmUvc2VydmljZS1idXMgZm9yIEF6dXJlIFNlcnZpY2UgQnVzIGNvbm5lY3Rpdml0eS5cbiAqIFJlcXVpcmVzOiBucG0gaW5zdGFsbCBAYXp1cmUvc2VydmljZS1idXNcbiAqXG4gKiBFbnZpcm9ubWVudCB2YXJpYWJsZXM6XG4gKiAtIEFaVVJFX1NFUlZJQ0VfQlVTX0NPTk5FQ1RJT05fU1RSSU5HOiBBenVyZSBTZXJ2aWNlIEJ1cyBjb25uZWN0aW9uIHN0cmluZ1xuICogLSBBWlVSRV9TRVJWSUNFX0JVU19GVUxMWV9RVUFMSUZJRURfTkFNRVNQQUNFOiBGdWxseSBxdWFsaWZpZWQgbmFtZXNwYWNlIChpZiB1c2luZyBEZWZhdWx0QXp1cmVDcmVkZW50aWFsKVxuICovXG5cbmltcG9ydCB0eXBlIHsgUHViU3ViVHJpZ2dlck9wdHMgfSBmcm9tIFwiQGJsb2svaGVscGVyXCI7XG5pbXBvcnQgeyB2NCBhcyB1dWlkIH0gZnJvbSBcInV1aWRcIjtcbmltcG9ydCB0eXBlIHsgUHViU3ViQWRhcHRlciwgUHViU3ViTWVzc2FnZSB9IGZyb20gXCIuLi9QdWJTdWJUcmlnZ2VyXCI7XG5cbi8qKlxuICogQXp1cmUgU2VydmljZSBCdXMgY29uZmlndXJhdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIEF6dXJlU2VydmljZUJ1c0NvbmZpZyB7XG5cdGNvbm5lY3Rpb25TdHJpbmc/OiBzdHJpbmc7XG5cdGZ1bGx5UXVhbGlmaWVkTmFtZXNwYWNlPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEF6dXJlU2VydmljZUJ1c0FkYXB0ZXIgLSBBenVyZSBTZXJ2aWNlIEJ1cyBpbXBsZW1lbnRhdGlvblxuICovXG5leHBvcnQgY2xhc3MgQXp1cmVTZXJ2aWNlQnVzQWRhcHRlciBpbXBsZW1lbnRzIFB1YlN1YkFkYXB0ZXIge1xuXHRyZWFkb25seSBwcm92aWRlciA9IFwiYXp1cmVcIiBhcyBjb25zdDtcblxuXHRwcml2YXRlIGNsaWVudDogYW55O1xuXHRwcml2YXRlIHJlY2VpdmVyczogTWFwPHN0cmluZywgYW55PiA9IG5ldyBNYXAoKTtcblx0cHJpdmF0ZSBjb25uZWN0ZWQgPSBmYWxzZTtcblx0cHJpdmF0ZSBjb25maWc6IEF6dXJlU2VydmljZUJ1c0NvbmZpZztcblxuXHRjb25zdHJ1Y3Rvcihjb25maWc/OiBBenVyZVNlcnZpY2VCdXNDb25maWcpIHtcblx0XHR0aGlzLmNvbmZpZyA9IHtcblx0XHRcdGNvbm5lY3Rpb25TdHJpbmc6IGNvbmZpZz8uY29ubmVjdGlvblN0cmluZyB8fCBwcm9jZXNzLmVudi5BWlVSRV9TRVJWSUNFX0JVU19DT05ORUNUSU9OX1NUUklORyxcblx0XHRcdGZ1bGx5UXVhbGlmaWVkTmFtZXNwYWNlOlxuXHRcdFx0XHRjb25maWc/LmZ1bGx5UXVhbGlmaWVkTmFtZXNwYWNlIHx8IHByb2Nlc3MuZW52LkFaVVJFX1NFUlZJQ0VfQlVTX0ZVTExZX1FVQUxJRklFRF9OQU1FU1BBQ0UsXG5cdFx0fTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb25uZWN0IHRvIEF6dXJlIFNlcnZpY2UgQnVzXG5cdCAqL1xuXHRhc3luYyBjb25uZWN0KCk6IFByb21pc2U8dm9pZD4ge1xuXHRcdGlmICh0aGlzLmNvbm5lY3RlZCkgcmV0dXJuO1xuXG5cdFx0dHJ5IHtcblx0XHRcdC8vIER5bmFtaWMgaW1wb3J0IG9mIEBhenVyZS9zZXJ2aWNlLWJ1c1xuXHRcdFx0Y29uc3QgeyBTZXJ2aWNlQnVzQ2xpZW50IH0gPSBhd2FpdCBpbXBvcnQoXCJAYXp1cmUvc2VydmljZS1idXNcIik7XG5cblx0XHRcdGlmICh0aGlzLmNvbmZpZy5jb25uZWN0aW9uU3RyaW5nKSB7XG5cdFx0XHRcdHRoaXMuY2xpZW50ID0gbmV3IFNlcnZpY2VCdXNDbGllbnQodGhpcy5jb25maWcuY29ubmVjdGlvblN0cmluZyk7XG5cdFx0XHR9IGVsc2UgaWYgKHRoaXMuY29uZmlnLmZ1bGx5UXVhbGlmaWVkTmFtZXNwYWNlKSB7XG5cdFx0XHRcdC8vIFdvdWxkIG5lZWQgQGF6dXJlL2lkZW50aXR5IGZvciBEZWZhdWx0QXp1cmVDcmVkZW50aWFsXG5cdFx0XHRcdHRocm93IG5ldyBFcnJvcihcIk1hbmFnZWQgaWRlbnRpdHkgYXV0aGVudGljYXRpb24gcmVxdWlyZXMgQGF6dXJlL2lkZW50aXR5IHBhY2thZ2VcIik7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJFaXRoZXIgY29ubmVjdGlvblN0cmluZyBvciBmdWxseVF1YWxpZmllZE5hbWVzcGFjZSBpcyByZXF1aXJlZFwiKTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5jb25uZWN0ZWQgPSB0cnVlO1xuXHRcdFx0Y29uc29sZS5sb2coXCJbQXp1cmVTZXJ2aWNlQnVzQWRhcHRlcl0gQ29ubmVjdGVkIHRvIEF6dXJlIFNlcnZpY2UgQnVzXCIpO1xuXHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXG5cdFx0XHRcdGBGYWlsZWQgdG8gY29ubmVjdCB0byBBenVyZSBTZXJ2aWNlIEJ1czogJHsoZXJyb3IgYXMgRXJyb3IpLm1lc3NhZ2V9LiBgICtcblx0XHRcdFx0XHRgTWFrZSBzdXJlIEBhenVyZS9zZXJ2aWNlLWJ1cyBpcyBpbnN0YWxsZWQ6IG5wbSBpbnN0YWxsIEBhenVyZS9zZXJ2aWNlLWJ1c2AsXG5cdFx0XHQpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBEaXNjb25uZWN0IGZyb20gQXp1cmUgU2VydmljZSBCdXNcblx0ICovXG5cdGFzeW5jIGRpc2Nvbm5lY3QoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0aWYgKCF0aGlzLmNvbm5lY3RlZCkgcmV0dXJuO1xuXG5cdFx0dHJ5IHtcblx0XHRcdC8vIENsb3NlIGFsbCByZWNlaXZlcnNcblx0XHRcdGZvciAoY29uc3QgW25hbWUsIHJlY2VpdmVyXSBvZiB0aGlzLnJlY2VpdmVycykge1xuXHRcdFx0XHRhd2FpdCByZWNlaXZlci5jbG9zZSgpO1xuXHRcdFx0fVxuXHRcdFx0dGhpcy5yZWNlaXZlcnMuY2xlYXIoKTtcblxuXHRcdFx0YXdhaXQgdGhpcy5jbGllbnQuY2xvc2UoKTtcblx0XHRcdHRoaXMuY29ubmVjdGVkID0gZmFsc2U7XG5cdFx0XHRjb25zb2xlLmxvZyhcIltBenVyZVNlcnZpY2VCdXNBZGFwdGVyXSBEaXNjb25uZWN0ZWQgZnJvbSBBenVyZSBTZXJ2aWNlIEJ1c1wiKTtcblx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0Y29uc29sZS5lcnJvcihgW0F6dXJlU2VydmljZUJ1c0FkYXB0ZXJdIEVycm9yIGRpc2Nvbm5lY3Rpbmc6ICR7KGVycm9yIGFzIEVycm9yKS5tZXNzYWdlfWApO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBTdWJzY3JpYmUgdG8gYW4gQXp1cmUgU2VydmljZSBCdXMgdG9waWMvc3Vic2NyaXB0aW9uIG9yIHF1ZXVlXG5cdCAqL1xuXHRhc3luYyBzdWJzY3JpYmUoY29uZmlnOiBQdWJTdWJUcmlnZ2VyT3B0cywgaGFuZGxlcjogKG1lc3NhZ2U6IFB1YlN1Yk1lc3NhZ2UpID0+IFByb21pc2U8dm9pZD4pOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRpZiAoIXRoaXMuY29ubmVjdGVkKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJOb3QgY29ubmVjdGVkIHRvIEF6dXJlIFNlcnZpY2UgQnVzLiBDYWxsIGNvbm5lY3QoKSBmaXJzdC5cIik7XG5cdFx0fVxuXG5cdFx0bGV0IHJlY2VpdmVyOiBhbnk7XG5cblx0XHQvLyBEZXRlcm1pbmUgaWYgdGhpcyBpcyBhIHRvcGljIHN1YnNjcmlwdGlvbiBvciBhIHF1ZXVlXG5cdFx0aWYgKGNvbmZpZy5zdWJzY3JpcHRpb24gJiYgY29uZmlnLnRvcGljKSB7XG5cdFx0XHQvLyBUb3BpYyB3aXRoIHN1YnNjcmlwdGlvblxuXHRcdFx0cmVjZWl2ZXIgPSB0aGlzLmNsaWVudC5jcmVhdGVSZWNlaXZlcihjb25maWcudG9waWMsIGNvbmZpZy5zdWJzY3JpcHRpb24sIHtcblx0XHRcdFx0cmVjZWl2ZU1vZGU6IGNvbmZpZy5hY2sgIT09IGZhbHNlID8gXCJwZWVrTG9ja1wiIDogXCJyZWNlaXZlQW5kRGVsZXRlXCIsXG5cdFx0XHR9KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gUXVldWVcblx0XHRcdHJlY2VpdmVyID0gdGhpcy5jbGllbnQuY3JlYXRlUmVjZWl2ZXIoY29uZmlnLnN1YnNjcmlwdGlvbiB8fCBjb25maWcudG9waWMsIHtcblx0XHRcdFx0cmVjZWl2ZU1vZGU6IGNvbmZpZy5hY2sgIT09IGZhbHNlID8gXCJwZWVrTG9ja1wiIDogXCJyZWNlaXZlQW5kRGVsZXRlXCIsXG5cdFx0XHR9KTtcblx0XHR9XG5cblx0XHRjb25zdCBzdWJzY3JpcHRpb25LZXkgPSBgJHtjb25maWcudG9waWN9LyR7Y29uZmlnLnN1YnNjcmlwdGlvbn1gO1xuXG5cdFx0Ly8gTWVzc2FnZSBoYW5kbGVyXG5cdFx0Y29uc3QgcHJvY2Vzc01lc3NhZ2UgPSBhc3luYyAoc2JNZXNzYWdlOiBhbnkpID0+IHtcblx0XHRcdC8vIFBhcnNlIG1lc3NhZ2UgYm9keVxuXHRcdFx0bGV0IGJvZHk6IHVua25vd247XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRpZiAodHlwZW9mIHNiTWVzc2FnZS5ib2R5ID09PSBcInN0cmluZ1wiKSB7XG5cdFx0XHRcdFx0Ym9keSA9IEpTT04ucGFyc2Uoc2JNZXNzYWdlLmJvZHkpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGJvZHkgPSBzYk1lc3NhZ2UuYm9keTtcblx0XHRcdFx0fVxuXHRcdFx0fSBjYXRjaCB7XG5cdFx0XHRcdGJvZHkgPSBzYk1lc3NhZ2UuYm9keTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gRXh0cmFjdCBhcHBsaWNhdGlvbiBwcm9wZXJ0aWVzIGFzIGF0dHJpYnV0ZXNcblx0XHRcdGNvbnN0IGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblx0XHRcdGlmIChzYk1lc3NhZ2UuYXBwbGljYXRpb25Qcm9wZXJ0aWVzKSB7XG5cdFx0XHRcdGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHNiTWVzc2FnZS5hcHBsaWNhdGlvblByb3BlcnRpZXMpKSB7XG5cdFx0XHRcdFx0YXR0cmlidXRlc1trZXldID0gU3RyaW5nKHZhbHVlKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBDcmVhdGUgcHViL3N1YiBtZXNzYWdlXG5cdFx0XHRjb25zdCBwdWJzdWJNZXNzYWdlOiBQdWJTdWJNZXNzYWdlID0ge1xuXHRcdFx0XHRpZDogc2JNZXNzYWdlLm1lc3NhZ2VJZCB8fCB1dWlkKCksXG5cdFx0XHRcdGJvZHksXG5cdFx0XHRcdGF0dHJpYnV0ZXMsXG5cdFx0XHRcdHJhdzogc2JNZXNzYWdlLFxuXHRcdFx0XHR0b3BpYzogY29uZmlnLnRvcGljLFxuXHRcdFx0XHRzdWJzY3JpcHRpb246IGNvbmZpZy5zdWJzY3JpcHRpb24sXG5cdFx0XHRcdHB1Ymxpc2hUaW1lOiBzYk1lc3NhZ2UuZW5xdWV1ZWRUaW1lVXRjID8gbmV3IERhdGUoc2JNZXNzYWdlLmVucXVldWVkVGltZVV0YykgOiBuZXcgRGF0ZSgpLFxuXHRcdFx0XHRhY2s6IGFzeW5jICgpID0+IHtcblx0XHRcdFx0XHRhd2FpdCByZWNlaXZlci5jb21wbGV0ZU1lc3NhZ2Uoc2JNZXNzYWdlKTtcblx0XHRcdFx0fSxcblx0XHRcdFx0bmFjazogYXN5bmMgKCkgPT4ge1xuXHRcdFx0XHRcdGF3YWl0IHJlY2VpdmVyLmFiYW5kb25NZXNzYWdlKHNiTWVzc2FnZSk7XG5cdFx0XHRcdH0sXG5cdFx0XHR9O1xuXG5cdFx0XHQvLyBQcm9jZXNzIG1lc3NhZ2Vcblx0XHRcdHRyeSB7XG5cdFx0XHRcdGF3YWl0IGhhbmRsZXIocHVic3ViTWVzc2FnZSk7XG5cdFx0XHR9IGNhdGNoIChlcnJvcikge1xuXHRcdFx0XHRjb25zb2xlLmVycm9yKGBbQXp1cmVTZXJ2aWNlQnVzQWRhcHRlcl0gRXJyb3IgcHJvY2Vzc2luZyBtZXNzYWdlOiAkeyhlcnJvciBhcyBFcnJvcikubWVzc2FnZX1gKTtcblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0Ly8gRXJyb3IgaGFuZGxlclxuXHRcdGNvbnN0IHByb2Nlc3NFcnJvciA9IGFzeW5jIChlcnJvcjogRXJyb3IpID0+IHtcblx0XHRcdGNvbnNvbGUuZXJyb3IoYFtBenVyZVNlcnZpY2VCdXNBZGFwdGVyXSBFcnJvcjogJHtlcnJvci5tZXNzYWdlfWApO1xuXHRcdH07XG5cblx0XHQvLyBTdWJzY3JpYmUgdG8gbWVzc2FnZXNcblx0XHRyZWNlaXZlci5zdWJzY3JpYmUoe1xuXHRcdFx0cHJvY2Vzc01lc3NhZ2UsXG5cdFx0XHRwcm9jZXNzRXJyb3IsXG5cdFx0fSk7XG5cblx0XHR0aGlzLnJlY2VpdmVycy5zZXQoc3Vic2NyaXB0aW9uS2V5LCByZWNlaXZlcik7XG5cblx0XHRjb25zb2xlLmxvZyhgW0F6dXJlU2VydmljZUJ1c0FkYXB0ZXJdIFN1YnNjcmliZWQgdG86ICR7c3Vic2NyaXB0aW9uS2V5fWApO1xuXHR9XG5cblx0LyoqXG5cdCAqIFVuc3Vic2NyaWJlIGZyb20gQXp1cmUgU2VydmljZSBCdXNcblx0ICovXG5cdGFzeW5jIHVuc3Vic2NyaWJlKHN1YnNjcmlwdGlvbktleTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0Y29uc3QgcmVjZWl2ZXIgPSB0aGlzLnJlY2VpdmVycy5nZXQoc3Vic2NyaXB0aW9uS2V5KTtcblx0XHRpZiAocmVjZWl2ZXIpIHtcblx0XHRcdGF3YWl0IHJlY2VpdmVyLmNsb3NlKCk7XG5cdFx0XHR0aGlzLnJlY2VpdmVycy5kZWxldGUoc3Vic2NyaXB0aW9uS2V5KTtcblx0XHRcdGNvbnNvbGUubG9nKGBbQXp1cmVTZXJ2aWNlQnVzQWRhcHRlcl0gVW5zdWJzY3JpYmVkIGZyb206ICR7c3Vic2NyaXB0aW9uS2V5fWApO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBDaGVjayBpZiBjb25uZWN0ZWQgdG8gQXp1cmUgU2VydmljZSBCdXNcblx0ICovXG5cdGlzQ29ubmVjdGVkKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiB0aGlzLmNvbm5lY3RlZDtcblx0fVxuXG5cdC8qKlxuXHQgKiBIZWFsdGggY2hlY2sgLSB2ZXJpZnkgQXp1cmUgU2VydmljZSBCdXMgY29ubmVjdGl2aXR5XG5cdCAqL1xuXHRhc3luYyBoZWFsdGhDaGVjaygpOiBQcm9taXNlPGJvb2xlYW4+IHtcblx0XHRpZiAoIXRoaXMuY29ubmVjdGVkKSByZXR1cm4gZmFsc2U7XG5cblx0XHR0cnkge1xuXHRcdFx0Ly8gQ3JlYXRlIGEgdGVtcG9yYXJ5IHJlY2VpdmVyIHRvIHRlc3QgY29ubmVjdGl2aXR5XG5cdFx0XHRjb25zdCB0ZXN0UmVjZWl2ZXIgPSB0aGlzLmNsaWVudC5jcmVhdGVSZWNlaXZlcihcIiRkZWZhdWx0XCIsIHtcblx0XHRcdFx0cmVjZWl2ZU1vZGU6IFwicGVla0xvY2tcIixcblx0XHRcdH0pO1xuXHRcdFx0YXdhaXQgdGVzdFJlY2VpdmVyLmNsb3NlKCk7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9IGNhdGNoIHtcblx0XHRcdC8vIFF1ZXVlIG1pZ2h0IG5vdCBleGlzdCBidXQgY29ubmVjdGlvbiBpcyBoZWFsdGh5IGlmIHdlIGdvdCBoZXJlXG5cdFx0XHRyZXR1cm4gdGhpcy5jb25uZWN0ZWQ7XG5cdFx0fVxuXHR9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEF6dXJlU2VydmljZUJ1c0FkYXB0ZXI7XG4iXX0=
@@ -0,0 +1,59 @@
1
+ /**
2
+ * GCPPubSubAdapter - Google Cloud Pub/Sub adapter for PubSubTrigger
3
+ *
4
+ * Uses @google-cloud/pubsub for GCP Pub/Sub connectivity.
5
+ * Requires: npm install @google-cloud/pubsub
6
+ *
7
+ * Environment variables:
8
+ * - GOOGLE_CLOUD_PROJECT: GCP project ID
9
+ * - GOOGLE_APPLICATION_CREDENTIALS: Path to service account key file (optional if using default credentials)
10
+ * - PUBSUB_EMULATOR_HOST: Pub/Sub emulator host for local development (optional)
11
+ */
12
+ import type { PubSubTriggerOpts } from "@blok/helper";
13
+ import type { PubSubAdapter, PubSubMessage } from "../PubSubTrigger";
14
+ /**
15
+ * GCP Pub/Sub configuration
16
+ */
17
+ export interface GCPPubSubConfig {
18
+ projectId?: string;
19
+ credentials?: {
20
+ client_email: string;
21
+ private_key: string;
22
+ };
23
+ }
24
+ /**
25
+ * GCPPubSubAdapter - Google Cloud Pub/Sub implementation
26
+ */
27
+ export declare class GCPPubSubAdapter implements PubSubAdapter {
28
+ readonly provider: "gcp";
29
+ private client;
30
+ private subscriptions;
31
+ private connected;
32
+ private config;
33
+ constructor(config?: GCPPubSubConfig);
34
+ /**
35
+ * Connect to GCP Pub/Sub
36
+ */
37
+ connect(): Promise<void>;
38
+ /**
39
+ * Disconnect from GCP Pub/Sub
40
+ */
41
+ disconnect(): Promise<void>;
42
+ /**
43
+ * Subscribe to a GCP Pub/Sub topic
44
+ */
45
+ subscribe(config: PubSubTriggerOpts, handler: (message: PubSubMessage) => Promise<void>): Promise<void>;
46
+ /**
47
+ * Unsubscribe from a GCP Pub/Sub subscription
48
+ */
49
+ unsubscribe(subscriptionName: string): Promise<void>;
50
+ /**
51
+ * Check if connected to GCP Pub/Sub
52
+ */
53
+ isConnected(): boolean;
54
+ /**
55
+ * Health check - verify GCP Pub/Sub connectivity
56
+ */
57
+ healthCheck(): Promise<boolean>;
58
+ }
59
+ export default GCPPubSubAdapter;