@schukai/monster 3.14.1 → 3.15.0
Sign up to get free protection for your applications and to get access to all the features.
- package/package.json +1 -1
- package/source/dom/customelement.mjs +1 -1
- package/source/dom/resourcemanager.mjs +22 -4
- package/source/types/base.mjs +2 -2
- package/source/types/basewithoptions.mjs +1 -0
- package/source/types/internal.mjs +181 -0
- package/source/types/version.mjs +1 -1
- package/test/cases/monster.mjs +1 -1
- package/test/cases/types/internal.mjs +153 -0
package/package.json
CHANGED
@@ -6,8 +6,9 @@
|
|
6
6
|
*/
|
7
7
|
|
8
8
|
import { extend } from "../data/extend.mjs";
|
9
|
-
import {
|
9
|
+
import { Base } from "../types/base.mjs";
|
10
10
|
import { getGlobalObject } from "../types/global.mjs";
|
11
|
+
import {equipWithInternal} from "../types/internal.mjs";
|
11
12
|
import { isArray } from "../types/is.mjs";
|
12
13
|
import { ATTRIBUTE_HREF, ATTRIBUTE_SRC } from "./constants.mjs";
|
13
14
|
import { Resource } from "./resource.mjs";
|
@@ -26,7 +27,7 @@ export { ResourceManager };
|
|
26
27
|
* @memberOf Monster.DOM
|
27
28
|
* @summary A Resource class
|
28
29
|
*/
|
29
|
-
class ResourceManager extends
|
30
|
+
class ResourceManager extends Base {
|
30
31
|
/**
|
31
32
|
*
|
32
33
|
* @param {Object} options
|
@@ -34,12 +35,21 @@ class ResourceManager extends BaseWithOptions {
|
|
34
35
|
*/
|
35
36
|
constructor(options) {
|
36
37
|
super(options);
|
38
|
+
equipWithInternal.call(this);
|
37
39
|
|
38
40
|
if (!(this.getOption("document") instanceof Document)) {
|
39
41
|
throw new Error("unsupported document type");
|
40
42
|
}
|
41
43
|
}
|
42
44
|
|
45
|
+
/**
|
46
|
+
* @deprecated since 3.15.0 use getInternal instead
|
47
|
+
* @property {string} baseurl
|
48
|
+
*/
|
49
|
+
getOption(key) {
|
50
|
+
return this.getInternal(key);
|
51
|
+
}
|
52
|
+
|
43
53
|
/**
|
44
54
|
* @property {string} baseurl
|
45
55
|
*/
|
@@ -47,6 +57,14 @@ class ResourceManager extends BaseWithOptions {
|
|
47
57
|
this.getOption("document")?.baseURL;
|
48
58
|
}
|
49
59
|
|
60
|
+
/**
|
61
|
+
* @property {string} baseurl
|
62
|
+
* @deprecated since 3.15.0 use internalDefaults instead
|
63
|
+
*/
|
64
|
+
get defaults() {
|
65
|
+
return this.internalDefaults;
|
66
|
+
}
|
67
|
+
|
50
68
|
/**
|
51
69
|
*
|
52
70
|
* @property {HTMLDocument} document=document Document
|
@@ -55,8 +73,8 @@ class ResourceManager extends BaseWithOptions {
|
|
55
73
|
* @property {Array} resources.stylesheets=[] array with {@link Monster.DOM.Resource.Link.Stylesheet} objects
|
56
74
|
* @property {Array} resources.data=[] array with {@link Monster.DOM.Resource.Data} objects
|
57
75
|
*/
|
58
|
-
get
|
59
|
-
return Object.assign({},
|
76
|
+
get internalDefaults() {
|
77
|
+
return Object.assign({}, {
|
60
78
|
document: getGlobalObject("document"),
|
61
79
|
resources: {
|
62
80
|
scripts: [],
|
package/source/types/base.mjs
CHANGED
@@ -10,14 +10,14 @@ import { instanceSymbol } from "../constants.mjs";
|
|
10
10
|
export { Base };
|
11
11
|
|
12
12
|
/**
|
13
|
-
* This is the base class from which
|
13
|
+
* This is the base class from which the most classes are derived.
|
14
14
|
*
|
15
15
|
* This class has besides a `toString` which returns the json representation of the object
|
16
16
|
* also a functionality to check if an object is an instance of a class.
|
17
17
|
*
|
18
18
|
* Therefor the class has a static method ` [Symbol.hasInstance](that)` which returns true if the object
|
19
19
|
* is an instance of the class.
|
20
|
-
*
|
20
|
+
*
|
21
21
|
* @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)
|
22
22
|
*
|
23
23
|
* Derived classes should implement a static getter `instanceSymbol` which returns a unique symbol.
|
@@ -26,6 +26,7 @@ export { BaseWithOptions };
|
|
26
26
|
* @since 1.13.0
|
27
27
|
* @copyright schukai GmbH
|
28
28
|
* @memberOf Monster.Types
|
29
|
+
* @deprecated since 3.15.0 use {@link Monster.Types.Base} with {@link Monster.Types.equipWithInternal} instead.
|
29
30
|
*/
|
30
31
|
class BaseWithOptions extends Base {
|
31
32
|
/**
|
@@ -0,0 +1,181 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright schukai GmbH and contributors 2022. All Rights Reserved.
|
3
|
+
* Node module: @schukai/monster
|
4
|
+
* This file is licensed under the AGPLv3 License.
|
5
|
+
* License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
|
6
|
+
*/
|
7
|
+
import {internalSymbol} from "../constants.mjs";
|
8
|
+
import {extend} from "../data/extend.mjs";
|
9
|
+
import {Pathfinder} from "../data/pathfinder.mjs";
|
10
|
+
import {parseDataURL} from "./dataurl.mjs";
|
11
|
+
import {isString} from "./is.mjs";
|
12
|
+
import {Observer} from "./observer.mjs";
|
13
|
+
import {ProxyObserver} from "./proxyobserver.mjs";
|
14
|
+
import {validateObject} from "./validate.mjs";
|
15
|
+
import {isObject} from "./is.mjs";
|
16
|
+
|
17
|
+
export {equipWithInternal}
|
18
|
+
|
19
|
+
/**
|
20
|
+
* @private
|
21
|
+
* @type {string}
|
22
|
+
*/
|
23
|
+
const propertyName = 'internalDefaults'
|
24
|
+
|
25
|
+
/**
|
26
|
+
* This function extends the given object with the following methods:
|
27
|
+
*
|
28
|
+
* - attachInternalObserver
|
29
|
+
* - detachInternalObserver
|
30
|
+
* - containsInternalObserver
|
31
|
+
* - setInternal
|
32
|
+
* - setInternals
|
33
|
+
* - getInternal
|
34
|
+
*
|
35
|
+
* @license AGPLv3
|
36
|
+
* @since 3.15.0
|
37
|
+
* @copyright schukai GmbH
|
38
|
+
* @memberOf Monster.Types
|
39
|
+
*/
|
40
|
+
function equipWithInternal() {
|
41
|
+
const self = this;
|
42
|
+
validateObject(self);
|
43
|
+
|
44
|
+
if (!hasGetter(self, propertyName)) {
|
45
|
+
Object.defineProperty(self, propertyName, {
|
46
|
+
get: function () {
|
47
|
+
return {};
|
48
|
+
}
|
49
|
+
});
|
50
|
+
}
|
51
|
+
|
52
|
+
const defaults = extend({}, self[propertyName] || {});
|
53
|
+
self[internalSymbol] = new ProxyObserver(defaults);
|
54
|
+
|
55
|
+
/**
|
56
|
+
* Attach a new observer
|
57
|
+
*
|
58
|
+
* @param {Observer} observer
|
59
|
+
* @returns {ProxyObserver}
|
60
|
+
*/
|
61
|
+
self["attachInternalObserver"] = (observer) => {
|
62
|
+
self[internalSymbol].attachObserver(observer);
|
63
|
+
return self;
|
64
|
+
}
|
65
|
+
|
66
|
+
/**
|
67
|
+
* Detach a observer
|
68
|
+
*
|
69
|
+
* @param {Observer} observer
|
70
|
+
* @returns {ProxyObserver}
|
71
|
+
*/
|
72
|
+
self["detachInternalObserver"] = (observer) => {
|
73
|
+
self[internalSymbol].detachObserver(observer);
|
74
|
+
return self;
|
75
|
+
}
|
76
|
+
|
77
|
+
/**
|
78
|
+
* Check if a observer is attached
|
79
|
+
*
|
80
|
+
* @param {Observer} observer
|
81
|
+
* @returns {boolean}
|
82
|
+
*/
|
83
|
+
self["containsInternalObserver"] = (observer) => {
|
84
|
+
return self[internalSymbol].containsObserver(observer);
|
85
|
+
}
|
86
|
+
|
87
|
+
|
88
|
+
/**
|
89
|
+
* Set an internal value, nested internals can be specified by path `a.b.c`
|
90
|
+
*
|
91
|
+
* @param {string} path
|
92
|
+
* @param {*} value
|
93
|
+
* @return {Datasource}
|
94
|
+
*/
|
95
|
+
self["setInternal"] = (path, value) => {
|
96
|
+
new Pathfinder(self[internalSymbol].getSubject()).setVia(path, value);
|
97
|
+
return self;
|
98
|
+
}
|
99
|
+
|
100
|
+
/**
|
101
|
+
* set multiple internals at once
|
102
|
+
*
|
103
|
+
* @param {string|object} options
|
104
|
+
* @return {Datasource}
|
105
|
+
* @throws {Error} the options does not contain a valid json definition
|
106
|
+
*/
|
107
|
+
self["setInternals"] = (options) => {
|
108
|
+
if (isString(options)) {
|
109
|
+
options = parseOptionsJSON(options);
|
110
|
+
}
|
111
|
+
|
112
|
+
extend(self[internalSymbol].getSubject(), defaults, options);
|
113
|
+
return self;
|
114
|
+
}
|
115
|
+
|
116
|
+
/**
|
117
|
+
* nested internals can be specified by path `a.b.c`
|
118
|
+
*
|
119
|
+
* @param {string} path
|
120
|
+
* @param {*} defaultValue
|
121
|
+
* @return {*}
|
122
|
+
*/
|
123
|
+
self["getInternal"] = (path, defaultValue) => {
|
124
|
+
let value;
|
125
|
+
|
126
|
+
try {
|
127
|
+
value = new Pathfinder(self[internalSymbol]
|
128
|
+
.getRealSubject()).getVia(path);
|
129
|
+
} catch (e) {
|
130
|
+
}
|
131
|
+
|
132
|
+
if (value === undefined) return defaultValue;
|
133
|
+
return value;
|
134
|
+
}
|
135
|
+
}
|
136
|
+
|
137
|
+
/**
|
138
|
+
* @private
|
139
|
+
* @param obj
|
140
|
+
* @param prop
|
141
|
+
* @return {boolean}
|
142
|
+
*/
|
143
|
+
function hasGetter(obj, prop) {
|
144
|
+
|
145
|
+
while (isObject(obj)) {
|
146
|
+
if (Object.getOwnPropertyDescriptor(obj, prop)?.['get']) {
|
147
|
+
return true;
|
148
|
+
}
|
149
|
+
obj = Object.getPrototypeOf(obj);
|
150
|
+
}
|
151
|
+
|
152
|
+
return false;
|
153
|
+
}
|
154
|
+
|
155
|
+
/**
|
156
|
+
* @private
|
157
|
+
* @param data
|
158
|
+
* @return {Object}
|
159
|
+
*/
|
160
|
+
function parseOptionsJSON(data) {
|
161
|
+
let obj = {};
|
162
|
+
|
163
|
+
if (!isString(data)) {
|
164
|
+
return obj;
|
165
|
+
}
|
166
|
+
|
167
|
+
// the configuration can be specified as a data url.
|
168
|
+
try {
|
169
|
+
let dataUrl = parseDataURL(data);
|
170
|
+
data = dataUrl.content;
|
171
|
+
} catch (e) {
|
172
|
+
}
|
173
|
+
|
174
|
+
try {
|
175
|
+
obj = JSON.parse(data);
|
176
|
+
} catch (e) {
|
177
|
+
throw e;
|
178
|
+
}
|
179
|
+
|
180
|
+
return validateObject(obj);
|
181
|
+
}
|
package/source/types/version.mjs
CHANGED
package/test/cases/monster.mjs
CHANGED
@@ -0,0 +1,153 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
import {expect} from "chai"
|
4
|
+
import {equipWithInternal} from "../../../../application/source/types/internal.mjs";
|
5
|
+
import {Observer} from "../../../../application/source/types/observer.mjs";
|
6
|
+
|
7
|
+
class SomeRandomClass1 extends Object {
|
8
|
+
|
9
|
+
doit() {
|
10
|
+
return "done";
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
class SomeRandomClass2 extends Object {
|
15
|
+
|
16
|
+
constructor() {
|
17
|
+
super();
|
18
|
+
equipWithInternal.call(this);
|
19
|
+
}
|
20
|
+
|
21
|
+
get defaultInternal() {
|
22
|
+
return {
|
23
|
+
test: "test"
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
}
|
28
|
+
|
29
|
+
describe('Base inject with options', function () {
|
30
|
+
|
31
|
+
describe('new SomeRandomClass', function () {
|
32
|
+
|
33
|
+
it('is instance of SomeRandomClass1', function () {
|
34
|
+
expect(new SomeRandomClass2).not.to.be.instanceOf(SomeRandomClass1);
|
35
|
+
expect(new SomeRandomClass2).to.be.instanceOf(SomeRandomClass2);
|
36
|
+
});
|
37
|
+
|
38
|
+
it('is instance of SomeRandomClass2', function () {
|
39
|
+
expect(new SomeRandomClass1).to.be.instanceOf(SomeRandomClass1);
|
40
|
+
expect(new SomeRandomClass1).not.to.be.instanceOf(SomeRandomClass2);
|
41
|
+
});
|
42
|
+
|
43
|
+
})
|
44
|
+
|
45
|
+
describe('Extends SomeRandomClass with internals', function () {
|
46
|
+
|
47
|
+
it('attach and notify internal observer', function (done) {
|
48
|
+
const c = new SomeRandomClass2;
|
49
|
+
c.attachInternalObserver(new Observer(() => {
|
50
|
+
done();
|
51
|
+
}));
|
52
|
+
|
53
|
+
c.setInternal("test", "test");
|
54
|
+
|
55
|
+
});
|
56
|
+
|
57
|
+
it('attach and remove internal observer', function () {
|
58
|
+
const c = new SomeRandomClass2;
|
59
|
+
|
60
|
+
|
61
|
+
const observer = new Observer(() => {
|
62
|
+
|
63
|
+
});
|
64
|
+
|
65
|
+
expect(c.containsInternalObserver(observer)).to.be.false;
|
66
|
+
c.attachInternalObserver(observer);
|
67
|
+
expect(c.containsInternalObserver(observer)).to.be.true;
|
68
|
+
c.detachInternalObserver(observer);
|
69
|
+
expect(c.containsInternalObserver(observer)).to.be.false;
|
70
|
+
|
71
|
+
});
|
72
|
+
|
73
|
+
it("getInternal and setInternal", function () {
|
74
|
+
const c = new SomeRandomClass2;
|
75
|
+
expect(c.setInternal("test", "yeah")).to.be.instanceOf(SomeRandomClass2);
|
76
|
+
expect(c.getInternal("test")).to.be.equal("yeah");
|
77
|
+
});
|
78
|
+
|
79
|
+
it("deal with default values", function () {
|
80
|
+
const testClass = class extends Object {
|
81
|
+
constructor() {
|
82
|
+
super();
|
83
|
+
equipWithInternal.call(this);
|
84
|
+
}
|
85
|
+
|
86
|
+
get internalDefaults() {
|
87
|
+
return {
|
88
|
+
test: "xyz"
|
89
|
+
}
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
|
94
|
+
const c = new testClass;
|
95
|
+
expect(c.getInternal("test")).to.be.equal("xyz");
|
96
|
+
expect(c.getInternal("test2", "abc")).to.be.equal("abc");
|
97
|
+
});
|
98
|
+
|
99
|
+
it("deal with defaults from defaults", function () {
|
100
|
+
const testClass = class extends Object {
|
101
|
+
constructor() {
|
102
|
+
super();
|
103
|
+
equipWithInternal.call(this);
|
104
|
+
}
|
105
|
+
|
106
|
+
get internalDefaults() {
|
107
|
+
return {
|
108
|
+
test: "xyz"
|
109
|
+
}
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
const testClass2 = class extends testClass {
|
114
|
+
constructor() {
|
115
|
+
super();
|
116
|
+
equipWithInternal.call(this);
|
117
|
+
}
|
118
|
+
|
119
|
+
get internalDefaults() {
|
120
|
+
return Object.assign({}, super.internalDefaults, {
|
121
|
+
test2: "abc"
|
122
|
+
})
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
const c = new testClass2;
|
127
|
+
expect(c.getInternal("test")).to.be.equal("xyz");
|
128
|
+
expect(c.getInternal("test2")).to.be.equal("abc");
|
129
|
+
});
|
130
|
+
|
131
|
+
it("set multiple values", function () {
|
132
|
+
const c = new SomeRandomClass2;
|
133
|
+
expect(c.setInternals({
|
134
|
+
test: "yeah",
|
135
|
+
test2: "yeah2"
|
136
|
+
})).to.be.instanceOf(SomeRandomClass2);
|
137
|
+
expect(c.getInternal("test")).to.be.equal("yeah");
|
138
|
+
expect(c.getInternal("test2")).to.be.equal("yeah2");
|
139
|
+
|
140
|
+
c.setInternals({
|
141
|
+
test2: "yeah2-new",
|
142
|
+
test3: "yeah3"
|
143
|
+
});
|
144
|
+
|
145
|
+
expect(c.getInternal("test")).to.be.equal("yeah");
|
146
|
+
expect(c.getInternal("test2")).to.be.equal("yeah2-new");
|
147
|
+
expect(c.getInternal("test3")).to.be.equal("yeah3");
|
148
|
+
});
|
149
|
+
|
150
|
+
});
|
151
|
+
|
152
|
+
|
153
|
+
})
|