dce-reactkit 3.12.1-beta-cross-server.8 → 4.0.0-beta-date-and-time.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/.vscode/settings.json +3 -1
- package/README.md +0 -20
- package/dist/cjs/index.js +7838 -15905
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/ItemPicker/index.d.ts +1 -0
- package/dist/cjs/types/components/LoadingSpinner.d.ts +2 -2
- package/dist/cjs/types/components/Modal/ModalProps.d.ts +2 -0
- package/dist/cjs/types/components/SimpleDateChooser.d.ts +3 -1
- package/dist/cjs/types/components/SimpleTimeChooser.d.ts +20 -0
- package/dist/cjs/types/components/TabBox.d.ts +1 -0
- package/dist/cjs/types/components/Tooltip.d.ts +1 -1
- package/dist/cjs/types/helpers/getWordCount.d.ts +10 -0
- package/dist/cjs/types/index.d.ts +13 -13
- package/dist/cjs/types/types/ParamType.d.ts +10 -10
- package/dist/cjs/types/types/ReactKitErrorCode.d.ts +2 -28
- package/dist/esm/index.js +6661 -14723
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/ItemPicker/index.d.ts +1 -0
- package/dist/esm/types/components/LoadingSpinner.d.ts +2 -2
- package/dist/esm/types/components/Modal/ModalProps.d.ts +2 -0
- package/dist/esm/types/components/SimpleDateChooser.d.ts +3 -1
- package/dist/esm/types/components/SimpleTimeChooser.d.ts +20 -0
- package/dist/esm/types/components/TabBox.d.ts +1 -0
- package/dist/esm/types/components/Tooltip.d.ts +1 -1
- package/dist/esm/types/helpers/getWordCount.d.ts +10 -0
- package/dist/esm/types/index.d.ts +13 -13
- package/dist/esm/types/types/ParamType.d.ts +10 -10
- package/dist/esm/types/types/ReactKitErrorCode.d.ts +2 -28
- package/dist/index.d.ts +189 -379
- package/package.json +5 -11
- package/src/components/AppWrapper.tsx +3 -1
- package/src/components/CheckboxButton.tsx +1 -1
- package/src/components/Dropdown.tsx +1 -1
- package/src/components/IntelliTable.tsx +1 -1
- package/src/components/ItemPicker/NestableItemList.tsx +1 -0
- package/src/components/ItemPicker/index.tsx +96 -0
- package/src/components/LogReviewer.tsx +2 -2
- package/src/components/Modal/ModalProps.ts +4 -0
- package/src/components/Modal/index.tsx +60 -21
- package/src/components/RadioButton.tsx +3 -1
- package/src/components/SimpleDateChooser.tsx +62 -26
- package/src/components/SimpleTimeChooser.tsx +195 -0
- package/src/components/TabBox.tsx +27 -9
- package/src/components/Tooltip.tsx +1 -1
- package/src/helpers/getWordCount.ts +26 -0
- package/src/{client → helpers}/initClient.tsx +5 -1
- package/src/helpers/logClientEvent.tsx +3 -1
- package/src/helpers/visitServerEndpoint.tsx +1 -1
- package/src/index.ts +22 -24
- package/src/types/ParamType.ts +10 -10
- package/src/types/ReactKitErrorCode.tsx +3 -31
- package/dist/cjs/types/components/ItemPicker/index.test.d.ts +0 -1
- package/dist/cjs/types/helpers/addDBEditorEndpoints.d.ts +0 -41
- package/dist/cjs/types/helpers/dataSigner.d.ts +0 -40
- package/dist/cjs/types/helpers/genRouteHandler.d.ts +0 -76
- package/dist/cjs/types/helpers/handleError.d.ts +0 -18
- package/dist/cjs/types/helpers/handleSuccess.d.ts +0 -8
- package/dist/cjs/types/helpers/parseUserAgent.d.ts +0 -17
- package/dist/cjs/types/helpers/visitEndpointOnAnotherServer/index.d.ts +0 -20
- package/dist/cjs/types/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.d.ts +0 -27
- package/dist/cjs/types/server/initCrossServerCredentialCollection.d.ts +0 -8
- package/dist/cjs/types/server/initLogCollection.d.ts +0 -8
- package/dist/cjs/types/server/initServer.d.ts +0 -53
- package/dist/cjs/types/types/CrossServerCredential.d.ts +0 -11
- package/dist/esm/types/components/ItemPicker/index.test.d.ts +0 -1
- package/dist/esm/types/helpers/addDBEditorEndpoints.d.ts +0 -41
- package/dist/esm/types/helpers/dataSigner.d.ts +0 -40
- package/dist/esm/types/helpers/genRouteHandler.d.ts +0 -76
- package/dist/esm/types/helpers/handleError.d.ts +0 -18
- package/dist/esm/types/helpers/handleSuccess.d.ts +0 -8
- package/dist/esm/types/helpers/parseUserAgent.d.ts +0 -17
- package/dist/esm/types/helpers/visitEndpointOnAnotherServer/index.d.ts +0 -20
- package/dist/esm/types/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.d.ts +0 -27
- package/dist/esm/types/server/initCrossServerCredentialCollection.d.ts +0 -8
- package/dist/esm/types/server/initLogCollection.d.ts +0 -8
- package/dist/esm/types/server/initServer.d.ts +0 -53
- package/dist/esm/types/types/CrossServerCredential.d.ts +0 -11
- package/src/components/ItemPicker/index.test.tsx +0 -783
- package/src/helpers/addDBEditorEndpoints.ts +0 -128
- package/src/helpers/dataSigner.ts +0 -342
- package/src/helpers/genRouteHandler.ts +0 -911
- package/src/helpers/handleError.ts +0 -65
- package/src/helpers/handleSuccess.ts +0 -18
- package/src/helpers/parseUserAgent.ts +0 -108
- package/src/helpers/visitEndpointOnAnotherServer/index.ts +0 -152
- package/src/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.ts +0 -162
- package/src/server/initCrossServerCredentialCollection.ts +0 -16
- package/src/server/initLogCollection.ts +0 -27
- package/src/server/initServer.ts +0 -305
- package/src/types/CrossServerCredential.ts +0 -16
- /package/dist/cjs/types/{client → helpers}/initClient.d.ts +0 -0
- /package/dist/esm/types/{client → helpers}/initClient.d.ts +0 -0
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
// Import shared types
|
|
2
|
-
import ReactKitErrorCode from '../types/ReactKitErrorCode';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Handle an error and respond to the client
|
|
6
|
-
* @author Gabe Abrams
|
|
7
|
-
* @param res express response
|
|
8
|
-
* @param error error info
|
|
9
|
-
* @param opts.err the error to send to the client
|
|
10
|
-
* or the error message
|
|
11
|
-
* @param [opts.code] an error code (only used if err.code is not
|
|
12
|
-
* included)
|
|
13
|
-
* @param [opts.status=500] the https status code to use
|
|
14
|
-
* defined)
|
|
15
|
-
*/
|
|
16
|
-
const handleError = (
|
|
17
|
-
res: any,
|
|
18
|
-
error: (
|
|
19
|
-
| {
|
|
20
|
-
message: any,
|
|
21
|
-
code?: string,
|
|
22
|
-
status?: number,
|
|
23
|
-
}
|
|
24
|
-
| Error
|
|
25
|
-
| string
|
|
26
|
-
| any
|
|
27
|
-
),
|
|
28
|
-
): undefined => {
|
|
29
|
-
// Get the error message
|
|
30
|
-
let message;
|
|
31
|
-
if (error && (error as any).message) {
|
|
32
|
-
message = (error.message || 'An unknown error occurred.');
|
|
33
|
-
} else if (typeof error === 'string') {
|
|
34
|
-
message = (
|
|
35
|
-
error.trim().length > 0
|
|
36
|
-
? error
|
|
37
|
-
: 'An unknown error occurred.'
|
|
38
|
-
);
|
|
39
|
-
} else {
|
|
40
|
-
message = 'An unknown error occurred.';
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Get the error code
|
|
44
|
-
const code = (error.code || ReactKitErrorCode.NoCode);
|
|
45
|
-
|
|
46
|
-
// Get the status code
|
|
47
|
-
const status = (error.status || 500);
|
|
48
|
-
|
|
49
|
-
// Respond to user
|
|
50
|
-
res
|
|
51
|
-
// Set the http status code
|
|
52
|
-
.status(status)
|
|
53
|
-
// Send a JSON response
|
|
54
|
-
.json({
|
|
55
|
-
// Error message
|
|
56
|
-
message,
|
|
57
|
-
// Error code
|
|
58
|
-
code,
|
|
59
|
-
// Success = false flag so client can detect server-side errors
|
|
60
|
-
success: false,
|
|
61
|
-
});
|
|
62
|
-
return undefined;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export default handleError;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Send successful API response
|
|
3
|
-
* @author Gabe Abrams
|
|
4
|
-
* @param res express response
|
|
5
|
-
* @param body the body of the response to send to the client
|
|
6
|
-
*/
|
|
7
|
-
const handleSuccess = (res: any, body: any): undefined => {
|
|
8
|
-
// Send a http 200 json response
|
|
9
|
-
res.json({
|
|
10
|
-
// Include the body as a parameter
|
|
11
|
-
body,
|
|
12
|
-
// Success = true flag so client can detect successful responses
|
|
13
|
-
success: true,
|
|
14
|
-
});
|
|
15
|
-
return undefined;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export default handleSuccess;
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Perform a rudimentary parsing of the user's browser agent string
|
|
3
|
-
* @author Gabe Abrams
|
|
4
|
-
* @param userAgent the user's browser agent
|
|
5
|
-
* @returns user info
|
|
6
|
-
*/
|
|
7
|
-
const parseUserAgent = (userAgent: string) => {
|
|
8
|
-
/* ------------- Browser ------------ */
|
|
9
|
-
|
|
10
|
-
let browser: { name: string, version: string } = {
|
|
11
|
-
name: 'Unknown',
|
|
12
|
-
version: 'Unknown',
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
// Parse user agent
|
|
16
|
-
let verOffset: number;
|
|
17
|
-
let nameOffset: number;
|
|
18
|
-
if ((verOffset = userAgent.indexOf('Opera')) !== -1) {
|
|
19
|
-
// In Opera, the true version is after 'Opera' or after 'Version'
|
|
20
|
-
browser = {
|
|
21
|
-
name: 'Opera',
|
|
22
|
-
version: userAgent.substring(verOffset + 6),
|
|
23
|
-
};
|
|
24
|
-
if ((verOffset = userAgent.indexOf('Version')) !== -1) {
|
|
25
|
-
browser.version = userAgent.substring(verOffset + 8);
|
|
26
|
-
}
|
|
27
|
-
} else if ((verOffset = userAgent.indexOf('MSIE')) !== -1) {
|
|
28
|
-
// In MSIE, the true version is after 'MSIE' in userAgent
|
|
29
|
-
browser = {
|
|
30
|
-
name: 'Internet Explorer',
|
|
31
|
-
version: userAgent.substring(verOffset + 5),
|
|
32
|
-
};
|
|
33
|
-
} else if ((verOffset = userAgent.indexOf('Chrome')) !== -1) {
|
|
34
|
-
// In Chrome, the true version is after 'Chrome'
|
|
35
|
-
browser = {
|
|
36
|
-
name: 'Chrome',
|
|
37
|
-
version: userAgent.substring(verOffset + 7),
|
|
38
|
-
};
|
|
39
|
-
} else if ((verOffset = userAgent.indexOf('Safari')) !== -1) {
|
|
40
|
-
// In Safari, the true version is after 'Safari' or after 'Version'
|
|
41
|
-
browser = {
|
|
42
|
-
name: 'Safari',
|
|
43
|
-
version: userAgent.substring(verOffset + 7),
|
|
44
|
-
};
|
|
45
|
-
if ((verOffset = userAgent.indexOf('Version')) !== -1) {
|
|
46
|
-
browser.version = userAgent.substring(verOffset + 8);
|
|
47
|
-
}
|
|
48
|
-
} else if ((verOffset = userAgent.indexOf('Firefox')) != -1) {
|
|
49
|
-
// In Firefox, the true version is after 'Firefox'
|
|
50
|
-
browser = {
|
|
51
|
-
name: 'Firefox',
|
|
52
|
-
version: userAgent.substring(verOffset + 8),
|
|
53
|
-
};
|
|
54
|
-
} else if (
|
|
55
|
-
(nameOffset = userAgent.lastIndexOf(' ') + 1)
|
|
56
|
-
< (verOffset = userAgent.lastIndexOf('/'))
|
|
57
|
-
) {
|
|
58
|
-
browser = {
|
|
59
|
-
name: userAgent.substring(nameOffset, verOffset),
|
|
60
|
-
version: userAgent.substring(verOffset + 1),
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Postprocess version
|
|
65
|
-
// trim the fullVersion string at semicolon/space if present
|
|
66
|
-
let ix: number;
|
|
67
|
-
if ((ix = browser.version.indexOf(';')) !== -1) {
|
|
68
|
-
browser.version = browser.version.substring(0, ix);
|
|
69
|
-
}
|
|
70
|
-
if ((ix = browser.version.indexOf(' ')) !== -1) {
|
|
71
|
-
browser.version = browser.version.substring(0, ix);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/* ------------- Device ------------- */
|
|
75
|
-
|
|
76
|
-
// Detect os
|
|
77
|
-
let os = 'Unknown';
|
|
78
|
-
if (userAgent.includes('Linux')) {
|
|
79
|
-
os = 'Linux';
|
|
80
|
-
} else if (userAgent.includes('like Mac')) {
|
|
81
|
-
os = 'iOS';
|
|
82
|
-
} else if (userAgent.includes('Mac')) {
|
|
83
|
-
os = 'Mac';
|
|
84
|
-
} else if (userAgent.includes('Android')) {
|
|
85
|
-
os = 'Android';
|
|
86
|
-
} else if (userAgent.includes('Win')) {
|
|
87
|
-
os = 'Win';
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Check if mobile
|
|
91
|
-
const isMobile = !!userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry)/);
|
|
92
|
-
|
|
93
|
-
// Device
|
|
94
|
-
const device = {
|
|
95
|
-
isMobile,
|
|
96
|
-
os,
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
/* ------------- Finish ------------- */
|
|
100
|
-
|
|
101
|
-
// Return info
|
|
102
|
-
return {
|
|
103
|
-
browser,
|
|
104
|
-
device,
|
|
105
|
-
};
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
export default parseUserAgent;
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
// Import data signer
|
|
2
|
-
import { signRequest } from '../dataSigner';
|
|
3
|
-
|
|
4
|
-
// Import shared types
|
|
5
|
-
import ErrorWithCode from '../../errors/ErrorWithCode';
|
|
6
|
-
import ReactKitErrorCode from '../../types/ReactKitErrorCode';
|
|
7
|
-
import sendServerToServerRequest from './sendServerToServerRequest';
|
|
8
|
-
|
|
9
|
-
/*------------------------------------------------------------------------*/
|
|
10
|
-
/* ----------------------------- Credentials ---------------------------- */
|
|
11
|
-
/*------------------------------------------------------------------------*/
|
|
12
|
-
|
|
13
|
-
/*
|
|
14
|
-
REACTKIT_CROSS_SERVER_CREDENTIALS format:
|
|
15
|
-
|host:key:secret||host:key:secret|...
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
const credentials: {
|
|
19
|
-
host: string,
|
|
20
|
-
key: string,
|
|
21
|
-
secret: string,
|
|
22
|
-
}[] = (
|
|
23
|
-
(process.env.REACTKIT_CROSS_SERVER_CREDENTIALS ?? '')
|
|
24
|
-
// Replace multiple | with a single one
|
|
25
|
-
.replace(/\|+/g, '|')
|
|
26
|
-
// Split by |
|
|
27
|
-
.split('|')
|
|
28
|
-
// Remove empty strings
|
|
29
|
-
.filter((str) => {
|
|
30
|
-
return str.trim().length > 0;
|
|
31
|
-
})
|
|
32
|
-
// Process each credential
|
|
33
|
-
.map((str) => {
|
|
34
|
-
// Split by :
|
|
35
|
-
const parts = str.split(':');
|
|
36
|
-
|
|
37
|
-
// Check for errors
|
|
38
|
-
if (parts.length !== 3) {
|
|
39
|
-
throw new ErrorWithCode(
|
|
40
|
-
'Invalid REACTKIT_CROSS_SERVER_CREDENTIALS format. Each credential must be in the format |host:key:secret|',
|
|
41
|
-
ReactKitErrorCode.InvalidCrossServerCredentialsFormat,
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Return the credential
|
|
46
|
-
return {
|
|
47
|
-
host: parts[0].trim(),
|
|
48
|
-
key: parts[1].trim(),
|
|
49
|
-
secret: parts[2].trim(),
|
|
50
|
-
};
|
|
51
|
-
})
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
/*------------------------------------------------------------------------*/
|
|
55
|
-
/* ------------------------------- Helpers ------------------------------ */
|
|
56
|
-
/*------------------------------------------------------------------------*/
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Get the credential to use for the request to another server
|
|
60
|
-
* @author Gabe Abrams
|
|
61
|
-
* @param host the host of the other server
|
|
62
|
-
* @return the credential to use
|
|
63
|
-
*/
|
|
64
|
-
const getCrossServerCredential = (host: string) => {
|
|
65
|
-
// Find the credential
|
|
66
|
-
const credential = credentials.find((cred) => {
|
|
67
|
-
return cred.host.toLowerCase() === host.toLowerCase();
|
|
68
|
-
});
|
|
69
|
-
if (!credential) {
|
|
70
|
-
throw new ErrorWithCode(
|
|
71
|
-
'Cannot send cross-server signed request there was no credential that matched the host that the request is being sent to.',
|
|
72
|
-
ReactKitErrorCode.CrossServerNoCredentialsToSignWith,
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Return credential
|
|
77
|
-
return credential;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
/*------------------------------------------------------------------------*/
|
|
81
|
-
/* -------------------------------- Main -------------------------------- */
|
|
82
|
-
/*------------------------------------------------------------------------*/
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Visit an endpoint on another server
|
|
86
|
-
* @author Gabe Abrams
|
|
87
|
-
* @param opts object containing all arguments
|
|
88
|
-
* @param opts.method the method of the endpoint
|
|
89
|
-
* @param opts.path the path of the other server's endpoint
|
|
90
|
-
* @param opts.host the host of the other server
|
|
91
|
-
* @param [opts.params={}] query/body parameters to include
|
|
92
|
-
* @param [opts.responseType=JSON] the response type from the other server
|
|
93
|
-
*/
|
|
94
|
-
const visitEndpointOnAnotherServer = async (
|
|
95
|
-
opts: {
|
|
96
|
-
method: 'GET' | 'POST' | 'DELETE' | 'PUT',
|
|
97
|
-
path: string,
|
|
98
|
-
host: string,
|
|
99
|
-
params?: { [key in string]: any },
|
|
100
|
-
responseType?: 'JSON' | 'Text',
|
|
101
|
-
},
|
|
102
|
-
): Promise<any> => {
|
|
103
|
-
// Get cross-server credential
|
|
104
|
-
const credential = getCrossServerCredential(opts.host);
|
|
105
|
-
|
|
106
|
-
// Sign the request, get new params
|
|
107
|
-
const augmentedParams = await signRequest({
|
|
108
|
-
method: opts.method,
|
|
109
|
-
path: opts.path,
|
|
110
|
-
params: opts.params ?? {},
|
|
111
|
-
key: credential.key,
|
|
112
|
-
secret: credential.secret,
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
// Send the request
|
|
116
|
-
const response = await sendServerToServerRequest({
|
|
117
|
-
path: opts.path,
|
|
118
|
-
host: opts.host,
|
|
119
|
-
method: opts.method,
|
|
120
|
-
params: augmentedParams,
|
|
121
|
-
responseType: opts.responseType,
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
// Check for failure
|
|
125
|
-
if (!response || !response.body) {
|
|
126
|
-
throw new ErrorWithCode(
|
|
127
|
-
'We didn\'t get a response from the other server. Please check the network between the two connection.',
|
|
128
|
-
ReactKitErrorCode.NoResponse,
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
if (!response.body.success) {
|
|
132
|
-
// Other errors
|
|
133
|
-
throw new ErrorWithCode(
|
|
134
|
-
(
|
|
135
|
-
response.body.message
|
|
136
|
-
|| 'An unknown error occurred. Please contact an admin.'
|
|
137
|
-
),
|
|
138
|
-
(
|
|
139
|
-
response.body.code
|
|
140
|
-
|| ReactKitErrorCode.NoCode
|
|
141
|
-
),
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Success! Extract the body
|
|
146
|
-
const { body } = response.body;
|
|
147
|
-
|
|
148
|
-
// Return
|
|
149
|
-
return body;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
export default visitEndpointOnAnotherServer;
|
|
@@ -1,162 +0,0 @@
|
|
|
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.responseType=JSON] expected response type
|
|
19
|
-
* @returns { body, status, headers } on success
|
|
20
|
-
*/
|
|
21
|
-
const sendServerToServerRequest = async (
|
|
22
|
-
opts: {
|
|
23
|
-
path: string,
|
|
24
|
-
host?: string,
|
|
25
|
-
method?: ('GET' | 'POST' | 'PUT' | 'DELETE'),
|
|
26
|
-
params?: { [k in string]: any },
|
|
27
|
-
responseType?: 'Text' | 'JSON',
|
|
28
|
-
},
|
|
29
|
-
): Promise<{
|
|
30
|
-
body: any,
|
|
31
|
-
status: number,
|
|
32
|
-
headers: { [k in string]: any },
|
|
33
|
-
}> => {
|
|
34
|
-
// Process method
|
|
35
|
-
const method: ('GET' | 'POST' | 'PUT' | 'DELETE') = (opts.method || 'GET');
|
|
36
|
-
|
|
37
|
-
// Encode objects within params
|
|
38
|
-
let params: {
|
|
39
|
-
[k in string]: any
|
|
40
|
-
} | undefined;
|
|
41
|
-
if (opts.params) {
|
|
42
|
-
params = {};
|
|
43
|
-
Object.entries(opts.params).forEach(([key, val]) => {
|
|
44
|
-
if (typeof val === 'object' && !Array.isArray(val)) {
|
|
45
|
-
(params as any)[key] = JSON.stringify(val);
|
|
46
|
-
} else {
|
|
47
|
-
(params as any)[key] = val;
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Stringify parameters
|
|
53
|
-
const stringifiedParams = qs.stringify(params || {}, {
|
|
54
|
-
encodeValuesOnly: true,
|
|
55
|
-
arrayFormat: 'brackets',
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
// Create url (include query if GET)
|
|
59
|
-
const query = (method === 'GET' ? `?${stringifiedParams}` : '');
|
|
60
|
-
let url;
|
|
61
|
-
if (!opts.host) {
|
|
62
|
-
// No host included at all. Just send to a path
|
|
63
|
-
url = `${opts.path}${query}`;
|
|
64
|
-
} else {
|
|
65
|
-
url = `https://${opts.host}${opts.path}${query}`;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Update headers
|
|
69
|
-
const headers: {
|
|
70
|
-
[k: string]: any,
|
|
71
|
-
} = {};
|
|
72
|
-
let data: string | null | { [k: string]: any } | undefined = null;
|
|
73
|
-
if (!headers['Content-Type']) {
|
|
74
|
-
// Form encoded
|
|
75
|
-
headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
|
76
|
-
// Add data if applicable
|
|
77
|
-
data = (method !== 'GET' ? stringifiedParams : null);
|
|
78
|
-
} else {
|
|
79
|
-
// JSON encode
|
|
80
|
-
data = params;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Encode data
|
|
84
|
-
let encodedData: URLSearchParams | string | undefined;
|
|
85
|
-
if (data) {
|
|
86
|
-
if (headers['Content-Type'] === 'application/x-www-form-urlencoded') {
|
|
87
|
-
encodedData = new URLSearchParams(params);
|
|
88
|
-
} else {
|
|
89
|
-
encodedData = JSON.stringify(data);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Send request
|
|
94
|
-
try {
|
|
95
|
-
const response = await fetch(
|
|
96
|
-
url,
|
|
97
|
-
{
|
|
98
|
-
method,
|
|
99
|
-
mode: 'cors',
|
|
100
|
-
headers: headers ?? {},
|
|
101
|
-
body: (
|
|
102
|
-
(method !== 'GET' && encodedData)
|
|
103
|
-
? encodedData
|
|
104
|
-
: undefined
|
|
105
|
-
),
|
|
106
|
-
redirect: 'follow',
|
|
107
|
-
},
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
// Get headers map
|
|
111
|
-
const responseHeaders: {
|
|
112
|
-
[k in string]: string
|
|
113
|
-
} = {};
|
|
114
|
-
response.headers.forEach((value, key) => {
|
|
115
|
-
responseHeaders[key] = value;
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// Process response based on responseType
|
|
119
|
-
try {
|
|
120
|
-
// Parse response
|
|
121
|
-
let responseBody: any;
|
|
122
|
-
if (
|
|
123
|
-
opts.responseType
|
|
124
|
-
&& opts.responseType === 'Text'
|
|
125
|
-
) {
|
|
126
|
-
// Response type is text
|
|
127
|
-
responseBody = await response.text();
|
|
128
|
-
} else {
|
|
129
|
-
// Response type is JSON
|
|
130
|
-
responseBody = await response.json();
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Return response
|
|
134
|
-
return {
|
|
135
|
-
body: responseBody,
|
|
136
|
-
status: response.status,
|
|
137
|
-
headers: responseHeaders,
|
|
138
|
-
};
|
|
139
|
-
} catch (err) {
|
|
140
|
-
throw new ErrorWithCode(
|
|
141
|
-
`Failed to parse response as ${opts.responseType}: ${(err as any)?.message}`,
|
|
142
|
-
ReactKitErrorCode.ResponseParseError,
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
} catch (err) {
|
|
146
|
-
// Self-signed certificate error:
|
|
147
|
-
if ((err as any)?.message?.includes('self signed certificate')) {
|
|
148
|
-
throw new ErrorWithCode(
|
|
149
|
-
'We refused to send a request because the receiver has self-signed certificates.',
|
|
150
|
-
ReactKitErrorCode.SelfSigned,
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// No tries left
|
|
155
|
-
throw new ErrorWithCode(
|
|
156
|
-
`We encountered an error when trying to send a network request. If this issue persists, contact an admin. Error: ${(err as any)?.message}`,
|
|
157
|
-
ReactKitErrorCode.NotConnected,
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
export default sendServerToServerRequest;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Initialize a cross-server credential collection given the dce-mango Collection class
|
|
3
|
-
* @author Gabe Abrams
|
|
4
|
-
* @param Collection the Collection class from dce-mango
|
|
5
|
-
* @returns initialized logCollection
|
|
6
|
-
*/
|
|
7
|
-
const initCrossServerCredentialCollection = (Collection: any) => {
|
|
8
|
-
return new Collection(
|
|
9
|
-
'CrossServerCredential',
|
|
10
|
-
{
|
|
11
|
-
uniqueIndexKey: 'key',
|
|
12
|
-
},
|
|
13
|
-
);
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export default initCrossServerCredentialCollection;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Initialize a log collection given the dce-mango Collection class
|
|
3
|
-
* @author Gabe Abrams
|
|
4
|
-
* @param Collection the Collection class from dce-mango
|
|
5
|
-
* @returns initialized logCollection
|
|
6
|
-
*/
|
|
7
|
-
const initLogCollection = (Collection: any) => {
|
|
8
|
-
return new Collection(
|
|
9
|
-
'Log',
|
|
10
|
-
{
|
|
11
|
-
uniqueIndexKey: 'id',
|
|
12
|
-
indexKeys: [
|
|
13
|
-
'courseId',
|
|
14
|
-
'context',
|
|
15
|
-
'subcontext',
|
|
16
|
-
'tags',
|
|
17
|
-
'year',
|
|
18
|
-
'month',
|
|
19
|
-
'day',
|
|
20
|
-
'hour',
|
|
21
|
-
'type',
|
|
22
|
-
],
|
|
23
|
-
},
|
|
24
|
-
);
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export default initLogCollection;
|