dce-reactkit 3.1.14 → 3.1.16
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 +205 -70
- 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 +182 -47
- 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 +47 -7
- package/src/html/genErrorPage.ts +141 -0
package/dist/cjs/index.js
CHANGED
|
@@ -11,29 +11,29 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
11
11
|
|
|
12
12
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
13
13
|
|
|
14
|
-
/******************************************************************************
|
|
15
|
-
Copyright (c) Microsoft Corporation.
|
|
16
|
-
|
|
17
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
18
|
-
purpose with or without fee is hereby granted.
|
|
19
|
-
|
|
20
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
21
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
22
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
23
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
24
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
25
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
26
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
27
|
-
***************************************************************************** */
|
|
28
|
-
|
|
29
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
30
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
31
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
32
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
33
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
34
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
35
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
36
|
-
});
|
|
14
|
+
/******************************************************************************
|
|
15
|
+
Copyright (c) Microsoft Corporation.
|
|
16
|
+
|
|
17
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
18
|
+
purpose with or without fee is hereby granted.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
21
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
22
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
23
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
24
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
25
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
26
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
27
|
+
***************************************************************************** */
|
|
28
|
+
|
|
29
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
30
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
31
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
32
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
33
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
34
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
35
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
36
|
+
});
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
// Highest error code = DRK10
|
|
@@ -2229,6 +2229,134 @@ 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
|
+
|
|
2232
2360
|
/**
|
|
2233
2361
|
* Generate an express API route handler
|
|
2234
2362
|
* @author Gabe Abrams
|
|
@@ -2236,21 +2364,23 @@ const handleSuccess = (res, body) => {
|
|
|
2236
2364
|
* @param opts.paramTypes map containing the types for each parameter that is
|
|
2237
2365
|
* included in the request (map: param name => type)
|
|
2238
2366
|
* @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
2367
|
* @returns express route handler that takes the following arguments:
|
|
2242
|
-
* params (map: param name => value),
|
|
2243
|
-
*
|
|
2244
|
-
*
|
|
2245
|
-
*
|
|
2246
|
-
*
|
|
2368
|
+
* params (map: param name => value),
|
|
2369
|
+
* req (express request object),
|
|
2370
|
+
* next (express next function),
|
|
2371
|
+
* send (a function that sends a string to the client),
|
|
2372
|
+
* redirect (takes a url and redirects the user to that url),
|
|
2373
|
+
* renderErrorPage (shows a static error page to the user),
|
|
2374
|
+
* and returns the value to send to the client as a JSON API response, or
|
|
2375
|
+
* calls next() or redirect(...) or send(...) or renderErrorPage(...).
|
|
2376
|
+
* Note: params also has userId, userFirstName,
|
|
2247
2377
|
* userLastName, isLearner, isTTM, isAdmin, and any other variables that
|
|
2248
2378
|
* are directly added to the session
|
|
2249
2379
|
*/
|
|
2250
2380
|
const genRouteHandler = (opts) => {
|
|
2251
2381
|
// Return a route handler
|
|
2252
2382
|
return (req, res, next) => __awaiter(void 0, void 0, void 0, function* () {
|
|
2253
|
-
var _a, _b
|
|
2383
|
+
var _a, _b;
|
|
2254
2384
|
// Output params
|
|
2255
2385
|
const output = {};
|
|
2256
2386
|
/*----------------------------------------*/
|
|
@@ -2417,52 +2547,40 @@ const genRouteHandler = (opts) => {
|
|
|
2417
2547
|
/*----------------------------------------*/
|
|
2418
2548
|
// Get launch info
|
|
2419
2549
|
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
|
|
2550
|
+
if (!launched || !launchInfo) {
|
|
2426
2551
|
return handleError(res, {
|
|
2427
2552
|
message: 'Your session has expired. Please refresh the page and try again.',
|
|
2428
2553
|
code: ReactKitErrorCode$1.SessionExpired,
|
|
2429
|
-
status:
|
|
2554
|
+
status: 401,
|
|
2430
2555
|
});
|
|
2431
2556
|
}
|
|
2432
2557
|
// 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
|
-
}
|
|
2558
|
+
if (!launchInfo.userId
|
|
2559
|
+
|| !launchInfo.userFirstName
|
|
2560
|
+
|| !launchInfo.userLastName
|
|
2561
|
+
|| (launchInfo.notInCourse
|
|
2562
|
+
&& !launchInfo.isAdmin)
|
|
2563
|
+
|| (!launchInfo.isTTM
|
|
2564
|
+
&& !launchInfo.isLearner
|
|
2565
|
+
&& !launchInfo.isAdmin)) {
|
|
2566
|
+
return handleError(res, {
|
|
2567
|
+
message: 'Your session was invalid. Please refresh the page and try again.',
|
|
2568
|
+
code: ReactKitErrorCode$1.SessionExpired,
|
|
2569
|
+
status: 401,
|
|
2570
|
+
});
|
|
2460
2571
|
}
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2572
|
+
// Add launch info to output
|
|
2573
|
+
output.userId = launchInfo.userId;
|
|
2574
|
+
output.userFirstName = launchInfo.userFirstName;
|
|
2575
|
+
output.userLastName = launchInfo.userLastName;
|
|
2576
|
+
output.userEmail = launchInfo.userEmail;
|
|
2577
|
+
output.isLearner = !!launchInfo.isLearner;
|
|
2578
|
+
output.isTTM = !!launchInfo.isTTM;
|
|
2579
|
+
output.isAdmin = !!launchInfo.isAdmin;
|
|
2580
|
+
output.courseId = ((_b = output.courseId) !== null && _b !== void 0 ? _b : launchInfo.courseId);
|
|
2581
|
+
output.courseName = launchInfo.contextLabel;
|
|
2464
2582
|
// Add other session variables
|
|
2465
|
-
Object.keys(
|
|
2583
|
+
Object.keys(req.session).forEach((propName) => {
|
|
2466
2584
|
// Skip if prop already in output
|
|
2467
2585
|
if (output[propName] !== undefined) {
|
|
2468
2586
|
return;
|
|
@@ -2480,7 +2598,6 @@ const genRouteHandler = (opts) => {
|
|
|
2480
2598
|
/*----------------------------------------*/
|
|
2481
2599
|
// Make sure the user actually launched from the appropriate course
|
|
2482
2600
|
if (output.courseId
|
|
2483
|
-
&& launchInfo
|
|
2484
2601
|
&& launchInfo.courseId
|
|
2485
2602
|
&& output.courseId !== launchInfo.courseId
|
|
2486
2603
|
&& !output.isTTM
|
|
@@ -2549,6 +2666,23 @@ const genRouteHandler = (opts) => {
|
|
|
2549
2666
|
responseSent = true;
|
|
2550
2667
|
res.status(status).send(text);
|
|
2551
2668
|
};
|
|
2669
|
+
/**
|
|
2670
|
+
* Render an error page
|
|
2671
|
+
* @author Gabe Abrams
|
|
2672
|
+
* @param opts object containing all arguments
|
|
2673
|
+
* @param [opts.title=An Error Occurred] title of the error box
|
|
2674
|
+
* @param [opts.description=An unknown server error occurred. Please contact support.]
|
|
2675
|
+
* a human-readable description of the error
|
|
2676
|
+
* @param [opts.code=ReactKitErrorCode.NoCode] error code to show
|
|
2677
|
+
* @param [opts.pageTitle=opts.title] title of the page/tab if it differs from
|
|
2678
|
+
* the title of the error
|
|
2679
|
+
* @param [opts.status=500] http status code
|
|
2680
|
+
*/
|
|
2681
|
+
const renderErrorPage = (opts = {}) => {
|
|
2682
|
+
var _a;
|
|
2683
|
+
const html = genErrorPage(opts);
|
|
2684
|
+
send(html, (_a = opts.status) !== null && _a !== void 0 ? _a : 500);
|
|
2685
|
+
};
|
|
2552
2686
|
// Call the handler
|
|
2553
2687
|
try {
|
|
2554
2688
|
const results = yield opts.handler({
|
|
@@ -2560,6 +2694,7 @@ const genRouteHandler = (opts) => {
|
|
|
2560
2694
|
next();
|
|
2561
2695
|
},
|
|
2562
2696
|
redirect,
|
|
2697
|
+
renderErrorPage,
|
|
2563
2698
|
});
|
|
2564
2699
|
// Send results to client (only if next wasn't called)
|
|
2565
2700
|
if (!responseSent) {
|