dce-reactkit 3.9.0-beta.1 → 3.9.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.
Files changed (39) hide show
  1. package/dist/cjs/index.js +562 -257
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/types/components/Dropdown.d.ts +32 -0
  4. package/dist/cjs/types/components/Modal/ModalProps.d.ts +0 -2
  5. package/dist/cjs/types/helpers/validators/ChicagoTitleCase.d.ts +9 -0
  6. package/dist/cjs/types/helpers/validators/validURL.d.ts +8 -0
  7. package/dist/cjs/types/helpers/visitEndpointOnAnotherServer/index.d.ts +22 -0
  8. package/dist/cjs/types/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.d.ts +33 -0
  9. package/dist/cjs/types/index.d.ts +4 -1
  10. package/dist/cjs/types/types/DropdownItemType.d.ts +6 -0
  11. package/dist/cjs/types/types/ReactKitErrorCode.d.ts +4 -1
  12. package/dist/esm/index.js +560 -259
  13. package/dist/esm/index.js.map +1 -1
  14. package/dist/esm/types/components/Dropdown.d.ts +32 -0
  15. package/dist/esm/types/components/Modal/ModalProps.d.ts +0 -2
  16. package/dist/esm/types/helpers/validators/ChicagoTitleCase.d.ts +9 -0
  17. package/dist/esm/types/helpers/validators/validURL.d.ts +8 -0
  18. package/dist/esm/types/helpers/visitEndpointOnAnotherServer/index.d.ts +22 -0
  19. package/dist/esm/types/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.d.ts +33 -0
  20. package/dist/esm/types/index.d.ts +4 -1
  21. package/dist/esm/types/types/DropdownItemType.d.ts +6 -0
  22. package/dist/esm/types/types/ReactKitErrorCode.d.ts +4 -1
  23. package/dist/index.d.ts +105 -46
  24. package/package.json +2 -1
  25. package/src/components/Dropdown.tsx +317 -0
  26. package/src/components/Modal/ModalProps.ts +0 -4
  27. package/src/components/Modal/index.tsx +3 -39
  28. package/src/components/MultiSwitch.tsx +1 -1
  29. package/src/helpers/validators/ChicagoTitleCase.test.ts +85 -0
  30. package/src/helpers/validators/ChicagoTitleCase.ts +32 -0
  31. package/src/helpers/validators/findURL.test.ts +83 -0
  32. package/src/helpers/validators/findURL.ts +43 -0
  33. package/src/helpers/validators/validURL.test.ts +90 -0
  34. package/src/helpers/validators/validURL.ts +18 -0
  35. package/src/helpers/visitEndpointOnAnotherServer/index.ts +90 -0
  36. package/src/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.ts +164 -0
  37. package/src/index.ts +6 -0
  38. package/src/types/DropdownItemType.ts +11 -0
  39. package/src/types/ReactKitErrorCode.tsx +6 -1
@@ -0,0 +1,90 @@
1
+
2
+ // Import the function to be tested
3
+ // import isValid from './validURL';
4
+
5
+ // // Import constants
6
+ // import { INVALID_STRING_ERRORS, INVALID_REGEX_ERROR } from './shared/constants/ERROR_MESSAGES';
7
+
8
+ // /*------------------------------------------------------------------------*/
9
+ // /* ---------------------------- Valid Tests --------------------------- */
10
+ // /*------------------------------------------------------------------------*/
11
+
12
+ // const validUrls: string[] = [
13
+ // 'http://example.com',
14
+ // 'https://example.com',
15
+ // 'http://www.example.com',
16
+ // 'https://www.example.com',
17
+ // 'https://example.com/path',
18
+ // 'http://example.com/path',
19
+ // 'https://example.com?query=string',
20
+ // 'http://example.com?query=string',
21
+ // 'https://example.com#fragment',
22
+ // 'http://example.com#fragment',
23
+ // 'http://localhost',
24
+ // 'https://localhost:3000',
25
+ // 'http://localhost:3000',
26
+ // 'http://127.0.0.1',
27
+ // 'http://127.0.0.1:3000',
28
+ // 'ftp://example.com/path',
29
+ // 'ftp://example.com',
30
+ // 'https://127.0.0.1:3000',
31
+ // 'file:///C:/path/to/file'
32
+ // ];
33
+
34
+ // test(
35
+ // 'Returns true for a given valid URL.',
36
+ // async () => {
37
+ // validUrls.forEach((url) => {
38
+ // expect(isValid(url)).toBe(true);
39
+ // });
40
+ // },
41
+ // );
42
+
43
+ // /*------------------------------------------------------------------------*/
44
+ // /* ---------------------------- Invalid Tests --------------------------- */
45
+ // /*------------------------------------------------------------------------*/
46
+
47
+ // const invalidUrls: string[] = [
48
+ // '',
49
+ // ' ',
50
+ // 'example',
51
+ // 'http://',
52
+ // 'http://.',
53
+ // 'http://..',
54
+ // 'http://##/',
55
+ // 'http://../',
56
+ // 'http://??/',
57
+ // 'http://#',
58
+ // 'http://##',
59
+ // '//',
60
+ // '//a',
61
+ // '///a',
62
+ // '///',
63
+ // 'http:///a',
64
+ // 'http://www.foo.bar./',
65
+ // 'http://foo.bar/foo(bar)baz quux',
66
+ // 'http://3628126748',
67
+ // 'http://.www.foo.bar/',
68
+ // 'http://.www.foo.bar./',
69
+ // 'http://123.123.123',
70
+ // 'http://1.1.1.1.1',
71
+ // 'http://example.com:99999',
72
+ // 'http://example.com:80:80',
73
+ // 'http://example.com::80',
74
+ // 'http://example.com:-80',
75
+ // 'http://-example.com',
76
+ // 'http://example.com-',
77
+ // 'http://example.com_',
78
+ // 'http://example..com',
79
+ // 'http://example.com.',
80
+ // 'http://.example.com'
81
+ // ];
82
+
83
+ // test(
84
+ // 'Returns false for a given invalid URL.',
85
+ // async () => {
86
+ // invalidUrls.forEach((url) => {
87
+ // expect(isValid(url)).toBe(false);
88
+ // });
89
+ // },
90
+ // );
@@ -0,0 +1,18 @@
1
+ /**
2
+ * This function checks if a given input string is a valid URL.
3
+ * @author Leisha Bhandari
4
+ * @param URL: The input string that needs checked as a URL or not.
5
+ * @returns A true boolean value if the input string is a valid URL, and a false
6
+ * boolean value if the input string is a invalid URL
7
+ */
8
+ function isValid(url: string): boolean {
9
+ // Uses the input URL to create a URL object
10
+ try {
11
+ new URL(url);
12
+ // URL constructor does not throw an error, so input URL is valid
13
+ return true;
14
+ } catch (err) {
15
+ // URL constructor throws an error, so input URL is invalid
16
+ return false;
17
+ }
18
+ }
@@ -0,0 +1,90 @@
1
+ // Import custom error
2
+ import ErrorWithCode from '../../errors/ErrorWithCode';
3
+
4
+ // Import shared types
5
+ import ReactKitErrorCode from '../../types/ReactKitErrorCode';
6
+
7
+ // Import other helpers
8
+ import sendServerToServerRequest from './sendServerToServerRequest';
9
+
10
+ /**
11
+ * Send a server-to-server request from this sever to another server that uses
12
+ * dce-reactkit [for server only]
13
+ * @author Gabe Abrams
14
+ * @param opts object containing all arguments
15
+ * @param opts.path - the path of the other server's endpoint
16
+ * @param [opts.method=GET] - the method of the endpoint
17
+ * @param [opts.params] - query/body parameters to include
18
+ * @param [opts.headers] - headers to include
19
+ * @returns response from server
20
+ */
21
+ const visitEndpointOnAnotherServer = async (
22
+ opts: {
23
+ path: string,
24
+ method?: ('GET' | 'POST' | 'DELETE' | 'PUT'),
25
+ params?: { [key in string]: any },
26
+ headers?: { [k in string]: any },
27
+ },
28
+ ): Promise<any> => {
29
+ // Remove properties with undefined values
30
+ let params: { [key in string]: any } | undefined;
31
+ if (opts.params) {
32
+ params = Object.fromEntries(
33
+ Object
34
+ .entries(opts.params)
35
+ .filter(([, value]) => {
36
+ return value !== undefined;
37
+ }),
38
+ );
39
+ }
40
+
41
+ // Automatically JSONify arrays and objects
42
+ if (params) {
43
+ params = Object.fromEntries(
44
+ Object
45
+ .entries(params)
46
+ .map(([key, value]) => {
47
+ if (Array.isArray(value) || typeof value === 'object') {
48
+ return [key, JSON.stringify(value)];
49
+ }
50
+ return [key, value];
51
+ }),
52
+ );
53
+ }
54
+
55
+ // Send the request
56
+ const response = await sendServerToServerRequest({
57
+ path: opts.path,
58
+ method: opts.method ?? 'GET',
59
+ params,
60
+ });
61
+
62
+ // Check for failure
63
+ if (!response || !response.body) {
64
+ throw new ErrorWithCode(
65
+ 'We didn\'t get a response from the server. Please check your internet connection.',
66
+ ReactKitErrorCode.NoResponse,
67
+ );
68
+ }
69
+ if (!response.body.success) {
70
+ // Other errors
71
+ throw new ErrorWithCode(
72
+ (
73
+ response.body.message
74
+ || 'An unknown error occurred. Please contact an admin.'
75
+ ),
76
+ (
77
+ response.body.code
78
+ || ReactKitErrorCode.NoCode
79
+ ),
80
+ );
81
+ }
82
+
83
+ // Success! Extract the body
84
+ const { body } = response.body;
85
+
86
+ // Return
87
+ return body;
88
+ };
89
+
90
+ export default visitEndpointOnAnotherServer;
@@ -0,0 +1,164 @@
1
+ // Import libs
2
+ import qs from 'qs';
3
+
4
+ // Import shared types
5
+ import ReactKitErrorCode from '../../types/ReactKitErrorCode';
6
+
7
+ // Import custom error
8
+ import ErrorWithCode from '../../errors/ErrorWithCode';
9
+
10
+ /**
11
+ * Sends and retries an http request
12
+ * @author Gabriel Abrams
13
+ * @param opts object containing all arguments
14
+ * @param opts.path path to send request to
15
+ * @param [opts.host] host to send request to
16
+ * @param [opts.method=GET] http method to use
17
+ * @param [opts.params] body/data to include in the request
18
+ * @param [opts.headers] headers to include in the request
19
+ * @param [opts.sendCrossDomainCredentials=true if in development mode] if true,
20
+ * send cross-domain credentials even if not in dev mode
21
+ * @param [opts.responseType=JSON] expected response type
22
+ * @returns { body, status, headers } on success
23
+ */
24
+ const sendServerToServerRequest = async (
25
+ opts: {
26
+ path: string,
27
+ host?: string,
28
+ method?: ('GET' | 'POST' | 'PUT' | 'DELETE'),
29
+ params?: { [k in string]: any },
30
+ headers?: { [k in string]: any },
31
+ responseType?: 'Text' | 'JSON',
32
+ },
33
+ ): Promise<{
34
+ body: any,
35
+ status: number,
36
+ headers: { [k in string]: any },
37
+ }> => {
38
+ // Process method
39
+ const method: ('GET' | 'POST' | 'PUT' | 'DELETE') = (opts.method || 'GET');
40
+
41
+ // Encode objects within params
42
+ let params: {
43
+ [k in string]: any
44
+ } | undefined;
45
+ if (opts.params) {
46
+ params = {};
47
+ Object.entries(opts.params).forEach(([key, val]) => {
48
+ if (typeof val === 'object' && !Array.isArray(val)) {
49
+ (params as any)[key] = JSON.stringify(val);
50
+ } else {
51
+ (params as any)[key] = val;
52
+ }
53
+ });
54
+ }
55
+
56
+ // Stringify parameters
57
+ const stringifiedParams = qs.stringify(params || {}, {
58
+ encodeValuesOnly: true,
59
+ arrayFormat: 'brackets',
60
+ });
61
+
62
+ // Create url (include query if GET)
63
+ const query = (method === 'GET' ? `?${stringifiedParams}` : '');
64
+ let url;
65
+ if (!opts.host) {
66
+ // No host included at all. Just send to a path
67
+ url = `${opts.path}${query}`;
68
+ } else {
69
+ url = `https://${opts.host}${opts.path}${query}`;
70
+ }
71
+
72
+ // Update headers
73
+ const headers = opts.headers || {};
74
+ let data: string | null | { [k: string]: any } | undefined = null;
75
+ if (!headers['Content-Type']) {
76
+ // Form encoded
77
+ headers['Content-Type'] = 'application/x-www-form-urlencoded';
78
+ // Add data if applicable
79
+ data = (method !== 'GET' ? stringifiedParams : null);
80
+ } else {
81
+ // JSON encode
82
+ data = params;
83
+ }
84
+
85
+ // Encode data
86
+ let encodedData: URLSearchParams | string | undefined;
87
+ if (data) {
88
+ if (headers['Content-Type'] === 'application/x-www-form-urlencoded') {
89
+ encodedData = new URLSearchParams(params);
90
+ } else {
91
+ encodedData = JSON.stringify(data);
92
+ }
93
+ }
94
+
95
+ // Send request
96
+ try {
97
+ const response = await fetch(
98
+ url,
99
+ {
100
+ method,
101
+ mode: 'cors',
102
+ headers: headers ?? {},
103
+ body: (
104
+ (method !== 'GET' && encodedData)
105
+ ? encodedData
106
+ : undefined
107
+ ),
108
+ redirect: 'follow',
109
+ },
110
+ );
111
+
112
+ // Get headers map
113
+ const responseHeaders: {
114
+ [k in string]: string
115
+ } = {};
116
+ response.headers.forEach((value, key) => {
117
+ responseHeaders[key] = value;
118
+ });
119
+
120
+ // Process response based on responseType
121
+ try {
122
+ // Parse response
123
+ let responseBody: any;
124
+ if (
125
+ opts.responseType
126
+ && opts.responseType === 'Text'
127
+ ) {
128
+ // Response type is text
129
+ responseBody = await response.text();
130
+ } else {
131
+ // Response type is JSON
132
+ responseBody = await response.json();
133
+ }
134
+
135
+ // Return response
136
+ return {
137
+ body: responseBody,
138
+ status: response.status,
139
+ headers: responseHeaders,
140
+ };
141
+ } catch (err) {
142
+ throw new ErrorWithCode(
143
+ `Failed to parse response as ${opts.responseType}: ${(err as any)?.message}`,
144
+ ReactKitErrorCode.ResponseParseError,
145
+ );
146
+ }
147
+ } catch (err) {
148
+ // Self-signed certificate error:
149
+ if ((err as any)?.message?.includes('self signed certificate')) {
150
+ throw new ErrorWithCode(
151
+ 'We refused to send a request because the receiver has self-signed certificates.',
152
+ ReactKitErrorCode.SelfSigned,
153
+ );
154
+ }
155
+
156
+ // No tries left
157
+ throw new ErrorWithCode(
158
+ `We encountered an error when trying to send a network request. If this issue persists, contact an admin. Error: ${(err as any)?.message}`,
159
+ ReactKitErrorCode.NotConnected,
160
+ );
161
+ }
162
+ };
163
+
164
+ export default sendServerToServerRequest;
package/src/index.ts CHANGED
@@ -28,6 +28,7 @@ import Tooltip from './components/Tooltip';
28
28
  import ToggleSwitch from './components/ToggleSwitch';
29
29
  import AutoscrollToBottomContainer from './components/AutoscrollToBottomContainer';
30
30
  import MultiSwitch from './components/MultiSwitch';
31
+ import Dropdown from './components/Dropdown';
31
32
 
32
33
  // Import errors
33
34
  import ErrorWithCode from './errors/ErrorWithCode';
@@ -92,6 +93,7 @@ import mapAsync from './helpers/asyncArrayFunctions/mapAsync';
92
93
  import someAsync from './helpers/asyncArrayFunctions/someAsync';
93
94
  import capitalize from './helpers/capitalize';
94
95
  import shuffleArray from './helpers/shuffleArray';
96
+ import visitEndpointOnAnotherServer from './helpers/visitEndpointOnAnotherServer';
95
97
 
96
98
  // Import types
97
99
  import ModalButtonType from './types/ModalButtonType';
@@ -109,6 +111,7 @@ import LogBuiltInMetadata from './types/LogBuiltInMetadata';
109
111
  import LogMetadataType from './types/LogMetadataType';
110
112
  import LogFunction from './types/LogFunction';
111
113
  import IntelliTableColumn from './types/IntelliTableColumn';
114
+ import DropdownItemType from './types/DropdownItemType';
112
115
 
113
116
  // Component-specific-types
114
117
  import PickableItem from './components/ItemPicker/types/PickableItem';
@@ -142,6 +145,7 @@ export {
142
145
  ToggleSwitch,
143
146
  AutoscrollToBottomContainer,
144
147
  MultiSwitch,
148
+ Dropdown,
145
149
  // Global functions
146
150
  alert,
147
151
  confirm,
@@ -211,6 +215,7 @@ export {
211
215
  handleSuccess,
212
216
  initLogCollection,
213
217
  addDBEditorEndpoints,
218
+ visitEndpointOnAnotherServer,
214
219
  // Types
215
220
  ModalButtonType,
216
221
  ModalSize,
@@ -226,6 +231,7 @@ export {
226
231
  LogMetadataType,
227
232
  LogFunction,
228
233
  IntelliTableColumn,
234
+ DropdownItemType,
229
235
  // Component-specific-types
230
236
  PickableItem,
231
237
  DBEntry,
@@ -0,0 +1,11 @@
1
+ // Types of dropdown items
2
+ enum DropdownItemType {
3
+ // Dropdown header
4
+ Header = 'Header',
5
+ // Dropdown divider
6
+ Divider = 'Divider',
7
+ // Dropdown item
8
+ Item = 'Item',
9
+ }
10
+
11
+ export default DropdownItemType;
@@ -1,4 +1,4 @@
1
- // Highest error code = DRK13
1
+ // Highest error code = DRK16
2
2
 
3
3
  /**
4
4
  * List of error codes built into the react kit
@@ -18,6 +18,11 @@ enum ReactKitErrorCode {
18
18
  NotAllowedToReviewLogs = 'DRK11',
19
19
  ThemeCheckedBeforeReactKitReady = 'DRK12',
20
20
  SessionExpiredMessageGottenBeforeReactKitReady = 'DRK13',
21
+
22
+ // Server-to-server requests
23
+ NotConnected = 'DRK14',
24
+ SelfSigned = 'DRK15',
25
+ ResponseParseError = 'DRK16',
21
26
  }
22
27
 
23
28
  export default ReactKitErrorCode;