@kikiutils/shared 13.1.0 → 13.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.
@@ -18,9 +18,10 @@ declare class EventAwaiter<T> {
18
18
  * Each promise will be resolved with the provided value.
19
19
  *
20
20
  * @param {string} [key] - Identifier for the awaited event
21
- * @param {T} [value] - Optional value to resolve the awaiting promises with
21
+ * @param {T | undefined} value - The value to resolve the awaiting promises with.
22
+ * May be `undefined` to indicate no result or a timeout-like behavior.
22
23
  */
23
- trigger(key: string, value?: T): void;
24
+ trigger(key: string, value: T | undefined): void;
24
25
  /**
25
26
  * Waits for an event associated with the given key.
26
27
  *
@@ -28,16 +29,41 @@ declare class EventAwaiter<T> {
28
29
  * - `trigger(key)` is called, in which case it resolves with the provided value.
29
30
  * - The optional timeout is reached, in which case it resolves with `undefined`.
30
31
  *
31
- * Multiple consumers can wait on the same key; all of them will be notified when triggered.
32
+ * Behavior when multiple waiters exist for the same key:
33
+ * - Default (no mode): multiple waiters are allowed, all will be resolved when triggered.
34
+ * - `strict` mode: throws an error if a waiter already exists for the given key.
35
+ * - `override` mode: cancels all existing waiters (resolving them with `undefined`)
36
+ * and only keeps the latest one.
32
37
  *
33
- * @param {string} [key] - Identifier for the awaited event
38
+ * @param {string} key - Identifier for the awaited event
34
39
  * @param {number} [timeoutMs] - Optional timeout (in milliseconds).
35
- * If reached, the promise resolves with `undefined`
40
+ * If reached, the promise resolves with `undefined`.
41
+ * @param {'override' | 'strict'} [mode] - Optional behavior mode for handling multiple waiters.
36
42
  *
37
43
  * @returns {Promise<T | undefined>} A promise that resolves with the triggered value
38
44
  * or `undefined` if timeout occurs
39
45
  */
40
- wait(key: string, timeoutMs?: number): Promise<T | undefined>;
46
+ wait(key: string, timeoutMs?: number, mode?: 'override' | 'strict'): Promise<T | undefined>;
47
+ /**
48
+ * Waits for an event in strict mode.
49
+ * Only one waiter is allowed per key. If another waiter already exists,
50
+ * this method will throw an error.
51
+ *
52
+ * @param {string} key - Identifier for the awaited event
53
+ * @param {number} [timeoutMs] - Optional timeout (in milliseconds).
54
+ * If reached, the promise resolves with `undefined`.
55
+ */
56
+ waitExclusive(key: string, timeoutMs?: number): Promise<T | undefined>;
57
+ /**
58
+ * Waits for an event in override mode.
59
+ * If another waiter already exists for the given key, it will be canceled
60
+ * (resolved with `undefined`) and replaced by the new waiter.
61
+ *
62
+ * @param {string} key - Identifier for the awaited event
63
+ * @param {number} [timeoutMs] - Optional timeout (in milliseconds).
64
+ * If reached, the promise resolves with `undefined`.
65
+ */
66
+ waitLatest(key: string, timeoutMs?: number): Promise<T | undefined>;
41
67
  }
42
68
  //#endregion
43
69
  export { EventAwaiter };
@@ -1 +1 @@
1
- {"version":3,"file":"event-awaiter.d.ts","names":[],"sources":["../src/event-awaiter.ts"],"sourcesContent":[],"mappings":";;AAYA;;;;;;;;;;;cAAa;;;;;;;;;+BAUoB;;;;;;;;;;;;;;;;;yCAwBO,QAAA"}
1
+ {"version":3,"file":"event-awaiter.d.ts","names":[],"sources":["../src/event-awaiter.ts"],"sourcesContent":[],"mappings":";;AAYA;;;;;;;;;;;cAAa;;;;;;;;;;8BAWmB;;;;;;;;;;;;;;;;;;;;;;uEA6BsC,QAAA;;;;;;;;;;kDA0CrB,QAAA;;;;;;;;;;+CAaH,QAAA"}
@@ -18,7 +18,8 @@ var EventAwaiter = class {
18
18
  * Each promise will be resolved with the provided value.
19
19
  *
20
20
  * @param {string} [key] - Identifier for the awaited event
21
- * @param {T} [value] - Optional value to resolve the awaiting promises with
21
+ * @param {T | undefined} value - The value to resolve the awaiting promises with.
22
+ * May be `undefined` to indicate no result or a timeout-like behavior.
22
23
  */
23
24
  trigger(key, value) {
24
25
  const resolvers = this.#promiseResolvers.get(key);
@@ -34,18 +35,30 @@ var EventAwaiter = class {
34
35
  * - `trigger(key)` is called, in which case it resolves with the provided value.
35
36
  * - The optional timeout is reached, in which case it resolves with `undefined`.
36
37
  *
37
- * Multiple consumers can wait on the same key; all of them will be notified when triggered.
38
+ * Behavior when multiple waiters exist for the same key:
39
+ * - Default (no mode): multiple waiters are allowed, all will be resolved when triggered.
40
+ * - `strict` mode: throws an error if a waiter already exists for the given key.
41
+ * - `override` mode: cancels all existing waiters (resolving them with `undefined`)
42
+ * and only keeps the latest one.
38
43
  *
39
- * @param {string} [key] - Identifier for the awaited event
44
+ * @param {string} key - Identifier for the awaited event
40
45
  * @param {number} [timeoutMs] - Optional timeout (in milliseconds).
41
- * If reached, the promise resolves with `undefined`
46
+ * If reached, the promise resolves with `undefined`.
47
+ * @param {'override' | 'strict'} [mode] - Optional behavior mode for handling multiple waiters.
42
48
  *
43
49
  * @returns {Promise<T | undefined>} A promise that resolves with the triggered value
44
50
  * or `undefined` if timeout occurs
45
51
  */
46
- wait(key, timeoutMs) {
52
+ wait(key, timeoutMs, mode) {
47
53
  return new Promise((resolve) => {
48
54
  const resolvers = this.#promiseResolvers.get(key) || [];
55
+ if (resolvers.length) switch (mode) {
56
+ case "override":
57
+ resolvers.forEach((r) => r(void 0));
58
+ resolvers.length = 0;
59
+ break;
60
+ case "strict": throw new Error(`Duplicate wait detected for key: ${key}`);
61
+ }
49
62
  resolvers.push(resolve);
50
63
  this.#promiseResolvers.set(key, resolvers);
51
64
  if (timeoutMs) setTimeout(() => {
@@ -59,6 +72,30 @@ var EventAwaiter = class {
59
72
  }, timeoutMs);
60
73
  });
61
74
  }
75
+ /**
76
+ * Waits for an event in strict mode.
77
+ * Only one waiter is allowed per key. If another waiter already exists,
78
+ * this method will throw an error.
79
+ *
80
+ * @param {string} key - Identifier for the awaited event
81
+ * @param {number} [timeoutMs] - Optional timeout (in milliseconds).
82
+ * If reached, the promise resolves with `undefined`.
83
+ */
84
+ waitExclusive(key, timeoutMs) {
85
+ return this.wait(key, timeoutMs, "strict");
86
+ }
87
+ /**
88
+ * Waits for an event in override mode.
89
+ * If another waiter already exists for the given key, it will be canceled
90
+ * (resolved with `undefined`) and replaced by the new waiter.
91
+ *
92
+ * @param {string} key - Identifier for the awaited event
93
+ * @param {number} [timeoutMs] - Optional timeout (in milliseconds).
94
+ * If reached, the promise resolves with `undefined`.
95
+ */
96
+ waitLatest(key, timeoutMs) {
97
+ return this.wait(key, timeoutMs, "override");
98
+ }
62
99
  };
63
100
 
64
101
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"event-awaiter.js","names":["#promiseResolvers","resolvers"],"sources":["../src/event-awaiter.ts"],"sourcesContent":["/**\n * EventAwaiter provides a mechanism to wait for events (by key) asynchronously.\n *\n * This class allows multiple consumers to `wait` for a specific key\n * and be resolved when `trigger` is called for that key, or automatically\n * resolved with `undefined` if a timeout occurs.\n *\n * Typical use cases include long-polling, request coordination,\n * or implementing event-driven primitives in applications or services.\n *\n * @template T - The type of value that will be resolved when the event is triggered\n */\nexport class EventAwaiter<T> {\n #promiseResolvers = new Map<string, ((value: PromiseLike<T | undefined> | T | undefined) => void)[]>();\n\n /**\n * Triggers all pending promises waiting for the given key.\n * Each promise will be resolved with the provided value.\n *\n * @param {string} [key] - Identifier for the awaited event\n * @param {T} [value] - Optional value to resolve the awaiting promises with\n */\n trigger(key: string, value?: T) {\n const resolvers = this.#promiseResolvers.get(key);\n if (resolvers) {\n this.#promiseResolvers.delete(key);\n resolvers?.forEach((resolve) => resolve(value));\n }\n }\n\n /**\n * Waits for an event associated with the given key.\n *\n * The returned promise will resolve when:\n * - `trigger(key)` is called, in which case it resolves with the provided value.\n * - The optional timeout is reached, in which case it resolves with `undefined`.\n *\n * Multiple consumers can wait on the same key; all of them will be notified when triggered.\n *\n * @param {string} [key] - Identifier for the awaited event\n * @param {number} [timeoutMs] - Optional timeout (in milliseconds).\n * If reached, the promise resolves with `undefined`\n *\n * @returns {Promise<T | undefined>} A promise that resolves with the triggered value\n * or `undefined` if timeout occurs\n */\n wait(key: string, timeoutMs?: number) {\n return new Promise<T | undefined>((resolve) => {\n const resolvers = this.#promiseResolvers.get(key) || [];\n resolvers.push(resolve);\n this.#promiseResolvers.set(key, resolvers);\n if (timeoutMs) {\n setTimeout(\n () => {\n const resolvers = this.#promiseResolvers.get(key);\n if (resolvers?.includes(resolve)) {\n resolve(undefined);\n const newResolvers = resolvers.filter((r) => r !== resolve);\n if (newResolvers.length) this.#promiseResolvers.set(key, newResolvers);\n else this.#promiseResolvers.delete(key);\n }\n },\n timeoutMs,\n );\n }\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAYA,IAAa,eAAb,MAA6B;CACzB,oCAAoB,IAAI,KAA8E;;;;;;;;CAStG,QAAQ,KAAa,OAAW;EAC5B,MAAM,YAAY,MAAKA,iBAAkB,IAAI,IAAI;AACjD,MAAI,WAAW;AACX,SAAKA,iBAAkB,OAAO,IAAI;AAClC,cAAW,SAAS,YAAY,QAAQ,MAAM,CAAC;;;;;;;;;;;;;;;;;;;CAoBvD,KAAK,KAAa,WAAoB;AAClC,SAAO,IAAI,SAAwB,YAAY;GAC3C,MAAM,YAAY,MAAKA,iBAAkB,IAAI,IAAI,IAAI,EAAE;AACvD,aAAU,KAAK,QAAQ;AACvB,SAAKA,iBAAkB,IAAI,KAAK,UAAU;AAC1C,OAAI,UACA,kBACU;IACF,MAAMC,cAAY,MAAKD,iBAAkB,IAAI,IAAI;AACjD,QAAIC,aAAW,SAAS,QAAQ,EAAE;AAC9B,aAAQ,OAAU;KAClB,MAAM,eAAeA,YAAU,QAAQ,MAAM,MAAM,QAAQ;AAC3D,SAAI,aAAa,OAAQ,OAAKD,iBAAkB,IAAI,KAAK,aAAa;SACjE,OAAKA,iBAAkB,OAAO,IAAI;;MAG/C,UACH;IAEP"}
1
+ {"version":3,"file":"event-awaiter.js","names":["#promiseResolvers","resolvers"],"sources":["../src/event-awaiter.ts"],"sourcesContent":["/**\n * EventAwaiter provides a mechanism to wait for events (by key) asynchronously.\n *\n * This class allows multiple consumers to `wait` for a specific key\n * and be resolved when `trigger` is called for that key, or automatically\n * resolved with `undefined` if a timeout occurs.\n *\n * Typical use cases include long-polling, request coordination,\n * or implementing event-driven primitives in applications or services.\n *\n * @template T - The type of value that will be resolved when the event is triggered\n */\nexport class EventAwaiter<T> {\n #promiseResolvers = new Map<string, ((value: PromiseLike<T | undefined> | T | undefined) => void)[]>();\n\n /**\n * Triggers all pending promises waiting for the given key.\n * Each promise will be resolved with the provided value.\n *\n * @param {string} [key] - Identifier for the awaited event\n * @param {T | undefined} value - The value to resolve the awaiting promises with.\n * May be `undefined` to indicate no result or a timeout-like behavior.\n */\n trigger(key: string, value: T | undefined) {\n const resolvers = this.#promiseResolvers.get(key);\n if (resolvers) {\n this.#promiseResolvers.delete(key);\n resolvers?.forEach((resolve) => resolve(value));\n }\n }\n\n /**\n * Waits for an event associated with the given key.\n *\n * The returned promise will resolve when:\n * - `trigger(key)` is called, in which case it resolves with the provided value.\n * - The optional timeout is reached, in which case it resolves with `undefined`.\n *\n * Behavior when multiple waiters exist for the same key:\n * - Default (no mode): multiple waiters are allowed, all will be resolved when triggered.\n * - `strict` mode: throws an error if a waiter already exists for the given key.\n * - `override` mode: cancels all existing waiters (resolving them with `undefined`)\n * and only keeps the latest one.\n *\n * @param {string} key - Identifier for the awaited event\n * @param {number} [timeoutMs] - Optional timeout (in milliseconds).\n * If reached, the promise resolves with `undefined`.\n * @param {'override' | 'strict'} [mode] - Optional behavior mode for handling multiple waiters.\n *\n * @returns {Promise<T | undefined>} A promise that resolves with the triggered value\n * or `undefined` if timeout occurs\n */\n wait(key: string, timeoutMs?: number, mode?: 'override' | 'strict') {\n return new Promise<T | undefined>((resolve) => {\n const resolvers = this.#promiseResolvers.get(key) || [];\n if (resolvers.length) {\n switch (mode) {\n case 'override':\n resolvers.forEach((r) => r(undefined));\n resolvers.length = 0;\n break;\n case 'strict':\n throw new Error(`Duplicate wait detected for key: ${key}`);\n }\n }\n\n resolvers.push(resolve);\n this.#promiseResolvers.set(key, resolvers);\n if (timeoutMs) {\n setTimeout(\n () => {\n const resolvers = this.#promiseResolvers.get(key);\n if (resolvers?.includes(resolve)) {\n resolve(undefined);\n const newResolvers = resolvers.filter((r) => r !== resolve);\n if (newResolvers.length) this.#promiseResolvers.set(key, newResolvers);\n else this.#promiseResolvers.delete(key);\n }\n },\n timeoutMs,\n );\n }\n });\n }\n\n /**\n * Waits for an event in strict mode.\n * Only one waiter is allowed per key. If another waiter already exists,\n * this method will throw an error.\n *\n * @param {string} key - Identifier for the awaited event\n * @param {number} [timeoutMs] - Optional timeout (in milliseconds).\n * If reached, the promise resolves with `undefined`.\n */\n waitExclusive(key: string, timeoutMs?: number) {\n return this.wait(key, timeoutMs, 'strict');\n }\n\n /**\n * Waits for an event in override mode.\n * If another waiter already exists for the given key, it will be canceled\n * (resolved with `undefined`) and replaced by the new waiter.\n *\n * @param {string} key - Identifier for the awaited event\n * @param {number} [timeoutMs] - Optional timeout (in milliseconds).\n * If reached, the promise resolves with `undefined`.\n */\n waitLatest(key: string, timeoutMs?: number) {\n return this.wait(key, timeoutMs, 'override');\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAYA,IAAa,eAAb,MAA6B;CACzB,oCAAoB,IAAI,KAA8E;;;;;;;;;CAUtG,QAAQ,KAAa,OAAsB;EACvC,MAAM,YAAY,MAAKA,iBAAkB,IAAI,IAAI;AACjD,MAAI,WAAW;AACX,SAAKA,iBAAkB,OAAO,IAAI;AAClC,cAAW,SAAS,YAAY,QAAQ,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;CAyBvD,KAAK,KAAa,WAAoB,MAA8B;AAChE,SAAO,IAAI,SAAwB,YAAY;GAC3C,MAAM,YAAY,MAAKA,iBAAkB,IAAI,IAAI,IAAI,EAAE;AACvD,OAAI,UAAU,OACV,SAAQ,MAAR;IACI,KAAK;AACD,eAAU,SAAS,MAAM,EAAE,OAAU,CAAC;AACtC,eAAU,SAAS;AACnB;IACJ,KAAK,SACD,OAAM,IAAI,MAAM,oCAAoC,MAAM;;AAItE,aAAU,KAAK,QAAQ;AACvB,SAAKA,iBAAkB,IAAI,KAAK,UAAU;AAC1C,OAAI,UACA,kBACU;IACF,MAAMC,cAAY,MAAKD,iBAAkB,IAAI,IAAI;AACjD,QAAIC,aAAW,SAAS,QAAQ,EAAE;AAC9B,aAAQ,OAAU;KAClB,MAAM,eAAeA,YAAU,QAAQ,MAAM,MAAM,QAAQ;AAC3D,SAAI,aAAa,OAAQ,OAAKD,iBAAkB,IAAI,KAAK,aAAa;SACjE,OAAKA,iBAAkB,OAAO,IAAI;;MAG/C,UACH;IAEP;;;;;;;;;;;CAYN,cAAc,KAAa,WAAoB;AAC3C,SAAO,KAAK,KAAK,KAAK,WAAW,SAAS;;;;;;;;;;;CAY9C,WAAW,KAAa,WAAoB;AACxC,SAAO,KAAK,KAAK,KAAK,WAAW,WAAW"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kikiutils/shared",
3
3
  "type": "module",
4
- "version": "13.1.0",
4
+ "version": "13.2.0",
5
5
  "description": "A lightweight and modular utility library for modern JavaScript and TypeScript — includes secure hashing, flexible logging, datetime tools, Vue/web helpers, storage abstraction, and more.",
6
6
  "author": "kiki-kanri",
7
7
  "license": "MIT",
@@ -18,9 +18,10 @@ export class EventAwaiter<T> {
18
18
  * Each promise will be resolved with the provided value.
19
19
  *
20
20
  * @param {string} [key] - Identifier for the awaited event
21
- * @param {T} [value] - Optional value to resolve the awaiting promises with
21
+ * @param {T | undefined} value - The value to resolve the awaiting promises with.
22
+ * May be `undefined` to indicate no result or a timeout-like behavior.
22
23
  */
23
- trigger(key: string, value?: T) {
24
+ trigger(key: string, value: T | undefined) {
24
25
  const resolvers = this.#promiseResolvers.get(key);
25
26
  if (resolvers) {
26
27
  this.#promiseResolvers.delete(key);
@@ -35,18 +36,34 @@ export class EventAwaiter<T> {
35
36
  * - `trigger(key)` is called, in which case it resolves with the provided value.
36
37
  * - The optional timeout is reached, in which case it resolves with `undefined`.
37
38
  *
38
- * Multiple consumers can wait on the same key; all of them will be notified when triggered.
39
+ * Behavior when multiple waiters exist for the same key:
40
+ * - Default (no mode): multiple waiters are allowed, all will be resolved when triggered.
41
+ * - `strict` mode: throws an error if a waiter already exists for the given key.
42
+ * - `override` mode: cancels all existing waiters (resolving them with `undefined`)
43
+ * and only keeps the latest one.
39
44
  *
40
- * @param {string} [key] - Identifier for the awaited event
45
+ * @param {string} key - Identifier for the awaited event
41
46
  * @param {number} [timeoutMs] - Optional timeout (in milliseconds).
42
- * If reached, the promise resolves with `undefined`
47
+ * If reached, the promise resolves with `undefined`.
48
+ * @param {'override' | 'strict'} [mode] - Optional behavior mode for handling multiple waiters.
43
49
  *
44
50
  * @returns {Promise<T | undefined>} A promise that resolves with the triggered value
45
51
  * or `undefined` if timeout occurs
46
52
  */
47
- wait(key: string, timeoutMs?: number) {
53
+ wait(key: string, timeoutMs?: number, mode?: 'override' | 'strict') {
48
54
  return new Promise<T | undefined>((resolve) => {
49
55
  const resolvers = this.#promiseResolvers.get(key) || [];
56
+ if (resolvers.length) {
57
+ switch (mode) {
58
+ case 'override':
59
+ resolvers.forEach((r) => r(undefined));
60
+ resolvers.length = 0;
61
+ break;
62
+ case 'strict':
63
+ throw new Error(`Duplicate wait detected for key: ${key}`);
64
+ }
65
+ }
66
+
50
67
  resolvers.push(resolve);
51
68
  this.#promiseResolvers.set(key, resolvers);
52
69
  if (timeoutMs) {
@@ -65,4 +82,30 @@ export class EventAwaiter<T> {
65
82
  }
66
83
  });
67
84
  }
85
+
86
+ /**
87
+ * Waits for an event in strict mode.
88
+ * Only one waiter is allowed per key. If another waiter already exists,
89
+ * this method will throw an error.
90
+ *
91
+ * @param {string} key - Identifier for the awaited event
92
+ * @param {number} [timeoutMs] - Optional timeout (in milliseconds).
93
+ * If reached, the promise resolves with `undefined`.
94
+ */
95
+ waitExclusive(key: string, timeoutMs?: number) {
96
+ return this.wait(key, timeoutMs, 'strict');
97
+ }
98
+
99
+ /**
100
+ * Waits for an event in override mode.
101
+ * If another waiter already exists for the given key, it will be canceled
102
+ * (resolved with `undefined`) and replaced by the new waiter.
103
+ *
104
+ * @param {string} key - Identifier for the awaited event
105
+ * @param {number} [timeoutMs] - Optional timeout (in milliseconds).
106
+ * If reached, the promise resolves with `undefined`.
107
+ */
108
+ waitLatest(key: string, timeoutMs?: number) {
109
+ return this.wait(key, timeoutMs, 'override');
110
+ }
68
111
  }