dce-reactkit 3.12.3 → 4.0.0-beta.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 (71) hide show
  1. package/.vscode/settings.json +1 -3
  2. package/README.md +20 -0
  3. package/dist/cjs/index.js +156 -1792
  4. package/dist/cjs/index.js.map +1 -1
  5. package/dist/cjs/types/components/ItemPicker/index.d.ts +0 -1
  6. package/dist/cjs/types/components/Modal/ModalProps.d.ts +0 -2
  7. package/dist/cjs/types/components/TabBox.d.ts +0 -1
  8. package/dist/cjs/types/index.d.ts +8 -12
  9. package/dist/cjs/types/types/ParamType.d.ts +10 -10
  10. package/dist/cjs/types/types/ReactKitErrorCode.d.ts +1 -15
  11. package/dist/esm/index.js +157 -1785
  12. package/dist/esm/index.js.map +1 -1
  13. package/dist/esm/types/components/ItemPicker/index.d.ts +0 -1
  14. package/dist/esm/types/components/Modal/ModalProps.d.ts +0 -2
  15. package/dist/esm/types/components/TabBox.d.ts +0 -1
  16. package/dist/esm/types/index.d.ts +8 -12
  17. package/dist/esm/types/types/ParamType.d.ts +10 -10
  18. package/dist/esm/types/types/ReactKitErrorCode.d.ts +1 -15
  19. package/dist/index.d.ts +122 -351
  20. package/genEncodedSecret.ts +84 -0
  21. package/package.json +7 -5
  22. package/rollup.config.js +2 -0
  23. package/src/components/AppWrapper.tsx +3 -1
  24. package/src/components/CheckboxButton.tsx +1 -1
  25. package/src/components/Dropdown.tsx +1 -1
  26. package/src/components/IntelliTable.tsx +1 -1
  27. package/src/components/ItemPicker/NestableItemList.tsx +0 -1
  28. package/src/components/ItemPicker/index.tsx +0 -96
  29. package/src/components/Modal/ModalProps.ts +0 -4
  30. package/src/components/Modal/index.tsx +21 -60
  31. package/src/components/RadioButton.tsx +3 -1
  32. package/src/components/TabBox.tsx +9 -27
  33. package/src/{client → helpers}/initClient.tsx +5 -1
  34. package/src/helpers/logClientEvent.tsx +3 -1
  35. package/src/helpers/visitServerEndpoint.tsx +1 -1
  36. package/src/index.ts +12 -22
  37. package/src/types/ParamType.ts +10 -10
  38. package/src/types/ReactKitErrorCode.tsx +1 -17
  39. package/dist/cjs/types/helpers/addDBEditorEndpoints.d.ts +0 -41
  40. package/dist/cjs/types/helpers/genRouteHandler.d.ts +0 -76
  41. package/dist/cjs/types/helpers/getWordCount.d.ts +0 -10
  42. package/dist/cjs/types/helpers/handleError.d.ts +0 -18
  43. package/dist/cjs/types/helpers/handleSuccess.d.ts +0 -8
  44. package/dist/cjs/types/helpers/parseUserAgent.d.ts +0 -17
  45. package/dist/cjs/types/helpers/visitEndpointOnAnotherServer/index.d.ts +0 -24
  46. package/dist/cjs/types/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.d.ts +0 -33
  47. package/dist/cjs/types/server/initLogCollection.d.ts +0 -8
  48. package/dist/cjs/types/server/initServer.d.ts +0 -42
  49. package/dist/esm/types/helpers/addDBEditorEndpoints.d.ts +0 -41
  50. package/dist/esm/types/helpers/genRouteHandler.d.ts +0 -76
  51. package/dist/esm/types/helpers/getWordCount.d.ts +0 -10
  52. package/dist/esm/types/helpers/handleError.d.ts +0 -18
  53. package/dist/esm/types/helpers/handleSuccess.d.ts +0 -8
  54. package/dist/esm/types/helpers/parseUserAgent.d.ts +0 -17
  55. package/dist/esm/types/helpers/visitEndpointOnAnotherServer/index.d.ts +0 -24
  56. package/dist/esm/types/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.d.ts +0 -33
  57. package/dist/esm/types/server/initLogCollection.d.ts +0 -8
  58. package/dist/esm/types/server/initServer.d.ts +0 -42
  59. package/src/components/ItemPicker/index.test.tsx +0 -783
  60. package/src/helpers/addDBEditorEndpoints.ts +0 -128
  61. package/src/helpers/genRouteHandler.ts +0 -948
  62. package/src/helpers/getWordCount.ts +0 -26
  63. package/src/helpers/handleError.ts +0 -65
  64. package/src/helpers/handleSuccess.ts +0 -18
  65. package/src/helpers/parseUserAgent.ts +0 -108
  66. package/src/helpers/visitEndpointOnAnotherServer/index.ts +0 -93
  67. package/src/helpers/visitEndpointOnAnotherServer/sendServerToServerRequest.ts +0 -164
  68. package/src/server/initLogCollection.ts +0 -27
  69. package/src/server/initServer.ts +0 -287
  70. /package/dist/cjs/types/{client → helpers}/initClient.d.ts +0 -0
  71. /package/dist/esm/types/{client → helpers}/initClient.d.ts +0 -0
@@ -1,26 +0,0 @@
1
- const punctuationRegex = /[!@#$%^&*(),.?\/;:'"\-\[\]]/g;
2
-
3
- /**
4
- * Get number of words in string
5
- * @author Gardenia Liu
6
- * @author Allison Zhang
7
- * @author Gabe Abrams
8
- * @param text the string to check
9
- * @returns number of words in the string
10
- */
11
- const getWordCount = (text: string): number => {
12
- const trimmedTextWithoutPunctuation = (
13
- text
14
- // Remove leading and trailing whitespace
15
- .trim()
16
- // Remove punctuation
17
- .replace(punctuationRegex, '')
18
- );
19
- if (trimmedTextWithoutPunctuation.length === 0) {
20
- return 0;
21
- }
22
-
23
- return trimmedTextWithoutPunctuation.split(/\s+/g).length;
24
- };
25
-
26
- export default getWordCount;
@@ -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,93 +0,0 @@
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.host - the host of the other server
16
- * @param opts.path - the path of the other server's endpoint
17
- * @param [opts.method=GET] - the method of the endpoint
18
- * @param [opts.params] - query/body parameters to include
19
- * @param [opts.headers] - headers to include
20
- * @returns response from server
21
- */
22
- const visitEndpointOnAnotherServer = async (
23
- opts: {
24
- host: string,
25
- path: string,
26
- method?: ('GET' | 'POST' | 'DELETE' | 'PUT'),
27
- params?: { [key in string]: any },
28
- headers?: { [k in string]: any },
29
- },
30
- ): Promise<any> => {
31
- // Remove properties with undefined values
32
- let params: { [key in string]: any } | undefined;
33
- if (opts.params) {
34
- params = Object.fromEntries(
35
- Object
36
- .entries(opts.params)
37
- .filter(([, value]) => {
38
- return value !== undefined;
39
- }),
40
- );
41
- }
42
-
43
- // Automatically JSONify arrays and objects
44
- if (params) {
45
- params = Object.fromEntries(
46
- Object
47
- .entries(params)
48
- .map(([key, value]) => {
49
- if (Array.isArray(value) || typeof value === 'object') {
50
- return [key, JSON.stringify(value)];
51
- }
52
- return [key, value];
53
- }),
54
- );
55
- }
56
-
57
- // Send the request
58
- const response = await sendServerToServerRequest({
59
- host: opts.host,
60
- path: opts.path,
61
- method: opts.method ?? 'GET',
62
- params,
63
- });
64
-
65
- // Check for failure
66
- if (!response || !response.body) {
67
- throw new ErrorWithCode(
68
- 'We didn\'t get a response from the server. Please check your internet connection.',
69
- ReactKitErrorCode.NoResponse,
70
- );
71
- }
72
- if (!response.body.success) {
73
- // Other errors
74
- throw new ErrorWithCode(
75
- (
76
- response.body.message
77
- || 'An unknown error occurred. Please contact an admin.'
78
- ),
79
- (
80
- response.body.code
81
- || ReactKitErrorCode.NoCode
82
- ),
83
- );
84
- }
85
-
86
- // Success! Extract the body
87
- const { body } = response.body;
88
-
89
- // Return
90
- return body;
91
- };
92
-
93
- export default visitEndpointOnAnotherServer;
@@ -1,164 +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.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;
@@ -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;