dce-reactkit 3.1.13 → 3.1.15
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/dist/cjs/index.js +188 -15
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/helpers/genRouteHandler.d.ts +18 -5
- package/dist/cjs/types/html/genErrorPage.d.ts +19 -0
- package/dist/esm/index.js +188 -15
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/helpers/genRouteHandler.d.ts +18 -5
- package/dist/esm/types/html/genErrorPage.d.ts +19 -0
- package/dist/index.d.ts +18 -5
- package/package.json +1 -1
- package/src/helpers/genRouteHandler.ts +84 -16
- package/src/html/genErrorPage.ts +141 -0
- package/tsconfig.json +0 -1
|
@@ -7,10 +7,15 @@ import ParamType from '../types/ParamType';
|
|
|
7
7
|
* included in the request (map: param name => type)
|
|
8
8
|
* @param opts.handler function that processes the request
|
|
9
9
|
* @returns express route handler that takes the following arguments:
|
|
10
|
-
* params (map: param name => value),
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
10
|
+
* params (map: param name => value),
|
|
11
|
+
* req (express request object),
|
|
12
|
+
* next (express next function),
|
|
13
|
+
* send (a function that sends a string to the client),
|
|
14
|
+
* redirect (takes a url and redirects the user to that url),
|
|
15
|
+
* renderErrorPage (shows a static error page to the user),
|
|
16
|
+
* and returns the value to send to the client as a JSON API response, or
|
|
17
|
+
* calls next() or redirect(...) or send(...) or renderErrorPage(...).
|
|
18
|
+
* Note: params also has userId, userFirstName,
|
|
14
19
|
* userLastName, isLearner, isTTM, isAdmin, and any other variables that
|
|
15
20
|
* are directly added to the session
|
|
16
21
|
*/
|
|
@@ -23,8 +28,16 @@ declare const genRouteHandler: (opts: {
|
|
|
23
28
|
[k: string]: any;
|
|
24
29
|
};
|
|
25
30
|
req: any;
|
|
26
|
-
res: any;
|
|
27
31
|
next: () => void;
|
|
32
|
+
redirect: (pathOrURL: string) => void;
|
|
33
|
+
send: (text: string, status?: number | undefined) => void;
|
|
34
|
+
renderErrorPage: (opts?: {
|
|
35
|
+
title?: string | undefined;
|
|
36
|
+
description?: string | undefined;
|
|
37
|
+
code?: string | undefined;
|
|
38
|
+
pageTitle?: string | undefined;
|
|
39
|
+
status?: number | undefined;
|
|
40
|
+
} | undefined) => void;
|
|
28
41
|
}) => any;
|
|
29
42
|
}) => (req: any, res: any, next: () => void) => Promise<undefined>;
|
|
30
43
|
export default genRouteHandler;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a static error page
|
|
3
|
+
* @author Gabe Abrams
|
|
4
|
+
* @param opts object containing all arguments
|
|
5
|
+
* @param [opts.title=An Error Occurred] title of the error box
|
|
6
|
+
* @param [opts.description=An unknown server error occurred. Please contact support.]
|
|
7
|
+
* a human-readable description of the error
|
|
8
|
+
* @param [opts.code=ReactKitErrorCode.NoCode] error code to show
|
|
9
|
+
* @param [opts.pageTitle=opts.title] title of the page/tab if it differs from
|
|
10
|
+
* the title of the error
|
|
11
|
+
* @returns html of the page
|
|
12
|
+
*/
|
|
13
|
+
declare const genErrorPage: (opts?: {
|
|
14
|
+
title?: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
code?: string;
|
|
17
|
+
pageTitle?: string;
|
|
18
|
+
}) => string;
|
|
19
|
+
export default genErrorPage;
|
package/dist/index.d.ts
CHANGED
|
@@ -510,10 +510,15 @@ declare enum ParamType {
|
|
|
510
510
|
* included in the request (map: param name => type)
|
|
511
511
|
* @param opts.handler function that processes the request
|
|
512
512
|
* @returns express route handler that takes the following arguments:
|
|
513
|
-
* params (map: param name => value),
|
|
514
|
-
*
|
|
515
|
-
*
|
|
516
|
-
*
|
|
513
|
+
* params (map: param name => value),
|
|
514
|
+
* req (express request object),
|
|
515
|
+
* next (express next function),
|
|
516
|
+
* send (a function that sends a string to the client),
|
|
517
|
+
* redirect (takes a url and redirects the user to that url),
|
|
518
|
+
* renderErrorPage (shows a static error page to the user),
|
|
519
|
+
* and returns the value to send to the client as a JSON API response, or
|
|
520
|
+
* calls next() or redirect(...) or send(...) or renderErrorPage(...).
|
|
521
|
+
* Note: params also has userId, userFirstName,
|
|
517
522
|
* userLastName, isLearner, isTTM, isAdmin, and any other variables that
|
|
518
523
|
* are directly added to the session
|
|
519
524
|
*/
|
|
@@ -526,8 +531,16 @@ declare const genRouteHandler: (opts: {
|
|
|
526
531
|
[k: string]: any;
|
|
527
532
|
};
|
|
528
533
|
req: any;
|
|
529
|
-
res: any;
|
|
530
534
|
next: () => void;
|
|
535
|
+
redirect: (pathOrURL: string) => void;
|
|
536
|
+
send: (text: string, status?: number | undefined) => void;
|
|
537
|
+
renderErrorPage: (opts?: {
|
|
538
|
+
title?: string | undefined;
|
|
539
|
+
description?: string | undefined;
|
|
540
|
+
code?: string | undefined;
|
|
541
|
+
pageTitle?: string | undefined;
|
|
542
|
+
status?: number | undefined;
|
|
543
|
+
} | undefined) => void;
|
|
531
544
|
}) => any;
|
|
532
545
|
}) => (req: any, res: any, next: () => void) => Promise<undefined>;
|
|
533
546
|
|
package/package.json
CHANGED
|
@@ -8,6 +8,15 @@ import ParamType from '../types/ParamType';
|
|
|
8
8
|
// Import helpers
|
|
9
9
|
import handleError from './handleError';
|
|
10
10
|
import handleSuccess from './handleSuccess';
|
|
11
|
+
import genErrorPage from '../html/genErrorPage';
|
|
12
|
+
|
|
13
|
+
/*------------------------------------------------------------------------*/
|
|
14
|
+
/* Helpers */
|
|
15
|
+
/*------------------------------------------------------------------------*/
|
|
16
|
+
|
|
17
|
+
/*------------------------------------------------------------------------*/
|
|
18
|
+
/* Main */
|
|
19
|
+
/*------------------------------------------------------------------------*/
|
|
11
20
|
|
|
12
21
|
/**
|
|
13
22
|
* Generate an express API route handler
|
|
@@ -17,10 +26,15 @@ import handleSuccess from './handleSuccess';
|
|
|
17
26
|
* included in the request (map: param name => type)
|
|
18
27
|
* @param opts.handler function that processes the request
|
|
19
28
|
* @returns express route handler that takes the following arguments:
|
|
20
|
-
* params (map: param name => value),
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
29
|
+
* params (map: param name => value),
|
|
30
|
+
* req (express request object),
|
|
31
|
+
* next (express next function),
|
|
32
|
+
* send (a function that sends a string to the client),
|
|
33
|
+
* redirect (takes a url and redirects the user to that url),
|
|
34
|
+
* renderErrorPage (shows a static error page to the user),
|
|
35
|
+
* and returns the value to send to the client as a JSON API response, or
|
|
36
|
+
* calls next() or redirect(...) or send(...) or renderErrorPage(...).
|
|
37
|
+
* Note: params also has userId, userFirstName,
|
|
24
38
|
* userLastName, isLearner, isTTM, isAdmin, and any other variables that
|
|
25
39
|
* are directly added to the session
|
|
26
40
|
*/
|
|
@@ -35,8 +49,18 @@ const genRouteHandler = (
|
|
|
35
49
|
[k: string]: any
|
|
36
50
|
},
|
|
37
51
|
req: any,
|
|
38
|
-
res: any,
|
|
39
52
|
next: () => void,
|
|
53
|
+
redirect: (pathOrURL: string) => void,
|
|
54
|
+
send: (text: string, status?: number) => void,
|
|
55
|
+
renderErrorPage: (
|
|
56
|
+
opts?: {
|
|
57
|
+
title?: string,
|
|
58
|
+
description?: string,
|
|
59
|
+
code?: string,
|
|
60
|
+
pageTitle?: string,
|
|
61
|
+
status?: number,
|
|
62
|
+
},
|
|
63
|
+
) => void,
|
|
40
64
|
},
|
|
41
65
|
) => any,
|
|
42
66
|
},
|
|
@@ -376,17 +400,53 @@ const genRouteHandler = (
|
|
|
376
400
|
/* Call handler */
|
|
377
401
|
/*------------------------------------------------------------------------*/
|
|
378
402
|
|
|
379
|
-
// Keep track of whether
|
|
380
|
-
let
|
|
403
|
+
// Keep track of whether a response was already sent
|
|
404
|
+
let responseSent = false;
|
|
381
405
|
|
|
382
406
|
/**
|
|
383
|
-
*
|
|
384
|
-
* are not sent
|
|
407
|
+
* Redirect the user to another path or url
|
|
385
408
|
* @author Gabe Abrams
|
|
409
|
+
* @param pathOrURL the path or url to redirect to
|
|
386
410
|
*/
|
|
387
|
-
const
|
|
388
|
-
|
|
389
|
-
|
|
411
|
+
const redirect = (pathOrURL: string) => {
|
|
412
|
+
responseSent = true;
|
|
413
|
+
res.redirect(pathOrURL);
|
|
414
|
+
};
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Send text to the client (with an optional status code)
|
|
418
|
+
* @author Gabe Abrams
|
|
419
|
+
* @param text the text to send to the client
|
|
420
|
+
* @parm [status=200] the http status code to send
|
|
421
|
+
*/
|
|
422
|
+
const send = (text: string, status: number = 200) => {
|
|
423
|
+
responseSent = true;
|
|
424
|
+
res.status(status).send(text);
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Render an error page
|
|
429
|
+
* @author Gabe Abrams
|
|
430
|
+
* @param opts object containing all arguments
|
|
431
|
+
* @param [opts.title=An Error Occurred] title of the error box
|
|
432
|
+
* @param [opts.description=An unknown server error occurred. Please contact support.]
|
|
433
|
+
* a human-readable description of the error
|
|
434
|
+
* @param [opts.code=ReactKitErrorCode.NoCode] error code to show
|
|
435
|
+
* @param [opts.pageTitle=opts.title] title of the page/tab if it differs from
|
|
436
|
+
* the title of the error
|
|
437
|
+
* @param [opts.status=500] http status code
|
|
438
|
+
*/
|
|
439
|
+
const renderErrorPage = (
|
|
440
|
+
opts: {
|
|
441
|
+
title?: string,
|
|
442
|
+
description?: string,
|
|
443
|
+
code?: string,
|
|
444
|
+
pageTitle?: string,
|
|
445
|
+
status?: number,
|
|
446
|
+
} = {},
|
|
447
|
+
) => {
|
|
448
|
+
const html = genErrorPage(opts);
|
|
449
|
+
send(html, opts.status ?? 500);
|
|
390
450
|
};
|
|
391
451
|
|
|
392
452
|
// Call the handler
|
|
@@ -394,19 +454,27 @@ const genRouteHandler = (
|
|
|
394
454
|
const results = await opts.handler({
|
|
395
455
|
params: output,
|
|
396
456
|
req,
|
|
397
|
-
|
|
398
|
-
next:
|
|
457
|
+
send,
|
|
458
|
+
next: () => {
|
|
459
|
+
responseSent = true;
|
|
460
|
+
next();
|
|
461
|
+
},
|
|
462
|
+
redirect,
|
|
463
|
+
renderErrorPage,
|
|
399
464
|
});
|
|
400
465
|
|
|
401
466
|
// Send results to client (only if next wasn't called)
|
|
402
|
-
if (!
|
|
467
|
+
if (!responseSent) {
|
|
403
468
|
return handleSuccess(res, results ?? undefined);
|
|
404
469
|
}
|
|
405
470
|
} catch (err) {
|
|
406
471
|
// Send error to client (only if next wasn't called)
|
|
407
|
-
if (!
|
|
472
|
+
if (!responseSent) {
|
|
408
473
|
return handleError(res, err);
|
|
409
474
|
}
|
|
475
|
+
|
|
476
|
+
// Log error that was not responded with
|
|
477
|
+
console.log('Error occurred but could not be sent to client because a response was already sent:', err);
|
|
410
478
|
}
|
|
411
479
|
};
|
|
412
480
|
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// Import shared types
|
|
2
|
+
import ReactKitErrorCode from '../types/ReactKitErrorCode';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Generate a static error page
|
|
6
|
+
* @author Gabe Abrams
|
|
7
|
+
* @param opts object containing all arguments
|
|
8
|
+
* @param [opts.title=An Error Occurred] title of the error box
|
|
9
|
+
* @param [opts.description=An unknown server error occurred. Please contact support.]
|
|
10
|
+
* a human-readable description of the error
|
|
11
|
+
* @param [opts.code=ReactKitErrorCode.NoCode] error code to show
|
|
12
|
+
* @param [opts.pageTitle=opts.title] title of the page/tab if it differs from
|
|
13
|
+
* the title of the error
|
|
14
|
+
* @returns html of the page
|
|
15
|
+
*/
|
|
16
|
+
const genErrorPage = (
|
|
17
|
+
opts: {
|
|
18
|
+
title?: string,
|
|
19
|
+
description?: string,
|
|
20
|
+
code?: string,
|
|
21
|
+
pageTitle?: string,
|
|
22
|
+
} = {},
|
|
23
|
+
): string => {
|
|
24
|
+
const title = (opts.title ?? 'An Error Occurred');
|
|
25
|
+
const pageTitle = (opts.pageTitle ?? title);
|
|
26
|
+
const description = (
|
|
27
|
+
opts.description
|
|
28
|
+
?? 'An unknown server error occurred. Please contact support.'
|
|
29
|
+
);
|
|
30
|
+
const code = (opts.code ?? ReactKitErrorCode.NoCode);
|
|
31
|
+
|
|
32
|
+
return `
|
|
33
|
+
<head>
|
|
34
|
+
<!-- Metadata -->
|
|
35
|
+
<meta
|
|
36
|
+
name="viewport"
|
|
37
|
+
content="width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0"
|
|
38
|
+
>
|
|
39
|
+
|
|
40
|
+
<!-- Title -->
|
|
41
|
+
<title>${pageTitle}</title>
|
|
42
|
+
|
|
43
|
+
<!-- Bootstrap -->
|
|
44
|
+
<link
|
|
45
|
+
rel="stylesheet"
|
|
46
|
+
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.1/css/bootstrap.min.css"
|
|
47
|
+
integrity="sha512-siwe/oXMhSjGCwLn+scraPOWrJxHlUgMBMZXdPe2Tnk3I0x3ESCoLz7WZ5NTH6SZrywMY+PB1cjyqJ5jAluCOg=="
|
|
48
|
+
crossorigin="anonymous"
|
|
49
|
+
referrerpolicy="no-referrer"
|
|
50
|
+
/>
|
|
51
|
+
<script
|
|
52
|
+
src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.1/js/bootstrap.min.js"
|
|
53
|
+
integrity="sha512-vyRAVI0IEm6LI/fVSv/Wq/d0KUfrg3hJq2Qz5FlfER69sf3ZHlOrsLriNm49FxnpUGmhx+TaJKwJ+ByTLKT+Yg=="
|
|
54
|
+
crossorigin="anonymous"
|
|
55
|
+
referrerpolicy="no-referrer"
|
|
56
|
+
></script>
|
|
57
|
+
|
|
58
|
+
<!-- FontAwesome -->
|
|
59
|
+
<link
|
|
60
|
+
rel="stylesheet"
|
|
61
|
+
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css"
|
|
62
|
+
integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A=="
|
|
63
|
+
crossorigin="anonymous"
|
|
64
|
+
referrerpolicy="no-referrer"
|
|
65
|
+
/>
|
|
66
|
+
|
|
67
|
+
<!-- Style -->
|
|
68
|
+
<style>
|
|
69
|
+
.DCEReactKit-pop-in {
|
|
70
|
+
animation-name: DCEReactKit-pop-in;
|
|
71
|
+
animation-duration: 0.5s;
|
|
72
|
+
animation-iteration-count: 1;
|
|
73
|
+
animation-timing-function: ease-out;
|
|
74
|
+
animation-fill-mode: both;
|
|
75
|
+
|
|
76
|
+
transform-origin: center;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@keyframes DCEReactKit-pop-in {
|
|
80
|
+
0% {
|
|
81
|
+
opacity: 0;
|
|
82
|
+
transform: scale(0.9);
|
|
83
|
+
}
|
|
84
|
+
100% {
|
|
85
|
+
opacity: 1;
|
|
86
|
+
transform: scale(1);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.DCEReactKit-slide-in {
|
|
91
|
+
animation-name: DCEReactKit-slide-in;
|
|
92
|
+
animation-duration: 1s;
|
|
93
|
+
animation-iteration-count: 1;
|
|
94
|
+
animation-timing-function: ease-out;
|
|
95
|
+
animation-fill-mode: both;
|
|
96
|
+
animation-delay: 0.2s;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@keyframes DCEReactKit-slide-in {
|
|
100
|
+
0% {
|
|
101
|
+
opacity: 0;
|
|
102
|
+
transform: translate(0, 0.3em);
|
|
103
|
+
}
|
|
104
|
+
100% {
|
|
105
|
+
opacity: 1;
|
|
106
|
+
transform: translate(0, 0);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
</style>
|
|
110
|
+
</head>
|
|
111
|
+
|
|
112
|
+
<!-- Body -->
|
|
113
|
+
<body class="bg-dark text-center pt-3 ps-3 pe-3">
|
|
114
|
+
<!-- Alert -->
|
|
115
|
+
<div
|
|
116
|
+
class="DCEReactKit-pop-in alert alert-warning d-inline-block"
|
|
117
|
+
style="width: 50em; max-width: 100%"
|
|
118
|
+
>
|
|
119
|
+
<!-- Title -->
|
|
120
|
+
<h2>
|
|
121
|
+
<i class="me-1 fa-solid fa-triangle-exclamation"></i>
|
|
122
|
+
${title}
|
|
123
|
+
</h2>
|
|
124
|
+
<!-- Description -->
|
|
125
|
+
<div>
|
|
126
|
+
${description}
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
<!-- Error Code -->
|
|
131
|
+
<div class="DCEReactKit-slide-in text-light">
|
|
132
|
+
<strong>
|
|
133
|
+
Error Code:
|
|
134
|
+
</strong>
|
|
135
|
+
${code}
|
|
136
|
+
</div>
|
|
137
|
+
</body>
|
|
138
|
+
`;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
export default genErrorPage;
|