dce-reactkit 3.1.14 → 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 +187 -46
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/helpers/genRouteHandler.d.ts +16 -8
- package/dist/cjs/types/html/genErrorPage.d.ts +19 -0
- package/dist/esm/index.js +187 -46
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/helpers/genRouteHandler.d.ts +16 -8
- package/dist/esm/types/html/genErrorPage.d.ts +19 -0
- package/dist/index.d.ts +16 -8
- package/package.json +1 -1
- package/src/helpers/genRouteHandler.ts +53 -5
- package/src/html/genErrorPage.ts +141 -0
package/dist/cjs/index.js
CHANGED
|
@@ -2229,6 +2229,140 @@ const handleSuccess = (res, body) => {
|
|
|
2229
2229
|
return undefined;
|
|
2230
2230
|
};
|
|
2231
2231
|
|
|
2232
|
+
// Import shared types
|
|
2233
|
+
/**
|
|
2234
|
+
* Generate a static error page
|
|
2235
|
+
* @author Gabe Abrams
|
|
2236
|
+
* @param opts object containing all arguments
|
|
2237
|
+
* @param [opts.title=An Error Occurred] title of the error box
|
|
2238
|
+
* @param [opts.description=An unknown server error occurred. Please contact support.]
|
|
2239
|
+
* a human-readable description of the error
|
|
2240
|
+
* @param [opts.code=ReactKitErrorCode.NoCode] error code to show
|
|
2241
|
+
* @param [opts.pageTitle=opts.title] title of the page/tab if it differs from
|
|
2242
|
+
* the title of the error
|
|
2243
|
+
* @returns html of the page
|
|
2244
|
+
*/
|
|
2245
|
+
const genErrorPage = (opts = {}) => {
|
|
2246
|
+
var _a, _b, _c, _d;
|
|
2247
|
+
const title = ((_a = opts.title) !== null && _a !== void 0 ? _a : 'An Error Occurred');
|
|
2248
|
+
const pageTitle = ((_b = opts.pageTitle) !== null && _b !== void 0 ? _b : title);
|
|
2249
|
+
const description = ((_c = opts.description) !== null && _c !== void 0 ? _c : 'An unknown server error occurred. Please contact support.');
|
|
2250
|
+
const code = ((_d = opts.code) !== null && _d !== void 0 ? _d : ReactKitErrorCode$1.NoCode);
|
|
2251
|
+
return `
|
|
2252
|
+
<head>
|
|
2253
|
+
<!-- Metadata -->
|
|
2254
|
+
<meta
|
|
2255
|
+
name="viewport"
|
|
2256
|
+
content="width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0"
|
|
2257
|
+
>
|
|
2258
|
+
|
|
2259
|
+
<!-- Title -->
|
|
2260
|
+
<title>${pageTitle}</title>
|
|
2261
|
+
|
|
2262
|
+
<!-- Bootstrap -->
|
|
2263
|
+
<link
|
|
2264
|
+
rel="stylesheet"
|
|
2265
|
+
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.1/css/bootstrap.min.css"
|
|
2266
|
+
integrity="sha512-siwe/oXMhSjGCwLn+scraPOWrJxHlUgMBMZXdPe2Tnk3I0x3ESCoLz7WZ5NTH6SZrywMY+PB1cjyqJ5jAluCOg=="
|
|
2267
|
+
crossorigin="anonymous"
|
|
2268
|
+
referrerpolicy="no-referrer"
|
|
2269
|
+
/>
|
|
2270
|
+
<script
|
|
2271
|
+
src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.1/js/bootstrap.min.js"
|
|
2272
|
+
integrity="sha512-vyRAVI0IEm6LI/fVSv/Wq/d0KUfrg3hJq2Qz5FlfER69sf3ZHlOrsLriNm49FxnpUGmhx+TaJKwJ+ByTLKT+Yg=="
|
|
2273
|
+
crossorigin="anonymous"
|
|
2274
|
+
referrerpolicy="no-referrer"
|
|
2275
|
+
></script>
|
|
2276
|
+
|
|
2277
|
+
<!-- FontAwesome -->
|
|
2278
|
+
<link
|
|
2279
|
+
rel="stylesheet"
|
|
2280
|
+
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css"
|
|
2281
|
+
integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A=="
|
|
2282
|
+
crossorigin="anonymous"
|
|
2283
|
+
referrerpolicy="no-referrer"
|
|
2284
|
+
/>
|
|
2285
|
+
|
|
2286
|
+
<!-- Style -->
|
|
2287
|
+
<style>
|
|
2288
|
+
.DCEReactKit-pop-in {
|
|
2289
|
+
animation-name: DCEReactKit-pop-in;
|
|
2290
|
+
animation-duration: 0.5s;
|
|
2291
|
+
animation-iteration-count: 1;
|
|
2292
|
+
animation-timing-function: ease-out;
|
|
2293
|
+
animation-fill-mode: both;
|
|
2294
|
+
|
|
2295
|
+
transform-origin: center;
|
|
2296
|
+
}
|
|
2297
|
+
|
|
2298
|
+
@keyframes DCEReactKit-pop-in {
|
|
2299
|
+
0% {
|
|
2300
|
+
opacity: 0;
|
|
2301
|
+
transform: scale(0.9);
|
|
2302
|
+
}
|
|
2303
|
+
100% {
|
|
2304
|
+
opacity: 1;
|
|
2305
|
+
transform: scale(1);
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2309
|
+
.DCEReactKit-slide-in {
|
|
2310
|
+
animation-name: DCEReactKit-slide-in;
|
|
2311
|
+
animation-duration: 1s;
|
|
2312
|
+
animation-iteration-count: 1;
|
|
2313
|
+
animation-timing-function: ease-out;
|
|
2314
|
+
animation-fill-mode: both;
|
|
2315
|
+
animation-delay: 0.2s;
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2318
|
+
@keyframes DCEReactKit-slide-in {
|
|
2319
|
+
0% {
|
|
2320
|
+
opacity: 0;
|
|
2321
|
+
transform: translate(0, 0.3em);
|
|
2322
|
+
}
|
|
2323
|
+
100% {
|
|
2324
|
+
opacity: 1;
|
|
2325
|
+
transform: translate(0, 0);
|
|
2326
|
+
}
|
|
2327
|
+
}
|
|
2328
|
+
</style>
|
|
2329
|
+
</head>
|
|
2330
|
+
|
|
2331
|
+
<!-- Body -->
|
|
2332
|
+
<body class="bg-dark text-center pt-3 ps-3 pe-3">
|
|
2333
|
+
<!-- Alert -->
|
|
2334
|
+
<div
|
|
2335
|
+
class="DCEReactKit-pop-in alert alert-warning d-inline-block"
|
|
2336
|
+
style="width: 50em; max-width: 100%"
|
|
2337
|
+
>
|
|
2338
|
+
<!-- Title -->
|
|
2339
|
+
<h2>
|
|
2340
|
+
<i class="me-1 fa-solid fa-triangle-exclamation"></i>
|
|
2341
|
+
${title}
|
|
2342
|
+
</h2>
|
|
2343
|
+
<!-- Description -->
|
|
2344
|
+
<div>
|
|
2345
|
+
${description}
|
|
2346
|
+
</div>
|
|
2347
|
+
</div>
|
|
2348
|
+
|
|
2349
|
+
<!-- Error Code -->
|
|
2350
|
+
<div class="DCEReactKit-slide-in text-light">
|
|
2351
|
+
<strong>
|
|
2352
|
+
Error Code:
|
|
2353
|
+
</strong>
|
|
2354
|
+
${code}
|
|
2355
|
+
</div>
|
|
2356
|
+
</body>
|
|
2357
|
+
`;
|
|
2358
|
+
};
|
|
2359
|
+
|
|
2360
|
+
/*------------------------------------------------------------------------*/
|
|
2361
|
+
/* Helpers */
|
|
2362
|
+
/*------------------------------------------------------------------------*/
|
|
2363
|
+
/*------------------------------------------------------------------------*/
|
|
2364
|
+
/* Main */
|
|
2365
|
+
/*------------------------------------------------------------------------*/
|
|
2232
2366
|
/**
|
|
2233
2367
|
* Generate an express API route handler
|
|
2234
2368
|
* @author Gabe Abrams
|
|
@@ -2236,21 +2370,23 @@ const handleSuccess = (res, body) => {
|
|
|
2236
2370
|
* @param opts.paramTypes map containing the types for each parameter that is
|
|
2237
2371
|
* included in the request (map: param name => type)
|
|
2238
2372
|
* @param opts.handler function that processes the request
|
|
2239
|
-
* @param [opts.allowNotLoggedIn] if true, allow the user to not be logged
|
|
2240
|
-
* in (the user will be allowed to not have launched via LTI)
|
|
2241
2373
|
* @returns express route handler that takes the following arguments:
|
|
2242
|
-
* params (map: param name => value),
|
|
2243
|
-
*
|
|
2244
|
-
*
|
|
2245
|
-
*
|
|
2246
|
-
*
|
|
2374
|
+
* params (map: param name => value),
|
|
2375
|
+
* req (express request object),
|
|
2376
|
+
* next (express next function),
|
|
2377
|
+
* send (a function that sends a string to the client),
|
|
2378
|
+
* redirect (takes a url and redirects the user to that url),
|
|
2379
|
+
* renderErrorPage (shows a static error page to the user),
|
|
2380
|
+
* and returns the value to send to the client as a JSON API response, or
|
|
2381
|
+
* calls next() or redirect(...) or send(...) or renderErrorPage(...).
|
|
2382
|
+
* Note: params also has userId, userFirstName,
|
|
2247
2383
|
* userLastName, isLearner, isTTM, isAdmin, and any other variables that
|
|
2248
2384
|
* are directly added to the session
|
|
2249
2385
|
*/
|
|
2250
2386
|
const genRouteHandler = (opts) => {
|
|
2251
2387
|
// Return a route handler
|
|
2252
2388
|
return (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
|
2253
|
-
var _a, _b
|
|
2389
|
+
var _a, _b;
|
|
2254
2390
|
// Output params
|
|
2255
2391
|
const output = {};
|
|
2256
2392
|
/*----------------------------------------*/
|
|
@@ -2417,12 +2553,7 @@ const genRouteHandler = (opts) => {
|
|
|
2417
2553
|
/*----------------------------------------*/
|
|
2418
2554
|
// Get launch info
|
|
2419
2555
|
const { launched, launchInfo } = cacclGetLaunchInfo(req);
|
|
2420
|
-
if (
|
|
2421
|
-
// Requiring user to be logged in
|
|
2422
|
-
!opts.allowNotLoggedIn
|
|
2423
|
-
// User is not logged in
|
|
2424
|
-
&& (!launched || !launchInfo)) {
|
|
2425
|
-
// Throw an error
|
|
2556
|
+
if (!launched || !launchInfo) {
|
|
2426
2557
|
return handleError(res, {
|
|
2427
2558
|
message: 'Your session has expired. Please refresh the page and try again.',
|
|
2428
2559
|
code: ReactKitErrorCode$1.SessionExpired,
|
|
@@ -2430,39 +2561,32 @@ const genRouteHandler = (opts) => {
|
|
|
2430
2561
|
});
|
|
2431
2562
|
}
|
|
2432
2563
|
// Error if user info cannot be found
|
|
2433
|
-
if (
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
});
|
|
2447
|
-
}
|
|
2448
|
-
else {
|
|
2449
|
-
// Add launch info to output
|
|
2450
|
-
output.userId = launchInfo.userId;
|
|
2451
|
-
output.userFirstName = launchInfo.userFirstName;
|
|
2452
|
-
output.userLastName = launchInfo.userLastName;
|
|
2453
|
-
output.userEmail = launchInfo.userEmail;
|
|
2454
|
-
output.isLearner = !!launchInfo.isLearner;
|
|
2455
|
-
output.isTTM = !!launchInfo.isTTM;
|
|
2456
|
-
output.isAdmin = !!launchInfo.isAdmin;
|
|
2457
|
-
output.courseId = ((_b = output.courseId) !== null && _b !== void 0 ? _b : launchInfo.courseId);
|
|
2458
|
-
output.courseName = launchInfo.contextLabel;
|
|
2459
|
-
}
|
|
2564
|
+
if (!launchInfo.userId
|
|
2565
|
+
|| !launchInfo.userFirstName
|
|
2566
|
+
|| !launchInfo.userLastName
|
|
2567
|
+
|| (launchInfo.notInCourse
|
|
2568
|
+
&& !launchInfo.isAdmin)
|
|
2569
|
+
|| (!launchInfo.isTTM
|
|
2570
|
+
&& !launchInfo.isLearner
|
|
2571
|
+
&& !launchInfo.isAdmin)) {
|
|
2572
|
+
return handleError(res, {
|
|
2573
|
+
message: 'Your session was invalid. Please refresh the page and try again.',
|
|
2574
|
+
code: ReactKitErrorCode$1.SessionExpired,
|
|
2575
|
+
status: 440,
|
|
2576
|
+
});
|
|
2460
2577
|
}
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2578
|
+
// Add launch info to output
|
|
2579
|
+
output.userId = launchInfo.userId;
|
|
2580
|
+
output.userFirstName = launchInfo.userFirstName;
|
|
2581
|
+
output.userLastName = launchInfo.userLastName;
|
|
2582
|
+
output.userEmail = launchInfo.userEmail;
|
|
2583
|
+
output.isLearner = !!launchInfo.isLearner;
|
|
2584
|
+
output.isTTM = !!launchInfo.isTTM;
|
|
2585
|
+
output.isAdmin = !!launchInfo.isAdmin;
|
|
2586
|
+
output.courseId = ((_b = output.courseId) !== null && _b !== void 0 ? _b : launchInfo.courseId);
|
|
2587
|
+
output.courseName = launchInfo.contextLabel;
|
|
2464
2588
|
// Add other session variables
|
|
2465
|
-
Object.keys(
|
|
2589
|
+
Object.keys(req.session).forEach((propName) => {
|
|
2466
2590
|
// Skip if prop already in output
|
|
2467
2591
|
if (output[propName] !== undefined) {
|
|
2468
2592
|
return;
|
|
@@ -2480,7 +2604,6 @@ const genRouteHandler = (opts) => {
|
|
|
2480
2604
|
/*----------------------------------------*/
|
|
2481
2605
|
// Make sure the user actually launched from the appropriate course
|
|
2482
2606
|
if (output.courseId
|
|
2483
|
-
&& launchInfo
|
|
2484
2607
|
&& launchInfo.courseId
|
|
2485
2608
|
&& output.courseId !== launchInfo.courseId
|
|
2486
2609
|
&& !output.isTTM
|
|
@@ -2549,6 +2672,23 @@ const genRouteHandler = (opts) => {
|
|
|
2549
2672
|
responseSent = true;
|
|
2550
2673
|
res.status(status).send(text);
|
|
2551
2674
|
};
|
|
2675
|
+
/**
|
|
2676
|
+
* Render an error page
|
|
2677
|
+
* @author Gabe Abrams
|
|
2678
|
+
* @param opts object containing all arguments
|
|
2679
|
+
* @param [opts.title=An Error Occurred] title of the error box
|
|
2680
|
+
* @param [opts.description=An unknown server error occurred. Please contact support.]
|
|
2681
|
+
* a human-readable description of the error
|
|
2682
|
+
* @param [opts.code=ReactKitErrorCode.NoCode] error code to show
|
|
2683
|
+
* @param [opts.pageTitle=opts.title] title of the page/tab if it differs from
|
|
2684
|
+
* the title of the error
|
|
2685
|
+
* @param [opts.status=500] http status code
|
|
2686
|
+
*/
|
|
2687
|
+
const renderErrorPage = (opts = {}) => {
|
|
2688
|
+
var _a;
|
|
2689
|
+
const html = genErrorPage(opts);
|
|
2690
|
+
send(html, (_a = opts.status) !== null && _a !== void 0 ? _a : 500);
|
|
2691
|
+
};
|
|
2552
2692
|
// Call the handler
|
|
2553
2693
|
try {
|
|
2554
2694
|
const results = yield opts.handler({
|
|
@@ -2560,6 +2700,7 @@ const genRouteHandler = (opts) => {
|
|
|
2560
2700
|
next();
|
|
2561
2701
|
},
|
|
2562
2702
|
redirect,
|
|
2703
|
+
renderErrorPage,
|
|
2563
2704
|
});
|
|
2564
2705
|
// Send results to client (only if next wasn't called)
|
|
2565
2706
|
if (!responseSent) {
|