@ouroboros/body 1.1.2 → 1.2.0

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 CHANGED
@@ -1,8 +1,8 @@
1
1
  Ouroboros Coding Inc. License
2
2
 
3
- Copyright (c) 2023 Ouroboros Coding Inc.
3
+ Copyright (c) 2025 Ouroboros Coding Inc.
4
4
 
5
5
  Permission is hereby granted, with limits, to any person using this software
6
- within a project created by Ouroboros Coding Inc. Any attempt to modify this
7
- code, or use it outside projects created by Ouroboros Coding Inc, will result
8
- in legal action taken against the party using the code.
6
+ within a project created by Ouroboros Coding Inc. Any attempt to use this
7
+ code outside projects created by Ouroboros Coding Inc, will result in legal
8
+ action taken against the party using the code.
package/README.md CHANGED
@@ -1,15 +1,324 @@
1
1
  # @ouroboros/body
2
+ [![npm version](https://img.shields.io/npm/v/@ouroboros/body.svg)](https://www.npmjs.com/package/@ouroboros/body) ![Custom License](https://img.shields.io/npm/l/@ouroboros/body.svg)
2
3
 
3
- [![npm version](https://img.shields.io/npm/v/@ouroboros/body.svg)](https://www.npmjs.com/package/@ouroboros/body)
4
+ Javascript/Typescript library for connecting to
5
+ [body_oc](https://pypi.org/project/body_oc/) RESTlike microservices.
4
6
 
5
- Shared javascript code for communication with all body parts (services) created
6
- by Ouroboros Coding Inc.
7
-
8
- This code comes without documentation as it's not meant to be used by anyone
9
- outside of Ouroboros Coding Inc. Please see LICENSE for further information.
7
+ See [Releases](https://github.com/ouroboroscoding/body-js/blob/main/releases.md)
8
+ for changes from release to release.
10
9
 
11
10
  ## Installation
12
- npm
13
- ```bash
14
- npm install @ouroboros/body
15
- ```
11
+
12
+ Install with npm
13
+
14
+ ```console
15
+ foo@bar:~$ npm install @ouroboros/body
16
+ ```
17
+
18
+ ## Contents
19
+ - [Body](#body)
20
+ - [domain](#domain)
21
+ - [request](#request)
22
+ - [on](#on)
23
+ - [onError](#onerror)
24
+ - [onErrorCode](#onerrorcode)
25
+ - [onNoSession](#onnosession)
26
+ - [onRequested](#onrequested)
27
+ - [onRequesting](#onrequesting)
28
+ - [onWarning](#onwarning)
29
+ - [session](#session)
30
+ - [Service](#service)
31
+ - [Errors](#errors)
32
+ - [Constants](#constants)
33
+ - [Regex](#regex)
34
+
35
+ ## Body
36
+ This is the primary export of the library, it provides a simple asynchronous
37
+ way to communicate with [body_oc](https://pypi.org/project/body_oc/) services
38
+ that have exposed themselves to http requests with the pattern
39
+ `https://domain.com/service/noun/`.
40
+
41
+ ```javascript
42
+ import body, { errors } from '@ouroboros/body';
43
+ import React, { useEffect, useState } from 'react';
44
+
45
+ body.domain('rest.mydomain.com');
46
+ body.onError((message, info) => {
47
+ console.error(message, info);
48
+ });
49
+
50
+ function MyApp() {
51
+ const [ loading, setLoading ] = useState(0);
52
+ const [ data, setData ] = useState();
53
+ const [ error, setError ] = useState(false);
54
+
55
+ useEffect(() => {
56
+ body.onRequesting(() => {
57
+ setLoading(i => i + 1);
58
+ });
59
+ body.onRequested(() => {
60
+ setLoading(i => {
61
+ i -= 1;
62
+ return (i < 0) ? 0 : i;
63
+ });
64
+ });
65
+ }, [ ]);
66
+
67
+ function fetchData() {
68
+ setError(false);
69
+ body.read(
70
+ 'my_service',
71
+ 'my_request',
72
+ { _id: 'someid' }
73
+ ).then(setData, setError);
74
+ }
75
+
76
+ return <>
77
+ <button onClick={fetchData}>Fetch</button>
78
+ <br />
79
+ {loading &&
80
+ <div>Loading{Array(loading).fill('.').join('')}</div>
81
+ }
82
+ {error &&
83
+ <pre className="error">{JSON.stringify(error, null, 4)}</pre>
84
+ }
85
+ {data ?
86
+ <pre>{JSON.stringify(data, null, 4)}</pre> :
87
+ <span>You haven't fetched the data yet.</span>
88
+ }
89
+ </>
90
+ }
91
+ ```
92
+
93
+ ### domain
94
+ The domain indicates the first part of every URL generated to talk to a service.
95
+ In the example above we set `rest.mydomain.com` to indicate we want to connect
96
+ to **mydomain.com** through a subdomain setup specifically for the services
97
+ called **rest**.
98
+
99
+ If you are unsure what the domain is in your project, contact whoever is in
100
+ charge of creating the [body_oc](https://pypi.org/project/body_oc/) services.
101
+
102
+ Pass nothing to see what the current domain is.
103
+
104
+ [ [top](#ouroborosbody), [contents](#contents), [body](#body) ]
105
+
106
+ ### request
107
+ `request` is the core of the `body` module. It's how you connect to all service
108
+ requests. It takes all the required data and generates an http request to the
109
+ server to fetch whatever data is required, then converts that data back into
110
+ usable Javascript data your project can use.
111
+
112
+ It has 4 arguments: `action`, `service`, `noun`, and `data`.
113
+
114
+ `action` Is the type of request you're making, it must be one of the 4 following
115
+ strings, **create**, **read**, **update**, or **delete**. These correspond to
116
+ **POST**, **GET**, **PUT**, and **DELETE** respectively.
117
+
118
+ `service` is the name of the service you want to connect to. This is the name
119
+ you have given your service and unique to your project.
120
+
121
+ `noun` is the name of the request on the service you want to call. This is the
122
+ name you have given the request and unique to your project. They correspond to
123
+ the methods on the server side by replacing _ with /. `users/by/id` on the
124
+ client side would be `users_by_id` on the server side.
125
+
126
+ `data` is the JSON safe data you are sending with the request. If your data
127
+ won't go through `JSON.stringify()` then you can't send it with a request.
128
+
129
+ Most of the time you won't see `request` used directly. Instead you'll see one
130
+ of `create`, `delete`, `read`, or `update` which work exactly like `request`
131
+ with the `action` substituted for the function name. So the `body.read` call in
132
+ the [example](#body) could have also been written as
133
+ ```javascript
134
+ body.request(
135
+ 'read',
136
+ 'my_service',
137
+ 'my_request',
138
+ { _id: 'someid' }
139
+ ).then(setData, setError);
140
+ ```
141
+
142
+ [ [top](#ouroborosbody), [contents](#contents), [body](#body) ]
143
+
144
+ ### on
145
+ `on` works as a shortcut for calling any or all of [onError](#onerror),
146
+ [onErrorCode](#onerrorcode), [onNoSession](#onnosession),
147
+ [onRequested](#onrequested), [onRequesting](#onrequesting), and
148
+ [onWarning](#onwarning). Just remove "on" and make the new first letter
149
+ lowercase, i.e. `onError` becomes `error`, `onRequested` becomes `requested`,
150
+ etc.
151
+
152
+ ```javascript
153
+ import body from '@ouroboros/body';
154
+ body.on({
155
+ error: (error, info) => {},
156
+ errorCode: (error, info) => {},
157
+ noSession: () => {},
158
+ warning: (warning, info) => {}
159
+ });
160
+ ```
161
+
162
+ [ [top](#ouroborosbody), [contents](#contents), [body](#body) ]
163
+
164
+ ### onError
165
+ `onError` sets a callback for whenever the http request fails for some reason
166
+ outside of the scope of `body`. The user's internet is down, the service doesn't
167
+ even exist, etc.
168
+
169
+ The first argument is a string describing the error. The second argument is an
170
+ object with `action`, `data`, and `url`.
171
+
172
+ [ [top](#ouroborosbody), [contents](#contents), [body](#body) ]
173
+
174
+ ### onErrorCode
175
+ `onErrorCode` sets a callback for whenever the request goes through, all the
176
+ http communication is fine, but the service returns an error with something
177
+ gone wrong, either on the server side, or because the client failed to provide
178
+ the correct data.
179
+
180
+ The first argument is the error response, it contains a `code` and a `msg`. The
181
+ second argument is an object with `action`, `data`, `res`, and `url`.
182
+
183
+ [ [top](#ouroborosbody), [contents](#contents), [body](#body) ]
184
+
185
+ ### onNoSession
186
+ `onNoSession` sets a callback for when a request is made with a session token
187
+ and the server response that it's not valid. No information is passed to the
188
+ callback.
189
+
190
+ [ [top](#ouroborosbody), [contents](#contents), [body](#body) ]
191
+
192
+ ### onRequested
193
+ `onRequested` sets a callback for after any request is made. It's helpful for
194
+ things like stoping loading animations.
195
+
196
+ The single argument is an object with `action`, `data`, `url`, and `res`.
197
+
198
+ [ [top](#ouroborosbody), [contents](#contents), [body](#body) ]
199
+
200
+ ### onRequesting
201
+ `onRequesting` sets a callback for before any request is made. It's helpful for
202
+ things like starting loading animations.
203
+
204
+ The single argument is an object with `action`, `data`, and `url`.
205
+
206
+ [ [top](#ouroborosbody), [contents](#contents), [body](#body) ]
207
+
208
+ ### onWarning
209
+ `onWarning` sets a callback for whenever a request returns a warning in the
210
+ result.
211
+
212
+ The first argument is the warning data, the second is an object with `action`,
213
+ `data`, `res`, and `url`.
214
+
215
+ [ [top](#ouroborosbody), [contents](#contents), [body](#body) ]
216
+
217
+ ### session
218
+ The `session` function is a getter/setter for the current session token. When
219
+ keeping track of user requests it's required that a token is used. The token
220
+ will most likely come from the server side and need to be stored, in a cookie,
221
+ in localStorage, in whatever system works for you.
222
+
223
+ When a session token is added to `body` it will add it to the **Authorization**
224
+ header of every [request](#request) made until `session` is called again with
225
+ a different token, or `null` in order to clear the current one.
226
+
227
+ Pass nothing to see what the current token is.
228
+
229
+ [ [top](#ouroborosbody), [contents](#contents), [body](#body) ]
230
+
231
+ ## Service
232
+ `Service` acts as a way to connect to one specific service without interacting
233
+ directly with `body`.
234
+
235
+ Say you have a project with a single service, or you are creating a re-usable
236
+ service and want to offer a simple way to connect to it. Let's call this service
237
+ **my_service**. You could create and export a `Service` in your files.
238
+
239
+ `my_service.js`
240
+ ```javascript
241
+ import { Service } from '@ouroboros/body';
242
+ const myService = new Service('my_service');
243
+ export default myService;
244
+ ```
245
+
246
+ And you could provide that file to anyone wanting to use your service. Making
247
+ the following...
248
+ ```javascript
249
+ import myService from 'my_service';
250
+ myService.domain('rest.mydomain.com');
251
+ myService.on({
252
+ error: (error, info) => {},
253
+ warning: (warning, info) => {}
254
+ });
255
+ myService.create(
256
+ 'my/request',
257
+ { /* request data */ }
258
+ );
259
+ ```
260
+ ... would be equivalent to this
261
+ ```javascript
262
+ import body from '@ouroboros/body';
263
+ body.domain('rest.mydomain.com');
264
+ body.on({
265
+ error: (error, info) => {},
266
+ warning: (warning, info) => {}
267
+ });
268
+ body.create(
269
+ 'my_service',
270
+ 'my/request',
271
+ { /* request data */ }
272
+ );
273
+ ```
274
+
275
+ Anything you can do with `body` you can do with a `Service` instance as it
276
+ contains all the same functions as `body`. The only difference is that any
277
+ function that expects a `service` argument is passed the name of the `Service`.
278
+
279
+ [ [top](#ouroborosbody), [contents](#contents) ]
280
+
281
+ ## Errors
282
+ `errors` contains constants for all the same errors available in
283
+ [body_oc](https://github.com/ouroboroscoding/body/blob/main/README.md#error-codes)
284
+
285
+ ```javascript
286
+ import body, { errors } from '@ouroboros/body';
287
+ body.domain('rest.mydomain.com');
288
+ body.read(
289
+ 'my_service',
290
+ 'my/request',
291
+ { _id: 'someid' }
292
+ ).then(res => {},
293
+ error => {
294
+ if(error.code === errors.DATA_FIELDS) {
295
+ // Bad data sent to request
296
+ } else if(error.code === errors.DB_NO_RECORD) {
297
+ // Bad ID, no such record
298
+ } else {
299
+ // Unknown error code
300
+ }
301
+ }
302
+ )
303
+ ```
304
+
305
+ [ [top](#ouroborosbody), [contents](#contents) ]
306
+
307
+ ## Constants
308
+ `constants` contains the same constants available in
309
+ [body_oc](https://github.com/ouroboroscoding/body/blob/main/README.md#constants)
310
+
311
+ [ [top](#ouroborosbody), [contents](#contents) ]
312
+
313
+ ## Regex
314
+ `regex` contains the same regular expressions available in
315
+ [body_oc](https://github.com/ouroboroscoding/body/blob/main/README.md#regular-expressions)
316
+
317
+ ```javascript
318
+ import { regex } from '@ouroboros/body';
319
+ if(!regex.EMAIL_ADDRESS.test('me#mydomain.com')) {
320
+ console.error('Invalid email address');
321
+ }
322
+ ```
323
+
324
+ [ [top](#ouroborosbody), [contents](#contents) ]
@@ -7,7 +7,7 @@
7
7
  * @copyright Ouroboros Coding Inc.
8
8
  * @created 2023-03-05
9
9
  */
10
- import { onError, onErrorCode, onRequested, onRequesting } from './';
10
+ import { onCallbacks, onError, onErrorCode, onRequested, onRequesting, onWarning } from './';
11
11
  /**
12
12
  * Service
13
13
  *
@@ -52,6 +52,27 @@ export default class Service {
52
52
  * @param data The data associated with the request
53
53
  */
54
54
  delete(noun: string, data?: any): Promise<any>;
55
+ /**
56
+ * Domain
57
+ *
58
+ * Set/Gets the current domain
59
+ *
60
+ * @name domain
61
+ * @access public
62
+ * @param domain The domain to make all calls to
63
+ * @returns void
64
+ */
65
+ domain(domain?: string): void | string;
66
+ /**
67
+ * On
68
+ *
69
+ * Called to set multiple events at once
70
+ *
71
+ * @name on
72
+ * @access public
73
+ * @param callbacks A name to callback object to set multiple events
74
+ */
75
+ on(callbacks: onCallbacks): void;
55
76
  /**
56
77
  * On Error
57
78
  *
@@ -90,6 +111,16 @@ export default class Service {
90
111
  * @param callback The function to call before making requests
91
112
  */
92
113
  onRequesting(callback: onRequesting): void;
114
+ /**
115
+ * On Warning
116
+ *
117
+ * Sets callback for whenever a request gets a warning back
118
+ *
119
+ * @name onWarning
120
+ * @access public
121
+ * @param callback The function to call if there's a warning
122
+ */
123
+ onWarning(callback: onWarning): void;
93
124
  /**
94
125
  * Read
95
126
  *
@@ -60,6 +60,31 @@ export default class Service {
60
60
  delete(noun, data = null) {
61
61
  return body.request('delete', this.service, noun, data);
62
62
  }
63
+ /**
64
+ * Domain
65
+ *
66
+ * Set/Gets the current domain
67
+ *
68
+ * @name domain
69
+ * @access public
70
+ * @param domain The domain to make all calls to
71
+ * @returns void
72
+ */
73
+ domain(domain) {
74
+ return body.domain(domain);
75
+ }
76
+ /**
77
+ * On
78
+ *
79
+ * Called to set multiple events at once
80
+ *
81
+ * @name on
82
+ * @access public
83
+ * @param callbacks A name to callback object to set multiple events
84
+ */
85
+ on(callbacks) {
86
+ return body.on(callbacks);
87
+ }
63
88
  /**
64
89
  * On Error
65
90
  *
@@ -106,6 +131,18 @@ export default class Service {
106
131
  onRequesting(callback) {
107
132
  return body.onRequesting(callback);
108
133
  }
134
+ /**
135
+ * On Warning
136
+ *
137
+ * Sets callback for whenever a request gets a warning back
138
+ *
139
+ * @name onWarning
140
+ * @access public
141
+ * @param callback The function to call if there's a warning
142
+ */
143
+ onWarning(callback) {
144
+ return body.onWarning(callback);
145
+ }
109
146
  /**
110
147
  * Read
111
148
  *
@@ -7,6 +7,7 @@
7
7
  * @copyright Ouroboros Coding Inc.
8
8
  * @created 2023-03-05
9
9
  */
10
+ export declare const EMPTY_TUUID = "00000000000040008000000000000000";
10
11
  export declare const EMPTY_UUID = "00000000-0000-4000-8000-000000000000";
11
12
  export declare const SECONDS_HOUR = 3600;
12
13
  export declare const SECONDS_DAY = 86400;
@@ -8,6 +8,7 @@
8
8
  * @created 2023-03-05
9
9
  */
10
10
  // Empty UUID
11
+ export const EMPTY_TUUID = '00000000000040008000000000000000';
11
12
  export const EMPTY_UUID = '00000000-0000-4000-8000-000000000000';
12
13
  // Seconds
13
14
  export const SECONDS_HOUR = 3600;
@@ -7,17 +7,16 @@
7
7
  * @copyright Ouroboros Coding Inc.
8
8
  * @created 2023-03-03
9
9
  */
10
- import XMLHttpRequest from 'xhr2';
11
10
  import * as constants from './constants';
12
11
  import * as errors from './errors';
13
12
  import * as regex from './regex';
14
13
  export { constants, errors, regex };
15
14
  export { default as Service } from './Service';
16
15
  export type actionOptions = 'create' | 'delete' | 'read' | 'update';
17
- export type callbackOptions = 'error' | 'errorCode' | 'requested' | 'requesting' | 'warning';
18
16
  export type onCallbacks = {
19
17
  error?: onError;
20
18
  errorCode?: onErrorCode;
19
+ noSession?: () => void;
21
20
  requested?: onRequested;
22
21
  requesting?: onRequesting;
23
22
  warning?: onWarning;
@@ -30,14 +29,12 @@ export type onRequestedStruct = {
30
29
  data: any;
31
30
  res?: responseStruct;
32
31
  url: string;
33
- xhr: XMLHttpRequest;
34
32
  };
35
33
  export type onRequesting = (info: onRequestingStruct) => void;
36
34
  export type onRequestingStruct = {
37
35
  action: actionOptions;
38
36
  data: any;
39
37
  url: string;
40
- xhr: XMLHttpRequest;
41
38
  };
42
39
  export type onWarning = (warning: any, info: onRequestedStruct) => void;
43
40
  export type responseStruct = {
@@ -48,7 +45,6 @@ export type responseStruct = {
48
45
  export type responseErrorStruct = {
49
46
  code: number;
50
47
  msg?: any;
51
- handle?: (message: string) => void;
52
48
  };
53
49
  export type responseResolve = (res: responseStruct) => void;
54
50
  export type responseReject = (error: responseErrorStruct) => boolean;
@@ -68,18 +64,18 @@ declare class Body {
68
64
  private requested;
69
65
  private requesting;
70
66
  private token;
71
- private verbose;
72
67
  private warning;
73
68
  /**
74
69
  * Domain
75
70
  *
76
- * Set the domain
71
+ * Sets/Gets the domain
77
72
  *
78
73
  * @name domain
79
74
  * @access public
80
- * @param domain The name of the domain to connect to
75
+ * @param @param domain The domain to set
76
+ * @returns the domain set
81
77
  */
82
- domain(domain: string): void;
78
+ domain(domain?: string): string | void;
83
79
  /**
84
80
  * Request
85
81
  *
@@ -87,6 +83,7 @@ declare class Body {
87
83
  *
88
84
  * @name request
89
85
  * @access public
86
+ * @param action The action to take in the call
90
87
  * @param service The service to call
91
88
  * @param noun The noun to call on the service
92
89
  * @param data The data associated with the request
@@ -141,7 +138,7 @@ declare class Body {
141
138
  *
142
139
  * Sets callback for whenever a request gets an error back
143
140
  *
144
- * @name onNoSession
141
+ * @name onErrorCode
145
142
  * @access public
146
143
  * @param callback The function to call if there's an error
147
144
  */
@@ -176,6 +173,16 @@ declare class Body {
176
173
  * @param callback The function to call before making requests
177
174
  */
178
175
  onRequesting(callback: onRequesting): void;
176
+ /**
177
+ * On Warning
178
+ *
179
+ * Sets callback for whenever a request gets a warning back
180
+ *
181
+ * @name onWarning
182
+ * @access public
183
+ * @param callback The function to call if there's a warning
184
+ */
185
+ onWarning(callback: onWarning): void;
179
186
  /**
180
187
  * Read
181
188
  *
@@ -211,24 +218,6 @@ declare class Body {
211
218
  * @param data The data associated with the request
212
219
  */
213
220
  update(service: string, noun: string, data?: any): Promise<any>;
214
- /**
215
- * Verbose Off
216
- *
217
- * Called to turn verbose mode off
218
- *
219
- * @name verbose_off
220
- * @access
221
- */
222
- verbose_off(): void;
223
- /**
224
- * Verbose On
225
- *
226
- * Called to turn verbose mode on
227
- *
228
- * @name verbose_on
229
- * @access
230
- */
231
- verbose_on(): void;
232
221
  }
233
222
  declare const body: Body;
234
223
  export default body;