@schukai/monster 3.4.1 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,14 @@
1
+ import {RestAPI} from '@schukai/monster/source/data/datasource/server/restapi.mjs';
2
+
3
+ const ds = new RestAPI({
4
+ write: {
5
+ url: 'https://httpbin.org/get'
6
+ },
7
+ read: {
8
+ url: 'https://httpbin.org/get'
9
+ }
10
+ });
11
+
12
+ ds.set({flag: true})
13
+ ds.write().then(() => console.log('done'));
14
+ ds.read().then(() => console.log('done'));
@@ -0,0 +1,9 @@
1
+ import {WebConnect} from '@schukai/monster/source/data/datasource/server/webconnect.mjs';
2
+
3
+ const ds = new WebConnect({
4
+ url: 'https://httpbin.org/get'
5
+ });
6
+
7
+ ds.set({flag: true})
8
+ ds.write().then(() => console.log('done'));
9
+ ds.read().then(() => console.log('done'));
@@ -0,0 +1,5 @@
1
+ import {Embed} from '@schukai/monster/source/i18n/providers/embed.mjs';
2
+
3
+ // read from scritp tag with id i18n
4
+ const translation = new Embed('i18n');
5
+
@@ -0,0 +1,16 @@
1
+ import {WebConnect} from '@schukai/monster/source/net/webconnect.mjs';
2
+
3
+ const connection = new WebConnect({
4
+ url: 'https://httpbin.org/get'
5
+ });
6
+
7
+ connection.connect().then(()=>{
8
+
9
+ connection.send({message:"Hello World!"}).then((response)=>{
10
+ console.log(response);
11
+ });
12
+
13
+ const message = connection.poll()
14
+
15
+
16
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@schukai/monster",
3
- "version": "3.4.1",
3
+ "version": "3.5.0",
4
4
  "description": "Monster is a simple library for creating fast, robust and lightweight websites.",
5
5
  "keywords": [
6
6
  "framework",
@@ -17,7 +17,7 @@ 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/datasource/server/restapi.mjs
21
21
  * @license AGPLv3
22
22
  * @since 1.22.0
23
23
  * @copyright schukai GmbH
@@ -114,44 +114,17 @@ class RestAPI extends Server {
114
114
  * @throws {Error} the data cannot be read
115
115
  */
116
116
  read() {
117
+
117
118
  const self = this;
118
- let response;
119
119
 
120
120
  let init = self.getOption('read.init');
121
121
  if (!isObject(init)) init = {};
122
+ if (!init['method']) init['method'] = 'GET';
122
123
 
123
- return new Promise((resolve, reject) => {
124
- fetch(self.getOption('read.url'), init).then(resp => {
125
- response = resp;
126
-
127
- const acceptedStatus = self.getOption('read.acceptedStatus', [200]);
128
-
129
- if (acceptedStatus.indexOf(resp.status) === -1) {
130
- throw Error('the data cannot be read (response ' + resp.status + ')')
131
- }
132
-
133
- return resp.text()
134
- }).then(body => {
135
-
136
- let obj;
137
-
138
- try {
139
- obj = JSON.parse(body);
140
-
141
- } catch (e) {
142
-
143
- if (body.length > 100) {
144
- body = body.substring(0, 97) + '...';
145
- }
146
-
147
- throw new Error('the response does not contain a valid json (actual: ' + body + ').');
148
- }
149
-
150
- self.set(self.transformServerPayload.call(self, obj));
151
- resolve(response);
152
- }).catch(reject);
124
+ return fetchData.call(this, 'read', (obj) => {
125
+ self.set(self.transformServerPayload.call(self, obj));
126
+ });
153
127
 
154
- })
155
128
  }
156
129
 
157
130
  /**
@@ -159,6 +132,7 @@ class RestAPI extends Server {
159
132
  * @throws {WriteError} the data cannot be written
160
133
  */
161
134
  write() {
135
+
162
136
  const self = this;
163
137
 
164
138
  let init = self.getOption('write.init');
@@ -168,60 +142,65 @@ class RestAPI extends Server {
168
142
  'Content-Type': 'application/json'
169
143
  }
170
144
  }
145
+ if (!init['method']) init['method'] = 'POST';
171
146
 
172
147
  let obj = self.prepareServerPayload(self.get());
173
148
  init['body'] = JSON.stringify(obj);
174
149
 
175
- return new Promise((resolve, reject) => {
176
- fetch(self.getOption('write.url'), init).then(response => {
177
- const acceptedStatus = self.getOption('write.acceptedStatus', [200, 201]);
150
+ return fetchData.call(this, init, 'write');
151
+ }
178
152
 
179
- if (acceptedStatus.indexOf(response.status) > -1) {
180
- reject(response);
181
- return;
182
- }
183
153
 
184
- response.text().then((body) => {
154
+ /**
155
+ * @return {RestAPI}
156
+ */
157
+ getClone() {
158
+ const self = this;
159
+ return new RestAPI(self[internalSymbol].getRealSubject()['options'].read, self[internalSymbol].getRealSubject()['options'].write);
160
+ }
185
161
 
186
- let obj = {}, validation = {};
187
- try {
188
- obj = JSON.parse(body);
162
+ }
189
163
 
190
- if (reportPath) {
191
- validation = (new Pathfinder(obj)).getVia(reportPath);
192
- }
193
164
 
165
+ function fetchData(init, key, callback) {
194
166
 
195
- } catch (e) {
167
+ const self = this;
168
+ let response;
196
169
 
197
- if (body.length > 100) {
198
- body = body.substring(0, 97) + '...';
199
- }
200
170
 
201
- reject(new Error('the response does not contain a valid json (actual: ' + body + ').'));
202
- return;
203
- }
171
+ return fetch(self.getOption(key + '.url'), init).then(resp => {
172
+ response = resp;
204
173
 
205
- reject(new WriteError('the data cannot be written (response ' + response.status + ')', response, validation))
206
- return;
174
+ const acceptedStatus = self.getOption(key + '.acceptedStatus', [200]);
207
175
 
208
- }).catch(reject);
176
+ if (acceptedStatus.indexOf(resp.status) === -1) {
177
+ throw Error('the data cannot be ' + key + ' (response ' + resp.status + ')')
178
+ }
209
179
 
180
+ return resp.text()
181
+ }).then(body => {
210
182
 
211
- }).catch(reject);
183
+ let obj;
212
184
 
213
- })
185
+ try {
186
+ obj = JSON.parse(body);
214
187
 
215
- }
188
+ } catch (e) {
216
189
 
190
+ if (body.length > 100) {
191
+ body = body.substring(0, 97) + '...';
192
+ }
193
+
194
+ throw new Error('the response does not contain a valid json (actual: ' + body + ').');
195
+ }
196
+
197
+ if (callback && isFunction(callback)) {
198
+ callback(obj);
199
+ }
200
+ return response;
201
+
202
+ });
217
203
 
218
- /**
219
- * @return {RestAPI}
220
- */
221
- getClone() {
222
- const self = this;
223
- return new RestAPI(self[internalSymbol].getRealSubject()['options'].read, self[internalSymbol].getRealSubject()['options'].write);
224
- }
225
204
 
226
205
  }
227
206
 
@@ -26,7 +26,7 @@ const webConnectSymbol = Symbol("connection");
26
26
  /**
27
27
  * The RestAPI is a class that enables a REST API server.
28
28
  *
29
- * @externalExample ../../../example/data/storage/restapi.mjs
29
+ * @externalExample ../../../../example/data/datasource/server/webconnect.mjs
30
30
  * @license AGPLv3
31
31
  * @since 3.1.0
32
32
  * @copyright schukai GmbH
@@ -81,7 +81,7 @@ class Server extends Datasource {
81
81
 
82
82
 
83
83
  /**
84
- *
84
+ * @private
85
85
  * @param self
86
86
  * @param obj
87
87
  * @returns {*}
@@ -6,8 +6,8 @@
6
6
  */
7
7
 
8
8
  import {parseLocale} from "../i18n/locale.mjs";
9
-
10
9
  import {getDocument} from "./util.mjs";
10
+ import {getGlobalObject} from "../types/global.mjs";
11
11
 
12
12
  export {getLocaleOfDocument}
13
13
 
@@ -46,6 +46,40 @@ function getLocaleOfDocument() {
46
46
  return new parseLocale(locale)
47
47
  }
48
48
  }
49
+
50
+ let navigatorLanguage = getNavigatorLanguage();
51
+ if (navigatorLanguage) {
52
+ return parseLocale(navigatorLanguage);
53
+ }
49
54
 
50
55
  return parseLocale(DEFAULT_LANGUAGE);
51
56
  }
57
+
58
+ /**
59
+ * @private
60
+ * @returns {string|undefined|*}
61
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/language
62
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/languages
63
+ */
64
+ const getNavigatorLanguage = () => {
65
+ const navigator = getGlobalObject('navigator');
66
+ if (navigator === undefined) {
67
+ return undefined;
68
+ }
69
+
70
+ if (navigator.hasOwnProperty('language')) {
71
+ const language = navigator.language;
72
+ if (typeof language === 'string' && language.length > 0) {
73
+ return language;
74
+ }
75
+
76
+ }
77
+
78
+ const languages = navigator?.languages;
79
+ if (Array.isArray(languages) && languages.length>0) {
80
+ return languages[0];
81
+ }
82
+
83
+ return undefined;
84
+
85
+ }
@@ -0,0 +1,125 @@
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} from "../../constants.mjs";
9
+ import {extend} from "../../data/extend.mjs";
10
+ import { getGlobalObject} from "../../types/global.mjs";
11
+ import {isString} from "../../types/is.mjs";
12
+ import {validateObject, validateString} from "../../types/validate.mjs";
13
+ import {parseLocale} from "../locale.mjs";
14
+ import {Provider} from "../provider.mjs";
15
+ import {Translations} from "../translations.mjs";
16
+
17
+ export {Embed}
18
+
19
+ /**
20
+ * The Embed provider retrieves a JSON file from the given Script Tag.
21
+ *
22
+ * @externalExample ../../../example/i18n/providers/embed.mjs
23
+ * @license AGPLv3
24
+ * @since 1.13.0
25
+ * @copyright schukai GmbH
26
+ * @memberOf Monster.I18n.Providers
27
+ * @see {@link https://datatracker.ietf.org/doc/html/rfc3066}
28
+ * @tutorial i18n-locale-and-formatter
29
+ */
30
+ class Embed extends Provider {
31
+
32
+ /**
33
+ * ```html
34
+ * <script id="translations" type="application/json">
35
+ * {
36
+ * "hello": "Hallo"
37
+ * }
38
+ * </script>
39
+ * ```
40
+ *
41
+ *
42
+ * ```javascript
43
+ * new Embed('translations')
44
+ * ```
45
+ *
46
+ * @param {string} id
47
+ * @param {Object} options
48
+ */
49
+ constructor(id, options) {
50
+ super(options);
51
+
52
+ if (options === undefined) {
53
+ options = {};
54
+ }
55
+
56
+ validateString(id);
57
+
58
+ /**
59
+ * @property {string}
60
+ */
61
+ this.textId = id;
62
+
63
+ /**
64
+ * @private
65
+ * @property {Object} options
66
+ */
67
+ this[internalSymbol] = extend({}, super.defaults, this.defaults, validateObject(options));
68
+
69
+ }
70
+
71
+ /**
72
+ * Defaults
73
+ *
74
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API}
75
+ */
76
+ get defaults() {
77
+ return extend({}, super.defaults);
78
+ }
79
+
80
+ /**
81
+ *
82
+ * @param {Locale|string} locale
83
+ * @return {Promise}
84
+ */
85
+ getTranslations(locale) {
86
+
87
+ if (isString(locale)) {
88
+ locale = parseLocale(locale);
89
+ }
90
+
91
+ return new Promise((resolve, reject) => {
92
+
93
+ let text = getGlobalObject('document').getElementById(this.textId);
94
+
95
+ if (text === null) {
96
+ reject(new Error('Text not found'));
97
+ return;
98
+ }
99
+
100
+ let translations = null;
101
+ try {
102
+ translations = JSON.parse(text.innerHTML);
103
+ } catch (e) {
104
+ reject(e);
105
+ return;
106
+ }
107
+
108
+
109
+ if (translations === null) {
110
+ reject(new Error('Translations not found or invalid'));
111
+ return;
112
+ }
113
+
114
+ const t = new Translations(locale);
115
+ t.assignTranslations(translations)
116
+
117
+ resolve(t);
118
+
119
+ });
120
+
121
+ }
122
+
123
+
124
+ }
125
+
@@ -84,16 +84,17 @@ export {Fetch}
84
84
  */
85
85
  get defaults() {
86
86
 
87
- return {
88
- fetch: {
89
- method: 'GET', // *GET, POST, PUT, DELETE, etc.
90
- mode: 'cors', // no-cors, *cors, same-origin
91
- cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
92
- credentials: 'omit', // include, *same-origin, omit
93
- redirect: 'follow', // manual, *follow, error
94
- referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
95
- }
96
- }
87
+ return extend(
88
+ {
89
+ fetch: {
90
+ method: 'GET', // *GET, POST, PUT, DELETE, etc.
91
+ mode: 'cors', // no-cors, *cors, same-origin
92
+ cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
93
+ credentials: 'omit', // include, *same-origin, omit
94
+ redirect: 'follow', // manual, *follow, error
95
+ referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
96
+ }
97
+ }, super.defaults);
97
98
 
98
99
  }
99
100
 
@@ -142,13 +142,16 @@ class Translations extends Base {
142
142
  }
143
143
 
144
144
  /**
145
- * This method can be used to transfer overlays from an object. The keys are transferred and the values are entered as text.
146
- *
147
- * The values can either be character strings or, in the case of texts with plural forms, objects. The plural forms must be stored as text via a standard key "zero", "one", "two", "few", "many" and "other".
148
- *
145
+ * This method can be used to transfer overlays from an object. The keys are transferred, and the values are entered
146
+ * as text.
147
+ *
148
+ * The values can either be character strings or, in the case of texts with plural forms, objects. The plural forms
149
+ * must be stored as text via a standard key "zero", "one", "two", "few", "many" and "other".
150
+ *
149
151
  * Additionally, the key default can be specified, which will be used if no other key fits.
150
- *
151
- * In some languages, like for example in german, there is no own more number at the value 0. In these languages the function applies additionally zero.
152
+ *
153
+ * In some languages, like for example in German, there is no own more number at the value 0. In these languages,
154
+ * the function applies additionally zero.
152
155
  *
153
156
  * ```
154
157
  * translations.assignTranslations({
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Copyright 2022 schukai GmbH
3
+ * SPDX-License-Identifier: AGPL-3.0
4
+ */
5
+
6
+
7
+
8
+ /**
9
+ * In this namespace you will find classes and methods for handling connections.
10
+ *
11
+ * @namespace Monster.Net
12
+ * @memberOf Monster
13
+ * @author schukai GmbH
14
+ */
15
+ const ns = {};
@@ -14,6 +14,12 @@ const dataSymbol = Symbol("@@data");
14
14
 
15
15
  /**
16
16
  * This class represents a WebSocket message.
17
+ *
18
+ * @license AGPLv3
19
+ * @since 3.4.0
20
+ * @copyright schukai GmbH
21
+ * @memberOf Monster.Net.WebSocket
22
+ * @summary The Message class encapsulates a WebSocket message.
17
23
  */
18
24
  class Message extends Base {
19
25
 
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Copyright 2022 schukai GmbH
3
+ * SPDX-License-Identifier: AGPL-3.0
4
+ */
5
+
6
+
7
+
8
+ /**
9
+ * In this namespace you will find classes and methods for handling data.
10
+ *
11
+ * @namespace Monster.Net.WebConnect
12
+ * @memberOf Monster.Net
13
+ * @author schukai GmbH
14
+ */
15
+ const ns = {};
@@ -158,18 +158,18 @@ function connectServer(resolve, reject) {
158
158
  /**
159
159
  * The RestAPI is a class that enables a REST API server.
160
160
  *
161
- * @externalExample ../../../example/data/storage/restapi.mjs
161
+ * @externalExample ../../example/net/webconnect.mjs
162
162
  * @license AGPLv3
163
163
  * @since 3.1.0
164
164
  * @copyright schukai GmbH
165
- * @memberOf Monster.Data.Datasource
165
+ * @memberOf Monster.Net
166
166
  * @summary The LocalStorage class encapsulates the access to data objects.
167
167
  */
168
168
  class WebConnect extends BaseWithOptions {
169
169
 
170
170
  /**
171
171
  *
172
- * @param {Object} [options] options contains definitions for the datasource.
172
+ * @param {Object} [options] options contains definitions for the webconnect.
173
173
  */
174
174
  constructor(options) {
175
175
 
@@ -149,7 +149,7 @@ function getMonsterVersion() {
149
149
  }
150
150
 
151
151
  /** don't touch, replaced by make with package.json version */
152
- monsterVersion = new Version('3.4.1')
152
+ monsterVersion = new Version('3.5.0')
153
153
 
154
154
  return monsterVersion;
155
155
 
@@ -7,7 +7,7 @@ import {validateObject} from "../../../../../../application/source/types/validat
7
7
 
8
8
  describe('RestAPI', function () {
9
9
 
10
- let fetchReference;
10
+ let fetchReference;
11
11
  let returnStatus;
12
12
 
13
13
  afterEach(() => {
@@ -28,9 +28,6 @@ describe('RestAPI', function () {
28
28
  a: "test"
29
29
  }));
30
30
  });
31
-
32
-
33
-
34
31
  },
35
32
  status: returnStatus
36
33
  });
@@ -55,19 +52,23 @@ describe('RestAPI', function () {
55
52
  });
56
53
 
57
54
  it('write should ', function (done) {
58
- const ds = new RestAPI({url: 'https://monsterjs.org/assets/world.json'},
59
- {
60
- url: 'https://monsterjs.org/assets/world.json',
61
- acceptedStatus: [99]
62
- })
55
+ const ds = new RestAPI({
56
+ read: {
57
+ url: 'https://monsterjs.org/assets/world.json'
58
+ },
59
+ write: {
60
+ url: 'https://monsterjs.org/assets/world.json',
61
+ acceptedStatus: [99]
62
+ }
63
+ }
64
+ )
63
65
  ds.write().then(data => {
64
66
  done("should not be here");
65
67
  }).catch(e => done());
66
68
  });
69
+ });
67
70
 
68
71
 
69
- })
70
-
71
72
  describe('rw with errors', function () {
72
73
 
73
74
  it('read should throw exception', function (done) {
@@ -2,6 +2,7 @@
2
2
 
3
3
  import {expect} from "chai"
4
4
 
5
+ import {Locale} from "../../../../application/source/i18n/locale.mjs";
5
6
  import {getLocaleOfDocument} from "../../../../application/source/dom/locale.mjs";
6
7
  import {initJSDOM} from "../../util/jsdom.mjs";
7
8
 
@@ -32,10 +33,24 @@ describe('Attributes', function () {
32
33
  node.setAttribute('lang', a);
33
34
  expect(getLocaleOfDocument().toString()).to.be.equal(a);
34
35
  })
36
+
37
+
35
38
 
36
39
  });
37
40
 
38
41
 
39
42
  });
43
+
44
+
45
+ it('return language en', function () {
46
+ let html = document.getElementsByTagName('html');
47
+ let node = html.item(0);
48
+
49
+ node.removeAttribute('lang');
50
+ const locale = getLocaleOfDocument();
51
+ expect(locale).to.be.instanceOf(Locale);
52
+ expect(locale.localeString).to.be.equal('en-US');
53
+ })
54
+
40
55
 
41
56
  })
@@ -0,0 +1,72 @@
1
+ import {expect} from "chai"
2
+
3
+
4
+ import {Embed} from "../../../../../application/source/i18n/providers/embed.mjs";
5
+ import {Translations} from "../../../../../application/source/i18n/translations.mjs";
6
+ import {getGlobal} from "../../../../../application/source/types/global.mjs";
7
+ import {initJSDOM} from "../../../util/jsdom.mjs";
8
+
9
+
10
+ const global = getGlobal();
11
+
12
+ const html1 = `
13
+ <script id="templocale" type="application/json">
14
+ {
15
+ "key": "translation"
16
+ }
17
+ </script>
18
+ `;
19
+
20
+ describe('Translation Provider Embed', function () {
21
+
22
+ before(function (done) {
23
+ initJSDOM().then(() => {
24
+ done()
25
+ });
26
+ });
27
+
28
+
29
+ afterEach(() => {
30
+ let mocks = document.getElementById('mocks');
31
+ mocks.innerHTML = "";
32
+ });
33
+
34
+ beforeEach(() => {
35
+ let mocks = document.getElementById('mocks');
36
+ mocks.innerHTML = html1;
37
+
38
+ })
39
+
40
+ describe('get mock data and create translation', function () {
41
+
42
+ it('embed', function (done) {
43
+
44
+ const e = new Embed('templocale');
45
+ let p = e.getTranslations('en');
46
+ expect(p).is.instanceof(Promise);
47
+
48
+ p.then(r => {
49
+
50
+ try {
51
+ expect(r).is.instanceof(Translations);
52
+
53
+ let t = r.getText('key')
54
+ expect(t).is.equal('translation');
55
+
56
+
57
+ done();
58
+ } catch (e) {
59
+ done(e);
60
+ }
61
+
62
+
63
+ }).catch(e => {
64
+ done(e);
65
+ })
66
+
67
+ });
68
+
69
+ });
70
+
71
+
72
+ });
@@ -7,7 +7,7 @@ describe('Monster', function () {
7
7
  let monsterVersion
8
8
 
9
9
  /** don´t touch, replaced by make with package.json version */
10
- monsterVersion = new Version('3.4.1')
10
+ monsterVersion = new Version('3.5.0')
11
11
 
12
12
  let m = getMonsterVersion();
13
13
 
@@ -1,11 +0,0 @@
1
- import {RestAPI} from '@schukai/monster/source/data/datasource/restapi.mjs';
2
-
3
- const ds = new RestAPI({
4
- url: 'https://httpbin.org/get'
5
- }, {
6
- url: 'https://httpbin.org/post'
7
- });
8
-
9
- ds.set({flag: true})
10
- ds.write().then(() => console.log('done'));
11
- ds.read().then(() => console.log('done'));