From ee5cc86bba4fbc89383831a22de32189b9c10388 Mon Sep 17 00:00:00 2001 From: Jared Wray Date: Sun, 8 Mar 2026 09:29:35 -0600 Subject: [PATCH 1/6] qified - chore: upgrading hookified to 2.1.0 --- packages/qified/package.json | 2 +- packages/rabbitmq/package.json | 2 +- packages/redis/package.json | 2 +- pnpm-lock.yaml | 17 +++++++++++------ pnpm-workspace.yaml | 3 +++ 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/packages/qified/package.json b/packages/qified/package.json index 2a6dc2c..049d1f9 100644 --- a/packages/qified/package.json +++ b/packages/qified/package.json @@ -46,6 +46,6 @@ "LICENSE" ], "dependencies": { - "hookified": "^1.15.1" + "hookified": "^2.1.0" } } \ No newline at end of file diff --git a/packages/rabbitmq/package.json b/packages/rabbitmq/package.json index 640628d..ddc5361 100644 --- a/packages/rabbitmq/package.json +++ b/packages/rabbitmq/package.json @@ -34,7 +34,7 @@ "license": "MIT", "dependencies": { "amqplib": "^0.10.9", - "hookified": "^1.15.1" + "hookified": "^2.1.0" }, "peerDependencies": { "qified": "workspace:^" diff --git a/packages/redis/package.json b/packages/redis/package.json index 21d6473..6a8c826 100644 --- a/packages/redis/package.json +++ b/packages/redis/package.json @@ -33,7 +33,7 @@ "author": "Jared Wray ", "license": "MIT", "dependencies": { - "hookified": "^1.15.1", + "hookified": "^2.1.0", "redis": "^5.10.0" }, "peerDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 868ef6b..bade1a6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -51,8 +51,8 @@ importers: packages/qified: dependencies: hookified: - specifier: ^1.15.1 - version: 1.15.1 + specifier: ^2.1.0 + version: 2.1.0 packages/rabbitmq: dependencies: @@ -60,8 +60,8 @@ importers: specifier: ^0.10.9 version: 0.10.9 hookified: - specifier: ^1.15.1 - version: 1.15.1 + specifier: ^2.1.0 + version: 2.1.0 qified: specifier: workspace:^ version: link:../qified @@ -73,8 +73,8 @@ importers: packages/redis: dependencies: hookified: - specifier: ^1.15.1 - version: 1.15.1 + specifier: ^2.1.0 + version: 2.1.0 qified: specifier: workspace:^ version: link:../qified @@ -1488,6 +1488,9 @@ packages: hookified@1.15.1: resolution: {integrity: sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==} + hookified@2.1.0: + resolution: {integrity: sha512-ootKng4eaxNxa7rx6FJv2YKef3DuhqbEj3l70oGXwddPQEEnISm50TEZQclqiLTAtilT2nu7TErtCO523hHkyg==} + html-dom-parser@5.1.8: resolution: {integrity: sha512-MCIUng//mF2qTtGHXJWr6OLfHWmg3Pm8ezpfiltF83tizPWY17JxT4dRLE8lykJ5bChJELoY3onQKPbufJHxYA==} @@ -3845,6 +3848,8 @@ snapshots: hookified@1.15.1: {} + hookified@2.1.0: {} + html-dom-parser@5.1.8: dependencies: domhandler: 5.0.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 61dea49..36ce617 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -3,6 +3,9 @@ packages: minimumReleaseAge: 2880 +minimumReleaseAgeExclude: + - hookified + onlyBuiltDependencies: - esbuild - unrs-resolver From 8d61f8adc1d680961dd04e12659c1e23eec08a85 Mon Sep 17 00:00:00 2001 From: Jared Wray Date: Sun, 8 Mar 2026 09:36:09 -0600 Subject: [PATCH 2/6] moving empty listeners to false --- packages/rabbitmq/src/task.ts | 2 +- packages/redis/src/task.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/rabbitmq/src/task.ts b/packages/rabbitmq/src/task.ts index 2a98716..480ec83 100644 --- a/packages/rabbitmq/src/task.ts +++ b/packages/rabbitmq/src/task.ts @@ -76,7 +76,7 @@ export class RabbitMqTaskProvider extends Hookified implements TaskProvider { * @param options Configuration options for the provider */ constructor(options: RabbitMqTaskProviderOptions = {}) { - super(); + super({ throwOnEmptyListeners: false }); this._uri = options.uri ?? defaultRabbitMqTaskUri; this._id = options.id ?? defaultRabbitMqTaskId; this._timeout = options.timeout ?? defaultTimeout; diff --git a/packages/redis/src/task.ts b/packages/redis/src/task.ts index 8ebc976..1c9370f 100644 --- a/packages/redis/src/task.ts +++ b/packages/redis/src/task.ts @@ -60,7 +60,7 @@ export class RedisTaskProvider extends Hookified implements TaskProvider { * @param options Configuration options for the provider */ constructor(options: RedisTaskProviderOptions = {}) { - super(); + super({ throwOnEmptyListeners: false }); const uri = options.uri ?? defaultRedisUri; this._id = options.id ?? defaultRedisTaskId; this._timeout = options.timeout ?? defaultTimeout; From 9b34c701b3d97cd017e8f05eee3781478e05145d Mon Sep 17 00:00:00 2001 From: Jared Wray Date: Sun, 8 Mar 2026 09:38:19 -0600 Subject: [PATCH 3/6] updating tests to handle it --- packages/rabbitmq/src/task.ts | 2 +- packages/redis/src/task.ts | 2 +- packages/redis/test/task.test.ts | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/rabbitmq/src/task.ts b/packages/rabbitmq/src/task.ts index 480ec83..2a98716 100644 --- a/packages/rabbitmq/src/task.ts +++ b/packages/rabbitmq/src/task.ts @@ -76,7 +76,7 @@ export class RabbitMqTaskProvider extends Hookified implements TaskProvider { * @param options Configuration options for the provider */ constructor(options: RabbitMqTaskProviderOptions = {}) { - super({ throwOnEmptyListeners: false }); + super(); this._uri = options.uri ?? defaultRabbitMqTaskUri; this._id = options.id ?? defaultRabbitMqTaskId; this._timeout = options.timeout ?? defaultTimeout; diff --git a/packages/redis/src/task.ts b/packages/redis/src/task.ts index 1c9370f..8ebc976 100644 --- a/packages/redis/src/task.ts +++ b/packages/redis/src/task.ts @@ -60,7 +60,7 @@ export class RedisTaskProvider extends Hookified implements TaskProvider { * @param options Configuration options for the provider */ constructor(options: RedisTaskProviderOptions = {}) { - super({ throwOnEmptyListeners: false }); + super(); const uri = options.uri ?? defaultRedisUri; this._id = options.id ?? defaultRedisTaskId; this._timeout = options.timeout ?? defaultTimeout; diff --git a/packages/redis/test/task.test.ts b/packages/redis/test/task.test.ts index 8ec12bc..3b57f14 100644 --- a/packages/redis/test/task.test.ts +++ b/packages/redis/test/task.test.ts @@ -985,6 +985,7 @@ describe("RedisTaskProvider", () => { timeout: 20, pollInterval: 30, }); + customProvider.throwOnEmptyListeners = false; await customProvider.connect(); await customProvider.clearQueue(testQueue); From a6ac54c0ef7505a52dbc9f10056648233c718c59 Mon Sep 17 00:00:00 2001 From: Jared Wray Date: Sun, 8 Mar 2026 09:46:57 -0600 Subject: [PATCH 4/6] Update README.md --- packages/qified/README.md | 53 +++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/packages/qified/README.md b/packages/qified/README.md index 000aa8f..2b01154 100644 --- a/packages/qified/README.md +++ b/packages/qified/README.md @@ -28,6 +28,30 @@ Task and Message Queues with Multiple Providers * Customizable Compress / Decompress Handlers (Coming in v1.0.0) * Provider Fail Over Support +# Table of Contents +- [Installation](#installation) +- [Quick Start](#quick-start) +- [Constructor](#constructor) +- [Properties](#properties) +- [Methods](#methods) + - [subscribe](#subscribe) + - [publish](#publish) + - [unsubscribe](#unsubscribe) + - [disconnect](#disconnect) +- [Events](#events) + - [Available Events](#available-events) + - [Listening to Events](#listening-to-events) + - [Error Handling with Events](#error-handling-with-events) +- [Hooks](#hooks) + - [Available Hooks](#available-hooks) + - [Using Hooks](#using-hooks) + - [Modifying Data with Before Hooks](#modifying-data-with-before-hooks) + - [Modifying Topics with Before Hooks](#modifying-topics-with-before-hooks) + - [Multiple Hooks](#multiple-hooks) + - [Hooks vs Events](#hooks-vs-events) +- [Providers](#providers) +- [Development and Testing](#development-and-testing) +- [License](#license) # Installation @@ -326,7 +350,7 @@ The following hooks are available via the `QifiedHooks` enum: ## Using Hooks -Use the `onHook()` method to register a hook handler: +Use the `onHook()` method to register a hook handler. Hooks use the `IHook` object format from [Hookified](https://hookified.org): ```js import { Qified, MemoryMessageProvider, QifiedHooks } from 'qified'; @@ -335,15 +359,30 @@ const qified = new Qified({ messageProviders: new MemoryMessageProvider() }); -// Register a before hook -qified.onHook(QifiedHooks.beforePublish, async (context) => { - console.log('About to publish to:', context.topic); +// Register a before hook using IHook object +qified.onHook({ + event: QifiedHooks.beforePublish, + handler: async (context) => { + console.log('About to publish to:', context.topic); + } }); -// Register an after hook -qified.onHook(QifiedHooks.afterPublish, async (context) => { - console.log('Published message:', context.message.id); +// Register an after hook with an id for later removal +qified.onHook({ + id: 'publish-logger', + event: QifiedHooks.afterPublish, + handler: async (context) => { + console.log('Published message:', context.message.id); + } }); + +// Register with options to control position +qified.onHook({ + event: QifiedHooks.beforePublish, + handler: async (context) => { + console.log('This runs first'); + } +}, { position: 'Top' }); ``` ## Modifying Data with Before Hooks From 38ce10c54023117e8f8c78de5513754c69793d3f Mon Sep 17 00:00:00 2001 From: Jared Wray Date: Sun, 8 Mar 2026 09:50:54 -0600 Subject: [PATCH 5/6] Update README.md --- packages/qified/README.md | 89 ++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 30 deletions(-) diff --git a/packages/qified/README.md b/packages/qified/README.md index 2b01154..b876ddd 100644 --- a/packages/qified/README.md +++ b/packages/qified/README.md @@ -397,28 +397,34 @@ const qified = new Qified({ }); // Add timestamp and headers to all messages -qified.onHook(QifiedHooks.beforePublish, async (context) => { - // Add timestamp if not present - context.message.timestamp = context.message.timestamp ?? Date.now(); - - // Add custom headers - context.message.headers = { - ...context.message.headers, - 'x-processed-by': 'qified', - 'x-environment': process.env.NODE_ENV - }; +qified.onHook({ + event: QifiedHooks.beforePublish, + handler: async (context) => { + // Add timestamp if not present + context.message.timestamp = context.message.timestamp ?? Date.now(); + + // Add custom headers + context.message.headers = { + ...context.message.headers, + 'x-processed-by': 'qified', + 'x-environment': process.env.NODE_ENV + }; + } }); // Modify message data -qified.onHook(QifiedHooks.beforePublish, async (context) => { - // Add metadata to the message data - context.message.data = { - ...context.message.data, - _meta: { - version: '1.0', - source: 'api' - } - }; +qified.onHook({ + event: QifiedHooks.beforePublish, + handler: async (context) => { + // Add metadata to the message data + context.message.data = { + ...context.message.data, + _meta: { + version: '1.0', + source: 'api' + } + }; + } }); // Subscribe to receive messages @@ -445,8 +451,11 @@ You can also modify the topic in before hooks: ```js // Route all messages to a prefixed topic -qified.onHook(QifiedHooks.beforePublish, async (context) => { - context.topic = `production/${context.topic}`; +qified.onHook({ + event: QifiedHooks.beforePublish, + handler: async (context) => { + context.topic = `production/${context.topic}`; + } }); // Subscribe to the prefixed topic @@ -469,20 +478,37 @@ await qified.publish('events', { Multiple hooks for the same event execute in the order they were registered: ```js -// First hook - runs first -qified.onHook(QifiedHooks.beforePublish, async (context) => { - context.message.timestamp = Date.now(); +// First hook - runs first (default position is 'Bottom') +qified.onHook({ + event: QifiedHooks.beforePublish, + handler: async (context) => { + context.message.timestamp = Date.now(); + } }); // Second hook - runs second, can see changes from first hook -qified.onHook(QifiedHooks.beforePublish, async (context) => { - context.message.headers = { 'x-timestamp': String(context.message.timestamp) }; +qified.onHook({ + event: QifiedHooks.beforePublish, + handler: async (context) => { + context.message.headers = { 'x-timestamp': String(context.message.timestamp) }; + } }); // Third hook - runs third -qified.onHook(QifiedHooks.beforePublish, async (context) => { - console.log('Final message:', context.message); +qified.onHook({ + event: QifiedHooks.beforePublish, + handler: async (context) => { + console.log('Final message:', context.message); + } }); + +// Use position option to insert at the top +qified.onHook({ + event: QifiedHooks.beforePublish, + handler: async (context) => { + console.log('This runs before all other hooks'); + } +}, { position: 'Top' }); ``` ## Hooks vs Events @@ -497,8 +523,11 @@ Both hooks and events are available, but they serve different purposes: ```js // Hook - can modify the message before it's published -qified.onHook(QifiedHooks.beforePublish, async (context) => { - context.message.timestamp = Date.now(); +qified.onHook({ + event: QifiedHooks.beforePublish, + handler: async (context) => { + context.message.timestamp = Date.now(); + } }); // Event - notified after publish completes (cannot modify) From cafac6e475b0dce642e1a73899e620bad15c1c9a Mon Sep 17 00:00:00 2001 From: Jared Wray Date: Sun, 8 Mar 2026 09:55:30 -0600 Subject: [PATCH 6/6] Update task.test.ts --- packages/redis/test/task.test.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/redis/test/task.test.ts b/packages/redis/test/task.test.ts index 3b57f14..ff00e41 100644 --- a/packages/redis/test/task.test.ts +++ b/packages/redis/test/task.test.ts @@ -109,6 +109,7 @@ describe("RedisTaskProvider", () => { beforeEach(async () => { provider = new RedisTaskProvider(); + provider.throwOnEmptyListeners = false; await provider.connect(); await provider.clearQueue(testQueue); }); @@ -468,6 +469,7 @@ describe("RedisTaskProvider", () => { retries: 3, pollInterval: 100, }); + customProvider.throwOnEmptyListeners = false; await customProvider.connect(); await customProvider.clearQueue(testQueue); @@ -502,6 +504,7 @@ describe("RedisTaskProvider", () => { timeout: 100, pollInterval: 50, }); + customProvider.throwOnEmptyListeners = false; await customProvider.connect(); await customProvider.clearQueue(testQueue); @@ -539,6 +542,7 @@ describe("RedisTaskProvider", () => { timeout: 200, pollInterval: 50, }); + customProvider.throwOnEmptyListeners = false; await customProvider.connect(); await customProvider.clearQueue(testQueue); @@ -952,6 +956,7 @@ describe("RedisTaskProvider", () => { retries: 2, pollInterval: 30, }); + customProvider.throwOnEmptyListeners = false; await customProvider.connect(); await customProvider.clearQueue(testQueue); @@ -1075,6 +1080,7 @@ describe("RedisTaskProvider", () => { timeout: 5000, pollInterval: 50, }); + customProvider.throwOnEmptyListeners = false; await customProvider.connect(); await customProvider.clearQueue(testQueue); @@ -1112,6 +1118,7 @@ describe("RedisTaskProvider", () => { test("should handle processQueue when _active becomes false after getClient", async () => { // This test covers line 376 (early return after getClient when _active is false) const customProvider = new RedisTaskProvider({ pollInterval: 30 }); + customProvider.throwOnEmptyListeners = false; await customProvider.connect(); await customProvider.clearQueue(testQueue); @@ -1143,6 +1150,7 @@ describe("RedisTaskProvider", () => { retries: 1, pollInterval: 20, }); + customProvider.throwOnEmptyListeners = false; await customProvider.connect(); await customProvider.clearQueue(testQueue); @@ -1212,6 +1220,7 @@ describe("RedisTaskProvider", () => { retries: 5, pollInterval: 20, }); + customProvider.throwOnEmptyListeners = false; await customProvider.connect(); await customProvider.clearQueue(testQueue); @@ -1250,6 +1259,7 @@ describe("RedisTaskProvider", () => { retries: 1, // Only 1 retry allowed pollInterval: 15, }); + customProvider.throwOnEmptyListeners = false; await customProvider.connect(); await customProvider.clearQueue(testQueue); @@ -1297,6 +1307,7 @@ describe("RedisTaskProvider", () => { retries: 5, pollInterval: 15, }); + customProvider.throwOnEmptyListeners = false; await customProvider.connect(); await customProvider.clearQueue(testQueue);