dce-reactkit 3.8.5 → 3.8.7

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.
@@ -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';
@@ -109,6 +110,7 @@ import LogBuiltInMetadata from './types/LogBuiltInMetadata';
109
110
  import LogMetadataType from './types/LogMetadataType';
110
111
  import LogFunction from './types/LogFunction';
111
112
  import IntelliTableColumn from './types/IntelliTableColumn';
113
+ import DropdownItemType from './types/DropdownItemType';
112
114
 
113
115
  // Component-specific-types
114
116
  import PickableItem from './components/ItemPicker/types/PickableItem';
@@ -142,6 +144,7 @@ export {
142
144
  ToggleSwitch,
143
145
  AutoscrollToBottomContainer,
144
146
  MultiSwitch,
147
+ Dropdown,
145
148
  // Global functions
146
149
  alert,
147
150
  confirm,
@@ -226,6 +229,7 @@ export {
226
229
  LogMetadataType,
227
230
  LogFunction,
228
231
  IntelliTableColumn,
232
+ DropdownItemType,
229
233
  // Component-specific-types
230
234
  PickableItem,
231
235
  DBEntry,
@@ -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;