From 635914025d9cee8fba1a663eb60d29b44774db27 Mon Sep 17 00:00:00 2001
From: Volker Schukai <volker.schukai@schukai.com>
Date: Thu, 23 Feb 2023 19:14:20 +0100
Subject: [PATCH] feat: deprecate BaseWithOption in favorit of
 equipWithInternal

---
 application/source/dom/customelement.mjs     |   2 +-
 application/source/dom/resourcemanager.mjs   |  26 ++-
 application/source/types/base.mjs            |   4 +-
 application/source/types/basewithoptions.mjs |   1 +
 application/source/types/internal.mjs        | 181 +++++++++++++++++++
 development/package.json                     |   2 +-
 development/pnpm-lock.yaml                   | 152 ++++++++--------
 development/test/cases/types/internal.mjs    | 153 ++++++++++++++++
 8 files changed, 437 insertions(+), 84 deletions(-)
 create mode 100644 application/source/types/internal.mjs
 create mode 100644 development/test/cases/types/internal.mjs

diff --git a/application/source/dom/customelement.mjs b/application/source/dom/customelement.mjs
index 656bf73c9..bdfb541a6 100644
--- a/application/source/dom/customelement.mjs
+++ b/application/source/dom/customelement.mjs
@@ -354,7 +354,7 @@ class CustomElement extends HTMLElement {
     static getCSSStyleSheet() {
         return undefined;
     }
-
+ 
     /**
      * attach a new observer
      *
diff --git a/application/source/dom/resourcemanager.mjs b/application/source/dom/resourcemanager.mjs
index cc4d9d15c..4a79b26b5 100644
--- a/application/source/dom/resourcemanager.mjs
+++ b/application/source/dom/resourcemanager.mjs
@@ -6,8 +6,9 @@
  */
 
 import { extend } from "../data/extend.mjs";
-import { BaseWithOptions } from "../types/basewithoptions.mjs";
+import { Base } from "../types/base.mjs";
 import { getGlobalObject } from "../types/global.mjs";
+import {equipWithInternal} from "../types/internal.mjs";
 import { isArray } from "../types/is.mjs";
 import { ATTRIBUTE_HREF, ATTRIBUTE_SRC } from "./constants.mjs";
 import { Resource } from "./resource.mjs";
@@ -26,7 +27,7 @@ export { ResourceManager };
  * @memberOf Monster.DOM
  * @summary A Resource class
  */
-class ResourceManager extends BaseWithOptions {
+class ResourceManager extends Base {
     /**
      *
      * @param {Object} options
@@ -34,12 +35,21 @@ class ResourceManager extends BaseWithOptions {
      */
     constructor(options) {
         super(options);
+        equipWithInternal.call(this);
 
         if (!(this.getOption("document") instanceof Document)) {
             throw new Error("unsupported document type");
         }
     }
 
+    /**
+     * @deprecated since 3.15.0 use getInternal instead
+     * @property {string} baseurl
+     */
+    getOption(key) {
+        return this.getInternal(key);
+    }
+
     /**
      * @property {string} baseurl
      */
@@ -47,6 +57,14 @@ class ResourceManager extends BaseWithOptions {
         this.getOption("document")?.baseURL;
     }
 
+    /**
+     * @property {string} baseurl
+     * @deprecated since 3.15.0 use internalDefaults instead
+     */
+    get defaults() {
+        return this.internalDefaults;
+    }
+
     /**
      *
      * @property {HTMLDocument} document=document Document
@@ -55,8 +73,8 @@ class ResourceManager extends BaseWithOptions {
      * @property {Array} resources.stylesheets=[] array with {@link Monster.DOM.Resource.Link.Stylesheet} objects
      * @property {Array} resources.data=[] array with {@link Monster.DOM.Resource.Data} objects
      */
-    get defaults() {
-        return Object.assign({}, super.defaults, {
+    get internalDefaults() {
+        return Object.assign({},  {
             document: getGlobalObject("document"),
             resources: {
                 scripts: [],
diff --git a/application/source/types/base.mjs b/application/source/types/base.mjs
index 09d4dcec5..b3a89f214 100644
--- a/application/source/types/base.mjs
+++ b/application/source/types/base.mjs
@@ -10,14 +10,14 @@ import { instanceSymbol } from "../constants.mjs";
 export { Base };
 
 /**
- * This is the base class from which all monster classes are derived.
+ * This is the base class from which the most classes are derived.
  *
  * This class has besides a `toString` which returns the json representation of the object
  * also a functionality to check if an object is an instance of a class.
  *
  * Therefor the class has a static method ` [Symbol.hasInstance](that)` which returns true if the object
  * is an instance of the class.
- * F
+ * 
  * @see [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/hasInstance](developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/hasInstance)
  *
  * Derived classes should implement a static getter `instanceSymbol` which returns a unique symbol.
diff --git a/application/source/types/basewithoptions.mjs b/application/source/types/basewithoptions.mjs
index cb0b5469d..10893b419 100644
--- a/application/source/types/basewithoptions.mjs
+++ b/application/source/types/basewithoptions.mjs
@@ -26,6 +26,7 @@ export { BaseWithOptions };
  * @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.
  */
 class BaseWithOptions extends Base {
     /**
diff --git a/application/source/types/internal.mjs b/application/source/types/internal.mjs
new file mode 100644
index 000000000..207f56ed5
--- /dev/null
+++ b/application/source/types/internal.mjs
@@ -0,0 +1,181 @@
+/**
+ * Copyright schukai GmbH and contributors 2022. All Rights Reserved.
+ * Node module: @schukai/monster
+ * This file is licensed under the AGPLv3 License.
+ * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
+ */
+import {internalSymbol} from "../constants.mjs";
+import {extend} from "../data/extend.mjs";
+import {Pathfinder} from "../data/pathfinder.mjs";
+import {parseDataURL} from "./dataurl.mjs";
+import {isString} from "./is.mjs";
+import {Observer} from "./observer.mjs";
+import {ProxyObserver} from "./proxyobserver.mjs";
+import {validateObject} from "./validate.mjs";
+import {isObject} from "./is.mjs";
+
+export {equipWithInternal}
+
+/**
+ * @private
+ * @type {string}
+ */
+const propertyName = 'internalDefaults'
+
+/**
+ * This function extends the given object with the following methods:
+ * 
+ * - attachInternalObserver
+ * - detachInternalObserver
+ * - containsInternalObserver
+ * - setInternal
+ * - setInternals
+ * - getInternal
+ * 
+ * @license AGPLv3
+ * @since 3.15.0
+ * @copyright schukai GmbH
+ * @memberOf Monster.Types
+ */
+function equipWithInternal() {
+    const self = this;
+    validateObject(self);
+
+    if (!hasGetter(self, propertyName)) {
+        Object.defineProperty(self, propertyName, {
+            get: function () {
+                return {};
+            }
+        });
+    }
+
+    const defaults = extend({}, self[propertyName] || {});
+    self[internalSymbol] = new ProxyObserver(defaults);
+
+    /**
+     * Attach a new observer
+     *
+     * @param {Observer} observer
+     * @returns {ProxyObserver}
+     */
+    self["attachInternalObserver"] = (observer) => {
+        self[internalSymbol].attachObserver(observer);
+        return self;
+    }
+
+    /**
+     * Detach a observer
+     *
+     * @param {Observer} observer
+     * @returns {ProxyObserver}
+     */
+    self["detachInternalObserver"] = (observer) => {
+        self[internalSymbol].detachObserver(observer);
+        return self;
+    }
+
+    /**
+     * Check if a observer is attached
+     * 
+     * @param {Observer} observer
+     * @returns {boolean}
+     */
+    self["containsInternalObserver"] = (observer) => {
+        return self[internalSymbol].containsObserver(observer);
+    }
+
+
+    /**
+     * Set an internal value, nested internals can be specified by path `a.b.c`
+     *
+     * @param {string} path
+     * @param {*} value
+     * @return {Datasource}
+     */
+    self["setInternal"] = (path, value) => {
+        new Pathfinder(self[internalSymbol].getSubject()).setVia(path, value);
+        return self;
+    }
+
+    /**
+     * set multiple internals at once
+     * 
+     * @param {string|object} options
+     * @return {Datasource}
+     * @throws {Error} the options does not contain a valid json definition
+     */
+    self["setInternals"] = (options) => {
+        if (isString(options)) {
+            options = parseOptionsJSON(options);
+        }
+
+        extend(self[internalSymbol].getSubject(), defaults, options);
+        return self;
+    }
+
+    /**
+     * nested internals can be specified by path `a.b.c`
+     *
+     * @param {string} path
+     * @param {*} defaultValue
+     * @return {*}
+     */
+    self["getInternal"] = (path, defaultValue) => {
+        let value;
+
+        try {
+            value = new Pathfinder(self[internalSymbol]
+                .getRealSubject()).getVia(path);
+        } catch (e) {
+        }
+
+        if (value === undefined) return defaultValue;
+        return value;
+    }
+}
+
+/**
+ * @private
+ * @param obj
+ * @param prop
+ * @return {boolean}
+ */
+function hasGetter(obj, prop) {
+
+    while (isObject(obj)) {
+        if (Object.getOwnPropertyDescriptor(obj, prop)?.['get']) {
+            return true;
+        }
+        obj = Object.getPrototypeOf(obj);
+    }
+
+    return false;
+}
+
+/**
+ * @private
+ * @param data
+ * @return {Object}
+ */
+function parseOptionsJSON(data) {
+    let obj = {};
+
+    if (!isString(data)) {
+        return obj;
+    }
+
+    // the configuration can be specified as a data url.
+    try {
+        let dataUrl = parseDataURL(data);
+        data = dataUrl.content;
+    } catch (e) {
+    }
+
+    try {
+        obj = JSON.parse(data);
+    } catch (e) {
+        throw e;
+    }
+
+    return validateObject(obj);
+}
diff --git a/development/package.json b/development/package.json
index 71e303694..ff8f99a85 100644
--- a/development/package.json
+++ b/development/package.json
@@ -61,7 +61,7 @@
     "url": "^0.11.0",
     "url-exist": "3.0.1",
     "util": "^0.12.5",
-    "vite": "^4.1.3",
+    "vite": "^4.1.4",
     "vite-plugin-banner": "^0.7.0",
     "vite-plugin-list-directory-contents": "^1.4.5",
     "vite-plugin-minify": "^1.5.2",
diff --git a/development/pnpm-lock.yaml b/development/pnpm-lock.yaml
index 06893715e..528c24ceb 100644
--- a/development/pnpm-lock.yaml
+++ b/development/pnpm-lock.yaml
@@ -42,7 +42,7 @@ specifiers:
   url: ^0.11.0
   url-exist: 3.0.1
   util: ^0.12.5
-  vite: ^4.1.3
+  vite: ^4.1.4
   vite-plugin-banner: ^0.7.0
   vite-plugin-list-directory-contents: ^1.4.5
   vite-plugin-minify: ^1.5.2
@@ -91,11 +91,11 @@ devDependencies:
   url: 0.11.0
   url-exist: 3.0.1
   util: 0.12.5
-  vite: 4.1.3
+  vite: 4.1.4
   vite-plugin-banner: 0.7.0
   vite-plugin-list-directory-contents: 1.4.5
-  vite-plugin-minify: 1.5.2_vite@4.1.3
-  vite-plugin-mkcert: 1.13.2_vite@4.1.3
+  vite-plugin-minify: 1.5.2_vite@4.1.4
+  vite-plugin-mkcert: 1.13.2_vite@4.1.4
   ws: 8.12.1
 
 packages:
@@ -128,12 +128,12 @@ packages:
       '@babel/code-frame': 7.18.6
       '@babel/generator': 7.21.1
       '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.21.0
-      '@babel/helper-module-transforms': 7.21.0
+      '@babel/helper-module-transforms': 7.21.2
       '@babel/helpers': 7.21.0
-      '@babel/parser': 7.21.1
+      '@babel/parser': 7.21.2
       '@babel/template': 7.20.7
-      '@babel/traverse': 7.21.0
-      '@babel/types': 7.21.0
+      '@babel/traverse': 7.21.2
+      '@babel/types': 7.21.2
       convert-source-map: 1.9.0
       debug: 4.3.4
       gensync: 1.0.0-beta.2
@@ -147,7 +147,7 @@ packages:
     resolution: {integrity: sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/types': 7.21.0
+      '@babel/types': 7.21.2
       '@jridgewell/gen-mapping': 0.3.2
       '@jridgewell/trace-mapping': 0.3.17
       jsesc: 2.5.2
@@ -177,25 +177,25 @@ packages:
     engines: {node: '>=6.9.0'}
     dependencies:
       '@babel/template': 7.20.7
-      '@babel/types': 7.21.0
+      '@babel/types': 7.21.2
     dev: true
 
   /@babel/helper-hoist-variables/7.18.6:
     resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/types': 7.21.0
+      '@babel/types': 7.21.2
     dev: true
 
   /@babel/helper-module-imports/7.18.6:
     resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/types': 7.21.0
+      '@babel/types': 7.21.2
     dev: true
 
-  /@babel/helper-module-transforms/7.21.0:
-    resolution: {integrity: sha512-eD/JQ21IG2i1FraJnTMbUarAUkA7G988ofehG5MDCRXaUU91rEBJuCeSoou2Sk1y4RbLYXzqEg1QLwEmRU4qcQ==}
+  /@babel/helper-module-transforms/7.21.2:
+    resolution: {integrity: sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==}
     engines: {node: '>=6.9.0'}
     dependencies:
       '@babel/helper-environment-visitor': 7.18.9
@@ -204,8 +204,8 @@ packages:
       '@babel/helper-split-export-declaration': 7.18.6
       '@babel/helper-validator-identifier': 7.19.1
       '@babel/template': 7.20.7
-      '@babel/traverse': 7.21.0
-      '@babel/types': 7.21.0
+      '@babel/traverse': 7.21.2
+      '@babel/types': 7.21.2
     transitivePeerDependencies:
       - supports-color
     dev: true
@@ -214,14 +214,14 @@ packages:
     resolution: {integrity: sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/types': 7.21.0
+      '@babel/types': 7.21.2
     dev: true
 
   /@babel/helper-split-export-declaration/7.18.6:
     resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==}
     engines: {node: '>=6.9.0'}
     dependencies:
-      '@babel/types': 7.21.0
+      '@babel/types': 7.21.2
     dev: true
 
   /@babel/helper-string-parser/7.19.4:
@@ -244,8 +244,8 @@ packages:
     engines: {node: '>=6.9.0'}
     dependencies:
       '@babel/template': 7.20.7
-      '@babel/traverse': 7.21.0
-      '@babel/types': 7.21.0
+      '@babel/traverse': 7.21.2
+      '@babel/types': 7.21.2
     transitivePeerDependencies:
       - supports-color
     dev: true
@@ -259,12 +259,12 @@ packages:
       js-tokens: 4.0.0
     dev: true
 
-  /@babel/parser/7.21.1:
-    resolution: {integrity: sha512-JzhBFpkuhBNYUY7qs+wTzNmyCWUHEaAFpQQD2YfU1rPL38/L43Wvid0fFkiOCnHvsGncRZgEPyGnltABLcVDTg==}
+  /@babel/parser/7.21.2:
+    resolution: {integrity: sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==}
     engines: {node: '>=6.0.0'}
     hasBin: true
     dependencies:
-      '@babel/types': 7.21.0
+      '@babel/types': 7.21.2
     dev: true
 
   /@babel/template/7.20.7:
@@ -272,12 +272,12 @@ packages:
     engines: {node: '>=6.9.0'}
     dependencies:
       '@babel/code-frame': 7.18.6
-      '@babel/parser': 7.21.1
-      '@babel/types': 7.21.0
+      '@babel/parser': 7.21.2
+      '@babel/types': 7.21.2
     dev: true
 
-  /@babel/traverse/7.21.0:
-    resolution: {integrity: sha512-Xdt2P1H4LKTO8ApPfnO1KmzYMFpp7D/EinoXzLYN/cHcBNrVCAkAtGUcXnHXrl/VGktureU6fkQrHSBE2URfoA==}
+  /@babel/traverse/7.21.2:
+    resolution: {integrity: sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==}
     engines: {node: '>=6.9.0'}
     dependencies:
       '@babel/code-frame': 7.18.6
@@ -286,16 +286,16 @@ packages:
       '@babel/helper-function-name': 7.21.0
       '@babel/helper-hoist-variables': 7.18.6
       '@babel/helper-split-export-declaration': 7.18.6
-      '@babel/parser': 7.21.1
-      '@babel/types': 7.21.0
+      '@babel/parser': 7.21.2
+      '@babel/types': 7.21.2
       debug: 4.3.4
       globals: 11.12.0
     transitivePeerDependencies:
       - supports-color
     dev: true
 
-  /@babel/types/7.21.0:
-    resolution: {integrity: sha512-uR7NWq2VNFnDi7EYqiRz2Jv/VQIu38tu64Zy8TX2nQFQ6etJ9V/Rr2msW8BS132mum2rL645qpDrLtAJtVpuow==}
+  /@babel/types/7.21.2:
+    resolution: {integrity: sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==}
     engines: {node: '>=6.9.0'}
     dependencies:
       '@babel/helper-string-parser': 7.19.4
@@ -808,12 +808,12 @@ packages:
       - '@types/node'
     dev: true
 
-  /@microsoft/api-extractor-model/7.26.4_@types+node@18.14.0:
+  /@microsoft/api-extractor-model/7.26.4_@types+node@18.14.1:
     resolution: {integrity: sha512-PDCgCzXDo+SLY5bsfl4bS7hxaeEtnXj7XtuzEE+BtALp7B5mK/NrS2kHWU69pohgsRmEALycQdaQPXoyT2i5MQ==}
     dependencies:
       '@microsoft/tsdoc': 0.14.2
       '@microsoft/tsdoc-config': 0.16.2
-      '@rushstack/node-core-library': 3.55.2_@types+node@18.14.0
+      '@rushstack/node-core-library': 3.55.2_@types+node@18.14.1
     transitivePeerDependencies:
       - '@types/node'
     dev: true
@@ -838,14 +838,14 @@ packages:
       - '@types/node'
     dev: true
 
-  /@microsoft/api-extractor/7.34.4_@types+node@18.14.0:
+  /@microsoft/api-extractor/7.34.4_@types+node@18.14.1:
     resolution: {integrity: sha512-HOdcci2nT40ejhwPC3Xja9G+WSJmWhCUKKryRfQYsmE9cD+pxmBaKBKCbuS9jUcl6bLLb4Gz+h7xEN5r0QiXnQ==}
     hasBin: true
     dependencies:
-      '@microsoft/api-extractor-model': 7.26.4_@types+node@18.14.0
+      '@microsoft/api-extractor-model': 7.26.4_@types+node@18.14.1
       '@microsoft/tsdoc': 0.14.2
       '@microsoft/tsdoc-config': 0.16.2
-      '@rushstack/node-core-library': 3.55.2_@types+node@18.14.0
+      '@rushstack/node-core-library': 3.55.2_@types+node@18.14.1
       '@rushstack/rig-package': 0.3.18
       '@rushstack/ts-command-line': 4.13.2
       colors: 1.2.5
@@ -1117,7 +1117,7 @@ packages:
       z-schema: 5.0.5
     dev: true
 
-  /@rushstack/node-core-library/3.55.2_@types+node@18.14.0:
+  /@rushstack/node-core-library/3.55.2_@types+node@18.14.1:
     resolution: {integrity: sha512-SaLe/x/Q/uBVdNFK5V1xXvsVps0y7h1sN7aSJllQyFbugyOaxhNRF25bwEDnicARNEjJw0pk0lYnJQ9Kr6ev0A==}
     peerDependencies:
       '@types/node': '*'
@@ -1125,7 +1125,7 @@ packages:
       '@types/node':
         optional: true
     dependencies:
-      '@types/node': 18.14.0
+      '@types/node': 18.14.1
       colors: 1.2.5
       fs-extra: 7.0.1
       import-lazy: 4.0.0
@@ -1225,16 +1225,16 @@ packages:
     resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==}
     dev: true
 
-  /@types/node/18.14.0:
-    resolution: {integrity: sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==}
+  /@types/node/18.14.1:
+    resolution: {integrity: sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ==}
     dev: true
 
   /@wesbos/code-icons/1.2.4:
     resolution: {integrity: sha512-ZiU0xf7epnCRrLDQIPnFstzoNWDvcUTtKoDU3VhpjsaGRzVClSmsi39c4kHxIOdfxvg4zwdW+goH96xr/vMTQQ==}
     dependencies:
-      '@types/node': 18.14.0
-      vite: 4.1.3_@types+node@18.14.0
-      vite-plugin-dts: 1.7.3_p5hrhorwe35jeumio2pz6ujxge
+      '@types/node': 18.14.1
+      vite: 4.1.4_@types+node@18.14.1
+      vite-plugin-dts: 1.7.3_75ucbpp7logpdg7n5tkyaoxqqm
       vscode-icons-js: 11.6.1
     transitivePeerDependencies:
       - less
@@ -1393,8 +1393,8 @@ packages:
     engines: {node: '>= 0.4'}
     dev: true
 
-  /axios/1.3.3_debug@4.3.4:
-    resolution: {integrity: sha512-eYq77dYIFS77AQlhzEL937yUBSepBfPIe8FcgEDN35vMNZKMrs81pgnyrQpwfy4NF4b4XWX1Zgx7yX+25w8QJA==}
+  /axios/1.3.4_debug@4.3.4:
+    resolution: {integrity: sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==}
     dependencies:
       follow-redirects: 1.15.2_debug@4.3.4
       form-data: 4.0.0
@@ -1454,7 +1454,7 @@ packages:
     hasBin: true
     dependencies:
       caniuse-lite: 1.0.30001457
-      electron-to-chromium: 1.4.304
+      electron-to-chromium: 1.4.308
       node-releases: 2.0.10
       update-browserslist-db: 1.0.10_browserslist@4.21.5
     dev: true
@@ -1750,7 +1750,7 @@ packages:
       execa: 4.1.0
       polyfill-library: 3.111.0
       semver: 7.3.8
-      snyk: 1.1107.0
+      snyk: 1.1108.0
       yargs: 15.4.1
     transitivePeerDependencies:
       - supports-color
@@ -2012,8 +2012,8 @@ packages:
       tslib: 2.5.0
     dev: true
 
-  /electron-to-chromium/1.4.304:
-    resolution: {integrity: sha512-6c8M+ojPgDIXN2NyfGn8oHASXYnayj+gSEnGeLMKb9zjsySeVB/j7KkNAAG9yDcv8gNlhvFg5REa1N/kQU6pgA==}
+  /electron-to-chromium/1.4.308:
+    resolution: {integrity: sha512-qyTx2aDFjEni4UnRWEME9ubd2Xc9c0zerTUl/ZinvD4QPsF0S7kJTV/Es/lPCTkNX6smyYar+z/n8Cl6pFr8yQ==}
     dev: true
 
   /emoji-regex/7.0.3:
@@ -2310,7 +2310,7 @@ packages:
     resolution: {integrity: sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==}
     dependencies:
       inherits: 2.0.4
-      readable-stream: 2.3.7
+      readable-stream: 2.3.8
     dev: true
 
   /fs-extra/10.1.0:
@@ -2509,7 +2509,7 @@ packages:
       he: 1.2.0
       param-case: 3.0.4
       relateurl: 0.2.7
-      terser: 5.16.4
+      terser: 5.16.5
     dev: true
 
   /html-minifier/4.0.0:
@@ -2751,7 +2751,7 @@ packages:
     engines: {node: '>=12.0.0'}
     hasBin: true
     dependencies:
-      '@babel/parser': 7.21.1
+      '@babel/parser': 7.21.2
       '@jsdoc/salty': 0.2.3
       '@types/markdown-it': 12.2.3
       bluebird: 3.7.2
@@ -3971,8 +3971,8 @@ packages:
       pify: 2.3.0
     dev: true
 
-  /readable-stream/2.3.7:
-    resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==}
+  /readable-stream/2.3.8:
+    resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
     dependencies:
       core-util-is: 1.0.3
       inherits: 2.0.4
@@ -4167,8 +4167,8 @@ packages:
       supports-color: 7.2.0
     dev: true
 
-  /snyk/1.1107.0:
-    resolution: {integrity: sha512-SMspMZFp32NSevt4HZrKAsomJ92ZteuSuQhvNqwiIEIKirrWg9IxaHfnWZLMLEWiB6D4g1xnjred0RFSDVzdTQ==}
+  /snyk/1.1108.0:
+    resolution: {integrity: sha512-HThKYgmcZgNG9ONuGUtJ/JuUaDzyqRHbPljJc50dtU9nEBmUc915jtPfrKKITdn6K+Ap9Rs8eVqnXWq0MGW0hA==}
     engines: {node: '>=12'}
     hasBin: true
     dev: true
@@ -4356,8 +4356,8 @@ packages:
     engines: {'0': node >=0.4.0}
     dev: true
 
-  /terser/5.16.4:
-    resolution: {integrity: sha512-5yEGuZ3DZradbogeYQ1NaGz7rXVBDWujWlx1PT8efXO6Txn+eWbfKqB2bTDVmFXmePFkoLU6XI8UektMIEA0ug==}
+  /terser/5.16.5:
+    resolution: {integrity: sha512-qcwfg4+RZa3YvlFh0qjifnzBHjKGNbtDo9yivMqMFDy9Q6FSaQWSB/j1xKhsoUFJIqDOM3TsN6D5xbrMrFcHbg==}
     engines: {node: '>=10'}
     hasBin: true
     dependencies:
@@ -4553,28 +4553,28 @@ packages:
     resolution: {integrity: sha512-g0cm0wbrR6b6wR8FWtfD1RSDPacdumKEOAnneXv+NpJ9ez+j6rklRv6lMOO+aPf+Y6Zb8OzgIk0FXBZ6h+DeZQ==}
     dev: true
 
-  /vite-plugin-dts/1.7.3_p5hrhorwe35jeumio2pz6ujxge:
+  /vite-plugin-dts/1.7.3_75ucbpp7logpdg7n5tkyaoxqqm:
     resolution: {integrity: sha512-u3t45p6fTbzUPMkwYe0ESwuUeiRMlwdPfD3dRyDKUwLe2WmEYcFyVp2o9/ke2EMrM51lQcmNWdV9eLcgjD1/ng==}
     engines: {node: ^14.18.0 || >=16.0.0}
     peerDependencies:
       vite: '>=2.9.0'
     dependencies:
-      '@microsoft/api-extractor': 7.34.4_@types+node@18.14.0
+      '@microsoft/api-extractor': 7.34.4_@types+node@18.14.1
       '@rollup/pluginutils': 5.0.2
-      '@rushstack/node-core-library': 3.55.2_@types+node@18.14.0
+      '@rushstack/node-core-library': 3.55.2_@types+node@18.14.1
       debug: 4.3.4
       fast-glob: 3.2.12
       fs-extra: 10.1.0
       kolorist: 1.7.0
       ts-morph: 17.0.1
-      vite: 4.1.3_@types+node@18.14.0
+      vite: 4.1.4_@types+node@18.14.1
     transitivePeerDependencies:
       - '@types/node'
       - rollup
       - supports-color
     dev: true
 
-  /vite-plugin-dts/1.7.3_vite@4.1.3:
+  /vite-plugin-dts/1.7.3_vite@4.1.4:
     resolution: {integrity: sha512-u3t45p6fTbzUPMkwYe0ESwuUeiRMlwdPfD3dRyDKUwLe2WmEYcFyVp2o9/ke2EMrM51lQcmNWdV9eLcgjD1/ng==}
     engines: {node: ^14.18.0 || >=16.0.0}
     peerDependencies:
@@ -4588,7 +4588,7 @@ packages:
       fs-extra: 10.1.0
       kolorist: 1.7.0
       ts-morph: 17.0.1
-      vite: 4.1.3
+      vite: 4.1.4
     transitivePeerDependencies:
       - '@types/node'
       - rollup
@@ -4599,8 +4599,8 @@ packages:
     resolution: {integrity: sha512-67Abh1X9rhJq7u9Hxq9CJznM0acAPynvumkQ33wzvigW1aaPfsHNNMnhArABYryXnqASlmiZHpbhYOtDI9KfYw==}
     dependencies:
       '@wesbos/code-icons': 1.2.4
-      vite: 4.1.3
-      vite-plugin-dts: 1.7.3_vite@4.1.3
+      vite: 4.1.4
+      vite-plugin-dts: 1.7.3_vite@4.1.4
       vscode-icons-js: 11.6.1
     transitivePeerDependencies:
       - '@types/node'
@@ -4613,33 +4613,33 @@ packages:
       - terser
     dev: true
 
-  /vite-plugin-minify/1.5.2_vite@4.1.3:
+  /vite-plugin-minify/1.5.2_vite@4.1.4:
     resolution: {integrity: sha512-clf3THHlet1jD35y8+mbw/xgACbdUQ1Eyc9zZFiqaxVOZLSC3UbrkOYOG+Nf4cleRjWgb8czbXrnQiWZICVh3Q==}
     peerDependencies:
       vite: '*'
     dependencies:
       html-minifier-terser: 6.1.0
-      vite: 4.1.3
+      vite: 4.1.4
     dev: true
 
-  /vite-plugin-mkcert/1.13.2_vite@4.1.3:
+  /vite-plugin-mkcert/1.13.2_vite@4.1.4:
     resolution: {integrity: sha512-zna6J66cgCaNt2vAP/kDLuBbzr3kivwS4wjBxGvoKK61PBdvlPW2M+vxEGEpuRrrW7X4vQAX9JzmXk1QSAI4Eg==}
     engines: {node: '>=v16.7.0'}
     peerDependencies:
       vite: '>=3'
     dependencies:
       '@octokit/rest': 19.0.7
-      axios: 1.3.3_debug@4.3.4
+      axios: 1.3.4_debug@4.3.4
       debug: 4.3.4
       picocolors: 1.0.0
-      vite: 4.1.3
+      vite: 4.1.4
     transitivePeerDependencies:
       - encoding
       - supports-color
     dev: true
 
-  /vite/4.1.3:
-    resolution: {integrity: sha512-0Zqo4/Fr/swSOBmbl+HAAhOjrqNwju+yTtoe4hQX9UsARdcuc9njyOdr6xU0DDnV7YP0RT6mgTTOiRtZgxfCxA==}
+  /vite/4.1.4:
+    resolution: {integrity: sha512-3knk/HsbSTKEin43zHu7jTwYWv81f8kgAL99G5NWBcA1LKvtvcVAC4JjBH1arBunO9kQka+1oGbrMKOjk4ZrBg==}
     engines: {node: ^14.18.0 || >=16.0.0}
     hasBin: true
     peerDependencies:
@@ -4671,8 +4671,8 @@ packages:
       fsevents: 2.3.2
     dev: true
 
-  /vite/4.1.3_@types+node@18.14.0:
-    resolution: {integrity: sha512-0Zqo4/Fr/swSOBmbl+HAAhOjrqNwju+yTtoe4hQX9UsARdcuc9njyOdr6xU0DDnV7YP0RT6mgTTOiRtZgxfCxA==}
+  /vite/4.1.4_@types+node@18.14.1:
+    resolution: {integrity: sha512-3knk/HsbSTKEin43zHu7jTwYWv81f8kgAL99G5NWBcA1LKvtvcVAC4JjBH1arBunO9kQka+1oGbrMKOjk4ZrBg==}
     engines: {node: ^14.18.0 || >=16.0.0}
     hasBin: true
     peerDependencies:
@@ -4696,7 +4696,7 @@ packages:
       terser:
         optional: true
     dependencies:
-      '@types/node': 18.14.0
+      '@types/node': 18.14.1
       esbuild: 0.16.17
       postcss: 8.4.21
       resolve: 1.22.1
diff --git a/development/test/cases/types/internal.mjs b/development/test/cases/types/internal.mjs
new file mode 100644
index 000000000..30a50107b
--- /dev/null
+++ b/development/test/cases/types/internal.mjs
@@ -0,0 +1,153 @@
+"use strict";
+
+import {expect} from "chai"
+import {equipWithInternal} from "../../../../application/source/types/internal.mjs";
+import {Observer} from "../../../../application/source/types/observer.mjs";
+
+class SomeRandomClass1 extends Object {
+
+    doit() {
+        return "done";
+    }
+}
+
+class SomeRandomClass2 extends Object {
+
+    constructor() {
+        super();
+        equipWithInternal.call(this);
+    }
+
+    get defaultInternal() {
+        return {
+            test: "test"
+        }
+    }
+
+}
+
+describe('Base inject with options', function () {
+
+    describe('new SomeRandomClass', function () {
+
+        it('is instance of SomeRandomClass1', function () {
+            expect(new SomeRandomClass2).not.to.be.instanceOf(SomeRandomClass1);
+            expect(new SomeRandomClass2).to.be.instanceOf(SomeRandomClass2);
+        });
+
+        it('is instance of SomeRandomClass2', function () {
+            expect(new SomeRandomClass1).to.be.instanceOf(SomeRandomClass1);
+            expect(new SomeRandomClass1).not.to.be.instanceOf(SomeRandomClass2);
+        });
+
+    })
+
+    describe('Extends SomeRandomClass with internals', function () {
+
+        it('attach and notify internal observer', function (done) {
+            const c = new SomeRandomClass2;
+            c.attachInternalObserver(new Observer(() => {
+                done();
+            }));
+
+            c.setInternal("test", "test");
+
+        });
+
+        it('attach and remove internal observer', function () {
+            const c = new SomeRandomClass2;
+
+
+            const observer = new Observer(() => {
+
+            });
+
+            expect(c.containsInternalObserver(observer)).to.be.false;
+            c.attachInternalObserver(observer);
+            expect(c.containsInternalObserver(observer)).to.be.true;
+            c.detachInternalObserver(observer);
+            expect(c.containsInternalObserver(observer)).to.be.false;
+
+        });
+
+        it("getInternal and setInternal", function () {
+            const c = new SomeRandomClass2;
+            expect(c.setInternal("test", "yeah")).to.be.instanceOf(SomeRandomClass2);
+            expect(c.getInternal("test")).to.be.equal("yeah");
+        });
+
+        it("deal with default values", function () {
+            const testClass = class extends Object {
+                constructor() {
+                    super();
+                    equipWithInternal.call(this);
+                }
+
+                get internalDefaults() {
+                    return {
+                        test: "xyz"
+                    }
+                }
+            }
+
+
+            const c = new testClass;
+            expect(c.getInternal("test")).to.be.equal("xyz");
+            expect(c.getInternal("test2", "abc")).to.be.equal("abc");
+        });
+
+        it("deal with defaults from defaults", function () {
+            const testClass = class extends Object {
+                constructor() {
+                    super();
+                    equipWithInternal.call(this);
+                }
+
+                get internalDefaults() {
+                    return {
+                        test: "xyz"
+                    }
+                }
+            }
+
+            const testClass2 = class extends testClass {
+                constructor() {
+                    super();
+                    equipWithInternal.call(this);
+                }
+
+                get internalDefaults() {
+                    return Object.assign({}, super.internalDefaults, {
+                        test2: "abc"
+                    })
+                }
+            }
+
+            const c = new testClass2;
+            expect(c.getInternal("test")).to.be.equal("xyz");
+            expect(c.getInternal("test2")).to.be.equal("abc");
+        });
+        
+        it("set multiple values", function () {
+            const c = new SomeRandomClass2;
+            expect(c.setInternals({
+                test: "yeah",
+                test2: "yeah2"
+            })).to.be.instanceOf(SomeRandomClass2);
+            expect(c.getInternal("test")).to.be.equal("yeah");
+            expect(c.getInternal("test2")).to.be.equal("yeah2");
+            
+            c.setInternals({
+                test2: "yeah2-new",
+                test3: "yeah3"
+            });
+            
+            expect(c.getInternal("test")).to.be.equal("yeah");
+            expect(c.getInternal("test2")).to.be.equal("yeah2-new");
+            expect(c.getInternal("test3")).to.be.equal("yeah3");
+        });
+
+    });
+
+
+})
\ No newline at end of file
-- 
GitLab