From d6fad15a1034cb740842452198ed98e002724e85 Mon Sep 17 00:00:00 2001
From: Volker Schukai <volker.schukai@schukai.com>
Date: Mon, 7 Oct 2024 21:10:18 +0200
Subject: [PATCH] doc: some optimisations

---
 source/components/layout/collapse.mjs         |  8 +--
 .../server/restapi/data-fetch-error.mjs       |  1 -
 source/dom/customcontrol.mjs                  | 25 ---------
 source/dom/customelement.mjs                  |  8 ---
 source/i18n/formatter.mjs                     |  2 -
 source/i18n/locale.mjs                        |  2 -
 source/i18n/provider.mjs                      |  2 -
 source/i18n/translations.mjs                  |  1 -
 source/logging/handler.mjs                    |  1 -
 source/logging/handler/console.mjs            |  1 -
 source/logging/logger.mjs                     | 13 +----
 source/net/webconnect/message.mjs             |  1 -
 source/types/basewithoptions.mjs              |  3 +-
 source/types/noderecursiveiterator.mjs        |  6 +-
 source/types/observablequeue.mjs              |  4 --
 source/types/observer.mjs                     |  3 -
 source/types/observerlist.mjs                 |  2 -
 source/types/queue.mjs                        |  1 -
 source/util/processing.mjs                    | 42 +-------------
 source/util/processing/callback.mjs           | 56 +++++++++++++++++++
 20 files changed, 66 insertions(+), 116 deletions(-)
 create mode 100644 source/util/processing/callback.mjs

diff --git a/source/components/layout/collapse.mjs b/source/components/layout/collapse.mjs
index 65e687f3e..701508b1f 100644
--- a/source/components/layout/collapse.mjs
+++ b/source/components/layout/collapse.mjs
@@ -201,8 +201,8 @@ class Collapse extends CustomElement {
 	/**
 	 * Open the collapse
 	 * @returns {Collapse}
-	 * @fires event:monster-collapse-before-open
-	 * @fires event:monster-collapse-open
+	 * @fires monster-collapse-before-open
+	 * @fires monster-collapse-open
 	 */
 	open() {
 		let node;
@@ -245,8 +245,8 @@ class Collapse extends CustomElement {
 	/**
 	 * Close the collapse
 	 * @returns {Collapse}
-	 * @fires event:monster-collapse-before-close
-	 * @fires event:monster-collapse-closed
+	 * @fires monster-collapse-before-close
+	 * @fires monster-collapse-closed
 	 */
 	close() {
 		if (!this[detailsElementSymbol].classList.contains("active")) {
diff --git a/source/data/datasource/server/restapi/data-fetch-error.mjs b/source/data/datasource/server/restapi/data-fetch-error.mjs
index 074e8f8e9..d27fe0ca1 100644
--- a/source/data/datasource/server/restapi/data-fetch-error.mjs
+++ b/source/data/datasource/server/restapi/data-fetch-error.mjs
@@ -41,7 +41,6 @@ class DataFetchError extends Error {
 	/**
 	 * This method is called by the `instanceof` operator.
 	 * @returns {symbol}
-	 * @since 2.1.0
 	 */
 	static get [instanceSymbol]() {
 		return Symbol.for(
diff --git a/source/dom/customcontrol.mjs b/source/dom/customcontrol.mjs
index abfb279ec..4169dfcb7 100644
--- a/source/dom/customcontrol.mjs
+++ b/source/dom/customcontrol.mjs
@@ -32,8 +32,6 @@ const attachedInternalSymbol = Symbol("attachedInternal");
  * After defining a `CustomElement`, the `registerCustomElement` method must be called with the new class name. Only then
  * will the tag defined via the `getTag` method be made known to the DOM.
  *
- * <img src="./images/custom-control.png">
- *
  * This control uses `attachInternals()` to integrate the control into a form. If the target environment does not support
  * this method, the [polyfill](https://www.npmjs.com/package/element-internals-polyfill) can be used.
  *
@@ -48,18 +46,9 @@ const attachedInternalSymbol = Symbol("attachedInternal");
  *
  * Read the HTML specification for Custom Element Reactions: {@link https://html.spec.whatwg.org/dev/custom-elements.html#custom-element-reactions|Custom Element Reactions}.
  *
- * @startuml custom-control.png
- * skinparam monochrome true
- * skinparam shadowing false
- * HTMLElement <|-- CustomElement
- * CustomElement <|-- CustomControl
- * @enduml
  * @summary A base class for custom controls based on CustomElement.
- * @copyright schukai GmbH
  * @license AGPLv3
  * @since 1.14.0
- * @memberOf Monster.DOM
- * @extends Monster.DOM.CustomElement
  */
 class CustomControl extends CustomElement {
 	/**
@@ -74,7 +63,6 @@ class CustomControl extends CustomElement {
 	 *
 	 * @inheritdoc
 	 * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
-	 * @since 1.7.0
 	 */
 	constructor() {
 		super();
@@ -117,14 +105,12 @@ class CustomControl extends CustomElement {
 	 *
 	 * @see [attachInternals()]{@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals}
 	 * @see [Custom Elements Face Example]{@link https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-face-example}
-	 * @since 1.14.0
 	 * @return {boolean}
 	 */
 	static formAssociated = true;
 
 	/**
 	 * @inheritdoc
-	 * @since 1.14.0
 	 **/
 	get defaults() {
 		return extend({}, super.defaults);
@@ -135,7 +121,6 @@ class CustomControl extends CustomElement {
 	 *
 	 * This is a method of [internal API](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals), which is a part of the web standard for custom elements.
 	 *
-	 * @since 1.14.0
 	 * @throws {Error} the value getter must be overwritten by the derived class
 	 */
 	get value() {
@@ -148,7 +133,6 @@ class CustomControl extends CustomElement {
 	 * This is a method of [internal API](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals), which is a part of the web standard for custom elements.
 	 *
 	 * @param {*} value The value to set.
-	 * @since 1.14.0
 	 * @throws {Error} the value setter must be overwritten by the derived class
 	 */
 	set value(value) {
@@ -159,7 +143,6 @@ class CustomControl extends CustomElement {
 	 * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
 	 *
 	 * @return {NodeList}
-	 * @since 1.14.0
 	 * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/labels}
 	 * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
 	 */
@@ -201,7 +184,6 @@ class CustomControl extends CustomElement {
 	 * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
 	 *
 	 * @return {string}
-	 * @since 1.14.0
 	 * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/validationMessage
 	 * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
 	 */
@@ -213,7 +195,6 @@ class CustomControl extends CustomElement {
 	 * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
 	 *
 	 * @return {boolean}
-	 * @since 1.14.0
 	 * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/willValidate
 	 * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
 	 */
@@ -225,7 +206,6 @@ class CustomControl extends CustomElement {
 	 * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
 	 *
 	 * @return {boolean}
-	 * @since 1.14.0
 	 * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/states
 	 * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
 	 */
@@ -237,7 +217,6 @@ class CustomControl extends CustomElement {
 	 * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
 	 *
 	 * @return {HTMLFontElement|null}
-	 * @since 1.14.0
 	 * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/form
 	 * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
 	 */
@@ -259,7 +238,6 @@ class CustomControl extends CustomElement {
 	 *
 	 * @param {File|string|FormData} value
 	 * @param {File|string|FormData} state
-	 * @since 1.14.0
 	 * @return {undefined}
 	 * @throws {DOMException} NotSupportedError
 	 * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
@@ -275,7 +253,6 @@ class CustomControl extends CustomElement {
 	 * @param {string|undefined} message
 	 * @param {HTMLElement} anchor
 	 * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/setValidity
-	 * @since 1.14.0
 	 * @return {undefined}
 	 * @throws {DOMException} NotSupportedError
 	 * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
@@ -288,7 +265,6 @@ class CustomControl extends CustomElement {
 	 * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
 	 *
 	 * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/checkValidity
-	 * @since 1.14.0
 	 * @return {boolean}
 	 * @throws {DOMException} NotSupportedError
 	 * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
@@ -301,7 +277,6 @@ class CustomControl extends CustomElement {
 	 * This is a method of [internal api](https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals)
 	 *
 	 * @return {boolean}
-	 * @since 1.14.0
 	 * @see https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals/reportValidity
 	 * @throws {Error} the ElementInternals is not supported and a polyfill is necessary
 	 * @throws {DOMException} NotSupportedError
diff --git a/source/dom/customelement.mjs b/source/dom/customelement.mjs
index 40b4b34f3..fd614b4a0 100644
--- a/source/dom/customelement.mjs
+++ b/source/dom/customelement.mjs
@@ -170,10 +170,6 @@ const scriptHostElementSymbol = Symbol("scriptHostElement");
  *
  * You can create an instance of the object via the `document.createElement()` function.
  *
- * ## Interaction
- *
- * <img src="./images/customelement-sequencediagram.png">
- *
  * ## Styling
  *
  * To display custom elements optimally, the `:defined` pseudo-class can be used. To prevent custom elements from being displayed and flickering until the control is registered,
@@ -234,12 +230,9 @@ const scriptHostElementSymbol = Symbol("scriptHostElement");
  * More information about Custom Elements can be found in the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements).
  * And in the [HTML Standard](https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements) or in the [WHATWG Wiki](https://wiki.whatwg.org/wiki/Custom_Elements).
  *
- * @externalExample ../../example/dom/theme.mjs
  * @license AGPLv3
  * @since 1.7.0
  * @copyright schukai GmbH
- * @memberOf Monster.DOM
- * @extends external:HTMLElement
  * @summary A base class for HTML5 custom controls.
  */
 class CustomElement extends HTMLElement {
@@ -250,7 +243,6 @@ class CustomElement extends HTMLElement {
 	 * IMPORTANT: CustomControls instances are not created via the constructor, but either via a tag in the HTML or via <code>document.createElement()</code>.
 	 *
 	 * @throws {Error} the options attribute does not contain a valid json definition.
-	 * @since 1.7.0
 	 */
 	constructor() {
 		super();
diff --git a/source/i18n/formatter.mjs b/source/i18n/formatter.mjs
index 8db7e5b0e..f2b40f1fc 100644
--- a/source/i18n/formatter.mjs
+++ b/source/i18n/formatter.mjs
@@ -30,11 +30,9 @@ const internalTranslationSymbol = Symbol("internalTranslation");
 /**
  * The Formatter extends the Text.Formatter with the possibility to replace the key by a translation.
  *
- * @externalExample ../../example/i18n/formatter.mjs
  * @license AGPLv3
  * @since 1.26.0
  * @copyright schukai GmbH
- * @memberOf Monster.I18n
  */
 class Formatter extends TextFormatter {
 	/**
diff --git a/source/i18n/locale.mjs b/source/i18n/locale.mjs
index b13b60a47..c67b95ee6 100644
--- a/source/i18n/locale.mjs
+++ b/source/i18n/locale.mjs
@@ -20,14 +20,12 @@ import { clone } from "../util/clone.mjs";
 export { Locale, parseLocale };
 
 /**
- * @memberOf Monster.I18n
  * @type {symbol}
  */
 const propertiesSymbol = Symbol("properties");
 
 /**
  * @type {symbol}
- * @memberOf Monster.I18n
  */
 const localeStringSymbol = Symbol("localeString");
 
diff --git a/source/i18n/provider.mjs b/source/i18n/provider.mjs
index f6d26675b..c7b87a381 100644
--- a/source/i18n/provider.mjs
+++ b/source/i18n/provider.mjs
@@ -26,7 +26,6 @@ import { Translations } from "./translations.mjs";
 export { Provider, translationsLinkSymbol };
 
 /**
- * @memberOf Monster.I18n
  * @type {symbol}
  * @license AGPLv3
  * @since 3.9.0
@@ -42,7 +41,6 @@ const translationsLinkSymbol = Symbol.for(
  * @license AGPLv3
  * @since 1.13.0
  * @copyright schukai GmbH
- * @memberOf Monster.I18n
  * @see {@link https://datatracker.ietf.org/doc/html/rfc3066}
  */
 class Provider extends BaseWithOptions {
diff --git a/source/i18n/translations.mjs b/source/i18n/translations.mjs
index 705b2806d..c5db03b25 100644
--- a/source/i18n/translations.mjs
+++ b/source/i18n/translations.mjs
@@ -35,7 +35,6 @@ export { Translations, getDocumentTranslations };
  * @license AGPLv3
  * @since 1.13.0
  * @copyright schukai GmbH
- * @memberOf Monster.I18n
  * @see https://datatracker.ietf.org/doc/html/rfc3066
  */
 class Translations extends Base {
diff --git a/source/logging/handler.mjs b/source/logging/handler.mjs
index 984b20f6d..abd00ec16 100644
--- a/source/logging/handler.mjs
+++ b/source/logging/handler.mjs
@@ -25,7 +25,6 @@ export { Handler };
  * @license AGPLv3
  * @since 1.5.0
  * @copyright schukai GmbH
- * @memberOf Monster.Logging
  */
 class Handler extends Base {
 	constructor() {
diff --git a/source/logging/handler/console.mjs b/source/logging/handler/console.mjs
index 85f4ad350..c7b830e6b 100644
--- a/source/logging/handler/console.mjs
+++ b/source/logging/handler/console.mjs
@@ -25,7 +25,6 @@ export { ConsoleHandler };
  * @license AGPLv3
  * @since 1.5.0
  * @copyright schukai GmbH
- * @memberOf Monster.Logging.Handler
  */
 class ConsoleHandler extends Handler {
 	/**
diff --git a/source/logging/logger.mjs b/source/logging/logger.mjs
index 27aa6df95..0b6e1e090 100644
--- a/source/logging/logger.mjs
+++ b/source/logging/logger.mjs
@@ -12,8 +12,8 @@
  * SPDX-License-Identifier: AGPL-3.0
  */
 
-import { Handler } from "../logging/handler.mjs";
-import { LogEntry } from "../logging/logentry.mjs";
+import { Handler } from "./handler.mjs";
+import { LogEntry } from "./logentry.mjs";
 
 import { Base } from "../types/base.mjs";
 import {
@@ -27,49 +27,41 @@ export { Logger, ALL, TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF };
 /**
  * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
  * @type {number}
- * @memberOf Monster.Logging
  */
 const ALL = 255;
 /**
  * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
  * @type {number}
- * @memberOf Monster.Logging
  */
 const TRACE = 64;
 /**
  * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
  * @type {number}
- * @memberOf Monster.Logging
  */
 const DEBUG = 32;
 /**
  * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
  * @type {number}
- * @memberOf Monster.Logging
  */
 const INFO = 16;
 /**
  * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
  * @type {number}
- * @memberOf Monster.Logging
  */
 const WARN = 8;
 /**
  * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
  * @type {number}
- * @memberOf Monster.Logging
  */
 const ERROR = 4;
 /**
  * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
  * @type {number}
- * @memberOf Monster.Logging
  */
 const FATAL = 2;
 /**
  * ALL > TRACE > DEBUG > INFO > WARN > ERROR > FATAL > OFF
  * @type {number}
- * @memberOf Monster.Logging
  */
 const OFF = 0;
 
@@ -79,7 +71,6 @@ const OFF = 0;
  * @license AGPLv3
  * @since 1.5.0
  * @copyright schukai GmbH
- * @memberOf Monster.Logging
  */
 class Logger extends Base {
 	/**
diff --git a/source/net/webconnect/message.mjs b/source/net/webconnect/message.mjs
index a9e2cf9ac..3d860755d 100644
--- a/source/net/webconnect/message.mjs
+++ b/source/net/webconnect/message.mjs
@@ -25,7 +25,6 @@ const dataSymbol = Symbol("@@data");
  * @license AGPLv3
  * @since 3.4.0
  * @copyright schukai GmbH
- * @memberOf Monster.Net.WebSocket
  * @summary The Message class encapsulates a WebSocket message.
  */
 class Message extends Base {
diff --git a/source/types/basewithoptions.mjs b/source/types/basewithoptions.mjs
index f1a0d45b8..0aefe87e9 100644
--- a/source/types/basewithoptions.mjs
+++ b/source/types/basewithoptions.mjs
@@ -32,8 +32,7 @@ export { BaseWithOptions };
  * @license AGPLv3
  * @since 1.13.0
  * @copyright schukai GmbH
- * @memberOf Monster.Types
- * @deprecated since 3.15.0 use {@link Monster.Types.Base} with {@link Monster.Types.equipWithInternal} instead.
+ * @deprecated since 3.15.0 use `BaseWithOptions` instead of `BaseWithOptions`
  */
 class BaseWithOptions extends Base {
 	/**
diff --git a/source/types/noderecursiveiterator.mjs b/source/types/noderecursiveiterator.mjs
index 400776096..b592434a1 100644
--- a/source/types/noderecursiveiterator.mjs
+++ b/source/types/noderecursiveiterator.mjs
@@ -31,11 +31,7 @@ const isNodeListSymbol = Symbol("isNodeList");
 /**
  * Represents a recursive iterator for traversing nodes in a DOM tree.
  *
- * @externalExample ../../example/types/noderecursiveiterator.mjs
- * @license AGPLv3
  * @since 1.26.0
- * @copyright schukai GmbH
- * @memberOf Monster.Types
  * @summary An iterator to run recursively through a tree of nodes
  * @extends Base
  */
@@ -91,7 +87,7 @@ class NodeRecursiveIterator extends Base {
 
 	/**
 	 * @param {function} callback
-	 * @return {Monster.Types.NodeRecursiveIterator}
+	 * @return {NodeRecursiveIterator}
 	 */
 	forEach(callback) {
 		for (const node of this) {
diff --git a/source/types/observablequeue.mjs b/source/types/observablequeue.mjs
index 0be2e4d5d..a57249515 100644
--- a/source/types/observablequeue.mjs
+++ b/source/types/observablequeue.mjs
@@ -23,11 +23,8 @@ export { ObservableQueue };
  *
  * `Queue.add()` and `Queue.clear()` notify all observers.
  *
- * @externalExample ../../example/types/queue.mjs
- * @license AGPLv3
  * @since 3.3.0
  * @copyright schukai GmbH
- * @memberOf Monster.Types
  * @summary An observable Queue (Fifo)
  */
 class ObservableQueue extends Queue {
@@ -44,7 +41,6 @@ class ObservableQueue extends Queue {
 	/**
 	 * This method is called by the `instanceof` operator.
 	 * @returns {symbol}
-	 * @since 2.1.0
 	 */
 	static get [instanceSymbol]() {
 		return Symbol.for("@schukai/monster/types/observablequeue");
diff --git a/source/types/observer.mjs b/source/types/observer.mjs
index 19033a2e9..2970d71f3 100644
--- a/source/types/observer.mjs
+++ b/source/types/observer.mjs
@@ -53,11 +53,8 @@ export { Observer };
  *
  * The callback function must have as many parameters as arguments are given.
  *
- * @externalExample ../../example/types/observer.mjs
  * @license AGPLv3
  * @since 1.0.0
- * @copyright schukai GmbH
- * @memberOf Monster.Types
  */
 class Observer extends Base {
 	/**
diff --git a/source/types/observerlist.mjs b/source/types/observerlist.mjs
index 11278cafc..898d4225e 100644
--- a/source/types/observerlist.mjs
+++ b/source/types/observerlist.mjs
@@ -23,8 +23,6 @@ export { ObserverList };
  *
  * @license AGPLv3
  * @since 1.0.0
- * @copyright schukai GmbH
- * @memberOf Monster.Types
  */
 class ObserverList extends Base {
 	/**
diff --git a/source/types/queue.mjs b/source/types/queue.mjs
index 153c0d3f6..7ea7a449e 100644
--- a/source/types/queue.mjs
+++ b/source/types/queue.mjs
@@ -28,7 +28,6 @@ export { Queue };
  *
  * @license AGPLv3
  * @since 1.4.0
- * @copyright schukai GmbH
  * @summary A Queue (Fifo)
  */
 class Queue extends Base {
diff --git a/source/util/processing.mjs b/source/util/processing.mjs
index 1db0393c8..a70dc941c 100644
--- a/source/util/processing.mjs
+++ b/source/util/processing.mjs
@@ -14,52 +14,14 @@
 
 import { internalSymbol } from "../constants.mjs";
 import { Base } from "../types/base.mjs";
-import { getGlobalFunction } from "../types/global.mjs";
 import { isFunction, isInteger } from "../types/is.mjs";
 import { Queue } from "../types/queue.mjs";
-import { validateFunction, validateInteger } from "../types/validate.mjs";
+import { Callback } from "./processing/callback.mjs";
 
 export { Processing };
 
 /**
- * @private
- */
-class Callback {
-	/**
-	 *
-	 * @param {function} callback
-	 * @param {int|undefined} time
-	 * @throws {TypeError} value is not a function
-	 * @throws {TypeError} value is not an integer
-	 * @private
-	 */
-	constructor(callback, time) {
-		this[internalSymbol] = {
-			callback: validateFunction(callback),
-			time: validateInteger(time ?? 0),
-		};
-	}
-
-	/**
-	 * @private
-	 * @param  {*} data
-	 * @return {Promise}
-	 */
-	run(data) {
-		return new Promise((resolve, reject) => {
-			getGlobalFunction("setTimeout")(() => {
-				try {
-					resolve(this[internalSymbol].callback(data));
-				} catch (e) {
-					reject(e);
-				}
-			}, this[internalSymbol].time);
-		});
-	}
-}
-
-/**
- * This class allows to execute several functions in order.
+ * This class allows executing several functions in order.
  *
  * Functions and timeouts can be passed. If a timeout is passed, it applies to all further functions.
  * In the example
diff --git a/source/util/processing/callback.mjs b/source/util/processing/callback.mjs
new file mode 100644
index 000000000..665ccb088
--- /dev/null
+++ b/source/util/processing/callback.mjs
@@ -0,0 +1,56 @@
+/**
+ * Copyright © schukai GmbH and all contributing authors, {{copyRightYear}}. All rights reserved.
+ * Node module: @schukai/monster
+ *
+ * This source code is licensed under the GNU Affero General Public License version 3 (AGPLv3).
+ * The full text of the license can be found at: https://www.gnu.org/licenses/agpl-3.0.en.html
+ *
+ * For those who do not wish to adhere to the AGPLv3, a commercial license is available.
+ * Acquiring a commercial license allows you to use this software without complying with the AGPLv3 terms.
+ * For more information about purchasing a commercial license, please contact schukai GmbH.
+ *
+ * SPDX-License-Identifier: AGPL-3.0
+ */
+
+import { internalSymbol } from "../../constants.mjs";
+import { getGlobalFunction } from "../../types/global.mjs";
+import { validateFunction, validateInteger } from "../../types/validate.mjs";
+
+export { Callback };
+
+/**
+ * @private
+ */
+class Callback {
+	/**
+	 *
+	 * @param {function} callback
+	 * @param {int|undefined} time
+	 * @throws {TypeError} value is not a function
+	 * @throws {TypeError} value is not an integer
+	 * @private
+	 */
+	constructor(callback, time) {
+		this[internalSymbol] = {
+			callback: validateFunction(callback),
+			time: validateInteger(time ?? 0),
+		};
+	}
+
+	/**
+	 * @private
+	 * @param  {*} data
+	 * @return {Promise}
+	 */
+	run(data) {
+		return new Promise((resolve, reject) => {
+			getGlobalFunction("setTimeout")(() => {
+				try {
+					resolve(this[internalSymbol].callback(data));
+				} catch (e) {
+					reject(e);
+				}
+			}, this[internalSymbol].time);
+		});
+	}
+}
-- 
GitLab