@fedify/amqp 2.0.0-dev.1604 → 2.0.0-dev.1641

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/deno.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fedify/amqp",
3
- "version": "2.0.0-dev.1604+23a1ea67",
3
+ "version": "2.0.0-dev.1641+6b0c942c",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./src/mod.ts",
@@ -11,6 +11,7 @@
11
11
  },
12
12
  "exclude": [
13
13
  ".github",
14
+ "dist",
14
15
  "node_modules",
15
16
  "npm",
16
17
  "pnpm-lock.yaml"
@@ -0,0 +1,30 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+
23
+ //#endregion
24
+
25
+ Object.defineProperty(exports, '__toESM', {
26
+ enumerable: true,
27
+ get: function () {
28
+ return __toESM;
29
+ }
30
+ });
package/dist/mod.cjs ADDED
@@ -0,0 +1,3 @@
1
+ const require_mq = require('./mq.cjs');
2
+
3
+ exports.AmqpMessageQueue = require_mq.AmqpMessageQueue;
package/dist/mod.d.cts ADDED
@@ -0,0 +1,2 @@
1
+ import { AmqpMessageQueue, AmqpMessageQueueOptions } from "./mq.cjs";
2
+ export { AmqpMessageQueue, AmqpMessageQueueOptions };
package/dist/mq.cjs ADDED
@@ -0,0 +1,121 @@
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
+ const node_buffer = require_rolldown_runtime.__toESM(require("node:buffer"));
3
+
4
+ //#region src/mq.ts
5
+ /**
6
+ * A message queue that uses AMQP.
7
+ *
8
+ * @example
9
+ * ``` typescript
10
+ * import { createFederation } from "@fedify/fedify";
11
+ * import { AmqpMessageQueue } from "@fedify/amqp";
12
+ * import { connect } from "amqplib";
13
+ *
14
+ * const federation = createFederation({
15
+ * queue: new AmqpMessageQueue(await connect("amqp://localhost")),
16
+ * // ... other configurations
17
+ * });
18
+ * ```
19
+ */
20
+ var AmqpMessageQueue = class {
21
+ #connection;
22
+ #queue;
23
+ #delayedQueuePrefix;
24
+ #durable;
25
+ #senderChannel;
26
+ nativeRetrial;
27
+ /**
28
+ * Creates a new `AmqpMessageQueue`.
29
+ * @param connection A connection to the AMQP server.
30
+ * @param options Options for the message queue.
31
+ */
32
+ constructor(connection, options = {}) {
33
+ this.#connection = connection;
34
+ this.#queue = options.queue ?? "fedify_queue";
35
+ this.#delayedQueuePrefix = options.delayedQueuePrefix ?? "fedify_delayed_";
36
+ this.#durable = options.durable ?? true;
37
+ this.nativeRetrial = options.nativeRetrial ?? false;
38
+ }
39
+ async #prepareQueue(channel) {
40
+ await channel.assertQueue(this.#queue, { durable: this.#durable });
41
+ }
42
+ async #getSenderChannel() {
43
+ if (this.#senderChannel != null) return this.#senderChannel;
44
+ const channel = await this.#connection.createChannel();
45
+ this.#senderChannel = channel;
46
+ this.#prepareQueue(channel);
47
+ return channel;
48
+ }
49
+ async enqueue(message, options) {
50
+ const channel = await this.#getSenderChannel();
51
+ const delay = options?.delay?.total("millisecond");
52
+ let queue;
53
+ if (delay == null || delay <= 0) queue = this.#queue;
54
+ else {
55
+ const delayStr = delay.toLocaleString("en", { useGrouping: false });
56
+ queue = this.#delayedQueuePrefix + delayStr;
57
+ await channel.assertQueue(queue, {
58
+ autoDelete: true,
59
+ durable: this.#durable,
60
+ deadLetterExchange: "",
61
+ deadLetterRoutingKey: this.#queue,
62
+ messageTtl: delay
63
+ });
64
+ }
65
+ channel.sendToQueue(queue, node_buffer.Buffer.from(JSON.stringify(message), "utf-8"), {
66
+ persistent: this.#durable,
67
+ contentType: "application/json"
68
+ });
69
+ }
70
+ async enqueueMany(messages, options) {
71
+ const channel = await this.#getSenderChannel();
72
+ const delay = options?.delay?.total("millisecond");
73
+ let queue;
74
+ if (delay == null || delay <= 0) queue = this.#queue;
75
+ else {
76
+ const delayStr = delay.toLocaleString("en", { useGrouping: false });
77
+ queue = this.#delayedQueuePrefix + delayStr;
78
+ await channel.assertQueue(queue, {
79
+ autoDelete: true,
80
+ durable: this.#durable,
81
+ deadLetterExchange: "",
82
+ deadLetterRoutingKey: this.#queue,
83
+ messageTtl: delay
84
+ });
85
+ }
86
+ for (const message of messages) channel.sendToQueue(queue, node_buffer.Buffer.from(JSON.stringify(message), "utf-8"), {
87
+ persistent: this.#durable,
88
+ contentType: "application/json"
89
+ });
90
+ }
91
+ async listen(handler, options = {}) {
92
+ const channel = await this.#connection.createChannel();
93
+ await this.#prepareQueue(channel);
94
+ await channel.prefetch(1);
95
+ const reply = await channel.consume(this.#queue, (msg) => {
96
+ if (msg == null) return;
97
+ const message = JSON.parse(msg.content.toString("utf-8"));
98
+ try {
99
+ const result = handler(message);
100
+ if (result instanceof Promise) if (this.nativeRetrial) result.then(() => channel.ack(msg)).catch(() => channel.nack(msg, void 0, true));
101
+ else result.finally(() => channel.ack(msg));
102
+ else if (this.nativeRetrial) channel.ack(msg);
103
+ } catch {
104
+ if (this.nativeRetrial) channel.nack(msg, void 0, true);
105
+ } finally {
106
+ if (!this.nativeRetrial) channel.ack(msg);
107
+ }
108
+ }, { noAck: false });
109
+ return await new Promise((resolve) => {
110
+ if (options.signal?.aborted) resolve();
111
+ options.signal?.addEventListener("abort", () => {
112
+ channel.cancel(reply.consumerTag).then(() => {
113
+ channel.close().then(() => resolve());
114
+ });
115
+ });
116
+ });
117
+ }
118
+ };
119
+
120
+ //#endregion
121
+ exports.AmqpMessageQueue = AmqpMessageQueue;
package/dist/mq.d.cts ADDED
@@ -0,0 +1,72 @@
1
+ import { MessageQueue, MessageQueueEnqueueOptions, MessageQueueListenOptions } from "@fedify/fedify";
2
+ import { ChannelModel } from "amqplib";
3
+
4
+ //#region src/mq.d.ts
5
+
6
+ /**
7
+ * Options for {@link AmqpMessageQueue}.
8
+ */
9
+ interface AmqpMessageQueueOptions {
10
+ /**
11
+ * The name of the queue to use. Defaults to `"fedify_queue"`.
12
+ * @default `"fedify_queue"`
13
+ */
14
+ queue?: string;
15
+ /**
16
+ * The prefix to use for the delayed queue. Defaults to `"fedify_delayed_"`.
17
+ * Defaults to `"fedify_delayed_"`.
18
+ * @default `"fedify_delayed_"`
19
+ */
20
+ delayedQueuePrefix?: string;
21
+ /**
22
+ * Whether the queue will survive a broker restart. Defaults to `true`.
23
+ * @default `true`
24
+ */
25
+ durable?: boolean;
26
+ /**
27
+ * Whether to use native retrial mechanism. If set to `true`, the queue will
28
+ * not acknowledge messages that are not processed successfully, allowing
29
+ * them to be retried later. If set to `false`, messages will be acknowledged
30
+ * whether they are processed successfully or not.
31
+ *
32
+ * Both approaches have their own advantages and disadvantages. With native
33
+ * retrials, much less chance of losing messages, but timing of retrials is
34
+ * less predictable. With non-native retrials, retrials are handled by Fedify
35
+ * itself, which allows for more control over the timing and behavior of
36
+ * retrials, but may result in lost messages if the process crashes before
37
+ * acknowledging the message.
38
+ * @default `false`
39
+ * @since 0.3.0
40
+ */
41
+ nativeRetrial?: boolean;
42
+ }
43
+ /**
44
+ * A message queue that uses AMQP.
45
+ *
46
+ * @example
47
+ * ``` typescript
48
+ * import { createFederation } from "@fedify/fedify";
49
+ * import { AmqpMessageQueue } from "@fedify/amqp";
50
+ * import { connect } from "amqplib";
51
+ *
52
+ * const federation = createFederation({
53
+ * queue: new AmqpMessageQueue(await connect("amqp://localhost")),
54
+ * // ... other configurations
55
+ * });
56
+ * ```
57
+ */
58
+ declare class AmqpMessageQueue implements MessageQueue {
59
+ #private;
60
+ readonly nativeRetrial: boolean;
61
+ /**
62
+ * Creates a new `AmqpMessageQueue`.
63
+ * @param connection A connection to the AMQP server.
64
+ * @param options Options for the message queue.
65
+ */
66
+ constructor(connection: ChannelModel, options?: AmqpMessageQueueOptions);
67
+ enqueue(message: any, options?: MessageQueueEnqueueOptions): Promise<void>;
68
+ enqueueMany(messages: any[], options?: MessageQueueEnqueueOptions): Promise<void>;
69
+ listen(handler: (message: any) => void | Promise<void>, options?: MessageQueueListenOptions): Promise<void>;
70
+ }
71
+ //#endregion
72
+ export { AmqpMessageQueue, AmqpMessageQueueOptions };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fedify/amqp",
3
- "version": "2.0.0-dev.1604+23a1ea67",
3
+ "version": "2.0.0-dev.1641+6b0c942c",
4
4
  "description": "AMQP/RabbitMQ driver for Fedify",
5
5
  "keywords": [
6
6
  "fedify",
@@ -27,25 +27,35 @@
27
27
  "https://github.com/sponsors/dahlia"
28
28
  ],
29
29
  "type": "module",
30
- "main": "./dist/mod.js",
30
+ "main": "./dist/mod.cjs",
31
31
  "module": "./dist/mod.js",
32
32
  "types": "./dist/mod.d.ts",
33
33
  "exports": {
34
34
  ".": {
35
- "types": "./dist/mod.d.ts",
35
+ "types": {
36
+ "import": "./dist/mod.d.ts",
37
+ "require": "./dist/mod.d.cts",
38
+ "default": "./dist/mod.d.ts"
39
+ },
36
40
  "import": "./dist/mod.js",
41
+ "require": "./dist/mod.cjs",
37
42
  "default": "./dist/mod.js"
38
43
  },
39
44
  "./mq": {
40
- "types": "./dist/mq.d.ts",
45
+ "types": {
46
+ "import": "./dist/mq.d.ts",
47
+ "require": "./dist/mq.d.cts",
48
+ "default": "./dist/mq.d.ts"
49
+ },
41
50
  "import": "./dist/mq.js",
51
+ "require": "./dist/mq.cjs",
42
52
  "default": "./dist/mq.js"
43
53
  },
44
54
  "./package.json": "./package.json"
45
55
  },
46
56
  "peerDependencies": {
47
57
  "amqplib": "^0.10.8",
48
- "@fedify/fedify": "^2.0.0-dev.1604+23a1ea67"
58
+ "@fedify/fedify": "^2.0.0-dev.1641+6b0c942c"
49
59
  },
50
60
  "devDependencies": {
51
61
  "@alinea/suite": "^0.6.3",
package/tsdown.config.ts CHANGED
@@ -4,5 +4,6 @@ export default defineConfig({
4
4
  entry: ["src/mod.ts", "src/mq.ts"],
5
5
  dts: true,
6
6
  unbundle: true,
7
+ format: ["esm", "cjs"],
7
8
  platform: "node",
8
9
  });