keyv 4.5.4 → 5.0.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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017-2021 Luke Childs
4
+ Copyright (c) 2021-2022 Jared Wray
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
package/README.md CHANGED
@@ -1,8 +1,4 @@
1
- <h1 align="center">
2
- <img width="250" src="https://jaredwray.com/images/keyv.svg" alt="keyv">
3
- <br>
4
- <br>
5
- </h1>
1
+ [<img width="100" align="right" src="https://jaredwray.com/images/keyv-symbol.svg" alt="keyv">](https://github.com/jaredwra/keyv)
6
2
 
7
3
  > Simple key-value storage with support for multiple backends
8
4
 
@@ -45,24 +41,49 @@ npm install --save @keyv/sqlite
45
41
  npm install --save @keyv/postgres
46
42
  npm install --save @keyv/mysql
47
43
  npm install --save @keyv/etcd
44
+ npm install --save @keyv/memcache
48
45
  ```
49
46
 
50
- Create a new Keyv instance, passing your connection string if applicable. Keyv will automatically load the correct storage adapter.
47
+ First, create a new Keyv instance.
51
48
 
52
49
  ```js
53
- const Keyv = require('keyv');
50
+ import Keyv from 'keyv';
51
+ ```
54
52
 
55
- // One of the following
56
- const keyv = new Keyv();
57
- const keyv = new Keyv('redis://user:pass@localhost:6379');
58
- const keyv = new Keyv('mongodb://user:pass@localhost:27017/dbname');
59
- const keyv = new Keyv('sqlite://path/to/database.sqlite');
60
- const keyv = new Keyv('postgresql://user:pass@localhost:5432/dbname');
61
- const keyv = new Keyv('mysql://user:pass@localhost:3306/dbname');
62
- const keyv = new Keyv('etcd://localhost:2379');
53
+ Once you have created your Keyv instance you can use it as a simple key-value store with `in-memory` by default. To use a storage adapter, create an instance of the adapter and pass it to the Keyv constructor. Here are some examples:
54
+
55
+ ```js
56
+ // redis
57
+ import KeyvRedis from '@keyv/redis';
58
+
59
+ const keyv = new Keyv(new KeyvRedis('redis://user:pass@localhost:6379'));
60
+ ```
61
+
62
+ You can also pass in a storage adapter with other options such as `ttl` and `namespace` (example using `sqlite`):
63
+
64
+ ```js
65
+ //sqlite
66
+ import KeyvSqlite from '@keyv/sqlite';
67
+
68
+ const keyvSqlite = new KeyvSqlite('sqlite://path/to/database.sqlite');
69
+ const keyv = new Keyv({ store: keyvSqlite, ttl: 5000, namespace: 'cache' });
70
+ ```
63
71
 
72
+ To handle an event you can do the following:
73
+
74
+ ```js
64
75
  // Handle DB connection errors
65
76
  keyv.on('error', err => console.log('Connection Error', err));
77
+ ```
78
+
79
+ Now lets do an end-to-end example using `Keyv` and the `Redis` storage adapter:
80
+
81
+ ```js
82
+ import Keyv from 'keyv';
83
+ import KeyvRedis from '@keyv/redis';
84
+
85
+ const keyvRedis = new KeyvRedis('redis://user:pass@localhost:6379');
86
+ const keyv = new Keyv({ store: keyvRedis });
66
87
 
67
88
  await keyv.set('foo', 'expires in 1 second', 1000); // true
68
89
  await keyv.set('foo', 'never expires'); // true
@@ -71,13 +92,15 @@ await keyv.delete('foo'); // true
71
92
  await keyv.clear(); // undefined
72
93
  ```
73
94
 
95
+ It's is just that simple! Keyv is designed to be simple and easy to use.
96
+
74
97
  ### Namespaces
75
98
 
76
99
  You can namespace your Keyv instance to avoid key collisions and allow you to clear only a certain namespace while using the same database.
77
100
 
78
101
  ```js
79
- const users = new Keyv('redis://user:pass@localhost:6379', { namespace: 'users' });
80
- const cache = new Keyv('redis://user:pass@localhost:6379', { namespace: 'cache' });
102
+ const users = new Keyv(new KeyvRedis('redis://user:pass@localhost:6379'), { namespace: 'users' });
103
+ const cache = new Keyv(new KeyvRedis('redis://user:pass@localhost:6379'), { namespace: 'cache' });
81
104
 
82
105
  await users.set('foo', 'users'); // true
83
106
  await cache.set('foo', 'cache'); // true
@@ -88,9 +111,70 @@ await users.get('foo'); // undefined
88
111
  await cache.get('foo'); // 'cache'
89
112
  ```
90
113
 
114
+ ### Events
115
+
116
+ Keyv is a custom `EventEmitter` and will emit an `'error'` event if there is an error. In addition it will emit a `clear` and `disconnect` event when the corresponding methods are called.
117
+
118
+ ```js
119
+ const keyv = new Keyv();
120
+ const handleConnectionError = err => console.log('Connection Error', err);
121
+ const handleClear = () => console.log('Cache Cleared');
122
+ const handleDisconnect = () => console.log('Disconnected');
123
+
124
+ keyv.on('error', handleConnectionError);
125
+ keyv.on('clear', handleClear);
126
+ keyv.on('disconnect', handleDisconnect);
127
+ ```
128
+
129
+ ### Hooks
130
+
131
+ Keyv supports hooks for `get`, `set`, and `delete` methods. Hooks are useful for logging, debugging, and other custom functionality. Here is a list of all the hooks:
132
+
133
+ ```
134
+ PRE_GET
135
+ POST_GET
136
+ PRE_GET_MANY
137
+ POST_GET_MANY
138
+ PRE_SET
139
+ POST_SET
140
+ PRE_DELETE
141
+ POST_DELETE
142
+ ```
143
+
144
+ You can access this by importing `KeyvHooks` from the main Keyv package.
145
+
146
+ ```js
147
+ import Keyv, { KeyvHooks } from 'keyv';
148
+ ```
149
+
150
+ ```js
151
+ //PRE_SET hook
152
+ const keyv = new Keyv();
153
+ keyv.hooks.addListener(KeyvHooks.PRE_SET, (key, value) => console.log(`Setting key ${key} to ${value}`));
154
+
155
+ //POST_SET hook
156
+ const keyv = new Keyv();
157
+ keyv.hooks.addListener(KeyvHooks.POST_SET, (key, value) => console.log(`Set key ${key} to ${value}`));
158
+ ```
159
+
160
+ In these examples you can also manipulate the value before it is set. For example, you could add a prefix to all keys.
161
+
162
+ ```js
163
+ const keyv = new Keyv();
164
+ keyv.hooks.addListener(KeyvHooks.PRE_SET, (key, value) => {
165
+ console.log(`Setting key ${key} to ${value}`);
166
+ key = `prefix-${key}`;
167
+ });
168
+ ```
169
+
170
+ Now this key will have prefix- added to it before it is set.
171
+
172
+ In `PRE_DELETE` and `POST_DELETE` hooks, the value could be a single item or an `Array`. This is based on the fact that `delete` can accept a single key or an `Array` of keys.
173
+
174
+
91
175
  ### Custom Serializers
92
176
 
93
- Keyv uses [`json-buffer`](https://github.com/dominictarr/json-buffer) for data serialization to ensure consistency across different backends.
177
+ Keyv uses [`buffer`](https://nodejs.org/api/buffer.html) for data serialization to ensure consistency across different backends.
94
178
 
95
179
  You can optionally provide your own serialization functions to support extra data types or to serialize to something other than JSON.
96
180
 
@@ -119,8 +203,8 @@ Memcache | [@keyv/memcache](https://github.com/jaredwray/keyv/tree/master/packag
119
203
  You can also use third-party storage adapters or build your own. Keyv will wrap these storage adapters in TTL functionality and handle complex types internally.
120
204
 
121
205
  ```js
122
- const Keyv = require('keyv');
123
- const myAdapter = require('./my-storage-adapter');
206
+ import Keyv from 'keyv';
207
+ import myAdapter from 'my-adapter';
124
208
 
125
209
  const keyv = new Keyv({ store: myAdapter });
126
210
  ```
@@ -134,8 +218,8 @@ new Keyv({ store: new Map() });
134
218
  For example, [`quick-lru`](https://github.com/sindresorhus/quick-lru) is a completely unrelated module that implements the Map API.
135
219
 
136
220
  ```js
137
- const Keyv = require('keyv');
138
- const QuickLRU = require('quick-lru');
221
+ import Keyv from 'keyv';
222
+ import QuickLRU from 'quick-lru';
139
223
 
140
224
  const lru = new QuickLRU({ maxSize: 1000 });
141
225
  const keyv = new Keyv({ store: lru });
@@ -177,7 +261,7 @@ class AwesomeModule {
177
261
  Now it can be consumed like this:
178
262
 
179
263
  ```js
180
- const AwesomeModule = require('awesome-module');
264
+ import AwesomeModule from 'awesome-module';
181
265
 
182
266
  // Caches stuff in memory by default
183
267
  const awesomeModule = new AwesomeModule();
@@ -194,8 +278,8 @@ const awesomeModule = new AwesomeModule({ cache: some3rdPartyStore });
194
278
  Keyv supports `gzip` and `brotli` compression. To enable compression, pass the `compress` option to the constructor.
195
279
 
196
280
  ```js
197
- const KeyvGzip = require('@keyv/compress-gzip');
198
- const Keyv = require('keyv');
281
+ import Keyv from 'keyv';
282
+ import KeyvGzip from '@keyv/compress-gzip';
199
283
 
200
284
  const keyvGzip = new KeyvGzip();
201
285
  const keyv = new Keyv({ compression: KeyvGzip });
@@ -219,23 +303,23 @@ interface CompressionAdapter {
219
303
  In addition to the interface, you can test it with our compression test suite using @keyv/test-suite:
220
304
 
221
305
  ```js
222
- const {keyvCompresstionTests} = require('@keyv/test-suite');
223
- const KeyvGzip = require('@keyv/compress-gzip');
306
+ import { keyvCompresstionTests } from '@keyv/test-suite';
307
+ import KeyvGzip from '@keyv/compress-gzip';
224
308
 
225
309
  keyvCompresstionTests(test, new KeyvGzip());
226
310
  ```
227
311
 
228
312
  ## API
229
313
 
230
- ### new Keyv([uri], [options])
314
+ ### new Keyv([storage-adapter], [options]) or new Keyv([options])
231
315
 
232
316
  Returns a new Keyv instance.
233
317
 
234
318
  The Keyv instance is also an `EventEmitter` that will emit an `'error'` event if the storage adapter connection fails.
235
319
 
236
- ### uri
320
+ ### storage-adapter
237
321
 
238
- Type: `String`<br>
322
+ Type: `KeyvStorageAdapter`<br />
239
323
  Default: `undefined`
240
324
 
241
325
  The connection string URI.
@@ -250,53 +334,46 @@ The options object is also passed through to the storage adapter. Check your sto
250
334
 
251
335
  #### options.namespace
252
336
 
253
- Type: `String`<br>
337
+ Type: `String`<br />
254
338
  Default: `'keyv'`
255
339
 
256
340
  Namespace for the current instance.
257
341
 
258
342
  #### options.ttl
259
343
 
260
- Type: `Number`<br>
344
+ Type: `Number`<br />
261
345
  Default: `undefined`
262
346
 
263
347
  Default TTL. Can be overridden by specififying a TTL on `.set()`.
264
348
 
265
349
  #### options.compression
266
350
 
267
- Type: `@keyv/compress-<compression_package_name>`<br>
351
+ Type: `@keyv/compress-<compression_package_name>`<br />
268
352
  Default: `undefined`
269
353
 
270
354
  Compression package to use. See [Compression](#compression) for more details.
271
355
 
272
356
  #### options.serialize
273
357
 
274
- Type: `Function`<br>
358
+ Type: `Function`<br />
275
359
  Default: `JSONB.stringify`
276
360
 
277
361
  A custom serialization function.
278
362
 
279
363
  #### options.deserialize
280
364
 
281
- Type: `Function`<br>
365
+ Type: `Function`<br />
282
366
  Default: `JSONB.parse`
283
367
 
284
368
  A custom deserialization function.
285
369
 
286
370
  #### options.store
287
371
 
288
- Type: `Storage adapter instance`<br>
372
+ Type: `Storage adapter instance`<br />
289
373
  Default: `new Map()`
290
374
 
291
375
  The storage adapter instance to be used by Keyv.
292
376
 
293
- #### options.adapter
294
-
295
- Type: `String`<br>
296
- Default: `undefined`
297
-
298
- Specify an adapter to use. e.g `'redis'` or `'mongodb'`.
299
-
300
377
  ### Instance
301
378
 
302
379
  Keys must always be strings. Values can be of any type.
@@ -315,7 +392,7 @@ Returns a promise which resolves to the retrieved value.
315
392
 
316
393
  ##### options.raw
317
394
 
318
- Type: `Boolean`<br>
395
+ Type: `Boolean`<br />
319
396
  Default: `false`
320
397
 
321
398
  If set to true the raw DB object Keyv stores internally will be returned instead of just the value.
@@ -349,81 +426,12 @@ for await (const [key, value] of this.keyv.iterator()) {
349
426
 
350
427
  # How to Contribute
351
428
 
352
- In this section of the documentation we will cover:
353
-
354
- 1) How to set up this repository locally
355
- 2) How to get started with running commands
356
- 3) How to contribute changes using Pull Requests
357
-
358
- ## Dependencies
359
-
360
- This package requires the following dependencies to run:
361
-
362
- 1) [Yarn V1](https://yarnpkg.com/getting-started/install)
363
- 3) [Docker](https://docs.docker.com/get-docker/)
364
-
365
- ## Setting up your workspace
366
-
367
- To contribute to this repository, start by setting up this project locally:
368
-
369
- 1) Fork this repository into your Git account
370
- 2) Clone the forked repository to your local directory using `git clone`
371
- 3) Install any of the above missing dependencies
372
-
373
- ## Launching the project
374
-
375
- Once the project is installed locally, you are ready to start up its services:
376
-
377
- 1) Ensure that your Docker service is running.
378
- 2) From the root directory of your project, run the `yarn` command in the command prompt to install yarn.
379
- 3) Run the `yarn bootstrap` command to install any necessary dependencies.
380
- 4) Run `yarn test:services:start` to start up this project's Docker container. The container will launch all services within your workspace.
381
-
382
- ## Available Commands
383
-
384
- Once the project is running, you can execute a variety of commands. The root workspace and each subpackage contain a `package.json` file with a `scripts` field listing all the commands that can be executed from that directory. This project also supports native `yarn`, and `docker` commands.
385
-
386
- Here, we'll cover the primary commands that can be executed from the root directory. Unless otherwise noted, these commands can also be executed from a subpackage. If executed from a subpackage, they will only affect that subpackage, rather than the entire workspace.
387
-
388
- ### `yarn`
389
-
390
- The `yarn` command installs yarn in the workspace.
391
-
392
- ### `yarn bootstrap`
393
-
394
- The `yarn bootstrap` command installs all dependencies in the workspace.
395
-
396
- ### `yarn test:services:start`
397
-
398
- The `yarn test:services:start` command starts up the project's Docker container, launching all services in the workspace. This command must be executed from the root directory.
399
-
400
- ### `yarn test:services:stop`
401
-
402
- The `yarn test:services:stop` command brings down the project's Docker container, halting all services. This command must be executed from the root directory.
403
-
404
- ### `yarn test`
405
-
406
- The `yarn test` command runs all tests in the workspace.
407
-
408
- ### `yarn clean`
409
-
410
- The `yarn clean` command removes yarn and all dependencies installed by yarn. After executing this command, you must repeat the steps in *Setting up your workspace* to rebuild your workspace.
411
-
412
- ## Contributing Changes
413
-
414
- Now that you've set up your workspace, you're ready to contribute changes to the `keyv` repository.
415
-
416
- 1) Make any changes that you would like to contribute in your local workspace.
417
- 2) After making these changes, ensure that the project's tests still pass by executing the `yarn test` command in the root directory.
418
- 3) Commit your changes and push them to your forked repository.
419
- 4) Navigate to the original `keyv` repository and go the *Pull Requests* tab.
420
- 5) Click the *New pull request* button, and open a pull request for the branch in your repository that contains your changes.
421
- 6) Once your pull request is created, ensure that all checks have passed and that your branch has no conflicts with the base branch. If there are any issues, resolve these changes in your local repository, and then commit and push them to git.
422
- 7) Similarly, respond to any reviewer comments or requests for changes by making edits to your local repository and pushing them to Git.
423
- 8) Once the pull request has been reviewed, those with write access to the branch will be able to merge your changes into the `keyv` repository.
429
+ We welcome contributions to Keyv! 🎉 Here are some guides to get you started with contributing:
424
430
 
425
- If you need more information on the steps to create a pull request, you can find a detailed walkthrough in the [Github documentation](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork)
431
+ * [Contributing](https://github.com/jaredwray/keyv/blob/main/CONTRIBUTING.md) - Learn about how to contribute to Keyv
432
+ * [Code of Conduct](https://github.com/jaredwray/keyv/blob/main/CODE_OF_CONDUCT.md) - Learn about the Keyv Code of Conduct
433
+ * [How to Contribute](https://github.com/jaredwray/keyv/blob/main/README.md) - How do develop in the Keyv mono repo!
426
434
 
427
- ## License
435
+ # License
428
436
 
429
- MIT © Jared Wray
437
+ [MIT © Jared Wray](LICENSE)
@@ -0,0 +1,16 @@
1
+ type EventListener = (...arguments_: any[]) => void;
2
+ declare class EventManager {
3
+ _eventListeners: Map<string, EventListener[]>;
4
+ _maxListeners: number;
5
+ constructor();
6
+ maxListeners(): number;
7
+ addListener(event: string, listener: EventListener): void;
8
+ on(event: string, listener: EventListener): void;
9
+ removeListener(event: string, listener: EventListener): void;
10
+ off(event: string, listener: EventListener): void;
11
+ emit(event: string, ...arguments_: any[]): void;
12
+ listeners(event: string): EventListener[];
13
+ removeAllListeners(event?: string): void;
14
+ setMaxListeners(n: number): void;
15
+ }
16
+ export default EventManager;
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class EventManager {
4
+ _eventListeners;
5
+ _maxListeners;
6
+ constructor() {
7
+ this._eventListeners = new Map();
8
+ this._maxListeners = 100; // Default maximum number of listeners
9
+ }
10
+ maxListeners() {
11
+ return this._maxListeners;
12
+ }
13
+ // Add an event listener
14
+ addListener(event, listener) {
15
+ this.on(event, listener);
16
+ }
17
+ on(event, listener) {
18
+ if (!this._eventListeners.has(event)) {
19
+ this._eventListeners.set(event, []);
20
+ }
21
+ const listeners = this._eventListeners.get(event);
22
+ if (listeners) {
23
+ if (listeners.length >= this._maxListeners) {
24
+ console.warn(`MaxListenersExceededWarning: Possible event memory leak detected. ${listeners.length + 1} ${event} listeners added. Use setMaxListeners() to increase limit.`);
25
+ }
26
+ listeners.push(listener);
27
+ }
28
+ }
29
+ // Remove an event listener
30
+ removeListener(event, listener) {
31
+ this.off(event, listener);
32
+ }
33
+ off(event, listener) {
34
+ const listeners = this._eventListeners.get(event) ?? [];
35
+ const index = listeners.indexOf(listener);
36
+ if (index > -1) {
37
+ listeners.splice(index, 1);
38
+ }
39
+ if (listeners.length === 0) {
40
+ this._eventListeners.delete(event);
41
+ }
42
+ }
43
+ // Emit an event
44
+ emit(event, ...arguments_) {
45
+ const listeners = this._eventListeners.get(event);
46
+ if (listeners && listeners.length > 0) {
47
+ for (const listener of listeners) {
48
+ listener(...arguments_);
49
+ }
50
+ }
51
+ else if (event === 'error') {
52
+ // If it's an 'error' event with no listeners, throw the error.
53
+ if (arguments_[0] instanceof Error) {
54
+ throw arguments_[0]; // Throws the error object if the first arg is an error
55
+ }
56
+ else {
57
+ const error = new CustomError(arguments_[0]);
58
+ error.context = arguments_[0];
59
+ throw error;
60
+ }
61
+ }
62
+ }
63
+ // Get all listeners for a specific event
64
+ listeners(event) {
65
+ return this._eventListeners.get(event) ?? [];
66
+ }
67
+ // Remove all listeners for a specific event
68
+ removeAllListeners(event) {
69
+ if (event) {
70
+ this._eventListeners.delete(event);
71
+ }
72
+ else {
73
+ this._eventListeners.clear();
74
+ }
75
+ }
76
+ // Set the maximum number of listeners for a single event
77
+ setMaxListeners(n) {
78
+ this._maxListeners = n;
79
+ }
80
+ }
81
+ class CustomError extends Error {
82
+ context;
83
+ constructor(message, context) {
84
+ super(message);
85
+ this.context = context;
86
+ // Maintains proper stack trace for where our error was thrown (only available on V8)
87
+ if (Error.captureStackTrace) {
88
+ Error.captureStackTrace(this, CustomError);
89
+ }
90
+ this.name = this.constructor.name;
91
+ }
92
+ }
93
+ exports.default = EventManager;
94
+ module.exports = EventManager;
95
+ //# sourceMappingURL=event-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-manager.js","sourceRoot":"","sources":["../../src/event-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import EventManager from './event-manager.js';
2
+ type HookHandler = (...arguments_: any[]) => void;
3
+ declare class HooksManager extends EventManager {
4
+ _hookHandlers: Map<string, HookHandler[]>;
5
+ constructor();
6
+ addHandler(event: string, handler: HookHandler): void;
7
+ removeHandler(event: string, handler: HookHandler): void;
8
+ trigger(event: string, data: any): void;
9
+ get handlers(): Map<string, HookHandler[]>;
10
+ }
11
+ export default HooksManager;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const event_manager_js_1 = __importDefault(require("./event-manager.js"));
7
+ class HooksManager extends event_manager_js_1.default {
8
+ _hookHandlers;
9
+ constructor() {
10
+ super();
11
+ this._hookHandlers = new Map();
12
+ }
13
+ // Adds a handler function for a specific event
14
+ addHandler(event, handler) {
15
+ const eventHandlers = this._hookHandlers.get(event);
16
+ if (eventHandlers) {
17
+ eventHandlers.push(handler);
18
+ }
19
+ else {
20
+ this._hookHandlers.set(event, [handler]);
21
+ }
22
+ }
23
+ // Removes a specific handler function for a specific event
24
+ removeHandler(event, handler) {
25
+ const eventHandlers = this._hookHandlers.get(event);
26
+ if (eventHandlers) {
27
+ const index = eventHandlers.indexOf(handler);
28
+ if (index !== -1) {
29
+ eventHandlers.splice(index, 1);
30
+ }
31
+ }
32
+ }
33
+ // Triggers all handlers for a specific event with provided data
34
+ trigger(event, data) {
35
+ const eventHandlers = this._hookHandlers.get(event);
36
+ if (eventHandlers) {
37
+ for (const handler of eventHandlers) {
38
+ try {
39
+ handler(data);
40
+ }
41
+ catch (error) {
42
+ this.emit('error', new Error(`Error in hook handler for event "${event}": ${error.message}`));
43
+ }
44
+ }
45
+ }
46
+ }
47
+ // Provides read-only access to the current handlers
48
+ get handlers() {
49
+ // Creating a new map to prevent external modifications to the original map
50
+ return new Map(this._hookHandlers);
51
+ }
52
+ }
53
+ exports.default = HooksManager;
54
+ module.exports = HooksManager;
55
+ //# sourceMappingURL=hooks-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks-manager.js","sourceRoot":"","sources":["../../src/hooks-manager.ts"],"names":[],"mappings":";;;;;AAAA,0EAA8C;AAI9C,MAAM,YAAa,SAAQ,0BAAY;IACtC,aAAa,CAA6B;IAE1C;QACC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,aAAa,GAAG,IAAI,GAAG,EAAE,CAAC;IAChC,CAAC;IAED,+CAA+C;IAC/C,UAAU,CAAC,KAAa,EAAE,OAAoB;QAC7C,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACpD,IAAI,aAAa,EAAE,CAAC;YACnB,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAC1C,CAAC;IACF,CAAC;IAED,2DAA2D;IAC3D,aAAa,CAAC,KAAa,EAAE,OAAoB;QAChD,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACpD,IAAI,aAAa,EAAE,CAAC;YACnB,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAC7C,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;gBAClB,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YAChC,CAAC;QACF,CAAC;IACF,CAAC;IAED,gEAAgE;IAChE,OAAO,CAAC,KAAa,EAAE,IAAS;QAC/B,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACpD,IAAI,aAAa,EAAE,CAAC;YACnB,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;gBACrC,IAAI,CAAC;oBACJ,OAAO,CAAC,IAAI,CAAC,CAAC;gBACf,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAChB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,KAAK,CAAC,oCAAoC,KAAK,MAAc,KAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;gBACxG,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAED,oDAAoD;IACpD,IAAI,QAAQ;QACX,2EAA2E;QAC3E,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IACpC,CAAC;CACD;AAED,kBAAe,YAAY,CAAC;AAC5B,MAAM,CAAC,OAAO,GAAG,YAAY,CAAC"}