@adobe-commerce/aio-toolkit 1.2.2 → 1.2.3
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 +55 -0
- package/README.md +101 -0
- package/dist/index.d.mts +45 -1
- package/dist/index.d.ts +45 -1
- package/dist/index.js +188 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +187 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -1
package/dist/index.mjs
CHANGED
|
@@ -5877,11 +5877,15 @@ var _AbdbCollection = class _AbdbCollection {
|
|
|
5877
5877
|
const collection = await client.collection(this._name);
|
|
5878
5878
|
return await callback(collection, client);
|
|
5879
5879
|
} catch (error) {
|
|
5880
|
-
if (error instanceof DbError) {
|
|
5881
|
-
|
|
5880
|
+
if (DbError && error instanceof DbError) {
|
|
5881
|
+
const dbErr = new Error(`AbdbCollection: database error: ${error.message}`);
|
|
5882
|
+
dbErr.cause = error;
|
|
5883
|
+
throw dbErr;
|
|
5882
5884
|
}
|
|
5883
5885
|
const detail = error instanceof Error ? error.message : String(error);
|
|
5884
|
-
|
|
5886
|
+
const unexpectedErr = new Error(`AbdbCollection: unexpected error: ${detail}`);
|
|
5887
|
+
unexpectedErr.cause = error;
|
|
5888
|
+
throw unexpectedErr;
|
|
5885
5889
|
} finally {
|
|
5886
5890
|
await client?.close();
|
|
5887
5891
|
}
|
|
@@ -11694,6 +11698,185 @@ __name(_OnboardCommerce, "OnboardCommerce");
|
|
|
11694
11698
|
var OnboardCommerce = _OnboardCommerce;
|
|
11695
11699
|
var onboard_commerce_default = OnboardCommerce;
|
|
11696
11700
|
|
|
11701
|
+
// src/integration/rabbit-mq-client/index.ts
|
|
11702
|
+
import amqplib from "amqplib";
|
|
11703
|
+
var _RabbitMQClient = class _RabbitMQClient {
|
|
11704
|
+
/**
|
|
11705
|
+
* @param credentials - AMQP connection credentials (host, port, username, password, vhost).
|
|
11706
|
+
*/
|
|
11707
|
+
constructor(credentials) {
|
|
11708
|
+
this.credentials = credentials;
|
|
11709
|
+
}
|
|
11710
|
+
/**
|
|
11711
|
+
* Opens an AMQP connection, checks queue depth, sets prefetch for concurrency control,
|
|
11712
|
+
* and starts a push consumer. The broker delivers at most `maxParallel` unacked messages
|
|
11713
|
+
* at a time, so processing concurrency is naturally bounded without a separate semaphore.
|
|
11714
|
+
* The consumer is cancelled once `effectiveBatch = min(batchSize, messageCount)` messages
|
|
11715
|
+
* are received and processed. The connection is always closed in a `finally` block.
|
|
11716
|
+
*
|
|
11717
|
+
* @param queueName - Name of the queue to consume from.
|
|
11718
|
+
* @param options - Consume configuration (batchSize, maxParallel, nackRequeue, exchange).
|
|
11719
|
+
* @param handler - Callback invoked with the queue name and decoded string content of each message.
|
|
11720
|
+
* @returns Counts of consumed, acked, and nacked messages; plus per-failure details in `errors`.
|
|
11721
|
+
* @throws Propagates connection, exchange-assertion, or queue-assertion errors to the caller.
|
|
11722
|
+
*/
|
|
11723
|
+
async consume(queueName, options, handler) {
|
|
11724
|
+
const connection = await amqplib.connect(this.buildConnectionUrl());
|
|
11725
|
+
let channel;
|
|
11726
|
+
try {
|
|
11727
|
+
channel = await connection.createChannel();
|
|
11728
|
+
if (options.exchange) {
|
|
11729
|
+
await channel.assertExchange(options.exchange, "direct", { durable: true });
|
|
11730
|
+
await channel.assertQueue(queueName, { durable: true });
|
|
11731
|
+
await channel.bindQueue(queueName, options.exchange, queueName);
|
|
11732
|
+
} else {
|
|
11733
|
+
await channel.assertQueue(queueName, { durable: true });
|
|
11734
|
+
}
|
|
11735
|
+
return await this.processBatch(channel, queueName, options, handler);
|
|
11736
|
+
} finally {
|
|
11737
|
+
await channel?.close();
|
|
11738
|
+
await connection.close();
|
|
11739
|
+
}
|
|
11740
|
+
}
|
|
11741
|
+
/**
|
|
11742
|
+
* Opens an AMQP connection, asserts the queue, and enqueues each payload in `payloads`.
|
|
11743
|
+
* Each payload is sent as a persistent message via `sendToQueue`. If the write buffer is
|
|
11744
|
+
* full (`sendToQueue` returns `false`) or the call throws, the payload is recorded in
|
|
11745
|
+
* `stats.errors` and counted as failed. The connection is always closed in a `finally`
|
|
11746
|
+
* block regardless of outcome.
|
|
11747
|
+
*
|
|
11748
|
+
* @param queueName - Name of the queue to publish to.
|
|
11749
|
+
* @param payloads - Array of string payloads to enqueue.
|
|
11750
|
+
* @returns Counts of published and failed messages; plus per-failure details in `errors`.
|
|
11751
|
+
* @throws Propagates connection or queue-assertion errors to the caller.
|
|
11752
|
+
*/
|
|
11753
|
+
async publish(queueName, payloads) {
|
|
11754
|
+
const connection = await amqplib.connect(this.buildConnectionUrl());
|
|
11755
|
+
let channel;
|
|
11756
|
+
try {
|
|
11757
|
+
channel = await connection.createChannel();
|
|
11758
|
+
await channel.assertQueue(queueName, { durable: true });
|
|
11759
|
+
return this.publishBatch(channel, queueName, payloads);
|
|
11760
|
+
} finally {
|
|
11761
|
+
await channel?.close();
|
|
11762
|
+
await connection.close();
|
|
11763
|
+
}
|
|
11764
|
+
}
|
|
11765
|
+
/**
|
|
11766
|
+
* Sends each payload to the queue via `sendToQueue`. Tracks published and failed counts.
|
|
11767
|
+
* A payload is considered failed when `sendToQueue` returns `false` (write buffer full)
|
|
11768
|
+
* or throws an error.
|
|
11769
|
+
*/
|
|
11770
|
+
publishBatch(channel, queueName, payloads) {
|
|
11771
|
+
const stats = { published: 0, failed: 0, errors: [] };
|
|
11772
|
+
for (const payload of payloads) {
|
|
11773
|
+
try {
|
|
11774
|
+
const sent = channel.sendToQueue(queueName, Buffer.from(payload), { persistent: true });
|
|
11775
|
+
if (sent) {
|
|
11776
|
+
stats.published++;
|
|
11777
|
+
} else {
|
|
11778
|
+
stats.failed++;
|
|
11779
|
+
stats.errors.push({ payload, error: new Error("Write buffer full") });
|
|
11780
|
+
}
|
|
11781
|
+
} catch (error) {
|
|
11782
|
+
stats.failed++;
|
|
11783
|
+
stats.errors.push({ payload, error });
|
|
11784
|
+
}
|
|
11785
|
+
}
|
|
11786
|
+
return stats;
|
|
11787
|
+
}
|
|
11788
|
+
/**
|
|
11789
|
+
* Builds the AMQP connection URL from the stored credentials.
|
|
11790
|
+
* Uses `amqps://` when `secure` is true, `amqp://` otherwise.
|
|
11791
|
+
* Username, password, and vhost are percent-encoded to handle special characters.
|
|
11792
|
+
*/
|
|
11793
|
+
buildConnectionUrl() {
|
|
11794
|
+
const { host, port, username, password, vhost, secure = false } = this.credentials;
|
|
11795
|
+
const protocol = secure ? "amqps" : "amqp";
|
|
11796
|
+
return `${protocol}://${encodeURIComponent(username)}:${encodeURIComponent(password)}@${host}:${port}/${encodeURIComponent(vhost)}`;
|
|
11797
|
+
}
|
|
11798
|
+
/**
|
|
11799
|
+
* Checks queue depth via `channel.checkQueue`, then sets `channel.prefetch(maxParallel)`
|
|
11800
|
+
* for broker-side concurrency control. Registers a push consumer that receives
|
|
11801
|
+
* `effectiveBatch = min(batchSize, messageCount)` messages. The Promise resolves after
|
|
11802
|
+
* `channel.consume` setup completes and all in-flight handlers have settled.
|
|
11803
|
+
*
|
|
11804
|
+
* Because the broker delivers at most `maxParallel` unacked messages at a time, processing
|
|
11805
|
+
* concurrency is bounded without a separate semaphore — each ack/nack releases a slot.
|
|
11806
|
+
*/
|
|
11807
|
+
async processBatch(channel, queueName, options, handler) {
|
|
11808
|
+
const stats = { consumed: 0, acked: 0, nacked: 0, errors: [] };
|
|
11809
|
+
const maxParallel = Math.floor(options.maxParallel);
|
|
11810
|
+
const batchSize = Math.floor(options.batchSize);
|
|
11811
|
+
const { messageCount } = await channel.checkQueue(queueName);
|
|
11812
|
+
if (messageCount === 0) return stats;
|
|
11813
|
+
const effectiveBatch = Math.min(batchSize, messageCount);
|
|
11814
|
+
await channel.prefetch(maxParallel);
|
|
11815
|
+
return new Promise((resolve, reject) => {
|
|
11816
|
+
let consumerTag = "";
|
|
11817
|
+
let cancelRequested = false;
|
|
11818
|
+
let received = 0;
|
|
11819
|
+
let pending = 0;
|
|
11820
|
+
let setupDone = false;
|
|
11821
|
+
const maybeResolve = /* @__PURE__ */ __name(() => {
|
|
11822
|
+
if ((received >= effectiveBatch || cancelRequested) && pending === 0 && setupDone) {
|
|
11823
|
+
resolve(stats);
|
|
11824
|
+
}
|
|
11825
|
+
}, "maybeResolve");
|
|
11826
|
+
const msgCallback = /* @__PURE__ */ __name(async (msg) => {
|
|
11827
|
+
if (!msg || received >= effectiveBatch) return;
|
|
11828
|
+
received++;
|
|
11829
|
+
stats.consumed++;
|
|
11830
|
+
pending++;
|
|
11831
|
+
if (received >= effectiveBatch) {
|
|
11832
|
+
cancelRequested = true;
|
|
11833
|
+
if (consumerTag) {
|
|
11834
|
+
channel.cancel(consumerTag).catch(reject);
|
|
11835
|
+
}
|
|
11836
|
+
}
|
|
11837
|
+
await this.processMessage(channel, queueName, msg, stats, options, handler);
|
|
11838
|
+
pending--;
|
|
11839
|
+
maybeResolve();
|
|
11840
|
+
}, "msgCallback");
|
|
11841
|
+
channel.consume(queueName, msgCallback, { noAck: false }).then(async ({ consumerTag: tag }) => {
|
|
11842
|
+
consumerTag = tag;
|
|
11843
|
+
setupDone = true;
|
|
11844
|
+
if (cancelRequested) {
|
|
11845
|
+
channel.cancel(tag).catch(reject);
|
|
11846
|
+
} else if (received === 0) {
|
|
11847
|
+
const { messageCount: remaining } = await channel.checkQueue(queueName);
|
|
11848
|
+
if (remaining === 0) {
|
|
11849
|
+
cancelRequested = true;
|
|
11850
|
+
channel.cancel(tag).catch(reject);
|
|
11851
|
+
}
|
|
11852
|
+
}
|
|
11853
|
+
maybeResolve();
|
|
11854
|
+
}).catch(reject);
|
|
11855
|
+
});
|
|
11856
|
+
}
|
|
11857
|
+
/**
|
|
11858
|
+
* Invokes `handler` with the queue name and decoded message content. Acks on success.
|
|
11859
|
+
* On failure, nacks the message and records the content and error in `stats.errors`.
|
|
11860
|
+
* Whether to requeue on nack is controlled by `options.nackRequeue` (default: true).
|
|
11861
|
+
*/
|
|
11862
|
+
async processMessage(channel, queueName, msg, stats, options, handler) {
|
|
11863
|
+
const { nackRequeue = true } = options;
|
|
11864
|
+
const content = msg.content.toString();
|
|
11865
|
+
try {
|
|
11866
|
+
await handler(queueName, content);
|
|
11867
|
+
channel.ack(msg);
|
|
11868
|
+
stats.acked++;
|
|
11869
|
+
} catch (error) {
|
|
11870
|
+
channel.nack(msg, false, nackRequeue);
|
|
11871
|
+
stats.errors.push({ content, error });
|
|
11872
|
+
stats.nacked++;
|
|
11873
|
+
}
|
|
11874
|
+
}
|
|
11875
|
+
};
|
|
11876
|
+
__name(_RabbitMQClient, "RabbitMQClient");
|
|
11877
|
+
var RabbitMQClient = _RabbitMQClient;
|
|
11878
|
+
var rabbit_mq_client_default = RabbitMQClient;
|
|
11879
|
+
|
|
11697
11880
|
// src/commerce/adobe-commerce-client/index.ts
|
|
11698
11881
|
import got from "got";
|
|
11699
11882
|
var _AdobeCommerceClient = class _AdobeCommerceClient {
|
|
@@ -12713,6 +12896,7 @@ export {
|
|
|
12713
12896
|
parameters_default as Parameters,
|
|
12714
12897
|
provider_default as ProviderManager,
|
|
12715
12898
|
publish_event_default as PublishEvent,
|
|
12899
|
+
rabbit_mq_client_default as RabbitMQClient,
|
|
12716
12900
|
registration_default as RegistrationManager,
|
|
12717
12901
|
rest_client_default as RestClient,
|
|
12718
12902
|
runtime_action_default as RuntimeAction,
|