@ouroboros/body 1.1.2 → 1.2.1
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/LICENSE +4 -4
- package/README.md +319 -10
- package/{build → lib}/Service.d.ts +32 -1
- package/{build → lib}/Service.js +37 -0
- package/{build → lib}/constants.d.ts +1 -0
- package/{build → lib}/constants.js +1 -0
- package/{build → lib}/index.d.ts +17 -28
- package/{build → lib}/index.js +119 -128
- package/{build → lib}/regex.js +2 -2
- package/package.json +5 -8
- package/releases.md +15 -0
- package/src/Service.ts +43 -1
- package/src/constants.ts +5 -4
- package/src/index.ts +158 -156
- package/src/regex.ts +2 -2
- package/build/types/xhr2.d.ts +0 -3
- package/src/types/xhr2.d.ts +0 -3
- /package/{build → lib}/errors.d.ts +0 -0
- /package/{build → lib}/errors.js +0 -0
- /package/{build → lib}/regex.d.ts +0 -0
package/{build → lib}/index.js
RENAMED
|
@@ -7,8 +7,6 @@
|
|
|
7
7
|
* @copyright Ouroboros Coding Inc.
|
|
8
8
|
* @created 2023-03-03
|
|
9
9
|
*/
|
|
10
|
-
// NPM modules
|
|
11
|
-
import XMLHttpRequest from 'xhr2';
|
|
12
10
|
// Import const files
|
|
13
11
|
import * as constants from './constants';
|
|
14
12
|
import * as errors from './errors';
|
|
@@ -17,7 +15,7 @@ import * as regex from './regex';
|
|
|
17
15
|
export { constants, errors, regex };
|
|
18
16
|
export { default as Service } from './Service';
|
|
19
17
|
// Actions to methods
|
|
20
|
-
const
|
|
18
|
+
const METHODS = {
|
|
21
19
|
create: 'POST',
|
|
22
20
|
delete: 'DELETE',
|
|
23
21
|
read: 'GET',
|
|
@@ -33,13 +31,13 @@ const ACTIONS_TO_METHODS = {
|
|
|
33
31
|
*/
|
|
34
32
|
class Body {
|
|
35
33
|
// The domain used to make requests to
|
|
36
|
-
_domain = '';
|
|
34
|
+
_domain = 'localhost';
|
|
37
35
|
// The function to call for http and related errors that need to be reported
|
|
38
36
|
error = null;
|
|
39
37
|
// The function to call if we get body errors
|
|
40
38
|
errorCode = null;
|
|
41
39
|
// The function to call when we get a status 401, or error code
|
|
42
|
-
//
|
|
40
|
+
// REST_AUTHORIZATION
|
|
43
41
|
noSession = null;
|
|
44
42
|
// The function to call after any request is sent
|
|
45
43
|
requested = null;
|
|
@@ -47,21 +45,27 @@ class Body {
|
|
|
47
45
|
requesting = null;
|
|
48
46
|
// The token associated with the current session
|
|
49
47
|
token = null;
|
|
50
|
-
// Flag for being verbose
|
|
51
|
-
verbose = false;
|
|
52
48
|
// The function to call if we get body warnings
|
|
53
49
|
warning = null;
|
|
54
50
|
/**
|
|
55
51
|
* Domain
|
|
56
52
|
*
|
|
57
|
-
*
|
|
53
|
+
* Sets/Gets the domain
|
|
58
54
|
*
|
|
59
55
|
* @name domain
|
|
60
56
|
* @access public
|
|
61
|
-
* @param domain The
|
|
57
|
+
* @param @param domain The domain to set
|
|
58
|
+
* @returns the domain set
|
|
62
59
|
*/
|
|
63
60
|
domain(domain) {
|
|
64
|
-
|
|
61
|
+
// If we are getting the token
|
|
62
|
+
if (domain === undefined) {
|
|
63
|
+
return this._domain;
|
|
64
|
+
}
|
|
65
|
+
// Else, we are setting the token
|
|
66
|
+
else {
|
|
67
|
+
this._domain = domain;
|
|
68
|
+
}
|
|
65
69
|
}
|
|
66
70
|
/**
|
|
67
71
|
* Request
|
|
@@ -70,6 +74,7 @@ class Body {
|
|
|
70
74
|
*
|
|
71
75
|
* @name request
|
|
72
76
|
* @access public
|
|
77
|
+
* @param action The action to take in the call
|
|
73
78
|
* @param service The service to call
|
|
74
79
|
* @param noun The noun to call on the service
|
|
75
80
|
* @param data The data associated with the request
|
|
@@ -77,124 +82,112 @@ class Body {
|
|
|
77
82
|
request(action, service, noun, data) {
|
|
78
83
|
// Generate the URL for the request
|
|
79
84
|
let url = `https://${this._domain}/${service}/${noun}`;
|
|
80
|
-
// Init the response
|
|
85
|
+
// Init the response and json variables
|
|
81
86
|
let res;
|
|
87
|
+
let json;
|
|
88
|
+
// If we got data
|
|
89
|
+
if (data !== null) {
|
|
90
|
+
// If we're in GET mode, append the data as a param "d" after
|
|
91
|
+
// turning it into JSON
|
|
92
|
+
if (action === 'read') {
|
|
93
|
+
url += '?d=' + encodeURIComponent(JSON.stringify(data));
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
json = JSON.stringify(data);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
82
99
|
// Set this
|
|
83
|
-
const
|
|
100
|
+
const _ = this;
|
|
101
|
+
// Handles an error based on whether an error handler is set
|
|
102
|
+
function handleError(message) {
|
|
103
|
+
if (_.error) {
|
|
104
|
+
_.error(message, { action, data, url });
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
throw new Error(message);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
84
110
|
// Create a new Promise and return it
|
|
85
111
|
return new Promise((resolve, reject) => {
|
|
86
|
-
//
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
$this.error(message, { action, data, res, url, xhr });
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
throw new Error(message);
|
|
112
|
+
// Init the fetch init
|
|
113
|
+
const fetchInit = {
|
|
114
|
+
method: METHODS[action],
|
|
115
|
+
headers: {
|
|
116
|
+
'Content-Type': 'application/json; charset=utf-8'
|
|
95
117
|
}
|
|
118
|
+
};
|
|
119
|
+
// If we have a session token, add it as the Authorization header
|
|
120
|
+
if (_.token) {
|
|
121
|
+
fetchInit.headers.Authorization = _.token;
|
|
96
122
|
}
|
|
97
|
-
//
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
123
|
+
// If we have JSON
|
|
124
|
+
if (json) {
|
|
125
|
+
fetchInit.body = json;
|
|
126
|
+
}
|
|
127
|
+
// If we have a requesting callback, call it
|
|
128
|
+
if (this.requesting) {
|
|
129
|
+
this.requesting({ action, data, url });
|
|
130
|
+
}
|
|
131
|
+
// Make the call
|
|
132
|
+
fetch(url, fetchInit).then(response => {
|
|
133
|
+
// If 2xx
|
|
134
|
+
if (response.ok) {
|
|
135
|
+
// If the Content-Type is missing or invalid
|
|
136
|
+
const ct = response.headers.get('Content-Type');
|
|
137
|
+
if (!ct || ct !== 'application/json; charset=utf-8') {
|
|
138
|
+
handleError(`${METHODS[action]} ${url} returned invalid Content-Type: ${ct}`);
|
|
139
|
+
}
|
|
140
|
+
// Return the JSON
|
|
141
|
+
return response.json();
|
|
115
142
|
}
|
|
116
|
-
// If
|
|
117
|
-
if (
|
|
118
|
-
// If
|
|
119
|
-
if (
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
return this.noSession();
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
throw new Error(`${ACTIONS_TO_METHODS[action]} ${url} return 401 NOT AUTHORIZED`);
|
|
126
|
-
}
|
|
143
|
+
// If it's 401
|
|
144
|
+
if (response.status === 401) {
|
|
145
|
+
// If we have a no session callback
|
|
146
|
+
if (_.noSession) {
|
|
147
|
+
_.noSession();
|
|
148
|
+
return Promise.resolve();
|
|
127
149
|
}
|
|
128
|
-
// Else, invalid status
|
|
129
150
|
else {
|
|
130
|
-
|
|
151
|
+
throw new Error(`${METHODS[action]} ${url} return 401 NOT AUTHORIZED`);
|
|
131
152
|
}
|
|
132
153
|
}
|
|
133
|
-
//
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
handleError(`${ACTIONS_TO_METHODS[action]} ${url} returned invalid Content-Type: ${contentType}`);
|
|
154
|
+
// Else, invalid status
|
|
155
|
+
else {
|
|
156
|
+
handleError(`${METHODS[action]} ${url} returned invalid status: ${response.status}`);
|
|
137
157
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
handleError(`${ACTIONS_TO_METHODS[action]} ${url} returned invalid JSON: ${xhr.responseText}`);
|
|
158
|
+
}).then(result => {
|
|
159
|
+
// If there's no result, do nothing
|
|
160
|
+
if (!result) {
|
|
161
|
+
return;
|
|
143
162
|
}
|
|
163
|
+
// Set res
|
|
164
|
+
res = result;
|
|
144
165
|
// If we got an error
|
|
145
|
-
if ('error' in
|
|
146
|
-
//
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
return reject(res.error);
|
|
166
|
+
if ('error' in result && result.error) {
|
|
167
|
+
// If we don't have an onErrorCode callback, or we do and
|
|
168
|
+
// calling it returns false
|
|
169
|
+
if (!_.errorCode ||
|
|
170
|
+
_.errorCode(result.error, { action, data, res, url }) === false) {
|
|
171
|
+
return reject(result.error);
|
|
152
172
|
}
|
|
153
173
|
}
|
|
174
|
+
// If we got a warning and we have an onWarning callback
|
|
175
|
+
if ('warning' in result && result.warning && _.warning) {
|
|
176
|
+
_.warning(result.warning, { action, data, res, url });
|
|
177
|
+
}
|
|
154
178
|
// If we got data
|
|
155
|
-
if ('data' in
|
|
179
|
+
if ('data' in result) {
|
|
156
180
|
// Resolve it
|
|
157
|
-
return resolve(
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
// Handle the request being finished
|
|
161
|
-
xhr.addEventListener('loadend', event => {
|
|
162
|
-
if (this.verbose) {
|
|
163
|
-
console.log(`xhr.loadend:\n\t${ACTIONS_TO_METHODS[action]} ${url}\n\t`, event);
|
|
181
|
+
return resolve(result.data);
|
|
164
182
|
}
|
|
183
|
+
}).catch(reason => {
|
|
184
|
+
handleError(`${METHODS[action]} ${url} failed because of "${reason}"`);
|
|
185
|
+
}).finally(() => {
|
|
165
186
|
// If we have a requested callback
|
|
166
187
|
if (this.requested) {
|
|
167
|
-
this.requested({ action, data, res, url
|
|
188
|
+
this.requested({ action, data, res, url });
|
|
168
189
|
}
|
|
169
190
|
});
|
|
170
|
-
// Init the request body
|
|
171
|
-
let xml = '';
|
|
172
|
-
// If we got data
|
|
173
|
-
if (data !== null) {
|
|
174
|
-
// If we're in GET mode
|
|
175
|
-
if (action === 'read') {
|
|
176
|
-
// Append the data as a param
|
|
177
|
-
url += '?d=' + encodeURIComponent(JSON.stringify(data));
|
|
178
|
-
}
|
|
179
|
-
// Else, DELETE, POST, PUT, just encode the data
|
|
180
|
-
else {
|
|
181
|
-
xml = JSON.stringify(data);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
// Open the request
|
|
185
|
-
xhr.open(ACTIONS_TO_METHODS[action], url);
|
|
186
|
-
// If we have a session token, add it as the Authorization header
|
|
187
|
-
if (this.token) {
|
|
188
|
-
xhr.setRequestHeader('Authorization', this.token);
|
|
189
|
-
}
|
|
190
|
-
// Set the Content-Type header
|
|
191
|
-
xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
|
|
192
|
-
// If we have a requesting callback, call it
|
|
193
|
-
if (this.requesting) {
|
|
194
|
-
this.requesting({ action, data, url, xhr });
|
|
195
|
-
}
|
|
196
|
-
// Send the request
|
|
197
|
-
xhr.send(xml);
|
|
198
191
|
});
|
|
199
192
|
}
|
|
200
193
|
/**
|
|
@@ -243,6 +236,9 @@ class Body {
|
|
|
243
236
|
case 'errorCode':
|
|
244
237
|
this.errorCode = callbacks.errorCode;
|
|
245
238
|
continue;
|
|
239
|
+
case 'noSession':
|
|
240
|
+
this.noSession = callbacks.noSession;
|
|
241
|
+
continue;
|
|
246
242
|
case 'requested':
|
|
247
243
|
this.requested = callbacks.requested;
|
|
248
244
|
continue;
|
|
@@ -277,7 +273,7 @@ class Body {
|
|
|
277
273
|
*
|
|
278
274
|
* Sets callback for whenever a request gets an error back
|
|
279
275
|
*
|
|
280
|
-
* @name
|
|
276
|
+
* @name onErrorCode
|
|
281
277
|
* @access public
|
|
282
278
|
* @param callback The function to call if there's an error
|
|
283
279
|
*/
|
|
@@ -340,6 +336,23 @@ class Body {
|
|
|
340
336
|
// Set the callback
|
|
341
337
|
this.requesting = callback;
|
|
342
338
|
}
|
|
339
|
+
/**
|
|
340
|
+
* On Warning
|
|
341
|
+
*
|
|
342
|
+
* Sets callback for whenever a request gets a warning back
|
|
343
|
+
*
|
|
344
|
+
* @name onWarning
|
|
345
|
+
* @access public
|
|
346
|
+
* @param callback The function to call if there's a warning
|
|
347
|
+
*/
|
|
348
|
+
onWarning(callback) {
|
|
349
|
+
// Make sure the callback is function
|
|
350
|
+
if (typeof callback !== 'function') {
|
|
351
|
+
throw new Error('onWarning() called with an invalid callback');
|
|
352
|
+
}
|
|
353
|
+
// Set the callback
|
|
354
|
+
this.warning = callback;
|
|
355
|
+
}
|
|
343
356
|
/**
|
|
344
357
|
* Read
|
|
345
358
|
*
|
|
@@ -388,28 +401,6 @@ class Body {
|
|
|
388
401
|
update(service, noun, data = null) {
|
|
389
402
|
return this.request('update', service, noun, data);
|
|
390
403
|
}
|
|
391
|
-
/**
|
|
392
|
-
* Verbose Off
|
|
393
|
-
*
|
|
394
|
-
* Called to turn verbose mode off
|
|
395
|
-
*
|
|
396
|
-
* @name verbose_off
|
|
397
|
-
* @access
|
|
398
|
-
*/
|
|
399
|
-
verbose_off() {
|
|
400
|
-
this.verbose = false;
|
|
401
|
-
}
|
|
402
|
-
/**
|
|
403
|
-
* Verbose On
|
|
404
|
-
*
|
|
405
|
-
* Called to turn verbose mode on
|
|
406
|
-
*
|
|
407
|
-
* @name verbose_on
|
|
408
|
-
* @access
|
|
409
|
-
*/
|
|
410
|
-
verbose_on() {
|
|
411
|
-
this.verbose = true;
|
|
412
|
-
}
|
|
413
404
|
}
|
|
414
405
|
// Create an instance of Body
|
|
415
406
|
const body = new Body();
|
package/{build → lib}/regex.js
RENAMED
|
@@ -8,6 +8,6 @@
|
|
|
8
8
|
* @created 2023-03-05
|
|
9
9
|
*/
|
|
10
10
|
// E-Mail address
|
|
11
|
-
export const EMAIL_ADDRESS =
|
|
11
|
+
export const EMAIL_ADDRESS = /^[^@\s]+@[^@\s]+\.[a-zA-Z0-9]{2,}$/;
|
|
12
12
|
// North American Phone Number
|
|
13
|
-
export const PHONE_NUMBER_NA =
|
|
13
|
+
export const PHONE_NUMBER_NA = /^\+?1?[ -]?\(?(\d{3})\)?[ -]?(\d{3})[ -]?(\d{4})$/;
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ouroboros/body",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Classes to communicate with Ouroboros Coding Inc. body services",
|
|
5
|
-
"main": "
|
|
6
|
-
"types": "
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"types": "lib/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "tslint -p tsconfig.json && tsc",
|
|
9
|
-
"clean": "rm
|
|
9
|
+
"clean": "rm lib/*",
|
|
10
10
|
"for_local": "npm install; tslint -p tsconfig.json && tsc; rm -Rf node_modules",
|
|
11
11
|
"test": "echo \"Error: no test specified.\" && exit 1"
|
|
12
12
|
},
|
|
@@ -26,9 +26,6 @@
|
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"tslint": "^6.1.3",
|
|
28
28
|
"tslint-config-prettier": "^1.18.0",
|
|
29
|
-
"typescript": "^4.
|
|
30
|
-
},
|
|
31
|
-
"dependencies": {
|
|
32
|
-
"xhr2": "^0.2.1"
|
|
29
|
+
"typescript": "^4.9.5"
|
|
33
30
|
}
|
|
34
31
|
}
|
package/releases.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# @ouroboros/body releases
|
|
2
|
+
|
|
3
|
+
## 1.2.1
|
|
4
|
+
- Fixed issue where 401 Unauthorized issues weren't properly handled causing thrown errors.
|
|
5
|
+
|
|
6
|
+
## 1.2.0
|
|
7
|
+
- Moved generated .js and .d.ts files into lib/ instead of build/, this changes the "main" from "build/index.js" to "lib/index.js".
|
|
8
|
+
- Removed `xhr2` from the project and replaced `XMLHttpRequest` with `fetch`.
|
|
9
|
+
- Removed `xhr` from `onRequestedStruct` and `onRequestingStruct`.
|
|
10
|
+
- Removed `Body.verbose_on()` and `Body.verbose_off()` functions as well as all `console.log` calls.
|
|
11
|
+
- Added missing `Body.onWarning` function.
|
|
12
|
+
- Added "noSession" as a valid key to the `on` function's argument.
|
|
13
|
+
- Added check in `Body.request` to trigger `this.warning` if a warning is returned.
|
|
14
|
+
- Added `domain`, `on`, and `onWarning` functions to `Service` class, each passes their arguments to, and returns from, the `body` function of the same name.
|
|
15
|
+
- Changed `body.domain` to getter/setter instead of just setter.
|
package/src/Service.ts
CHANGED
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
import body from './';
|
|
13
13
|
|
|
14
14
|
// Types
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
onCallbacks, onError, onErrorCode, onRequested, onRequesting, onWarning
|
|
17
|
+
} from './';
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
20
|
* Service
|
|
@@ -70,6 +72,33 @@ export default class Service {
|
|
|
70
72
|
return body.request('delete', this.service, noun, data);
|
|
71
73
|
}
|
|
72
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Domain
|
|
77
|
+
*
|
|
78
|
+
* Set/Gets the current domain
|
|
79
|
+
*
|
|
80
|
+
* @name domain
|
|
81
|
+
* @access public
|
|
82
|
+
* @param domain The domain to make all calls to
|
|
83
|
+
* @returns void
|
|
84
|
+
*/
|
|
85
|
+
domain(domain?: string): void | string {
|
|
86
|
+
return body.domain(domain);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* On
|
|
91
|
+
*
|
|
92
|
+
* Called to set multiple events at once
|
|
93
|
+
*
|
|
94
|
+
* @name on
|
|
95
|
+
* @access public
|
|
96
|
+
* @param callbacks A name to callback object to set multiple events
|
|
97
|
+
*/
|
|
98
|
+
on(callbacks: onCallbacks): void {
|
|
99
|
+
return body.on(callbacks);
|
|
100
|
+
}
|
|
101
|
+
|
|
73
102
|
/**
|
|
74
103
|
* On Error
|
|
75
104
|
*
|
|
@@ -120,6 +149,19 @@ export default class Service {
|
|
|
120
149
|
return body.onRequesting(callback);
|
|
121
150
|
}
|
|
122
151
|
|
|
152
|
+
/**
|
|
153
|
+
* On Warning
|
|
154
|
+
*
|
|
155
|
+
* Sets callback for whenever a request gets a warning back
|
|
156
|
+
*
|
|
157
|
+
* @name onWarning
|
|
158
|
+
* @access public
|
|
159
|
+
* @param callback The function to call if there's a warning
|
|
160
|
+
*/
|
|
161
|
+
onWarning(callback: onWarning): void {
|
|
162
|
+
return body.onWarning(callback);
|
|
163
|
+
}
|
|
164
|
+
|
|
123
165
|
/**
|
|
124
166
|
* Read
|
|
125
167
|
*
|
package/src/constants.ts
CHANGED
|
@@ -9,9 +9,10 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
// Empty UUID
|
|
12
|
-
export const
|
|
12
|
+
export const EMPTY_TUUID = '00000000000040008000000000000000';
|
|
13
|
+
export const EMPTY_UUID = '00000000-0000-4000-8000-000000000000';
|
|
13
14
|
|
|
14
15
|
// Seconds
|
|
15
|
-
export const SECONDS_HOUR = 3600
|
|
16
|
-
export const SECONDS_DAY = 86400
|
|
17
|
-
export const SECONDS_WEEK = 604800
|
|
16
|
+
export const SECONDS_HOUR = 3600;
|
|
17
|
+
export const SECONDS_DAY = 86400;
|
|
18
|
+
export const SECONDS_WEEK = 604800;
|