@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.
- package/CHANGELOG.md +22 -0
- package/dist/PubSubTrigger.d.ts +116 -0
- package/dist/PubSubTrigger.js +219 -0
- package/dist/adapters/AWSSNSAdapter.d.ts +67 -0
- package/dist/adapters/AWSSNSAdapter.js +257 -0
- package/dist/adapters/AzureServiceBusAdapter.d.ts +55 -0
- package/dist/adapters/AzureServiceBusAdapter.js +229 -0
- package/dist/adapters/GCPPubSubAdapter.d.ts +59 -0
- package/dist/adapters/GCPPubSubAdapter.js +201 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +64 -0
- package/package.json +53 -0
- package/src/PubSubTrigger.test.ts +151 -0
- package/src/PubSubTrigger.ts +337 -0
- package/src/adapters/AWSSNSAdapter.ts +258 -0
- package/src/adapters/AzureServiceBusAdapter.ts +220 -0
- package/src/adapters/GCPPubSubAdapter.ts +196 -0
- package/src/index.ts +68 -0
- package/template/.env.example +8 -0
- package/template/package.json +44 -0
- package/template/src/Nodes.ts +10 -0
- package/template/src/Workflows.ts +8 -0
- package/template/src/index.ts +41 -0
- package/template/src/runner/PubSubServer.ts +39 -0
- package/template/src/runner/types/Workflows.ts +7 -0
- package/template/src/workflows/messages/on-message.ts +44 -0
- package/template/tsconfig.json +31 -0
- package/template/vitest.config.ts +39 -0
- package/tsconfig.json +32 -0
|
@@ -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;
|