@schukai/monster 3.3.0 → 3.4.1

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -73,7 +73,7 @@ We do try to work around some browser bugs, but on the whole we don't use polyfi
73
73
  However, many functions can be mapped via [polyfill.io](https://polyfill.io/) and thus the compatibility can be increased.
74
74
 
75
75
  ```html
76
- <script id="polyfill" src="https://polyfill.io/v3/polyfill.min.js?features=Array.from,Array.isArray,Array.prototype.entries,Array.prototype.fill,Array.prototype.filter,Array.prototype.forEach,Array.prototype.indexOf,Array.prototype.keys,Array.prototype.lastIndexOf,Array.prototype.map,Array.prototype.reduce,Array.prototype.sort,ArrayBuffer,atob,CustomEvent,DataView,document,Document,DocumentFragment,Element,Event,fetch,globalThis,HTMLDocument,HTMLTemplateElement,Intl,JSON,Map,Math.log2,Number.isInteger,Object.assign,Object.defineProperty,Object.entries,Object.freeze,Object.getOwnPropertyDescriptor,Object.getOwnPropertyNames,Object.getPrototypeOf,Object.keys,Promise,Reflect,Reflect.defineProperty,Reflect.get,Reflect.getOwnPropertyDescriptor,Reflect.setPrototypeOf,Set,String.prototype.endsWith,String.prototype.matchAll,String.prototype.padStart,String.prototype.startsWith,String.prototype.trim,Symbol,Symbol.for,Symbol.hasInstance,Symbol.iterator,Uint16Array,Uint8Array,URL,WeakMap,WeakSet"
76
+ <script id="polyfill" src="https://polyfill.io/v3/polyfill.min.js?features=Array.from,Array.isArray,Array.prototype.entries,Array.prototype.fill,Array.prototype.filter,Array.prototype.forEach,Array.prototype.indexOf,Array.prototype.keys,Array.prototype.lastIndexOf,Array.prototype.map,Array.prototype.reduce,Array.prototype.sort,ArrayBuffer,atob,Blob,CustomEvent,DataView,document,Document,DocumentFragment,Element,Event,fetch,globalThis,HTMLDocument,HTMLTemplateElement,Intl,JSON,Map,Math.log2,Number.isInteger,Object.assign,Object.defineProperty,Object.entries,Object.freeze,Object.getOwnPropertyDescriptor,Object.getOwnPropertyNames,Object.getPrototypeOf,Object.keys,Promise,Reflect,Reflect.defineProperty,Reflect.get,Reflect.getOwnPropertyDescriptor,Reflect.setPrototypeOf,Set,String.prototype.endsWith,String.prototype.matchAll,String.prototype.padStart,String.prototype.startsWith,String.prototype.trim,Symbol,Symbol.for,Symbol.hasInstance,Symbol.iterator,Uint16Array,Uint8Array,URL,WeakMap,WeakSet"
77
77
  crossorigin="anonymous"
78
78
  referrerpolicy="no-referrer"></script>
79
79
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schukai/monster",
3
- "version": "3.3.0",
3
+ "version": "3.4.1",
4
4
  "description": "Monster is a simple library for creating fast, robust and lightweight websites.",
5
5
  "keywords": [
6
6
  "framework",
@@ -4,9 +4,9 @@
4
4
  */
5
5
 
6
6
  /**
7
- * Namespace for storages
7
+ * Namespace for server
8
8
  *
9
- * @namespace Monster.Data.Datasource.RestAPI
9
+ * @namespace Monster.Data.Datasource.Server
10
10
  * @memberOf Monster.Data.Datasource
11
11
  * @author schukai GmbH
12
12
  */
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Copyright 2022 schukai GmbH
3
+ * SPDX-License-Identifier: AGPL-3.0
4
+ */
5
+
6
+ /**
7
+ * Namespace for storages
8
+ *
9
+ * @namespace Monster.Data.Datasource.Server.RestAPI
10
+ * @memberOf Monster.Data.Datasource.Server
11
+ * @author schukai GmbH
12
+ */
13
+ const ns = {};
@@ -5,7 +5,7 @@
5
5
  * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
6
6
  */
7
7
 
8
- import {internalSymbol,instanceSymbol} from "../../../constants.mjs";
8
+ import {internalSymbol,instanceSymbol} from "../../../../constants.mjs";
9
9
 
10
10
  export {WriteError}
11
11
 
@@ -15,7 +15,7 @@ export {WriteError}
15
15
  * @license AGPLv3
16
16
  * @since 1.24.0
17
17
  * @copyright schukai GmbH
18
- * @memberOf Monster.Data.Datasource.RestAPI
18
+ * @memberOf Monster.Data.Datasource.Server.RestAPI
19
19
  * @summary the error is thrown by the rest api in case of error
20
20
  */
21
21
  class WriteError extends Error {
@@ -38,7 +38,7 @@ class WriteError extends Error {
38
38
  * @since 2.1.0
39
39
  */
40
40
  static get [instanceSymbol]() {
41
- return Symbol.for("@schukai/monster/data/datasource/restapi/writeerror");
41
+ return Symbol.for("@schukai/monster/data/datasource/server/restapi/writeerror");
42
42
  }
43
43
 
44
44
  /**
@@ -5,11 +5,11 @@
5
5
  * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
6
6
  */
7
7
 
8
- import {internalSymbol,instanceSymbol} from "../../constants.mjs";
9
- import {isObject} from "../../types/is.mjs";
10
- import {Datasource} from "../datasource.mjs";
11
- import {Pathfinder} from "../pathfinder.mjs";
12
- import {Pipe} from "../pipe.mjs";
8
+ import {internalSymbol, instanceSymbol} from "../../../constants.mjs";
9
+ import {isObject} from "../../../types/is.mjs";
10
+ import {Server} from "../server.mjs";
11
+ import {Pathfinder} from "../../pathfinder.mjs";
12
+ import {Pipe} from "../../pipe.mjs";
13
13
  import {WriteError} from "./restapi/writeerror.mjs";
14
14
 
15
15
  export {RestAPI}
@@ -17,29 +17,25 @@ export {RestAPI}
17
17
  /**
18
18
  * The RestAPI is a class that enables a REST API server.
19
19
  *
20
- * @externalExample ../../../example/data/storage/restapi.mjs
20
+ * @externalExample ../../../example/data/storage/restapi.mjs
21
21
  * @license AGPLv3
22
22
  * @since 1.22.0
23
23
  * @copyright schukai GmbH
24
- * @memberOf Monster.Data.Datasource
24
+ * @memberOf Monster.Data.Datasource.Server
25
25
  * @summary The RestAPI is a class that binds a REST API server.
26
26
  */
27
- class RestAPI extends Datasource {
27
+ class RestAPI extends Server {
28
28
 
29
29
  /**
30
30
  *
31
- * @param {Object} [readDefinition] An options object containing any custom settings that you want to apply to the read request.
32
- * @param {Object} [writeDefinition] An options object containing any custom settings that you want to apply to the write request.
31
+ * @param {Object} [options] options contains definitions for the datasource.
33
32
  */
34
- constructor(readDefinition, writeDefinition) {
33
+ constructor(options) {
35
34
  super();
36
35
 
37
- const options = {}
38
-
39
- if (isObject(readDefinition)) options.read = readDefinition;
40
- if (isObject(writeDefinition)) options.write = writeDefinition;
41
-
42
- this.setOptions(options);
36
+ if (isObject(options)) {
37
+ this.setOptions(options);
38
+ }
43
39
 
44
40
  }
45
41
 
@@ -49,9 +45,9 @@ class RestAPI extends Datasource {
49
45
  * @since 2.1.0
50
46
  */
51
47
  static get [instanceSymbol]() {
52
- return Symbol.for("@schukai/monster/data/datasource/restapi");
53
- }
54
-
48
+ return Symbol.for("@schukai/monster/data/datasource/server/restapi");
49
+ }
50
+
55
51
  /**
56
52
  * @property {Object} write={} Options
57
53
  * @property {Object} write.init={} An options 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}
@@ -64,9 +60,9 @@ class RestAPI extends Datasource {
64
60
  * @property {Monster.Data.Datasource~exampleCallback[]} write.mapping.callback with the help of the callback, the structures can be adjusted before writing.
65
61
  * @property {Object} write.report
66
62
  * @property {String} write.report.path Path to validations
67
- * @property {Object} write.sheathing
63
+ * @property {Object} write.sheathing
68
64
  * @property {Object} write.sheathing.object Object to be wrapped
69
- * @property {string} write.sheathing.path Path to the data
65
+ * @property {string} write.sheathing.path Path to the data
70
66
  * @property {Object} read={} Options
71
67
  * @property {Object} read.init={} An options 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}
72
68
  * @property {string} read.init.method=GET
@@ -124,45 +120,37 @@ class RestAPI extends Datasource {
124
120
  let init = self.getOption('read.init');
125
121
  if (!isObject(init)) init = {};
126
122
 
127
- return fetch(self.getOption('read.url'), init).then(resp => {
128
- response = resp;
123
+ return new Promise((resolve, reject) => {
124
+ fetch(self.getOption('read.url'), init).then(resp => {
125
+ response = resp;
129
126
 
130
- const acceptedStatus = self.getOption('read.acceptedStatus', [200]);
127
+ const acceptedStatus = self.getOption('read.acceptedStatus', [200]);
131
128
 
132
- if (acceptedStatus.indexOf(resp.status) === -1) {
133
- throw Error('the data cannot be read (response ' + resp.status + ')')
134
- }
129
+ if (acceptedStatus.indexOf(resp.status) === -1) {
130
+ throw Error('the data cannot be read (response ' + resp.status + ')')
131
+ }
135
132
 
136
- return resp.text()
137
- }).then(body => {
133
+ return resp.text()
134
+ }).then(body => {
138
135
 
139
- let obj;
136
+ let obj;
140
137
 
141
- try {
142
- obj = JSON.parse(body);
138
+ try {
139
+ obj = JSON.parse(body);
143
140
 
144
- } catch (e) {
141
+ } catch (e) {
145
142
 
146
- if (body.length > 100) {
147
- body = body.substring(0, 97) + '...';
148
- }
143
+ if (body.length > 100) {
144
+ body = body.substring(0, 97) + '...';
145
+ }
149
146
 
150
- throw new Error('the response does not contain a valid json (actual: ' + body + ').');
151
- }
147
+ throw new Error('the response does not contain a valid json (actual: ' + body + ').');
148
+ }
152
149
 
153
- let transformation = self.getOption('read.mapping.transformer');
154
- if (transformation !== undefined) {
155
- const pipe = new Pipe(transformation);
150
+ self.set(self.transformServerPayload.call(self, obj));
151
+ resolve(response);
152
+ }).catch(reject);
156
153
 
157
- for (const callback of self.getOption('read.mapping.callbacks')) {
158
- pipe.setCallback(callback.constructor.name, callback);
159
- }
160
-
161
- obj = pipe.run(obj);
162
- }
163
-
164
- self.set(obj);
165
- return response;
166
154
  })
167
155
  }
168
156
 
@@ -173,7 +161,6 @@ class RestAPI extends Datasource {
173
161
  write() {
174
162
  const self = this;
175
163
 
176
-
177
164
  let init = self.getOption('write.init');
178
165
  if (!isObject(init)) init = {};
179
166
  if (typeof init['headers'] !== 'object') {
@@ -182,42 +169,28 @@ class RestAPI extends Datasource {
182
169
  }
183
170
  }
184
171
 
185
- let obj = self.get();
186
- let transformation = self.getOption('write.mapping.transformer');
187
- if (transformation !== undefined) {
188
- const pipe = new Pipe(transformation);
189
-
190
- for (const callback of self.getOption('write.mapping.callbacks')) {
191
- pipe.setCallback(callback.constructor.name, callback);
192
- }
193
-
194
- obj = pipe.run(obj);
195
- }
196
-
197
- let sheathingObject = self.getOption('write.sheathing.object');
198
- let sheathingPath = self.getOption('write.sheathing.path');
199
- let reportPath = self.getOption('write.report.path');
200
-
201
- if (sheathingObject && sheathingPath) {
202
- const sub = obj;
203
- obj = sheathingObject;
204
- (new Pathfinder(obj)).setVia(sheathingPath, sub);
205
- }
206
-
172
+ let obj = self.prepareServerPayload(self.get());
207
173
  init['body'] = JSON.stringify(obj);
208
174
 
209
- return fetch(self.getOption('write.url'), init).then(response => {
175
+ return new Promise((resolve, reject) => {
176
+ fetch(self.getOption('write.url'), init).then(response => {
177
+ const acceptedStatus = self.getOption('write.acceptedStatus', [200, 201]);
210
178
 
211
- const acceptedStatus = self.getOption('write.acceptedStatus', [200, 2001]);
212
-
213
- if (acceptedStatus.indexOf(response.status) === -1) {
179
+ if (acceptedStatus.indexOf(response.status) > -1) {
180
+ reject(response);
181
+ return;
182
+ }
214
183
 
215
- return response.text().then((body) => {
184
+ response.text().then((body) => {
216
185
 
217
- let obj, validation;
186
+ let obj = {}, validation = {};
218
187
  try {
219
188
  obj = JSON.parse(body);
220
- validation = new Pathfinder(obj).getVia(reportPath)
189
+
190
+ if (reportPath) {
191
+ validation = (new Pathfinder(obj)).getVia(reportPath);
192
+ }
193
+
221
194
 
222
195
  } catch (e) {
223
196
 
@@ -225,18 +198,20 @@ class RestAPI extends Datasource {
225
198
  body = body.substring(0, 97) + '...';
226
199
  }
227
200
 
228
- throw new Error('the response does not contain a valid json (actual: ' + body + ').');
201
+ reject(new Error('the response does not contain a valid json (actual: ' + body + ').'));
202
+ return;
229
203
  }
230
204
 
231
- throw new WriteError('the data cannot be written (response ' + response.status + ')', response, validation)
205
+ reject(new WriteError('the data cannot be written (response ' + response.status + ')', response, validation))
206
+ return;
232
207
 
233
- })
208
+ }).catch(reject);
234
209
 
235
210
 
236
- }
211
+ }).catch(reject);
212
+
213
+ })
237
214
 
238
- return response;
239
- });
240
215
  }
241
216
 
242
217
 
@@ -5,16 +5,13 @@
5
5
  * License text available at https://www.gnu.org/licenses/agpl-3.0.en.html
6
6
  */
7
7
 
8
- import {internalSymbol, instanceSymbol} from "../../constants.mjs";
9
- import {isString, isObject} from "../../types/is.mjs";
10
- import {WebConnect} from "../../net/webconnect.mjs";
11
- import {Message} from "../../net/webconnect/message.mjs";
12
- import {Datasource} from "../datasource.mjs";
13
- import {Pathfinder} from "../pathfinder.mjs";
14
- import {Pipe} from "../pipe.mjs";
15
-
16
- export {WebSocketDatasource}
8
+ import {internalSymbol, instanceSymbol} from "../../../constants.mjs";
9
+ import {isString, isObject} from "../../../types/is.mjs";
10
+ import {WebConnect as NetWebConnect} from "../../../net/webconnect.mjs";
11
+ import {Message} from "../../../net/webconnect/message.mjs";
12
+ import {Server} from "../server.mjs";
17
13
 
14
+ export {WebConnect}
18
15
 
19
16
  /**
20
17
  * @private
@@ -24,32 +21,7 @@ export {WebSocketDatasource}
24
21
  */
25
22
  const webConnectSymbol = Symbol("connection");
26
23
 
27
- /**
28
- *
29
- * @param self
30
- * @param obj
31
- * @returns {*}
32
- */
33
- function doTransform(type, obj) {
34
- const self = this;
35
- let transformation = self.getOption(type + '.mapping.transformer');
36
- if (transformation !== undefined) {
37
- const pipe = new Pipe(transformation);
38
- const callbacks = self.getOption(type + '.mapping.callbacks')
39
24
 
40
- if (isObject(callbacks)) {
41
- for (const key in callbacks) {
42
- if (callbacks.hasOwnProperty(key) && typeof callbacks[key] === 'function') {
43
- pipe.setCallback(key, callbacks[key]);
44
- }
45
- }
46
- }
47
-
48
- obj = pipe.run(obj);
49
- }
50
-
51
- return obj;
52
- }
53
25
 
54
26
  /**
55
27
  * The RestAPI is a class that enables a REST API server.
@@ -58,10 +30,10 @@ function doTransform(type, obj) {
58
30
  * @license AGPLv3
59
31
  * @since 3.1.0
60
32
  * @copyright schukai GmbH
61
- * @memberOf Monster.Data.Datasource
33
+ * @memberOf Monster.Data.Datasource.Server
62
34
  * @summary The LocalStorage class encapsulates the access to data objects.
63
35
  */
64
- class WebSocketDatasource extends Datasource {
36
+ class WebConnect extends Server {
65
37
 
66
38
  /**
67
39
  *
@@ -78,7 +50,7 @@ class WebSocketDatasource extends Datasource {
78
50
 
79
51
  if (!isObject(options)) options = {};
80
52
  this.setOptions(options);
81
- this[webConnectSymbol] = new WebConnect({
53
+ this[webConnectSymbol] = new NetWebConnect({
82
54
  url: self.getOption('url'),
83
55
  connection: {
84
56
  timeout: self.getOption('connection.timeout'),
@@ -111,7 +83,7 @@ class WebSocketDatasource extends Datasource {
111
83
  * @returns {symbol}
112
84
  */
113
85
  static get [instanceSymbol]() {
114
- return Symbol.for("@schukai/monster/data/datasource/websocket");
86
+ return Symbol.for("@schukai/monster/data/datasource/server/webconnect");
115
87
  }
116
88
 
117
89
  /**
@@ -195,7 +167,6 @@ class WebSocketDatasource extends Datasource {
195
167
  }
196
168
 
197
169
  obj = obj.getData();
198
-
199
170
  obj = self.transformServerPayload.call(self, obj);
200
171
  self.set( obj);
201
172
  }
@@ -206,95 +177,6 @@ class WebSocketDatasource extends Datasource {
206
177
 
207
178
  };
208
179
 
209
- // const self = this;
210
- // let response;
211
- //
212
- // if (self[webConnectSymbol]?.socket?.readyState !== 1) {
213
- // return Promise.reject('The connection is not established.');
214
- // }
215
- //
216
- // return new Promise((resolve, reject) => {
217
- // if (self[receiveQueueSymbol].isEmpty()) {
218
- // resolve();
219
- // }
220
- //
221
- // while (!self[receiveQueueSymbol].isEmpty()) {
222
- //
223
- // const event = self[receiveQueueSymbol].poll();
224
- // const body = event?.data;
225
- // if (!body) continue;
226
- //
227
- // let obj;
228
- // try {
229
- // obj = JSON.parse(body);
230
- // } catch (e) {
231
- //
232
- // let msg = 'the response does not contain a valid json (actual: ';
233
- //
234
- // if (body.length > 100) {
235
- // msg += body.substring(0, 97) + '...';
236
- // } else {
237
- // msg += body;
238
- // }
239
- //
240
- // msg += "; " + e.message + ')';
241
- //
242
- // reject(msg);
243
- // return;
244
- // }
245
- //
246
- // obj = self.transformServerPayload.call(self, obj);
247
- //
248
- //
249
- // self.set(obj);
250
- // return response;
251
- // }
252
- // })
253
- //}
254
-
255
- /**
256
- * This prepares the data that comes from the server.
257
- * Should not be called directly.
258
- *
259
- * @private
260
- * @param {Object} payload
261
- * @returns {Object}
262
- */
263
- transformServerPayload(payload) {
264
- const self = this;
265
- payload = doTransform.call(self, 'read', payload);
266
-
267
- const dataPath = self.getOption('read.path');
268
- if (dataPath) {
269
- payload = (new Pathfinder(payload)).getVia(dataPath);
270
- }
271
-
272
- return payload;
273
- }
274
-
275
- /**
276
- * This prepares the data for writing and should not be called directly.
277
- *
278
- * @private
279
- * @param {Object} payload
280
- * @returns {Object}
281
- */
282
- prepareServerPayload(payload) {
283
- const self = this;
284
-
285
- payload = doTransform.call(self, 'write', payload);
286
-
287
- let sheathingObject = self.getOption('write.sheathing.object');
288
- let sheathingPath = self.getOption('write.sheathing.path');
289
-
290
- if (sheathingObject && sheathingPath) {
291
- const sub = payload;
292
- payload = sheathingObject;
293
- (new Pathfinder(payload)).setVia(sheathingPath, sub);
294
- }
295
-
296
- return payload;
297
- }
298
180
 
299
181
  /**
300
182
  * @return {Promise}
@@ -305,13 +187,12 @@ class WebSocketDatasource extends Datasource {
305
187
  return self[webConnectSymbol].send(obj)
306
188
  }
307
189
 
308
-
309
190
  /**
310
191
  * @return {RestAPI}
311
192
  */
312
193
  getClone() {
313
194
  const self = this;
314
- return new WebSocketDatasource(self[internalSymbol].getRealSubject()['options']);
195
+ return new WebConnect(self[internalSymbol].getRealSubject()['options']);
315
196
  }
316
197
 
317
198
  }
@@ -0,0 +1,108 @@
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
+
8
+ import {internalSymbol,instanceSymbol} from "../../constants.mjs";
9
+ import {isObject} from "../../types/is.mjs";
10
+ import {Datasource} from "../datasource.mjs";
11
+ import {Pathfinder} from "../pathfinder.mjs";
12
+ import {Pipe} from "../pipe.mjs";
13
+
14
+ export {Server}
15
+
16
+ /**
17
+ * Base class for all server datasources
18
+ *
19
+ * @license AGPLv3
20
+ * @since 3.4.0
21
+ * @copyright schukai GmbH
22
+ * @memberOf Monster.Data.Datasource
23
+ * @summary The Server class encapsulates the access to a server datasource
24
+ */
25
+ class Server extends Datasource {
26
+
27
+ /**
28
+ * This method is called by the `instanceof` operator.
29
+ * @returns {symbol}
30
+ */
31
+ static get [instanceSymbol]() {
32
+ return Symbol.for("@schukai/monster/data/datasource/server");
33
+ }
34
+
35
+
36
+ /**
37
+ * This prepares the data that comes from the server.
38
+ * Should not be called directly.
39
+ *
40
+ * @private
41
+ * @param {Object} payload
42
+ * @returns {Object}
43
+ */
44
+ transformServerPayload(payload) {
45
+ const self = this;
46
+ payload = doTransform.call(self, 'read', payload);
47
+
48
+ const dataPath = self.getOption('read.path');
49
+ if (dataPath) {
50
+ payload = (new Pathfinder(payload)).getVia(dataPath);
51
+ }
52
+
53
+ return payload;
54
+ }
55
+
56
+ /**
57
+ * This prepares the data for writing and should not be called directly.
58
+ *
59
+ * @private
60
+ * @param {Object} payload
61
+ * @returns {Object}
62
+ */
63
+ prepareServerPayload(payload) {
64
+ const self = this;
65
+
66
+ payload = doTransform.call(self, 'write', payload);
67
+
68
+ let sheathingObject = self.getOption('write.sheathing.object');
69
+ let sheathingPath = self.getOption('write.sheathing.path');
70
+
71
+ if (sheathingObject && sheathingPath) {
72
+ const sub = payload;
73
+ payload = sheathingObject;
74
+ (new Pathfinder(payload)).setVia(sheathingPath, sub);
75
+ }
76
+
77
+ return payload;
78
+ }
79
+
80
+ }
81
+
82
+
83
+ /**
84
+ *
85
+ * @param self
86
+ * @param obj
87
+ * @returns {*}
88
+ */
89
+ function doTransform(type, obj) {
90
+ const self = this;
91
+ let transformation = self.getOption(type + '.mapping.transformer');
92
+ if (transformation !== undefined) {
93
+ const pipe = new Pipe(transformation);
94
+ const callbacks = self.getOption(type + '.mapping.callbacks')
95
+
96
+ if (isObject(callbacks)) {
97
+ for (const key in callbacks) {
98
+ if (callbacks.hasOwnProperty(key) && typeof callbacks[key] === 'function') {
99
+ pipe.setCallback(key, callbacks[key]);
100
+ }
101
+ }
102
+ }
103
+
104
+ obj = pipe.run(obj);
105
+ }
106
+
107
+ return obj;
108
+ }
@@ -191,7 +191,7 @@ class Locale extends Base {
191
191
  *
192
192
  * ```
193
193
  * <script type="module">
194
- * import {Monster} from '@schukai/monster/source//monster.mjs';
194
+ * import {Monster} from '@schukai/monster/source/monster.mjs';
195
195
  * new Monster.I18n.createLocale()
196
196
  * </script>
197
197
  * ```