dce-expresskit 4.0.0-beta.10
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/.eslintrc.js +93 -0
- package/LICENSE +21 -0
- package/README.md +17 -0
- package/genEncodedSecret.ts +107 -0
- package/genSalt.ts +15 -0
- package/lib/constants/LOG_REVIEW_ROUTE_PATH_PREFIX.d.ts +6 -0
- package/lib/constants/LOG_REVIEW_ROUTE_PATH_PREFIX.js +13 -0
- package/lib/constants/LOG_REVIEW_ROUTE_PATH_PREFIX.js.map +1 -0
- package/lib/constants/LOG_REVIEW_STATUS_ROUTE.d.ts +7 -0
- package/lib/constants/LOG_REVIEW_STATUS_ROUTE.js +14 -0
- package/lib/constants/LOG_REVIEW_STATUS_ROUTE.js.map +1 -0
- package/lib/constants/LOG_ROUTE_PATH.d.ts +6 -0
- package/lib/constants/LOG_ROUTE_PATH.js +13 -0
- package/lib/constants/LOG_ROUTE_PATH.js.map +1 -0
- package/lib/constants/ROUTE_PATH_PREFIX.d.ts +6 -0
- package/lib/constants/ROUTE_PATH_PREFIX.js +9 -0
- package/lib/constants/ROUTE_PATH_PREFIX.js.map +1 -0
- package/lib/errors/ErrorWithCode.d.ts +9 -0
- package/lib/errors/ErrorWithCode.js +33 -0
- package/lib/errors/ErrorWithCode.js.map +1 -0
- package/lib/helpers/addDBEditorEndpoints/generateEndpointPath.d.ts +9 -0
- package/lib/helpers/addDBEditorEndpoints/generateEndpointPath.js +17 -0
- package/lib/helpers/addDBEditorEndpoints/generateEndpointPath.js.map +1 -0
- package/lib/helpers/addDBEditorEndpoints/index.d.ts +41 -0
- package/lib/helpers/addDBEditorEndpoints/index.js +134 -0
- package/lib/helpers/addDBEditorEndpoints/index.js.map +1 -0
- package/lib/helpers/dataSigner.d.ts +40 -0
- package/lib/helpers/dataSigner.js +236 -0
- package/lib/helpers/dataSigner.js.map +1 -0
- package/lib/helpers/genRouteHandler.d.ts +75 -0
- package/lib/helpers/genRouteHandler.js +661 -0
- package/lib/helpers/genRouteHandler.js.map +1 -0
- package/lib/helpers/handleError.d.ts +18 -0
- package/lib/helpers/handleError.js +51 -0
- package/lib/helpers/handleError.js.map +1 -0
- package/lib/helpers/handleSuccess.d.ts +8 -0
- package/lib/helpers/handleSuccess.js +20 -0
- package/lib/helpers/handleSuccess.js.map +1 -0
- package/lib/helpers/initCrossServerCredentialCollection.d.ts +11 -0
- package/lib/helpers/initCrossServerCredentialCollection.js +15 -0
- package/lib/helpers/initCrossServerCredentialCollection.js.map +1 -0
- package/lib/helpers/initLogCollection.d.ts +11 -0
- package/lib/helpers/initLogCollection.js +26 -0
- package/lib/helpers/initLogCollection.js.map +1 -0
- package/lib/helpers/initServer.d.ts +45 -0
- package/lib/helpers/initServer.js +293 -0
- package/lib/helpers/initServer.js.map +1 -0
- package/lib/helpers/parseUserAgent.d.ts +17 -0
- package/lib/helpers/parseUserAgent.js +108 -0
- package/lib/helpers/parseUserAgent.js.map +1 -0
- package/lib/helpers/visitEndpointOnAnotherServer/index.d.ts +18 -0
- package/lib/helpers/visitEndpointOnAnotherServer/index.js +156 -0
- package/lib/helpers/visitEndpointOnAnotherServer/index.js.map +1 -0
- package/lib/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.d.ts +23 -0
- package/lib/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.js +168 -0
- package/lib/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.js.map +1 -0
- package/lib/html/genErrorPage.d.ts +19 -0
- package/lib/html/genErrorPage.js +27 -0
- package/lib/html/genErrorPage.js.map +1 -0
- package/lib/html/genInfoPage.d.ts +13 -0
- package/lib/html/genInfoPage.js +16 -0
- package/lib/html/genInfoPage.js.map +1 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.js +68 -0
- package/lib/index.js.map +1 -0
- package/lib/types/CrossServerCredential.d.ts +11 -0
- package/lib/types/CrossServerCredential.js +3 -0
- package/lib/types/CrossServerCredential.js.map +1 -0
- package/lib/types/ExpressKitErrorCode.d.ts +31 -0
- package/lib/types/ExpressKitErrorCode.js +38 -0
- package/lib/types/ExpressKitErrorCode.js.map +1 -0
- package/package.json +53 -0
- package/src/constants/LOG_REVIEW_ROUTE_PATH_PREFIX.ts +9 -0
- package/src/constants/LOG_REVIEW_STATUS_ROUTE.ts +10 -0
- package/src/constants/LOG_ROUTE_PATH.ts +9 -0
- package/src/constants/ROUTE_PATH_PREFIX.ts +7 -0
- package/src/errors/ErrorWithCode.tsx +15 -0
- package/src/helpers/addDBEditorEndpoints/generateEndpointPath.ts +16 -0
- package/src/helpers/addDBEditorEndpoints/index.ts +130 -0
- package/src/helpers/dataSigner.ts +306 -0
- package/src/helpers/genRouteHandler.ts +914 -0
- package/src/helpers/handleError.ts +66 -0
- package/src/helpers/handleSuccess.ts +18 -0
- package/src/helpers/initCrossServerCredentialCollection.ts +19 -0
- package/src/helpers/initLogCollection.ts +31 -0
- package/src/helpers/initServer.ts +284 -0
- package/src/helpers/parseUserAgent.ts +108 -0
- package/src/helpers/visitEndpointOnAnotherServer/index.ts +157 -0
- package/src/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.ts +164 -0
- package/src/html/genErrorPage.ts +144 -0
- package/src/html/genInfoPage.ts +101 -0
- package/src/index.ts +125 -0
- package/src/types/CrossServerCredential.ts +16 -0
- package/src/types/ExpressKitErrorCode.ts +37 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// Import libs
|
|
2
|
+
import qs from 'qs';
|
|
3
|
+
|
|
4
|
+
// Import dce-reactkit
|
|
5
|
+
import {
|
|
6
|
+
ErrorWithCode,
|
|
7
|
+
} from 'dce-reactkit';
|
|
8
|
+
|
|
9
|
+
// Import shared types
|
|
10
|
+
import ExpressKitErrorCode from '../../types/ExpressKitErrorCode';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Sends and retries an http request
|
|
14
|
+
* @author Gabriel Abrams
|
|
15
|
+
* @param opts object containing all arguments
|
|
16
|
+
* @param opts.path path to send request to
|
|
17
|
+
* @param [opts.host] host to send request to
|
|
18
|
+
* @param [opts.method=GET] http method to use
|
|
19
|
+
* @param [opts.params] body/data to include in the request
|
|
20
|
+
* @param [opts.responseType=JSON] expected response type
|
|
21
|
+
* @returns { body, status, headers } on success
|
|
22
|
+
*/
|
|
23
|
+
const sendServerToServerRequest = async (
|
|
24
|
+
opts: {
|
|
25
|
+
path: string,
|
|
26
|
+
host?: string,
|
|
27
|
+
method?: ('GET' | 'POST' | 'PUT' | 'DELETE'),
|
|
28
|
+
params?: { [k in string]: any },
|
|
29
|
+
responseType?: 'Text' | 'JSON',
|
|
30
|
+
},
|
|
31
|
+
): Promise<{
|
|
32
|
+
body: any,
|
|
33
|
+
status: number,
|
|
34
|
+
headers: { [k in string]: any },
|
|
35
|
+
}> => {
|
|
36
|
+
// Process method
|
|
37
|
+
const method: ('GET' | 'POST' | 'PUT' | 'DELETE') = (opts.method || 'GET');
|
|
38
|
+
|
|
39
|
+
// Encode objects within params
|
|
40
|
+
let params: {
|
|
41
|
+
[k in string]: any
|
|
42
|
+
} | undefined;
|
|
43
|
+
if (opts.params) {
|
|
44
|
+
params = {};
|
|
45
|
+
Object.entries(opts.params).forEach(([key, val]) => {
|
|
46
|
+
if (typeof val === 'object' && !Array.isArray(val)) {
|
|
47
|
+
(params as any)[key] = JSON.stringify(val);
|
|
48
|
+
} else {
|
|
49
|
+
(params as any)[key] = val;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Stringify parameters
|
|
55
|
+
const stringifiedParams = qs.stringify(params || {}, {
|
|
56
|
+
encodeValuesOnly: true,
|
|
57
|
+
arrayFormat: 'brackets',
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Create url (include query if GET)
|
|
61
|
+
const query = (method === 'GET' ? `?${stringifiedParams}` : '');
|
|
62
|
+
let url;
|
|
63
|
+
if (!opts.host) {
|
|
64
|
+
// No host included at all. Just send to a path
|
|
65
|
+
url = `${opts.path}${query}`;
|
|
66
|
+
} else {
|
|
67
|
+
url = `https://${opts.host}${opts.path}${query}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Update headers
|
|
71
|
+
const headers: {
|
|
72
|
+
[k: string]: any,
|
|
73
|
+
} = {};
|
|
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
|
+
ExpressKitErrorCode.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
|
+
ExpressKitErrorCode.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
|
+
ExpressKitErrorCode.NotConnected,
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
export default sendServerToServerRequest;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// Import dce-reactkit
|
|
2
|
+
import { ReactKitErrorCode } from 'dce-reactkit';
|
|
3
|
+
|
|
4
|
+
// Import shared types
|
|
5
|
+
import ExpressKitErrorCode from '../types/ExpressKitErrorCode';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generate a static error page
|
|
9
|
+
* @author Gabe Abrams
|
|
10
|
+
* @param opts object containing all arguments
|
|
11
|
+
* @param [opts.title=An Error Occurred] title of the error box
|
|
12
|
+
* @param [opts.description=An unknown server error occurred. Please contact support.]
|
|
13
|
+
* a human-readable description of the error
|
|
14
|
+
* @param [opts.code=ReactKitErrorCode.NoCode] error code to show
|
|
15
|
+
* @param [opts.pageTitle=opts.title] title of the page/tab if it differs from
|
|
16
|
+
* the title of the error
|
|
17
|
+
* @returns html of the page
|
|
18
|
+
*/
|
|
19
|
+
const genErrorPage = (
|
|
20
|
+
opts: {
|
|
21
|
+
title?: string,
|
|
22
|
+
description?: string,
|
|
23
|
+
code?: string,
|
|
24
|
+
pageTitle?: string,
|
|
25
|
+
} = {},
|
|
26
|
+
): string => {
|
|
27
|
+
const title = (opts.title ?? 'An Error Occurred');
|
|
28
|
+
const pageTitle = (opts.pageTitle ?? title);
|
|
29
|
+
const description = (
|
|
30
|
+
opts.description
|
|
31
|
+
?? 'An unknown server error occurred. Please contact support.'
|
|
32
|
+
);
|
|
33
|
+
const code = (opts.code ?? ReactKitErrorCode.NoCode);
|
|
34
|
+
|
|
35
|
+
return `
|
|
36
|
+
<head>
|
|
37
|
+
<!-- Metadata -->
|
|
38
|
+
<meta
|
|
39
|
+
name="viewport"
|
|
40
|
+
content="width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0"
|
|
41
|
+
>
|
|
42
|
+
|
|
43
|
+
<!-- Title -->
|
|
44
|
+
<title>${pageTitle}</title>
|
|
45
|
+
|
|
46
|
+
<!-- Bootstrap -->
|
|
47
|
+
<link
|
|
48
|
+
rel="stylesheet"
|
|
49
|
+
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.1/css/bootstrap.min.css"
|
|
50
|
+
integrity="sha512-siwe/oXMhSjGCwLn+scraPOWrJxHlUgMBMZXdPe2Tnk3I0x3ESCoLz7WZ5NTH6SZrywMY+PB1cjyqJ5jAluCOg=="
|
|
51
|
+
crossorigin="anonymous"
|
|
52
|
+
referrerpolicy="no-referrer"
|
|
53
|
+
/>
|
|
54
|
+
<script
|
|
55
|
+
src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.1/js/bootstrap.min.js"
|
|
56
|
+
integrity="sha512-vyRAVI0IEm6LI/fVSv/Wq/d0KUfrg3hJq2Qz5FlfER69sf3ZHlOrsLriNm49FxnpUGmhx+TaJKwJ+ByTLKT+Yg=="
|
|
57
|
+
crossorigin="anonymous"
|
|
58
|
+
referrerpolicy="no-referrer"
|
|
59
|
+
></script>
|
|
60
|
+
|
|
61
|
+
<!-- FontAwesome -->
|
|
62
|
+
<link
|
|
63
|
+
rel="stylesheet"
|
|
64
|
+
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css"
|
|
65
|
+
integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A=="
|
|
66
|
+
crossorigin="anonymous"
|
|
67
|
+
referrerpolicy="no-referrer"
|
|
68
|
+
/>
|
|
69
|
+
|
|
70
|
+
<!-- Style -->
|
|
71
|
+
<style>
|
|
72
|
+
.DCEReactKit-pop-in {
|
|
73
|
+
animation-name: DCEReactKit-pop-in;
|
|
74
|
+
animation-duration: 0.5s;
|
|
75
|
+
animation-iteration-count: 1;
|
|
76
|
+
animation-timing-function: ease-out;
|
|
77
|
+
animation-fill-mode: both;
|
|
78
|
+
|
|
79
|
+
transform-origin: center;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@keyframes DCEReactKit-pop-in {
|
|
83
|
+
0% {
|
|
84
|
+
opacity: 0;
|
|
85
|
+
transform: scale(0.9);
|
|
86
|
+
}
|
|
87
|
+
100% {
|
|
88
|
+
opacity: 1;
|
|
89
|
+
transform: scale(1);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.DCEReactKit-slide-in {
|
|
94
|
+
animation-name: DCEReactKit-slide-in;
|
|
95
|
+
animation-duration: 1s;
|
|
96
|
+
animation-iteration-count: 1;
|
|
97
|
+
animation-timing-function: ease-out;
|
|
98
|
+
animation-fill-mode: both;
|
|
99
|
+
animation-delay: 0.2s;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@keyframes DCEReactKit-slide-in {
|
|
103
|
+
0% {
|
|
104
|
+
opacity: 0;
|
|
105
|
+
transform: translate(0, 0.3em);
|
|
106
|
+
}
|
|
107
|
+
100% {
|
|
108
|
+
opacity: 1;
|
|
109
|
+
transform: translate(0, 0);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
</style>
|
|
113
|
+
</head>
|
|
114
|
+
|
|
115
|
+
<!-- Body -->
|
|
116
|
+
<body class="bg-dark text-center pt-3 ps-3 pe-3">
|
|
117
|
+
<!-- Alert -->
|
|
118
|
+
<div
|
|
119
|
+
class="DCEReactKit-pop-in alert alert-warning d-inline-block"
|
|
120
|
+
style="width: 50em; max-width: 100%"
|
|
121
|
+
>
|
|
122
|
+
<!-- Title -->
|
|
123
|
+
<h2>
|
|
124
|
+
<i class="me-1 fa-solid fa-triangle-exclamation"></i>
|
|
125
|
+
${title}
|
|
126
|
+
</h2>
|
|
127
|
+
<!-- Description -->
|
|
128
|
+
<div>
|
|
129
|
+
${description}
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
<!-- Error Code -->
|
|
134
|
+
<div class="DCEReactKit-slide-in text-light">
|
|
135
|
+
<strong>
|
|
136
|
+
Error Code:
|
|
137
|
+
</strong>
|
|
138
|
+
${code}
|
|
139
|
+
</div>
|
|
140
|
+
</body>
|
|
141
|
+
`;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export default genErrorPage;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a static info page
|
|
3
|
+
* @author Gabe Abrams
|
|
4
|
+
* @param opts object containing all arguments
|
|
5
|
+
* @param opts.title title of the info box
|
|
6
|
+
* @param opts.body a human-readable text body for the info alert
|
|
7
|
+
* @returns the HTML for the info page
|
|
8
|
+
*/
|
|
9
|
+
const genInfoPage = (
|
|
10
|
+
opts: {
|
|
11
|
+
title: string,
|
|
12
|
+
body: string,
|
|
13
|
+
},
|
|
14
|
+
): string => {
|
|
15
|
+
const {
|
|
16
|
+
title,
|
|
17
|
+
body,
|
|
18
|
+
} = opts;
|
|
19
|
+
|
|
20
|
+
return `
|
|
21
|
+
<head>
|
|
22
|
+
<!-- Metadata -->
|
|
23
|
+
<meta
|
|
24
|
+
name="viewport"
|
|
25
|
+
content="width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0"
|
|
26
|
+
>
|
|
27
|
+
|
|
28
|
+
<!-- Title -->
|
|
29
|
+
<title>${title}</title>
|
|
30
|
+
|
|
31
|
+
<!-- Bootstrap -->
|
|
32
|
+
<link
|
|
33
|
+
rel="stylesheet"
|
|
34
|
+
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.1/css/bootstrap.min.css"
|
|
35
|
+
integrity="sha512-siwe/oXMhSjGCwLn+scraPOWrJxHlUgMBMZXdPe2Tnk3I0x3ESCoLz7WZ5NTH6SZrywMY+PB1cjyqJ5jAluCOg=="
|
|
36
|
+
crossorigin="anonymous"
|
|
37
|
+
referrerpolicy="no-referrer"
|
|
38
|
+
/>
|
|
39
|
+
<script
|
|
40
|
+
src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.1/js/bootstrap.min.js"
|
|
41
|
+
integrity="sha512-vyRAVI0IEm6LI/fVSv/Wq/d0KUfrg3hJq2Qz5FlfER69sf3ZHlOrsLriNm49FxnpUGmhx+TaJKwJ+ByTLKT+Yg=="
|
|
42
|
+
crossorigin="anonymous"
|
|
43
|
+
referrerpolicy="no-referrer"
|
|
44
|
+
></script>
|
|
45
|
+
|
|
46
|
+
<!-- FontAwesome -->
|
|
47
|
+
<link
|
|
48
|
+
rel="stylesheet"
|
|
49
|
+
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css"
|
|
50
|
+
integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A=="
|
|
51
|
+
crossorigin="anonymous"
|
|
52
|
+
referrerpolicy="no-referrer"
|
|
53
|
+
/>
|
|
54
|
+
|
|
55
|
+
<!-- Style -->
|
|
56
|
+
<style>
|
|
57
|
+
.DCEReactKit-pop-in {
|
|
58
|
+
animation-name: DCEReactKit-pop-in;
|
|
59
|
+
animation-duration: 0.5s;
|
|
60
|
+
animation-iteration-count: 1;
|
|
61
|
+
animation-timing-function: ease-out;
|
|
62
|
+
animation-fill-mode: both;
|
|
63
|
+
|
|
64
|
+
transform-origin: center;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@keyframes DCEReactKit-pop-in {
|
|
68
|
+
0% {
|
|
69
|
+
opacity: 0;
|
|
70
|
+
transform: scale(0.9);
|
|
71
|
+
}
|
|
72
|
+
100% {
|
|
73
|
+
opacity: 1;
|
|
74
|
+
transform: scale(1);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
</style>
|
|
78
|
+
</head>
|
|
79
|
+
|
|
80
|
+
<!-- Body -->
|
|
81
|
+
<body class="bg-dark text-center pt-3 ps-3 pe-3">
|
|
82
|
+
<!-- Alert -->
|
|
83
|
+
<div
|
|
84
|
+
class="DCEReactKit-pop-in alert alert-info d-inline-block"
|
|
85
|
+
style="width: 50em; max-width: 100%"
|
|
86
|
+
>
|
|
87
|
+
<!-- Title -->
|
|
88
|
+
<h2>
|
|
89
|
+
<i class="me-1 fa-solid fa-circle-info"></i>
|
|
90
|
+
${title}
|
|
91
|
+
</h2>
|
|
92
|
+
<!-- Body -->
|
|
93
|
+
<div>
|
|
94
|
+
${body}
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
</body>
|
|
98
|
+
`;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export default genInfoPage;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// Import dce-reactkit
|
|
2
|
+
import {
|
|
3
|
+
abbreviate,
|
|
4
|
+
avg,
|
|
5
|
+
ceilToNumDecimals,
|
|
6
|
+
floorToNumDecimals,
|
|
7
|
+
forceNumIntoBounds,
|
|
8
|
+
padDecimalZeros,
|
|
9
|
+
padZerosLeft,
|
|
10
|
+
roundToNumDecimals,
|
|
11
|
+
sum,
|
|
12
|
+
waitMs,
|
|
13
|
+
getOrdinal,
|
|
14
|
+
getTimeInfoInET,
|
|
15
|
+
startMinWait,
|
|
16
|
+
getHumanReadableDate,
|
|
17
|
+
getPartOfDay,
|
|
18
|
+
stringsToHumanReadableList,
|
|
19
|
+
onlyKeepLetters,
|
|
20
|
+
parallelLimit,
|
|
21
|
+
getMonthName,
|
|
22
|
+
genCSV,
|
|
23
|
+
extractProp,
|
|
24
|
+
compareArraysByProp,
|
|
25
|
+
getLocalTimeInfo,
|
|
26
|
+
genCommaList,
|
|
27
|
+
prefixWithAOrAn,
|
|
28
|
+
everyAsync,
|
|
29
|
+
filterAsync,
|
|
30
|
+
forEachAsync,
|
|
31
|
+
mapAsync,
|
|
32
|
+
someAsync,
|
|
33
|
+
capitalize,
|
|
34
|
+
shuffleArray,
|
|
35
|
+
DayOfWeek,
|
|
36
|
+
Log,
|
|
37
|
+
LogType,
|
|
38
|
+
LogSource,
|
|
39
|
+
LogAction,
|
|
40
|
+
LogBuiltInMetadata,
|
|
41
|
+
LogMetadataType,
|
|
42
|
+
LogFunction,
|
|
43
|
+
MINUTE_IN_MS,
|
|
44
|
+
HOUR_IN_MS,
|
|
45
|
+
DAY_IN_MS,
|
|
46
|
+
ErrorWithCode,
|
|
47
|
+
ParamType,
|
|
48
|
+
} from 'dce-reactkit';
|
|
49
|
+
|
|
50
|
+
// Import helpers
|
|
51
|
+
import initCrossServerCredentialCollection from './helpers/initCrossServerCredentialCollection';
|
|
52
|
+
import initLogCollection from './helpers/initLogCollection';
|
|
53
|
+
import initServer from './helpers/initServer';
|
|
54
|
+
import genRouteHandler from './helpers/genRouteHandler';
|
|
55
|
+
import handleError from './helpers/handleError';
|
|
56
|
+
import handleSuccess from './helpers/handleSuccess';
|
|
57
|
+
import addDBEditorEndpoints from './helpers/addDBEditorEndpoints';
|
|
58
|
+
import visitEndpointOnAnotherServer from './helpers/visitEndpointOnAnotherServer';
|
|
59
|
+
|
|
60
|
+
// Import types
|
|
61
|
+
import CrossServerCredential from './types/CrossServerCredential';
|
|
62
|
+
|
|
63
|
+
// Export each item
|
|
64
|
+
export {
|
|
65
|
+
// Errors
|
|
66
|
+
ErrorWithCode,
|
|
67
|
+
// Constants
|
|
68
|
+
MINUTE_IN_MS,
|
|
69
|
+
HOUR_IN_MS,
|
|
70
|
+
DAY_IN_MS,
|
|
71
|
+
// Helpers
|
|
72
|
+
abbreviate,
|
|
73
|
+
avg,
|
|
74
|
+
ceilToNumDecimals,
|
|
75
|
+
floorToNumDecimals,
|
|
76
|
+
forceNumIntoBounds,
|
|
77
|
+
padDecimalZeros,
|
|
78
|
+
padZerosLeft,
|
|
79
|
+
roundToNumDecimals,
|
|
80
|
+
sum,
|
|
81
|
+
waitMs,
|
|
82
|
+
getOrdinal,
|
|
83
|
+
getTimeInfoInET,
|
|
84
|
+
startMinWait,
|
|
85
|
+
getHumanReadableDate,
|
|
86
|
+
getPartOfDay,
|
|
87
|
+
stringsToHumanReadableList,
|
|
88
|
+
onlyKeepLetters,
|
|
89
|
+
parallelLimit,
|
|
90
|
+
getMonthName,
|
|
91
|
+
genCSV,
|
|
92
|
+
extractProp,
|
|
93
|
+
compareArraysByProp,
|
|
94
|
+
genCommaList,
|
|
95
|
+
getLocalTimeInfo,
|
|
96
|
+
prefixWithAOrAn,
|
|
97
|
+
everyAsync,
|
|
98
|
+
filterAsync,
|
|
99
|
+
forEachAsync,
|
|
100
|
+
mapAsync,
|
|
101
|
+
someAsync,
|
|
102
|
+
capitalize,
|
|
103
|
+
shuffleArray,
|
|
104
|
+
// Server helpers
|
|
105
|
+
initServer,
|
|
106
|
+
genRouteHandler,
|
|
107
|
+
handleError,
|
|
108
|
+
handleSuccess,
|
|
109
|
+
initLogCollection,
|
|
110
|
+
initCrossServerCredentialCollection,
|
|
111
|
+
addDBEditorEndpoints,
|
|
112
|
+
visitEndpointOnAnotherServer,
|
|
113
|
+
// Types
|
|
114
|
+
DayOfWeek,
|
|
115
|
+
Log,
|
|
116
|
+
LogType,
|
|
117
|
+
LogSource,
|
|
118
|
+
LogAction,
|
|
119
|
+
LogBuiltInMetadata,
|
|
120
|
+
LogMetadataType,
|
|
121
|
+
LogFunction,
|
|
122
|
+
CrossServerCredential,
|
|
123
|
+
// Server types
|
|
124
|
+
ParamType,
|
|
125
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single cross-server credential
|
|
3
|
+
* @author Gabe Abrams
|
|
4
|
+
*/
|
|
5
|
+
type CrossServerCredential = {
|
|
6
|
+
// Description of the credential (human-readable)
|
|
7
|
+
description: string,
|
|
8
|
+
// The key of the credential
|
|
9
|
+
key: string,
|
|
10
|
+
// The encoded secret of the credential
|
|
11
|
+
encodedeSecret: string,
|
|
12
|
+
// The list of scopes for the credential
|
|
13
|
+
scopes: string[],
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default CrossServerCredential;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Highest error code = DEK34
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* List of error codes built into the express kit
|
|
5
|
+
* @author Gabe Abrams
|
|
6
|
+
*/
|
|
7
|
+
enum ExpressKitErrorCode {
|
|
8
|
+
// General errors
|
|
9
|
+
WrongCourse = 'DEK6',
|
|
10
|
+
NotTTM = 'DEK9',
|
|
11
|
+
NotAdmin = 'DEK10',
|
|
12
|
+
NotAllowedToReviewLogs = 'DEK11',
|
|
13
|
+
ThemeCheckedBeforeReactKitReady = 'DEK12',
|
|
14
|
+
InvalidParameter = 'DEK5',
|
|
15
|
+
MissingParameter = 'DEK4',
|
|
16
|
+
|
|
17
|
+
// Server-to-server requests
|
|
18
|
+
NotConnected = 'DEK14',
|
|
19
|
+
SelfSigned = 'DEK15',
|
|
20
|
+
ResponseParseError = 'DEK16',
|
|
21
|
+
SignedRequestUnparseable = 'DEK28',
|
|
22
|
+
SignedRequestInvalidCollection = 'DEK21',
|
|
23
|
+
SignedRequestInvalidCredential = 'DEK23',
|
|
24
|
+
SignedRequestInvalidScope = 'DEK22',
|
|
25
|
+
SignedRequestInvalidTimestamp = 'DEK24',
|
|
26
|
+
SignedRequestInvalidSignature = 'DEK25',
|
|
27
|
+
SignedRequestInvalidBody = 'DEK26',
|
|
28
|
+
CrossServerNoCredentialsToSignWith = 'DEK27',
|
|
29
|
+
CrossServerMissingSignedRequestInfo = 'DEK29',
|
|
30
|
+
CrossServerNoCredentialEncodingSalt = 'DEK30',
|
|
31
|
+
NoOauthLib = 'DEK31',
|
|
32
|
+
NoCryptoLib = 'DEK32',
|
|
33
|
+
InvalidCrossServerCredentialsFormat = 'DEK33',
|
|
34
|
+
UnknownCrossServerError = 'DEK34',
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export default ExpressKitErrorCode;
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"module": "commonjs",
|
|
4
|
+
"esModuleInterop": true,
|
|
5
|
+
"noImplicitAny": true,
|
|
6
|
+
"noEmitOnError": true,
|
|
7
|
+
"removeComments": false,
|
|
8
|
+
"declaration": true,
|
|
9
|
+
"sourceMap": true,
|
|
10
|
+
"target": "es5",
|
|
11
|
+
"outDir": "./lib"
|
|
12
|
+
},
|
|
13
|
+
"include": [
|
|
14
|
+
"./src"
|
|
15
|
+
],
|
|
16
|
+
"ts-node": {
|
|
17
|
+
"files": true
|
|
18
|
+
}
|
|
19
|
+
}
|