@shopgate/pwa-core 7.30.0-alpha.6 → 7.30.0-alpha.8
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/classes/AppCommand/index.js +115 -11
- package/classes/AppCommand/spec.js +260 -6
- package/classes/AppCommandRequest/index.js +129 -20
- package/classes/AppPermissionsRequest/AppPermissionsRequest.js +45 -7
- package/classes/AppPermissionsRequest/GetAppPermissionsRequest.js +48 -9
- package/classes/AppPermissionsRequest/RequestAppPermissionsRequest.js +54 -9
- package/classes/Bridge/index.js +34 -4
- package/classes/Bridge/spec.js +24 -1
- package/classes/BrightnessRequest/index.js +59 -10
- package/classes/BrightnessRequest/spec.js +111 -6
- package/classes/BrowserConnector/index.js +180 -26
- package/classes/Conditioner/index.js +74 -8
- package/classes/Conditioner/spec.js +75 -1
- package/classes/DataRequest/index.js +116 -13
- package/classes/DevServerBridge/index.js +86 -9
- package/classes/DevServerBridge/spec.js +231 -14
- package/classes/ErrorManager/index.js +144 -20
- package/classes/ErrorManager/spec.js +244 -2
- package/classes/Event/index.js +101 -15
- package/classes/HttpRequest/index.js +182 -21
- package/classes/PipelineDependencies/index.js +42 -6
- package/classes/PipelineDependencies/spec.js +46 -3
- package/classes/PipelineManager/index.js +517 -71
- package/classes/PipelineManager/spec.js +733 -15
- package/classes/PipelineRequest/index.js +167 -19
- package/classes/PipelineRequest/mock.js +118 -21
- package/classes/PipelineRequest/spec.js +333 -2
- package/classes/PipelineSequence/index.js +34 -6
- package/classes/Request/index.js +61 -13
- package/classes/RequestBuffer/index.js +43 -6
- package/classes/RequestManager/index.js +216 -33
- package/classes/RequestManager/spec.js +188 -1
- package/classes/Scanner/index.js +246 -67
- package/classes/ScannerEvent/index.js +23 -9
- package/classes/ScannerEventHandler/index.js +39 -16
- package/classes/ScannerEventListener/index.js +84 -24
- package/classes/ScannerManager/ScanProcessingError.js +11 -3
- package/classes/ScannerManager/index.js +133 -21
- package/classes/WebStorageRequest/index.js +76 -9
- package/commands/analyticsSetCustomValues.js +8 -2
- package/commands/appPermissions.js +10 -3
- package/commands/brightness.js +33 -5
- package/commands/broadcastEvent.js +8 -2
- package/commands/cleanTab.js +11 -3
- package/commands/closeInAppBrowser.js +22 -2
- package/commands/flushTab.js +8 -2
- package/commands/getWebStorageEntry.js +11 -2
- package/commands/hideMenuBar.js +8 -2
- package/commands/hideNavigationBar.js +8 -2
- package/commands/hideSplashScreen.js +8 -2
- package/commands/onload.js +13 -3
- package/commands/openAppSettings.js +8 -2
- package/commands/openPage.js +8 -2
- package/commands/openPageExtern.js +8 -2
- package/commands/performCommandsAfterDelay.js +11 -3
- package/commands/plotProjects.js +65 -7
- package/commands/popTabToRoot.js +11 -3
- package/commands/registerEvents.js +10 -2
- package/commands/scanner.js +76 -7
- package/commands/setCookie.js +8 -2
- package/commands/setDebugLoggingEnabled.js +8 -2
- package/commands/setScrollingEnabled.js +7 -2
- package/commands/setWebStorageEntry.js +8 -2
- package/commands/shareItem.js +18 -2
- package/commands/showNavigationBar.js +8 -2
- package/commands/showTab.js +13 -2
- package/commands/unifiedTracking.js +128 -30
- package/constants/AppCommands.js +6 -1
- package/constants/AppEvents.js +9 -1
- package/constants/AppPermissions.js +57 -13
- package/constants/Command.js +1 -1
- package/constants/ErrorHandleTypes.js +2 -1
- package/constants/ErrorManager.js +15 -1
- package/constants/Pipeline.js +52 -17
- package/constants/ProcessTypes.js +3 -1
- package/constants/RequestManagerModes.js +19 -7
- package/constants/RequestTypes.js +2 -1
- package/constants/Scanner.js +39 -10
- package/constants/Trilean.js +6 -1
- package/emitters/ui.js +2 -1
- package/helpers/index.js +66 -8
- package/helpers/logGroup.js +56 -8
- package/helpers/version.js +216 -22
- package/index.js +60 -5
- package/package.json +1 -1
|
@@ -1,2 +1,244 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import errorManager, { emitter } from '.';
|
|
2
|
+
import { DEFAULT_CONTEXT, DEFAULT_SEVERITY } from "../../constants/ErrorManager";
|
|
3
|
+
describe('ErrorManager', () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
errorManager.errorQueue.clear();
|
|
6
|
+
errorManager.messages = {};
|
|
7
|
+
});
|
|
8
|
+
describe('errorManager.validate', () => {
|
|
9
|
+
it('should accept a valid error object', () => {
|
|
10
|
+
const code = 'EUNKNOWN';
|
|
11
|
+
const message = 'Something went horribly wrong!';
|
|
12
|
+
const source = 'pipeline';
|
|
13
|
+
const response = errorManager.validate({
|
|
14
|
+
code,
|
|
15
|
+
message,
|
|
16
|
+
source
|
|
17
|
+
});
|
|
18
|
+
expect(response).toEqual(true);
|
|
19
|
+
});
|
|
20
|
+
it('should accept a valid error object with cb message', () => {
|
|
21
|
+
const code = 'EUNKNOWN';
|
|
22
|
+
const message = jest.fn();
|
|
23
|
+
const source = 'pipeline';
|
|
24
|
+
const response = errorManager.validate({
|
|
25
|
+
code,
|
|
26
|
+
message,
|
|
27
|
+
source
|
|
28
|
+
});
|
|
29
|
+
expect(response).toEqual(true);
|
|
30
|
+
});
|
|
31
|
+
it('should reject an error object with missing mandatory fields', () => {
|
|
32
|
+
const response = errorManager.validate();
|
|
33
|
+
expect(response).toEqual(false);
|
|
34
|
+
});
|
|
35
|
+
it('should reject an error object with fields that are not a string', () => {
|
|
36
|
+
const code = 404;
|
|
37
|
+
const message = 'Something went horribly wrong!';
|
|
38
|
+
const source = 'pipeline';
|
|
39
|
+
const response = errorManager.validate({
|
|
40
|
+
code,
|
|
41
|
+
message,
|
|
42
|
+
source
|
|
43
|
+
});
|
|
44
|
+
expect(response).toEqual(false);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
describe('errorManager.getMessage', () => {
|
|
48
|
+
const code = 'EUNKNOWN';
|
|
49
|
+
const source = 'pipeline';
|
|
50
|
+
const context = 'shopgate.catalog.getFoo';
|
|
51
|
+
const message = 'Test Message';
|
|
52
|
+
it('should return the null when no override message is found', () => {
|
|
53
|
+
const errorMessage = errorManager.getMessage({
|
|
54
|
+
code,
|
|
55
|
+
context,
|
|
56
|
+
source
|
|
57
|
+
});
|
|
58
|
+
expect(errorMessage).toBeNull();
|
|
59
|
+
});
|
|
60
|
+
it('should return the message', () => {
|
|
61
|
+
errorManager.setMessage({
|
|
62
|
+
code,
|
|
63
|
+
context,
|
|
64
|
+
message
|
|
65
|
+
});
|
|
66
|
+
const errorMessage = errorManager.getMessage({
|
|
67
|
+
code,
|
|
68
|
+
context,
|
|
69
|
+
source,
|
|
70
|
+
message
|
|
71
|
+
});
|
|
72
|
+
expect(errorMessage).toBe(message);
|
|
73
|
+
});
|
|
74
|
+
it('should use callback for error message', () => {
|
|
75
|
+
const overrideMessage = jest.fn().mockReturnValue('CB Error');
|
|
76
|
+
errorManager.setMessage({
|
|
77
|
+
code,
|
|
78
|
+
context,
|
|
79
|
+
message: overrideMessage
|
|
80
|
+
});
|
|
81
|
+
const error = {
|
|
82
|
+
code,
|
|
83
|
+
context,
|
|
84
|
+
source,
|
|
85
|
+
message
|
|
86
|
+
};
|
|
87
|
+
expect(errorManager.getMessage(error)).toBe('CB Error');
|
|
88
|
+
expect(overrideMessage).toBeCalledWith(error);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe('errorManager.setMessage', () => {
|
|
92
|
+
it('should add an override message', () => {
|
|
93
|
+
const code = 'EUNKNOWN';
|
|
94
|
+
const context = 'shopgate.catalog.getUser';
|
|
95
|
+
const message = 'Something went horribly wrong!';
|
|
96
|
+
const source = 'pipeline';
|
|
97
|
+
errorManager.setMessage({
|
|
98
|
+
code,
|
|
99
|
+
context,
|
|
100
|
+
message,
|
|
101
|
+
source
|
|
102
|
+
});
|
|
103
|
+
expect(errorManager.messages[`${source}-${context}-${code}`]).toEqual(message);
|
|
104
|
+
});
|
|
105
|
+
it('should add an override message with no set context', () => {
|
|
106
|
+
const code = 'EUNKNOWN';
|
|
107
|
+
const message = 'Something went horribly wrong!';
|
|
108
|
+
const source = 'pipeline';
|
|
109
|
+
errorManager.setMessage({
|
|
110
|
+
code,
|
|
111
|
+
message,
|
|
112
|
+
source
|
|
113
|
+
});
|
|
114
|
+
expect(errorManager.messages[`${source}-${DEFAULT_CONTEXT}-${code}`]).toEqual(message);
|
|
115
|
+
});
|
|
116
|
+
it('should ignore setting a message with missing error object', () => {
|
|
117
|
+
const code = 'EUNKNOWN';
|
|
118
|
+
const source = 'pipeline';
|
|
119
|
+
errorManager.setMessage();
|
|
120
|
+
expect(errorManager.messages[`${source}-${DEFAULT_CONTEXT}-${code}`]).toBeUndefined();
|
|
121
|
+
});
|
|
122
|
+
it('should ignore setting a message with missing mandatory fields', () => {
|
|
123
|
+
const code = 'EUNKNOWN';
|
|
124
|
+
const message = 'Something went horribly wrong!';
|
|
125
|
+
const source = 'pipeline';
|
|
126
|
+
errorManager.setMessage({
|
|
127
|
+
message,
|
|
128
|
+
source
|
|
129
|
+
});
|
|
130
|
+
expect(errorManager.messages[`${source}-${DEFAULT_CONTEXT}-${code}`]).toBeUndefined();
|
|
131
|
+
});
|
|
132
|
+
it('should ignore setting a message with invalid input', () => {
|
|
133
|
+
const code = 404;
|
|
134
|
+
const message = 'Something went horribly wrong!';
|
|
135
|
+
const source = 'pipeline';
|
|
136
|
+
errorManager.setMessage({
|
|
137
|
+
code,
|
|
138
|
+
message,
|
|
139
|
+
source
|
|
140
|
+
});
|
|
141
|
+
expect(errorManager.messages[`${source}-${DEFAULT_CONTEXT}-${code}`]).toBeUndefined();
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
describe('errorManager.queue', () => {
|
|
145
|
+
it('should not queue a missing error', () => {
|
|
146
|
+
const code = 'EUNKNOWN';
|
|
147
|
+
const source = 'pipeline';
|
|
148
|
+
errorManager.queue();
|
|
149
|
+
expect(errorManager.messages[`${source}-${DEFAULT_CONTEXT}-${code}`]).toBeUndefined();
|
|
150
|
+
});
|
|
151
|
+
it('should not queue an invalid error', () => {
|
|
152
|
+
const code = 404;
|
|
153
|
+
const message = 'Something went horribly wrong!';
|
|
154
|
+
const source = 'pipeline';
|
|
155
|
+
errorManager.queue({
|
|
156
|
+
code,
|
|
157
|
+
message,
|
|
158
|
+
source
|
|
159
|
+
});
|
|
160
|
+
expect(errorManager.errorQueue.has(`${source}-${DEFAULT_CONTEXT}-${code}`)).toEqual(false);
|
|
161
|
+
});
|
|
162
|
+
it('should queue errors only once', () => {
|
|
163
|
+
const code = 'EUNKNOWN';
|
|
164
|
+
const message = 'Something went horribly wrong!';
|
|
165
|
+
const source = 'pipeline';
|
|
166
|
+
const callback = jest.fn();
|
|
167
|
+
emitter.addListener('pipeline', callback);
|
|
168
|
+
errorManager.queue({
|
|
169
|
+
code,
|
|
170
|
+
message,
|
|
171
|
+
source
|
|
172
|
+
});
|
|
173
|
+
errorManager.queue({
|
|
174
|
+
code,
|
|
175
|
+
message,
|
|
176
|
+
source
|
|
177
|
+
});
|
|
178
|
+
expect(errorManager.errorQueue.has(`${source}-${DEFAULT_CONTEXT}-${code}`)).toEqual(true);
|
|
179
|
+
expect(errorManager.errorQueue.size).toEqual(1);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
it('should not dispatch when there are no errors', async () => {
|
|
183
|
+
const callback = jest.fn();
|
|
184
|
+
emitter.addListener('pipeline', callback);
|
|
185
|
+
const dispatch = errorManager.dispatch();
|
|
186
|
+
expect(dispatch).toEqual(false);
|
|
187
|
+
});
|
|
188
|
+
it('should dispatch the errors through events', async () => {
|
|
189
|
+
const code = 'EUNKNOWN';
|
|
190
|
+
const message = 'Something went horribly wrong!';
|
|
191
|
+
const source = 'pipeline';
|
|
192
|
+
const callback = jest.fn();
|
|
193
|
+
const callback2 = jest.fn();
|
|
194
|
+
emitter.addListener('pipeline', callback);
|
|
195
|
+
emitter.addListener('pipeline', callback2);
|
|
196
|
+
await errorManager.queue({
|
|
197
|
+
code,
|
|
198
|
+
message,
|
|
199
|
+
source
|
|
200
|
+
});
|
|
201
|
+
await errorManager.queue({
|
|
202
|
+
code: 'EUNKNOWN2',
|
|
203
|
+
message,
|
|
204
|
+
source
|
|
205
|
+
});
|
|
206
|
+
expect(errorManager.errorQueue.size).toEqual(2);
|
|
207
|
+
errorManager.dispatch();
|
|
208
|
+
expect(callback).toBeCalled();
|
|
209
|
+
expect(callback2).toBeCalled();
|
|
210
|
+
expect(errorManager.errorQueue.size).toEqual(0);
|
|
211
|
+
});
|
|
212
|
+
it('should set a queue entry with meta data', () => {
|
|
213
|
+
const code = 'EUNKNOWN';
|
|
214
|
+
const replacementMessage = 'Replacement Message';
|
|
215
|
+
const message = 'Original Message';
|
|
216
|
+
const source = 'pipeline';
|
|
217
|
+
|
|
218
|
+
// Setup a replacement message for the error code.
|
|
219
|
+
errorManager.setMessage({
|
|
220
|
+
code,
|
|
221
|
+
source,
|
|
222
|
+
message: replacementMessage
|
|
223
|
+
});
|
|
224
|
+
const callback = jest.fn();
|
|
225
|
+
emitter.addListener('pipeline', callback);
|
|
226
|
+
errorManager.queue({
|
|
227
|
+
message,
|
|
228
|
+
code,
|
|
229
|
+
source
|
|
230
|
+
});
|
|
231
|
+
errorManager.dispatch();
|
|
232
|
+
expect(callback).toBeCalledWith({
|
|
233
|
+
id: `${source}-${DEFAULT_CONTEXT}-${code}`,
|
|
234
|
+
context: DEFAULT_CONTEXT,
|
|
235
|
+
message: replacementMessage,
|
|
236
|
+
code,
|
|
237
|
+
source,
|
|
238
|
+
meta: {
|
|
239
|
+
message
|
|
240
|
+
},
|
|
241
|
+
severity: DEFAULT_SEVERITY
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
});
|
package/classes/Event/index.js
CHANGED
|
@@ -1,44 +1,130 @@
|
|
|
1
|
-
|
|
1
|
+
import EventEmitter from 'events';
|
|
2
|
+
import { logger } from "../../helpers";
|
|
3
|
+
const HANDLER_ADD = 'add';
|
|
4
|
+
const HANDLER_REMOVE = 'remove';
|
|
5
|
+
|
|
6
|
+
/* eslint-disable extra-rules/potential-point-free */
|
|
7
|
+
|
|
8
|
+
/**
|
|
2
9
|
* Event class.
|
|
3
|
-
*/
|
|
10
|
+
*/
|
|
11
|
+
class Event extends EventEmitter {
|
|
12
|
+
/**
|
|
4
13
|
* Constructor.
|
|
5
|
-
*/
|
|
14
|
+
*/
|
|
15
|
+
constructor() {
|
|
16
|
+
super();
|
|
17
|
+
this.events = new Set();
|
|
18
|
+
this.setMaxListeners(20);
|
|
19
|
+
|
|
20
|
+
/**
|
|
6
21
|
* A global implementation of the call function to make it accessible to the app.
|
|
7
22
|
*
|
|
8
23
|
* We have to check here if there is already a __call from the cake2 project present.
|
|
9
24
|
* This could happen because we use the tracking-core in the cake2 project.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
window.SGEvent.__call
|
|
13
|
-
|
|
25
|
+
*/
|
|
26
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
27
|
+
const legacy = window.SGEvent.__call;
|
|
28
|
+
if (typeof legacy !== 'function') {
|
|
29
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
30
|
+
window.SGEvent.__call = this.call.bind(this);
|
|
31
|
+
} else {
|
|
32
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
33
|
+
window.SGEvent.__call = (...args) => {
|
|
34
|
+
legacy(...args);
|
|
35
|
+
this.call(...args);
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
14
41
|
* Registers a new event
|
|
15
42
|
* @param {string} eventName The new event name
|
|
16
|
-
*/
|
|
43
|
+
*/
|
|
44
|
+
registerEvent(eventName) {
|
|
45
|
+
this.events.add(eventName);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
17
49
|
* Registers a callback function for one or multiple events.
|
|
18
50
|
* @param {string} events A single event or multiple events separated by comma.
|
|
19
51
|
* @param {Function} callback The callback function.
|
|
20
|
-
*/
|
|
52
|
+
*/
|
|
53
|
+
addCallback(events, callback) {
|
|
54
|
+
this.handleCallbacks(HANDLER_ADD, events, callback);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
21
58
|
* De-registers a callback function for one or multiple events.
|
|
22
59
|
* @param {string} events A single event or multiple events separated by comma.
|
|
23
60
|
* @param {Function} callback The callback function.
|
|
24
|
-
*/
|
|
61
|
+
*/
|
|
62
|
+
removeCallback(events, callback) {
|
|
63
|
+
this.handleCallbacks(HANDLER_REMOVE, events, callback);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
25
67
|
* Handles the register and de-register of a callback.
|
|
26
68
|
* @param {string} type What type of action should be performed.
|
|
27
69
|
* @param {string} events A single event or multiple events separated by comma.
|
|
28
70
|
* @param {Function} callback The callback function.
|
|
29
|
-
*/
|
|
71
|
+
*/
|
|
72
|
+
handleCallbacks(type, events, callback) {
|
|
73
|
+
const eventNames = events.split(',');
|
|
74
|
+
eventNames.forEach(event => {
|
|
75
|
+
switch (type) {
|
|
76
|
+
case HANDLER_ADD:
|
|
77
|
+
this.addListener(event, callback);
|
|
78
|
+
break;
|
|
79
|
+
case HANDLER_REMOVE:
|
|
80
|
+
this.removeListener(event, callback);
|
|
81
|
+
break;
|
|
82
|
+
default:
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
30
89
|
* Triggers an event.
|
|
31
90
|
* @param {string} event The event name.
|
|
32
91
|
* @param {Object} params Custom parameters for the event.
|
|
33
|
-
*/
|
|
92
|
+
*/
|
|
93
|
+
trigger(event, params = null) {
|
|
94
|
+
setTimeout(() => this.emit(event, params), 0);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
34
98
|
* This function will be called by the app to trigger events.
|
|
35
99
|
* @param {string} event The event name.
|
|
36
100
|
* @param {Array} [parameters=[]] The event parameters.
|
|
37
|
-
*/
|
|
101
|
+
*/
|
|
102
|
+
call(event, parameters = []) {
|
|
103
|
+
let eventName = event;
|
|
104
|
+
|
|
105
|
+
/**
|
|
38
106
|
* Some system events relate to request commands.
|
|
39
107
|
* When these commands were fired, a serial was created in order
|
|
40
108
|
* to identify an appropriate callback event.
|
|
41
109
|
* To identify these callbacks, the serial has to be decoded from the parameter list.
|
|
42
|
-
*/
|
|
110
|
+
*/
|
|
111
|
+
if (['pipelineResponse', 'httpResponse'].includes(event)) {
|
|
112
|
+
eventName += `:${parameters[1]}`;
|
|
113
|
+
} else if (['dataResponse', 'webStorageResponse'].includes(event) || Array.from(this.events).includes(event)) {
|
|
114
|
+
eventName += `:${parameters[0]}`;
|
|
115
|
+
}
|
|
116
|
+
const calledEvent = this.emit(eventName, ...parameters);
|
|
117
|
+
if (!calledEvent) {
|
|
118
|
+
logger.warn(`Attempt to call unknown event: ${eventName}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* eslint-enable extra-rules/potential-point-free */
|
|
124
|
+
|
|
125
|
+
// TODO:
|
|
43
126
|
// We need this as a temporary solution because of double node_modules form extensions and theme.
|
|
44
|
-
if(!window.TmpEventInstance){
|
|
127
|
+
if (!window.TmpEventInstance) {
|
|
128
|
+
window.TmpEventInstance = new Event();
|
|
129
|
+
}
|
|
130
|
+
export default window.TmpEventInstance;
|
|
@@ -1,64 +1,225 @@
|
|
|
1
|
-
|
|
1
|
+
import { logger } from "../../helpers";
|
|
2
|
+
import logGroup from "../../helpers/logGroup";
|
|
3
|
+
import event from "../Event";
|
|
4
|
+
import AppCommand from "../AppCommand";
|
|
5
|
+
import Request from "../Request";
|
|
6
|
+
import requestBuffer from "../RequestBuffer";
|
|
7
|
+
|
|
8
|
+
/**
|
|
2
9
|
* The http request class.
|
|
3
10
|
* It sends a http request and returns a promise.
|
|
4
|
-
*/
|
|
11
|
+
*/
|
|
12
|
+
class HttpRequest extends Request {
|
|
13
|
+
/**
|
|
5
14
|
* Initializes the HttpRequest object
|
|
6
15
|
* @param {string} url The url for the request
|
|
7
|
-
*/
|
|
16
|
+
*/
|
|
17
|
+
constructor(url) {
|
|
18
|
+
super();
|
|
19
|
+
this.url = url;
|
|
20
|
+
this.method = 'GET';
|
|
21
|
+
this.followRedirects = false;
|
|
22
|
+
this.timeout = 30000;
|
|
23
|
+
this.payload = null;
|
|
24
|
+
this.contentType = null;
|
|
25
|
+
this.headers = null;
|
|
26
|
+
this.createSerial(this.url);
|
|
27
|
+
this.createEventCallbackName('httpResponse');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
8
31
|
* Sets the payload for the HttpRequest
|
|
9
32
|
* @param {Object|string} [payload={}] The payload to send with the request
|
|
10
33
|
* @returns {HttpRequest}
|
|
11
|
-
*/
|
|
34
|
+
*/
|
|
35
|
+
setPayload(payload = {}) {
|
|
36
|
+
this.payload = payload;
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
12
41
|
* Sets the contentType for the HttpRequest
|
|
13
42
|
* @param {string} type The contentType for request
|
|
14
43
|
* @deprecated Not supported anymore by app version >= 11.0.0
|
|
15
44
|
* @returns {HttpRequest}
|
|
16
|
-
*/
|
|
45
|
+
*/
|
|
46
|
+
setContentType(type) {
|
|
47
|
+
this.contentType = type;
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
17
52
|
* @typedef {Object.<string, string>} HeaderMap
|
|
18
|
-
*/
|
|
53
|
+
*/
|
|
54
|
+
|
|
55
|
+
/**
|
|
19
56
|
* Sets the headers for the HttpRequest.
|
|
20
57
|
* @param {HeaderMap} headers - An object mapping header names to values.
|
|
21
58
|
* @returns {HttpRequest} The current HttpRequest instance (for chaining).
|
|
22
|
-
*/
|
|
59
|
+
*/
|
|
60
|
+
setHeaders(headers) {
|
|
61
|
+
if (typeof headers !== 'object') {
|
|
62
|
+
logger.error('HttpRequest: setHeaders expects an object as parameter');
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
65
|
+
this.headers = headers;
|
|
66
|
+
return this;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
23
70
|
* Sets the request method
|
|
24
71
|
* @param {string} method The method string
|
|
25
72
|
* @return {HttpRequest}
|
|
26
|
-
*/
|
|
73
|
+
*/
|
|
74
|
+
setMethod(method) {
|
|
75
|
+
if (['GET', 'POST', 'PUT', 'DELETE'].includes(method)) {
|
|
76
|
+
this.method = method;
|
|
77
|
+
} else {
|
|
78
|
+
logger.error(`Unknown HttpRequest method: ${method}`);
|
|
79
|
+
}
|
|
80
|
+
return this;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
27
84
|
* Tells if the redirects will be followed
|
|
28
85
|
* @param {boolean} value The value
|
|
29
86
|
* @return {HttpRequest}
|
|
30
|
-
*/
|
|
87
|
+
*/
|
|
88
|
+
setFollowRedirects(value) {
|
|
89
|
+
this.followRedirects = value;
|
|
90
|
+
return this;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
31
94
|
* Sets the timeout for the request
|
|
32
95
|
* @param {number} timeout The timeout
|
|
33
96
|
* @return {HttpRequest}
|
|
34
|
-
*/
|
|
97
|
+
*/
|
|
98
|
+
setTimeout(timeout) {
|
|
99
|
+
this.timeout = timeout;
|
|
100
|
+
return this;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
35
104
|
* Determines the right content type for the request payload
|
|
36
105
|
* @private
|
|
37
106
|
* @return {string} The content type
|
|
38
|
-
*/
|
|
107
|
+
*/
|
|
108
|
+
getContentType() {
|
|
109
|
+
let contentType = 'text/plain';
|
|
110
|
+
if (typeof this.payload === 'object') {
|
|
111
|
+
contentType = 'application/x-www-form-urlencoded; charset=UTF-8';
|
|
112
|
+
}
|
|
113
|
+
return contentType;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
39
117
|
* Determines the headers for the request
|
|
40
118
|
* @returns {Object} The headers
|
|
41
|
-
*/
|
|
119
|
+
*/
|
|
120
|
+
getHeaders() {
|
|
121
|
+
if (!this.headers) {
|
|
122
|
+
return {};
|
|
123
|
+
}
|
|
124
|
+
return this.headers;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
42
128
|
* Creates the data request body from the payload
|
|
43
129
|
* @private
|
|
44
130
|
* @return {string} The request body
|
|
45
|
-
*/
|
|
131
|
+
*/
|
|
132
|
+
getRequestBody() {
|
|
133
|
+
/**
|
|
46
134
|
* Serializes a javascript object for a data request body
|
|
47
135
|
* @param {Object} obj The object that shall be serialized
|
|
48
136
|
* @param {string} [prefix] An optional prefix for the object keys
|
|
49
137
|
* @return {string} The serialized object
|
|
50
|
-
*/
|
|
138
|
+
*/
|
|
139
|
+
const serializeObject = (obj, prefix) => {
|
|
140
|
+
const result = [];
|
|
141
|
+
Object.keys(obj).forEach(propName => {
|
|
142
|
+
const key = prefix ? `${prefix}[${propName}]` : propName;
|
|
143
|
+
const value = obj[propName];
|
|
144
|
+
let tmp;
|
|
145
|
+
if (typeof value === 'object' && value !== null) {
|
|
146
|
+
tmp = serializeObject(value, key);
|
|
147
|
+
} else {
|
|
148
|
+
tmp = `${window.encodeURIComponent(key)}=${window.encodeURIComponent(value)}`;
|
|
149
|
+
}
|
|
150
|
+
result.push(tmp);
|
|
151
|
+
});
|
|
152
|
+
return result.join('&');
|
|
153
|
+
};
|
|
154
|
+
let body = '';
|
|
155
|
+
if (this.payload) {
|
|
156
|
+
if (typeof this.payload === 'object') {
|
|
157
|
+
if (this.contentType === 'application/json') {
|
|
158
|
+
body = JSON.stringify(this.payload);
|
|
159
|
+
} else {
|
|
160
|
+
body = serializeObject(this.payload);
|
|
161
|
+
}
|
|
162
|
+
} else if (typeof this.payload === 'string') {
|
|
163
|
+
body = this.payload;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return body;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
51
170
|
* Sends the HttpRequest and returns a promise.
|
|
52
171
|
* @returns {Promise}
|
|
53
|
-
*/
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
172
|
+
*/
|
|
173
|
+
dispatch() {
|
|
174
|
+
return new Promise((resolve, reject) => {
|
|
175
|
+
const requestCallbackName = this.getEventCallbackName();
|
|
176
|
+
requestBuffer.add(this, this.serial);
|
|
177
|
+
|
|
178
|
+
// Prepare the options for the request
|
|
179
|
+
const options = {
|
|
180
|
+
url: this.url,
|
|
181
|
+
serial: this.serial,
|
|
182
|
+
method: this.method,
|
|
183
|
+
timeout: this.timeout,
|
|
184
|
+
followRedirects: this.followRedirects,
|
|
185
|
+
body: this.getRequestBody(),
|
|
186
|
+
// the iOS Cloud Flight app will use this over any content type passed in
|
|
187
|
+
// the headers and breaks if it's not set:
|
|
188
|
+
contentType: this.contentType ? this.contentType : this.getContentType(),
|
|
189
|
+
headers: this.getHeaders()
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/**
|
|
57
193
|
* The request event callback for the response call.
|
|
58
194
|
* @param {Object|null} error The error object if an error happened.
|
|
59
195
|
* @param {string} serial The serial that was used to identify the HttpRequest callback
|
|
60
196
|
* @param {Object} response The response for the HttpRequest
|
|
61
197
|
* @return {Object}
|
|
62
|
-
*/
|
|
63
|
-
|
|
64
|
-
|
|
198
|
+
*/
|
|
199
|
+
const requestCallback = (error, serial, response) => {
|
|
200
|
+
event.removeCallback(requestCallbackName, requestCallback);
|
|
201
|
+
requestBuffer.remove(serial);
|
|
202
|
+
logGroup(`HttpResponse %c${this.url}`, {
|
|
203
|
+
options,
|
|
204
|
+
error,
|
|
205
|
+
response
|
|
206
|
+
});
|
|
207
|
+
if (error) {
|
|
208
|
+
return reject(error);
|
|
209
|
+
}
|
|
210
|
+
return resolve(response);
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// Apply the event callback.
|
|
214
|
+
event.addCallback(requestCallbackName, requestCallback);
|
|
215
|
+
logGroup(`HttpRequest %c${this.url}`, {
|
|
216
|
+
payload: this.payload
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
// Send the HttpRequest.
|
|
220
|
+
const command = new AppCommand();
|
|
221
|
+
command.setCommandName('sendHttpRequest').setLibVersion('13.0').dispatch(options);
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
export default HttpRequest;
|