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.
Files changed (92) hide show
  1. package/.vscode/settings.json +3 -1
  2. package/README.md +0 -20
  3. package/dist/cjs/index.js +7838 -15905
  4. package/dist/cjs/index.js.map +1 -1
  5. package/dist/cjs/types/components/ItemPicker/index.d.ts +1 -0
  6. package/dist/cjs/types/components/LoadingSpinner.d.ts +2 -2
  7. package/dist/cjs/types/components/Modal/ModalProps.d.ts +2 -0
  8. package/dist/cjs/types/components/SimpleDateChooser.d.ts +3 -1
  9. package/dist/cjs/types/components/SimpleTimeChooser.d.ts +20 -0
  10. package/dist/cjs/types/components/TabBox.d.ts +1 -0
  11. package/dist/cjs/types/components/Tooltip.d.ts +1 -1
  12. package/dist/cjs/types/helpers/getWordCount.d.ts +10 -0
  13. package/dist/cjs/types/index.d.ts +13 -13
  14. package/dist/cjs/types/types/ParamType.d.ts +10 -10
  15. package/dist/cjs/types/types/ReactKitErrorCode.d.ts +2 -28
  16. package/dist/esm/index.js +6661 -14723
  17. package/dist/esm/index.js.map +1 -1
  18. package/dist/esm/types/components/ItemPicker/index.d.ts +1 -0
  19. package/dist/esm/types/components/LoadingSpinner.d.ts +2 -2
  20. package/dist/esm/types/components/Modal/ModalProps.d.ts +2 -0
  21. package/dist/esm/types/components/SimpleDateChooser.d.ts +3 -1
  22. package/dist/esm/types/components/SimpleTimeChooser.d.ts +20 -0
  23. package/dist/esm/types/components/TabBox.d.ts +1 -0
  24. package/dist/esm/types/components/Tooltip.d.ts +1 -1
  25. package/dist/esm/types/helpers/getWordCount.d.ts +10 -0
  26. package/dist/esm/types/index.d.ts +13 -13
  27. package/dist/esm/types/types/ParamType.d.ts +10 -10
  28. package/dist/esm/types/types/ReactKitErrorCode.d.ts +2 -28
  29. package/dist/index.d.ts +189 -379
  30. package/package.json +5 -11
  31. package/src/components/AppWrapper.tsx +3 -1
  32. package/src/components/CheckboxButton.tsx +1 -1
  33. package/src/components/Dropdown.tsx +1 -1
  34. package/src/components/IntelliTable.tsx +1 -1
  35. package/src/components/ItemPicker/NestableItemList.tsx +1 -0
  36. package/src/components/ItemPicker/index.tsx +96 -0
  37. package/src/components/LogReviewer.tsx +2 -2
  38. package/src/components/Modal/ModalProps.ts +4 -0
  39. package/src/components/Modal/index.tsx +60 -21
  40. package/src/components/RadioButton.tsx +3 -1
  41. package/src/components/SimpleDateChooser.tsx +62 -26
  42. package/src/components/SimpleTimeChooser.tsx +195 -0
  43. package/src/components/TabBox.tsx +27 -9
  44. package/src/components/Tooltip.tsx +1 -1
  45. package/src/helpers/getWordCount.ts +26 -0
  46. package/src/{client → helpers}/initClient.tsx +5 -1
  47. package/src/helpers/logClientEvent.tsx +3 -1
  48. package/src/helpers/visitServerEndpoint.tsx +1 -1
  49. package/src/index.ts +22 -24
  50. package/src/types/ParamType.ts +10 -10
  51. package/src/types/ReactKitErrorCode.tsx +3 -31
  52. package/dist/cjs/types/components/ItemPicker/index.test.d.ts +0 -1
  53. package/dist/cjs/types/helpers/addDBEditorEndpoints.d.ts +0 -41
  54. package/dist/cjs/types/helpers/dataSigner.d.ts +0 -40
  55. package/dist/cjs/types/helpers/genRouteHandler.d.ts +0 -76
  56. package/dist/cjs/types/helpers/handleError.d.ts +0 -18
  57. package/dist/cjs/types/helpers/handleSuccess.d.ts +0 -8
  58. package/dist/cjs/types/helpers/parseUserAgent.d.ts +0 -17
  59. package/dist/cjs/types/helpers/visitEndpointOnAnotherServer/index.d.ts +0 -20
  60. package/dist/cjs/types/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.d.ts +0 -27
  61. package/dist/cjs/types/server/initCrossServerCredentialCollection.d.ts +0 -8
  62. package/dist/cjs/types/server/initLogCollection.d.ts +0 -8
  63. package/dist/cjs/types/server/initServer.d.ts +0 -53
  64. package/dist/cjs/types/types/CrossServerCredential.d.ts +0 -11
  65. package/dist/esm/types/components/ItemPicker/index.test.d.ts +0 -1
  66. package/dist/esm/types/helpers/addDBEditorEndpoints.d.ts +0 -41
  67. package/dist/esm/types/helpers/dataSigner.d.ts +0 -40
  68. package/dist/esm/types/helpers/genRouteHandler.d.ts +0 -76
  69. package/dist/esm/types/helpers/handleError.d.ts +0 -18
  70. package/dist/esm/types/helpers/handleSuccess.d.ts +0 -8
  71. package/dist/esm/types/helpers/parseUserAgent.d.ts +0 -17
  72. package/dist/esm/types/helpers/visitEndpointOnAnotherServer/index.d.ts +0 -20
  73. package/dist/esm/types/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.d.ts +0 -27
  74. package/dist/esm/types/server/initCrossServerCredentialCollection.d.ts +0 -8
  75. package/dist/esm/types/server/initLogCollection.d.ts +0 -8
  76. package/dist/esm/types/server/initServer.d.ts +0 -53
  77. package/dist/esm/types/types/CrossServerCredential.d.ts +0 -11
  78. package/src/components/ItemPicker/index.test.tsx +0 -783
  79. package/src/helpers/addDBEditorEndpoints.ts +0 -128
  80. package/src/helpers/dataSigner.ts +0 -342
  81. package/src/helpers/genRouteHandler.ts +0 -911
  82. package/src/helpers/handleError.ts +0 -65
  83. package/src/helpers/handleSuccess.ts +0 -18
  84. package/src/helpers/parseUserAgent.ts +0 -108
  85. package/src/helpers/visitEndpointOnAnotherServer/index.ts +0 -152
  86. package/src/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.ts +0 -162
  87. package/src/server/initCrossServerCredentialCollection.ts +0 -16
  88. package/src/server/initLogCollection.ts +0 -27
  89. package/src/server/initServer.ts +0 -305
  90. package/src/types/CrossServerCredential.ts +0 -16
  91. /package/dist/cjs/types/{client → helpers}/initClient.d.ts +0 -0
  92. /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;