@schukai/monster 3.100.17 → 3.100.19
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/CHANGELOG.md +19 -0
- package/package.json +1 -1
- package/source/data/datasource/server/restapi.mjs +215 -207
- package/source/types/version.mjs +1 -1
- package/test/cases/monster.mjs +1 -1
- package/test/web/test.html +2 -2
- package/test/web/tests.js +229 -155
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,25 @@
|
|
2
2
|
|
3
3
|
|
4
4
|
|
5
|
+
## [3.100.19] - 2025-01-21
|
6
|
+
|
7
|
+
### Bug Fixes
|
8
|
+
|
9
|
+
- check header by rest api
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
## [3.100.18] - 2025-01-20
|
14
|
+
|
15
|
+
### Bug Fixes
|
16
|
+
|
17
|
+
- set request header if not set
|
18
|
+
### Changes
|
19
|
+
|
20
|
+
- update tests
|
21
|
+
|
22
|
+
|
23
|
+
|
5
24
|
## [3.100.17] - 2025-01-20
|
6
25
|
|
7
26
|
### Bug Fixes
|
package/package.json
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.13","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"3.100.
|
1
|
+
{"author":"schukai GmbH","dependencies":{"@floating-ui/dom":"^1.6.13","@popperjs/core":"^2.11.8"},"description":"Monster is a simple library for creating fast, robust and lightweight websites.","homepage":"https://monsterjs.org/","keywords":["framework","web","dom","css","sass","mobile-first","app","front-end","templates","schukai","core","shopcloud","alvine","monster","buildmap","stack","observer","observable","uuid","node","nodelist","css-in-js","logger","log","theme"],"license":"AGPL 3.0","main":"source/monster.mjs","module":"source/monster.mjs","name":"@schukai/monster","repository":{"type":"git","url":"https://gitlab.schukai.com/oss/libraries/javascript/monster.git"},"type":"module","version":"3.100.19"}
|
@@ -12,15 +12,15 @@
|
|
12
12
|
* SPDX-License-Identifier: AGPL-3.0
|
13
13
|
*/
|
14
14
|
|
15
|
-
import {
|
16
|
-
import {
|
17
|
-
import {
|
18
|
-
import {
|
19
|
-
import {
|
20
|
-
import {
|
21
|
-
import {
|
15
|
+
import {internalSymbol, instanceSymbol} from "../../../constants.mjs";
|
16
|
+
import {isObject, isFunction, isArray} from "../../../types/is.mjs";
|
17
|
+
import {diff} from "../../diff.mjs";
|
18
|
+
import {Server} from "../server.mjs";
|
19
|
+
import {WriteError} from "./restapi/writeerror.mjs";
|
20
|
+
import {DataFetchError} from "./restapi/data-fetch-error.mjs";
|
21
|
+
import {clone} from "../../../util/clone.mjs";
|
22
22
|
|
23
|
-
export {
|
23
|
+
export {RestAPI};
|
24
24
|
|
25
25
|
/**
|
26
26
|
* @type {symbol}
|
@@ -28,7 +28,7 @@ export { RestAPI };
|
|
28
28
|
* @since 3.12.0
|
29
29
|
*/
|
30
30
|
const rawDataSymbol = Symbol.for(
|
31
|
-
|
31
|
+
"@schukai/monster/data/datasource/server/restapi/rawdata",
|
32
32
|
);
|
33
33
|
|
34
34
|
/**
|
@@ -41,159 +41,163 @@ const rawDataSymbol = Symbol.for(
|
|
41
41
|
* @summary The RestAPI is a class that binds a REST API server.
|
42
42
|
*/
|
43
43
|
class RestAPI extends Server {
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
44
|
+
/**
|
45
|
+
*
|
46
|
+
* @param {Object} [options] options contains definitions for the datasource.
|
47
|
+
*/
|
48
|
+
constructor(options) {
|
49
|
+
super();
|
50
|
+
|
51
|
+
if (isObject(options)) {
|
52
|
+
this.setOptions(options);
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
/**
|
57
|
+
* This method is called by the `instanceof` operator.
|
58
|
+
* @return {symbol}
|
59
|
+
* @since 2.1.0
|
60
|
+
*/
|
61
|
+
static get [instanceSymbol]() {
|
62
|
+
return Symbol.for("@schukai/monster/data/datasource/server/restapi");
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* @property {Object} write={} Options
|
67
|
+
* @property {Object} write.init={} An option object, containing any custom settings that you want to apply to the request. The parameters are identical to those of the {@link https://developer.mozilla.org/en-US/docs/Web/API/Request/Request|Request constructor}
|
68
|
+
* @property {string} write.init.method=POST
|
69
|
+
* @property {Headers} write.init.headers Object containing any custom headers that you want to apply to the request.
|
70
|
+
* @property {string} write.responseCallback Callback function to be executed after the request has been completed.
|
71
|
+
* @property {string} write.acceptedStatus=[200,201]
|
72
|
+
* @property {string} write.url URL
|
73
|
+
* @property {Object} write.mapping the mapping is applied before writing.
|
74
|
+
* @property {String} write.mapping.transformer Transformer to select the appropriate entries
|
75
|
+
* @property {exampleCallback[]} write.mapping.callback with the help of the callback, the structures can be adjusted before writing.
|
76
|
+
* @property {Object} write.report
|
77
|
+
* @property {String} write.report.path Path to validations
|
78
|
+
* @property {Object} write.partial
|
79
|
+
* @property {Function} write.partial.callback Callback function to be executed after the request has been completed. (obj, diffResult) => obj
|
80
|
+
* @property {Object} write.sheathing
|
81
|
+
* @property {Object} write.sheathing.object Object to be wrapped
|
82
|
+
* @property {string} write.sheathing.path Path to the data
|
83
|
+
* @property {Object} read={} Options
|
84
|
+
* @property {Object} read.init={} An option object containing any custom settings that you want to apply to the request. The parameters are identical to those of the {@link https://developer.mozilla.org/en-US/docs/Web/API/Request/Request|Request constructor}
|
85
|
+
* @property {string} read.init.method=GET
|
86
|
+
* @property {array} read.acceptedStatus=[200]
|
87
|
+
* @property {string} read.url URL
|
88
|
+
* @property {Object} read.mapping the mapping is applied after reading.
|
89
|
+
* @property {String} read.mapping.transformer Transformer to select the appropriate entries
|
90
|
+
* @property {exampleCallback[]} read.mapping.callback with the help of the callback, the structures can be adjusted after reading.
|
91
|
+
*/
|
92
|
+
get defaults() {
|
93
|
+
return Object.assign({}, super.defaults, {
|
94
|
+
write: {
|
95
|
+
init: {
|
96
|
+
method: "POST",
|
97
|
+
headers: {
|
98
|
+
Accept: "application/json",
|
99
|
+
"Content-Type": "application/json",
|
100
|
+
},
|
101
|
+
},
|
102
|
+
responseCallback: null,
|
103
|
+
acceptedStatus: [200, 201],
|
104
|
+
url: null,
|
105
|
+
mapping: {
|
106
|
+
transformer: null,
|
107
|
+
callbacks: [],
|
108
|
+
},
|
109
|
+
sheathing: {
|
110
|
+
object: null,
|
111
|
+
path: null,
|
112
|
+
},
|
113
|
+
report: {
|
114
|
+
path: null,
|
115
|
+
},
|
116
|
+
|
117
|
+
partial: {
|
118
|
+
callback: null,
|
119
|
+
},
|
120
|
+
},
|
121
|
+
read: {
|
122
|
+
init: {
|
123
|
+
method: "GET",
|
124
|
+
headers: {
|
125
|
+
Accept: "application/json"
|
126
|
+
},
|
127
|
+
},
|
128
|
+
path: null,
|
129
|
+
responseCallback: null,
|
130
|
+
acceptedStatus: [200],
|
131
|
+
url: null,
|
132
|
+
mapping: {
|
133
|
+
transformer: null,
|
134
|
+
callbacks: [],
|
135
|
+
},
|
136
|
+
},
|
137
|
+
});
|
138
|
+
}
|
139
|
+
|
140
|
+
/**
|
141
|
+
* @return {Promise}
|
142
|
+
* @throws {Error} the options does not contain a valid json definition
|
143
|
+
* @throws {TypeError} value is not a object
|
144
|
+
* @throws {Error} the data cannot be read
|
145
|
+
*/
|
146
|
+
read() {
|
147
|
+
let init = this.getOption("read.init");
|
148
|
+
if (!isObject(init)) init = {};
|
149
|
+
if (!(init["headers"] instanceof Headers) && !isObject(init["headers"])) {
|
150
|
+
init["headers"] = new Headers();
|
151
|
+
init["headers"].append("Accept", "application/json");
|
152
|
+
}
|
153
|
+
|
154
|
+
if (!init["method"]) init["method"] = "GET";
|
155
|
+
|
156
|
+
let callback = this.getOption("read.responseCallback");
|
157
|
+
if (!callback) {
|
158
|
+
callback = (obj) => {
|
159
|
+
this.set(this.transformServerPayload.call(this, obj));
|
160
|
+
};
|
161
|
+
}
|
162
|
+
|
163
|
+
return fetchData.call(this, init, "read", callback);
|
164
|
+
}
|
165
|
+
|
166
|
+
/**
|
167
|
+
* @return {Promise}
|
168
|
+
* @throws {WriteError} the data cannot be written
|
169
|
+
*/
|
170
|
+
write() {
|
171
|
+
let init = this.getOption("write.init");
|
172
|
+
if (!isObject(init)) init = {};
|
173
|
+
if (!(init["headers"] instanceof Headers) && !isObject(init["headers"])) {
|
174
|
+
init["headers"] = new Headers();
|
175
|
+
init["headers"].append("Accept", "application/json");
|
176
|
+
init["headers"].append("Content-Type", "application/json");
|
177
|
+
}
|
178
|
+
if (!init["method"]) init["method"] = "POST";
|
179
|
+
|
180
|
+
const obj = this.prepareServerPayload(this.get());
|
181
|
+
init["body"] = JSON.stringify(obj);
|
182
|
+
|
183
|
+
const callback = this.getOption("write.responseCallback");
|
184
|
+
return fetchData.call(this, init, "write", callback);
|
185
|
+
}
|
186
|
+
|
187
|
+
/**
|
188
|
+
* @return {RestAPI}
|
189
|
+
*/
|
190
|
+
getClone() {
|
191
|
+
const api = new RestAPI();
|
192
|
+
|
193
|
+
const read = clone(this[internalSymbol].getRealSubject()["options"].read);
|
194
|
+
const write = clone(this[internalSymbol].getRealSubject()["options"].write);
|
195
|
+
|
196
|
+
api.setOption("read", read);
|
197
|
+
api.setOption("write", write);
|
198
|
+
|
199
|
+
return api;
|
200
|
+
}
|
197
201
|
}
|
198
202
|
|
199
203
|
/**
|
@@ -204,49 +208,53 @@ class RestAPI extends Server {
|
|
204
208
|
* @return {Promise<string>}
|
205
209
|
*/
|
206
210
|
function fetchData(init, key, callback) {
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
211
|
+
let response;
|
212
|
+
|
213
|
+
if (init?.headers === null) {
|
214
|
+
init.headers = new Headers();
|
215
|
+
}
|
216
|
+
|
217
|
+
return fetch(this.getOption(`${key}.url`), init)
|
218
|
+
.then((resp) => {
|
219
|
+
response = resp;
|
220
|
+
|
221
|
+
const acceptedStatus = this.getOption(`${key}.acceptedStatus`, [200]).map(
|
222
|
+
Number,
|
223
|
+
);
|
224
|
+
|
225
|
+
if (acceptedStatus.indexOf(resp.status) === -1) {
|
226
|
+
throw new DataFetchError(
|
227
|
+
`the response does not contain an accepted status (actual: ${resp.status}).`,
|
228
|
+
response,
|
229
|
+
);
|
230
|
+
}
|
231
|
+
|
232
|
+
return resp.text();
|
233
|
+
})
|
234
|
+
.then((body) => {
|
235
|
+
let obj;
|
236
|
+
|
237
|
+
try {
|
238
|
+
obj = JSON.parse(body);
|
239
|
+
|
240
|
+
response[rawDataSymbol] = obj;
|
241
|
+
} catch (e) {
|
242
|
+
if (body.length > 100) {
|
243
|
+
body = `${body.substring(0, 97)}...`;
|
244
|
+
}
|
245
|
+
|
246
|
+
throw new DataFetchError(
|
247
|
+
`the response does not contain a valid json (actual: ${body}).`,
|
248
|
+
response,
|
249
|
+
);
|
250
|
+
}
|
251
|
+
|
252
|
+
if (callback && isFunction(callback)) {
|
253
|
+
callback(obj);
|
254
|
+
}
|
255
|
+
return response;
|
256
|
+
})
|
257
|
+
.catch((e) => {
|
258
|
+
throw e;
|
259
|
+
});
|
252
260
|
}
|
package/source/types/version.mjs
CHANGED
package/test/cases/monster.mjs
CHANGED
package/test/web/test.html
CHANGED
@@ -9,8 +9,8 @@
|
|
9
9
|
</head>
|
10
10
|
<body>
|
11
11
|
<div id="headline" style="display: flex;align-items: center;justify-content: center;flex-direction: column;">
|
12
|
-
<h1 style='margin-bottom: 0.1em;'>Monster 3.
|
13
|
-
<div id="lastupdate" style='font-size:0.7em'>last update
|
12
|
+
<h1 style='margin-bottom: 0.1em;'>Monster 3.100.17</h1>
|
13
|
+
<div id="lastupdate" style='font-size:0.7em'>last update Di 21. Jan 00:44:02 CET 2025</div>
|
14
14
|
</div>
|
15
15
|
<div id="mocha-errors"
|
16
16
|
style="color: red;font-weight: bold;display: flex;align-items: center;justify-content: center;flex-direction: column;margin:20px;"></div>
|