@epic-web/workshop-app 5.0.1 → 5.0.3
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/build/client/assets/{_-D0Tgngwe.js → _-ZHCWB__B.js} +2 -2
- package/build/client/assets/{_-D0Tgngwe.js.map → _-ZHCWB__B.js.map} +1 -1
- package/build/client/assets/_exerciseNumber-BFTlBdr4.js +2 -0
- package/build/client/assets/_exerciseNumber-BFTlBdr4.js.map +1 -0
- package/build/client/assets/{_exerciseNumber_._stepNumber-7kSd_6hH.js → _exerciseNumber_._stepNumber-_687iGFh.js} +2 -2
- package/build/client/assets/{_exerciseNumber_._stepNumber-7kSd_6hH.js.map → _exerciseNumber_._stepNumber-_687iGFh.js.map} +1 -1
- package/build/client/assets/_exerciseNumber_.finished-BEfn-nJi.js +2 -0
- package/build/client/assets/_exerciseNumber_.finished-BEfn-nJi.js.map +1 -0
- package/build/client/assets/{_layout-BwzhY4NI.js → _layout-BLJr2x2F.js} +2 -2
- package/build/client/assets/{_layout-BwzhY4NI.js.map → _layout-BLJr2x2F.js.map} +1 -1
- package/build/client/assets/_layout-BriOqd2R.js +2 -0
- package/build/client/assets/_layout-BriOqd2R.js.map +1 -0
- package/build/client/assets/{_layout-BUs3av-e.js → _layout-Cfbi6StB.js} +2 -2
- package/build/client/assets/{_layout-BUs3av-e.js.map → _layout-Cfbi6StB.js.map} +1 -1
- package/build/client/assets/_layout-frPHZWgR.js +6 -0
- package/build/client/assets/_layout-frPHZWgR.js.map +1 -0
- package/build/client/assets/{accordion-OfO-5m5D.js → accordion-DuE9VejZ.js} +2 -2
- package/build/client/assets/{accordion-OfO-5m5D.js.map → accordion-DuE9VejZ.js.map} +1 -1
- package/build/client/assets/{account-BatJhmSV.js → account-DDuV9rZX.js} +2 -2
- package/build/client/assets/{account-BatJhmSV.js.map → account-DDuV9rZX.js.map} +1 -1
- package/build/client/assets/app-wbMCZEiv.js +2 -0
- package/build/client/assets/{app-CJ9ElQg6.js.map → app-wbMCZEiv.js.map} +1 -1
- package/build/client/assets/{button-EE0aPg10.js → button-CMkJ8p0a.js} +2 -2
- package/build/client/assets/{button-EE0aPg10.js.map → button-CMkJ8p0a.js.map} +1 -1
- package/build/client/assets/{components-CME-nGId.js → components-DZ8XIeZ3.js} +2 -2
- package/build/client/assets/{components-CME-nGId.js.map → components-DZ8XIeZ3.js.map} +1 -1
- package/build/client/assets/diff-B6thd_Sf.js +2 -0
- package/build/client/assets/diff-B6thd_Sf.js.map +1 -0
- package/build/client/assets/diff-BEk79KPK.js +2 -0
- package/build/client/assets/{diff-Cvtc-qzL.js.map → diff-BEk79KPK.js.map} +1 -1
- package/build/client/assets/{discord-BRTW4Rnh.js → discord-C9bVfiZ6.js} +2 -2
- package/build/client/assets/{discord-BRTW4Rnh.js.map → discord-C9bVfiZ6.js.map} +1 -1
- package/build/client/assets/discord-DYeU0QX6.js +2 -0
- package/build/client/assets/discord-DYeU0QX6.js.map +1 -0
- package/build/client/assets/{entry.client-3M2p-8I3.js → entry.client-CW5CUf_W.js} +2 -2
- package/build/client/assets/{entry.client-3M2p-8I3.js.map → entry.client-CW5CUf_W.js.map} +1 -1
- package/build/client/assets/{epic-video-yrWoJVFy.js → epic-video-bs7WmhbC.js} +2 -2
- package/build/client/assets/{epic-video-yrWoJVFy.js.map → epic-video-bs7WmhbC.js.map} +1 -1
- package/build/client/assets/{error-boundary-COkPRBOZ.js → error-boundary-BcGxKpte.js} +2 -2
- package/build/client/assets/{error-boundary-COkPRBOZ.js.map → error-boundary-BcGxKpte.js.map} +1 -1
- package/build/client/assets/finished-C2dgX1d-.js +2 -0
- package/build/client/assets/finished-C2dgX1d-.js.map +1 -0
- package/build/client/assets/{index-BwhlO_gF.js → index-BczhSZ3e.js} +2 -2
- package/build/client/assets/{index-BwhlO_gF.js.map → index-BczhSZ3e.js.map} +1 -1
- package/build/client/assets/{index-CXyf3Reb.js → index-BjNhezSK.js} +2 -2
- package/build/client/assets/{index-CXyf3Reb.js.map → index-BjNhezSK.js.map} +1 -1
- package/build/client/assets/{index-YNIH4TH8.js → index-BvihEwfB.js} +2 -2
- package/build/client/assets/{index-YNIH4TH8.js.map → index-BvihEwfB.js.map} +1 -1
- package/build/client/assets/index-C2yr7Uiu.js +2 -0
- package/build/client/assets/index-C2yr7Uiu.js.map +1 -0
- package/build/client/assets/{index-R-sUGQfT.js → index-CuV1bRbu.js} +2 -2
- package/build/client/assets/{index-R-sUGQfT.js.map → index-CuV1bRbu.js.map} +1 -1
- package/build/client/assets/{index-Dx5GmdYq.js → index-DBrRQJxF.js} +2 -2
- package/build/client/assets/{index-Dx5GmdYq.js.map → index-DBrRQJxF.js.map} +1 -1
- package/build/client/assets/{index-1cKOJFpX.js → index-DF_XBInP.js} +2 -2
- package/build/client/assets/{index-1cKOJFpX.js.map → index-DF_XBInP.js.map} +1 -1
- package/build/client/assets/{index-B-hHvmeV.js → index-YtpQLUzj.js} +2 -2
- package/build/client/assets/{index-B-hHvmeV.js.map → index-YtpQLUzj.js.map} +1 -1
- package/build/client/assets/{loading-sXkYDMsx.js → loading-Br41_Pbf.js} +2 -2
- package/build/client/assets/{loading-sXkYDMsx.js.map → loading-Br41_Pbf.js.map} +1 -1
- package/build/client/assets/{login-Cc73KLYm.js → login-kjV7hrVt.js} +2 -2
- package/build/client/assets/{login-Cc73KLYm.js.map → login-kjV7hrVt.js.map} +1 -1
- package/build/client/assets/manifest-d7c89645.js +1 -0
- package/build/client/assets/{mdx-CpyquP9i.js → mdx-CRxPouxB.js} +2 -2
- package/build/client/assets/{mdx-CpyquP9i.js.map → mdx-CRxPouxB.js.map} +1 -1
- package/build/client/assets/{misc-CxCgA-_O.js → misc-BE75ioh8.js} +2 -2
- package/build/client/assets/{misc-CxCgA-_O.js.map → misc-BE75ioh8.js.map} +1 -1
- package/build/client/assets/{nav-chevrons-g-C0ilNz.js → nav-chevrons-DYiI8EMU.js} +2 -2
- package/build/client/assets/{nav-chevrons-g-C0ilNz.js.map → nav-chevrons-DYiI8EMU.js.map} +1 -1
- package/build/client/assets/{onboarding-B7TLVi2l.js → onboarding-B4Z_yevk.js} +2 -2
- package/build/client/assets/{onboarding-B7TLVi2l.js.map → onboarding-B4Z_yevk.js.map} +1 -1
- package/build/client/assets/{pe-CUZaIcdt.js → pe-CvPIToj6.js} +2 -2
- package/build/client/assets/{pe-CUZaIcdt.js.map → pe-CvPIToj6.js.map} +1 -1
- package/build/client/assets/{presence-Cr--lRCr.js → presence-Dd98AJ_5.js} +2 -2
- package/build/client/assets/{presence-Cr--lRCr.js.map → presence-Dd98AJ_5.js.map} +1 -1
- package/build/client/assets/{preview-C7dtR2VR.js → preview-DZcdG4kw.js} +2 -2
- package/build/client/assets/{preview-C7dtR2VR.js.map → preview-DZcdG4kw.js.map} +1 -1
- package/build/client/assets/{product-BAWG1Vut.js → product-mjsTrqXs.js} +2 -2
- package/build/client/assets/{product-BAWG1Vut.js.map → product-mjsTrqXs.js.map} +1 -1
- package/build/client/assets/{progress-BFm2U-l5.js → progress-Co-59mG2.js} +2 -2
- package/build/client/assets/{progress-BFm2U-l5.js.map → progress-Co-59mG2.js.map} +1 -1
- package/build/client/assets/{progress-bar-D3kudPcr.js → progress-bar-F8_2mvYp.js} +2 -2
- package/build/client/assets/{progress-bar-D3kudPcr.js.map → progress-bar-F8_2mvYp.js.map} +1 -1
- package/build/client/assets/{request-info-CEhUGODY.js → request-info-DGnmXtfj.js} +2 -2
- package/build/client/assets/{request-info-CEhUGODY.js.map → request-info-DGnmXtfj.js.map} +1 -1
- package/build/client/assets/revalidation-ws-DcvYvzyj.js +2 -0
- package/build/client/assets/revalidation-ws-DcvYvzyj.js.map +1 -0
- package/build/client/assets/root-Cl86OUog.js +11 -0
- package/build/client/assets/root-Cl86OUog.js.map +1 -0
- package/build/client/assets/{set-playground-DW0yVaNn.js → set-playground-pMKmtPtz.js} +2 -2
- package/build/client/assets/{set-playground-DW0yVaNn.js.map → set-playground-pMKmtPtz.js.map} +1 -1
- package/build/client/assets/{support-hcqGIpir.js → support-B0E_F4Zh.js} +2 -2
- package/build/client/assets/{support-hcqGIpir.js.map → support-B0E_F4Zh.js.map} +1 -1
- package/build/client/assets/test-B6zIK2V6.js +2 -0
- package/build/client/assets/{test-DbZkv25C.js.map → test-B6zIK2V6.js.map} +1 -1
- package/build/client/assets/{tests-BR7RFlr5.js → tests-BeAEgPAw.js} +2 -2
- package/build/client/assets/{tests-BR7RFlr5.js.map → tests-BeAEgPAw.js.map} +1 -1
- package/build/client/assets/{tooltip-kD4kSf1i.js → tooltip-6-WS-Xux.js} +2 -2
- package/build/client/assets/{tooltip-kD4kSf1i.js.map → tooltip-6-WS-Xux.js.map} +1 -1
- package/build/client/assets/{use-event-source-A_0lEOPX.js → use-event-source-CCGBLG92.js} +2 -2
- package/build/client/assets/{use-event-source-A_0lEOPX.js.map → use-event-source-CCGBLG92.js.map} +1 -1
- package/build/client/assets/{user-DvujSs-t.js → user-Boua6jiU.js} +2 -2
- package/build/client/assets/{user-DvujSs-t.js.map → user-Boua6jiU.js.map} +1 -1
- package/build/client/assets/{workshop-config-CL4F08kr.js → workshop-config-Ce9sSc3I.js} +2 -2
- package/build/client/assets/{workshop-config-CL4F08kr.js.map → workshop-config-Ce9sSc3I.js.map} +1 -1
- package/build/server/index.js +768 -692
- package/build/server/index.js.map +1 -1
- package/dist/server/index.js +83 -34
- package/package.json +4 -4
- package/build/client/assets/_exerciseNumber-1JworToC.js +0 -2
- package/build/client/assets/_exerciseNumber-1JworToC.js.map +0 -1
- package/build/client/assets/_exerciseNumber_.finished-B4D2ZAmj.js +0 -2
- package/build/client/assets/_exerciseNumber_.finished-B4D2ZAmj.js.map +0 -1
- package/build/client/assets/_layout-BPwIOXxN.js +0 -6
- package/build/client/assets/_layout-BPwIOXxN.js.map +0 -1
- package/build/client/assets/_layout-CKnDy_9Z.js +0 -2
- package/build/client/assets/_layout-CKnDy_9Z.js.map +0 -1
- package/build/client/assets/app-CJ9ElQg6.js +0 -2
- package/build/client/assets/diff-Cvtc-qzL.js +0 -2
- package/build/client/assets/diff-jgZ_RGra.js +0 -2
- package/build/client/assets/diff-jgZ_RGra.js.map +0 -1
- package/build/client/assets/discord-BhzUjmbI.js +0 -2
- package/build/client/assets/discord-BhzUjmbI.js.map +0 -1
- package/build/client/assets/finished-Ct6I1SZV.js +0 -2
- package/build/client/assets/finished-Ct6I1SZV.js.map +0 -1
- package/build/client/assets/index-Ccssehd9.js +0 -2
- package/build/client/assets/index-Ccssehd9.js.map +0 -1
- package/build/client/assets/manifest-f5f44d87.js +0 -1
- package/build/client/assets/root-9wVBEzOq.js +0 -68
- package/build/client/assets/root-9wVBEzOq.js.map +0 -1
- package/build/client/assets/test-DbZkv25C.js +0 -2
package/build/server/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
var _a;
|
|
2
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
3
2
|
import { PassThrough } from "stream";
|
|
4
3
|
import { createReadableStreamFromReadable, redirect, json as json$1, createCookieSessionStorage, defer } from "@remix-run/node";
|
|
@@ -15,14 +14,13 @@ import fsExtra from "fs-extra";
|
|
|
15
14
|
import { LRUCache } from "lru-cache";
|
|
16
15
|
import md5 from "md5-hex";
|
|
17
16
|
import { z } from "zod";
|
|
18
|
-
import fs from "node:fs";
|
|
17
|
+
import fs$1 from "node:fs";
|
|
18
|
+
import chokidar from "chokidar";
|
|
19
19
|
import "@total-typescript/ts-reset";
|
|
20
|
+
import closeWithGrace from "close-with-grace";
|
|
20
21
|
import { execa } from "execa";
|
|
21
|
-
import { glob } from "glob";
|
|
22
22
|
import { isGitIgnored, globby } from "globby";
|
|
23
|
-
import
|
|
24
|
-
import closeWithGrace from "close-with-grace";
|
|
25
|
-
import fs$1 from "fs";
|
|
23
|
+
import fs from "fs";
|
|
26
24
|
import { remarkCodeBlocksShiki } from "@kentcdodds/md-temp";
|
|
27
25
|
import { bundleMDX } from "mdx-bundler";
|
|
28
26
|
import PQueue from "p-queue";
|
|
@@ -35,13 +33,14 @@ import net from "node:net";
|
|
|
35
33
|
import chalk from "chalk";
|
|
36
34
|
import fkill from "fkill";
|
|
37
35
|
import { cssBundleHref } from "@remix-run/css-bundle";
|
|
38
|
-
import
|
|
39
|
-
import React__default, { useRef, useEffect, useMemo, useState, createContext, useContext, useSyncExternalStore, forwardRef, useImperativeHandle, Suspense, useReducer } from "react";
|
|
36
|
+
import { promiseHash } from "remix-utils/promise";
|
|
40
37
|
import { useSpinDelay } from "spin-delay";
|
|
41
38
|
import { Index as Index$1 } from "confetti-react";
|
|
42
39
|
import { ClientOnly } from "remix-utils/client-only";
|
|
43
40
|
import slugify from "@sindresorhus/slugify";
|
|
44
41
|
import clsx$1, { clsx } from "clsx";
|
|
42
|
+
import * as React from "react";
|
|
43
|
+
import React__default, { useRef, useEffect, useMemo, useState, createContext, useContext, useSyncExternalStore, forwardRef, useImperativeHandle, Suspense, useReducer } from "react";
|
|
45
44
|
import { extendTailwindMerge } from "tailwind-merge";
|
|
46
45
|
import { Toaster, toast } from "sonner";
|
|
47
46
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
@@ -219,6 +218,9 @@ const compiledMarkdownCache = makeSingletonCache(
|
|
|
219
218
|
const compiledCodeCache = makeSingletonCache("CompiledCodeCache");
|
|
220
219
|
const ogCache = makeSingletonCache("OgCache");
|
|
221
220
|
const compiledInstructionMarkdownCache = makeSingletonFsCache("CompiledInstructionMarkdownCache");
|
|
221
|
+
const dirModifiedTimeCache = makeSingletonCache(
|
|
222
|
+
"DirModifiedTimeCache"
|
|
223
|
+
);
|
|
222
224
|
const cacheDir = path.join(os.homedir(), ".epicshop", "cache");
|
|
223
225
|
const fsCache = makeSingletonFsCache("FsCache");
|
|
224
226
|
async function getAllFileCacheEntries() {
|
|
@@ -410,12 +412,12 @@ async function getAuthInfo() {
|
|
|
410
412
|
return (data == null ? void 0 : data.authInfo) ?? null;
|
|
411
413
|
}
|
|
412
414
|
async function getUserInfo() {
|
|
413
|
-
var
|
|
415
|
+
var _a, _b;
|
|
414
416
|
const db = await readDb();
|
|
415
417
|
if (!(db == null ? void 0 : db.authInfo)) return null;
|
|
416
418
|
return {
|
|
417
419
|
id: db.authInfo.id,
|
|
418
|
-
name: ((
|
|
420
|
+
name: ((_a = db.discordMember) == null ? void 0 : _a.displayName) ?? db.authInfo.name ?? null,
|
|
419
421
|
email: db.authInfo.email,
|
|
420
422
|
avatarUrl: ((_b = db.discordMember) == null ? void 0 : _b.avatarURL) ?? getGravatar({ email: db.authInfo.email, size: 288 })
|
|
421
423
|
};
|
|
@@ -598,7 +600,180 @@ function uniqueUsers(users) {
|
|
|
598
600
|
return true;
|
|
599
601
|
});
|
|
600
602
|
}
|
|
603
|
+
function trimCodeBlocks() {
|
|
604
|
+
return async function transformer(tree) {
|
|
605
|
+
visit(tree, "element", (preNode) => {
|
|
606
|
+
if (preNode.tagName !== "pre" || !preNode.children.length) {
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
const codeNode = preNode.children[0];
|
|
610
|
+
if (!codeNode || codeNode.type !== "element" || codeNode.tagName !== "code") {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
const [codeStringNode] = codeNode.children;
|
|
614
|
+
if (!codeStringNode) return;
|
|
615
|
+
if (codeStringNode.type !== "text") {
|
|
616
|
+
console.warn(
|
|
617
|
+
`trimCodeBlocks: Unexpected: codeStringNode type is not "text": ${codeStringNode.type}`
|
|
618
|
+
);
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
621
|
+
codeStringNode.value = codeStringNode.value.trimEnd();
|
|
622
|
+
});
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
function removePreContainerDivs() {
|
|
626
|
+
return async function preContainerDivsTransformer(tree) {
|
|
627
|
+
visit(
|
|
628
|
+
tree,
|
|
629
|
+
{ type: "element", tagName: "pre" },
|
|
630
|
+
function visitor(node, index, parent) {
|
|
631
|
+
if ((parent == null ? void 0 : parent.type) !== "element") return;
|
|
632
|
+
if (parent.tagName !== "div") return;
|
|
633
|
+
if (parent.children.length !== 1 && index === 0) return;
|
|
634
|
+
Object.assign(parent, node);
|
|
635
|
+
}
|
|
636
|
+
);
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
const rehypePlugins = [
|
|
640
|
+
trimCodeBlocks,
|
|
641
|
+
remarkCodeBlocksShiki,
|
|
642
|
+
removePreContainerDivs
|
|
643
|
+
];
|
|
644
|
+
const verboseLog = process.env.EPICSHOP_VERBOSE_LOG === "true" ? console.log : () => {
|
|
645
|
+
};
|
|
646
|
+
async function compileMdx(file, {
|
|
647
|
+
request,
|
|
648
|
+
timings,
|
|
649
|
+
forceFresh
|
|
650
|
+
} = {}) {
|
|
651
|
+
const stat = await fs.promises.stat(file).catch((error) => ({ error }));
|
|
652
|
+
if ("error" in stat) {
|
|
653
|
+
throw new Error(`File stat cannot be read: ${stat.error}`);
|
|
654
|
+
}
|
|
655
|
+
const key = `file:${file}`;
|
|
656
|
+
forceFresh = await shouldForceFresh({ forceFresh, request, key });
|
|
657
|
+
const existingCacheEntry = await compiledInstructionMarkdownCache.get(key);
|
|
658
|
+
if (!forceFresh && existingCacheEntry) {
|
|
659
|
+
forceFresh = stat.mtimeMs > existingCacheEntry.metadata.createdTime;
|
|
660
|
+
}
|
|
661
|
+
return cachified({
|
|
662
|
+
key,
|
|
663
|
+
cache: compiledInstructionMarkdownCache,
|
|
664
|
+
request,
|
|
665
|
+
timings,
|
|
666
|
+
forceFresh,
|
|
667
|
+
getFreshValue: () => compileMdxImpl(file)
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
async function compileMdxImpl(file) {
|
|
671
|
+
let title = null;
|
|
672
|
+
const epicVideoEmbeds = [];
|
|
673
|
+
try {
|
|
674
|
+
verboseLog(`Compiling ${file}`);
|
|
675
|
+
const bundleResult = await queuedBundleMDX({
|
|
676
|
+
file,
|
|
677
|
+
cwd: path.dirname(file),
|
|
678
|
+
mdxOptions(options) {
|
|
679
|
+
options.remarkPlugins = [
|
|
680
|
+
...options.remarkPlugins ?? [],
|
|
681
|
+
[remarkAutolinkHeadings, { behavior: "wrap" }],
|
|
682
|
+
gfm,
|
|
683
|
+
() => (tree) => {
|
|
684
|
+
visit(tree, "heading", (node) => {
|
|
685
|
+
if (title) return;
|
|
686
|
+
if (node.depth === 1) {
|
|
687
|
+
visit(node, "text", (textNode) => {
|
|
688
|
+
title = textNode.value.trim();
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
});
|
|
692
|
+
title = title ? title.replace(/^\d+\. /, "").trim() : null;
|
|
693
|
+
},
|
|
694
|
+
() => (tree) => {
|
|
695
|
+
visit(tree, "mdxJsxFlowElement", (jsxEl) => {
|
|
696
|
+
if (jsxEl.name !== "EpicVideo") return;
|
|
697
|
+
const urlAttr = jsxEl.attributes.find(
|
|
698
|
+
// @ts-expect-error no idea why this started being an issue suddenly 🤷♂️
|
|
699
|
+
(a) => a.type === "mdxJsxAttribute" && a.name === "url"
|
|
700
|
+
);
|
|
701
|
+
if (!urlAttr) return;
|
|
702
|
+
let url = urlAttr.value;
|
|
703
|
+
if (typeof url !== "string") return;
|
|
704
|
+
if (url.endsWith("/")) url = url.slice(0, -1);
|
|
705
|
+
epicVideoEmbeds.push(url);
|
|
706
|
+
});
|
|
707
|
+
},
|
|
708
|
+
emoji
|
|
709
|
+
];
|
|
710
|
+
options.rehypePlugins = [
|
|
711
|
+
...options.rehypePlugins ?? [],
|
|
712
|
+
...rehypePlugins
|
|
713
|
+
];
|
|
714
|
+
options.mdxExtensions = [".mdx", ".md"];
|
|
715
|
+
options.format = "mdx";
|
|
716
|
+
options.development = false;
|
|
717
|
+
return options;
|
|
718
|
+
}
|
|
719
|
+
});
|
|
720
|
+
if (!bundleResult) throw new Error(`Timeout for file: ${file}`);
|
|
721
|
+
const result = { code: bundleResult.code, title, epicVideoEmbeds };
|
|
722
|
+
return result;
|
|
723
|
+
} catch (error) {
|
|
724
|
+
console.error(`Compilation error for file: `, file, error);
|
|
725
|
+
throw error;
|
|
726
|
+
} finally {
|
|
727
|
+
verboseLog(`Successfully compiled ${file}`);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
async function compileMarkdownString(markdownString) {
|
|
731
|
+
return cachified({
|
|
732
|
+
key: markdownString,
|
|
733
|
+
cache: compiledMarkdownCache,
|
|
734
|
+
ttl: 1e3 * 60 * 60 * 24,
|
|
735
|
+
getFreshValue: async () => {
|
|
736
|
+
try {
|
|
737
|
+
verboseLog(`Compiling string`, markdownString);
|
|
738
|
+
const result = await queuedBundleMDX({
|
|
739
|
+
source: markdownString,
|
|
740
|
+
mdxOptions(options) {
|
|
741
|
+
options.rehypePlugins = [
|
|
742
|
+
...options.rehypePlugins ?? [],
|
|
743
|
+
...rehypePlugins
|
|
744
|
+
];
|
|
745
|
+
options.development = false;
|
|
746
|
+
return options;
|
|
747
|
+
}
|
|
748
|
+
});
|
|
749
|
+
if (!result) throw new Error(`Timed out compiling markdown string`);
|
|
750
|
+
return result.code;
|
|
751
|
+
} catch (error) {
|
|
752
|
+
console.error(`Compilation error for code: `, markdownString, error);
|
|
753
|
+
throw error;
|
|
754
|
+
} finally {
|
|
755
|
+
verboseLog(`Successfully compiled string`, markdownString);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
let _queue$1 = null;
|
|
761
|
+
async function getQueue$1() {
|
|
762
|
+
if (_queue$1) return _queue$1;
|
|
763
|
+
_queue$1 = new PQueue({
|
|
764
|
+
concurrency: 1,
|
|
765
|
+
throwOnTimeout: true,
|
|
766
|
+
timeout: 1e3 * 60
|
|
767
|
+
});
|
|
768
|
+
return _queue$1;
|
|
769
|
+
}
|
|
770
|
+
async function queuedBundleMDX(...args) {
|
|
771
|
+
const queue = await getQueue$1();
|
|
772
|
+
const result = await queue.add(() => bundleMDX(...args));
|
|
773
|
+
return result;
|
|
774
|
+
}
|
|
601
775
|
const workshopRoot$1 = process.env.EPICSHOP_CONTEXT_CWD ?? process.cwd();
|
|
776
|
+
const rootPkgJson = path$1.join(workshopRoot$1, "package.json");
|
|
602
777
|
const StackBlitzConfigSchema = z.object({
|
|
603
778
|
// we default this to `${exerciseTitle} (${type})`
|
|
604
779
|
title: z.string().optional(),
|
|
@@ -663,16 +838,18 @@ const WorkshopConfigSchema = z.object({
|
|
|
663
838
|
}
|
|
664
839
|
};
|
|
665
840
|
});
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
}
|
|
841
|
+
const configCache = {
|
|
842
|
+
config: null,
|
|
843
|
+
modified: 0
|
|
844
|
+
};
|
|
670
845
|
function getWorkshopConfig() {
|
|
671
|
-
if (
|
|
846
|
+
if (configCache.config && configCache.modified > fs$1.statSync(rootPkgJson).mtimeMs) {
|
|
847
|
+
return configCache.config;
|
|
848
|
+
}
|
|
672
849
|
const packageJsonPath = path$1.join(workshopRoot$1, "package.json");
|
|
673
850
|
let packageJson;
|
|
674
851
|
try {
|
|
675
|
-
const packageJsonContent = fs.readFileSync(packageJsonPath, "utf8");
|
|
852
|
+
const packageJsonContent = fs$1.readFileSync(packageJsonPath, "utf8");
|
|
676
853
|
packageJson = JSON.parse(packageJsonContent);
|
|
677
854
|
} catch (error) {
|
|
678
855
|
console.error(`Error reading or parsing package.json:`, error);
|
|
@@ -705,7 +882,8 @@ function getWorkshopConfig() {
|
|
|
705
882
|
}
|
|
706
883
|
try {
|
|
707
884
|
const parsedConfig = WorkshopConfigSchema.parse(epicshopConfig);
|
|
708
|
-
|
|
885
|
+
configCache.config = parsedConfig;
|
|
886
|
+
configCache.modified = fs$1.statSync(rootPkgJson).mtimeMs;
|
|
709
887
|
return parsedConfig;
|
|
710
888
|
} catch (error) {
|
|
711
889
|
if (error instanceof z.ZodError) {
|
|
@@ -724,7 +902,7 @@ async function getStackBlitzUrl({
|
|
|
724
902
|
title,
|
|
725
903
|
type
|
|
726
904
|
}) {
|
|
727
|
-
var
|
|
905
|
+
var _a;
|
|
728
906
|
const workshopConfig = getWorkshopConfig();
|
|
729
907
|
const appConfig = await getAppConfig(fullPath);
|
|
730
908
|
if (appConfig.stackBlitzConfig === null) return null;
|
|
@@ -735,7 +913,7 @@ async function getStackBlitzUrl({
|
|
|
735
913
|
const githubPart = githubRootUrl.pathname;
|
|
736
914
|
const stackBlitzConfig = {
|
|
737
915
|
...appConfig.stackBlitzConfig,
|
|
738
|
-
title: ((
|
|
916
|
+
title: ((_a = appConfig.stackBlitzConfig) == null ? void 0 : _a.title) ?? `${title} (${type})`
|
|
739
917
|
};
|
|
740
918
|
const params = new URLSearchParams(stackBlitzConfig);
|
|
741
919
|
const relativePath = fullPath.replace(`${workshopRoot$1}${path$1.sep}`, "");
|
|
@@ -746,15 +924,15 @@ async function getStackBlitzUrl({
|
|
|
746
924
|
return stackBlitzUrl.toString();
|
|
747
925
|
}
|
|
748
926
|
async function getAppConfig(fullPath) {
|
|
749
|
-
var
|
|
927
|
+
var _a, _b;
|
|
750
928
|
const workshopConfig = getWorkshopConfig();
|
|
751
929
|
let epicshopConfig = {};
|
|
752
930
|
let scripts = {};
|
|
753
931
|
const packageJsonPath = path$1.join(fullPath, "package.json");
|
|
754
|
-
const packageJsonExists = await fs.promises.access(packageJsonPath, fs.constants.F_OK).then(() => true).catch(() => false);
|
|
932
|
+
const packageJsonExists = await fs$1.promises.access(packageJsonPath, fs$1.constants.F_OK).then(() => true).catch(() => false);
|
|
755
933
|
if (packageJsonExists) {
|
|
756
934
|
const pkg = JSON.parse(
|
|
757
|
-
await fs.promises.readFile(path$1.join(fullPath, "package.json"), "utf8")
|
|
935
|
+
await fs$1.promises.readFile(path$1.join(fullPath, "package.json"), "utf8")
|
|
758
936
|
);
|
|
759
937
|
epicshopConfig = pkg.epicshop ?? {};
|
|
760
938
|
scripts = pkg.scripts ?? {};
|
|
@@ -768,7 +946,7 @@ async function getAppConfig(fullPath) {
|
|
|
768
946
|
};
|
|
769
947
|
}),
|
|
770
948
|
testTab: z.object({
|
|
771
|
-
enabled: z.boolean().optional().default(((
|
|
949
|
+
enabled: z.boolean().optional().default(((_a = workshopConfig.testTab) == null ? void 0 : _a.enabled) ?? true)
|
|
772
950
|
}).default({}),
|
|
773
951
|
scripts: z.object({
|
|
774
952
|
test: z.string().optional(),
|
|
@@ -790,251 +968,16 @@ async function getAppConfig(fullPath) {
|
|
|
790
968
|
try {
|
|
791
969
|
return AppConfigSchema.parse(appConfig);
|
|
792
970
|
} catch (error) {
|
|
793
|
-
if (error instanceof z.ZodError) {
|
|
794
|
-
const flattenedErrors = error.flatten();
|
|
795
|
-
const errorMessages = Object.entries(flattenedErrors.fieldErrors).map(([field, errors]) => `${field}: ${errors == null ? void 0 : errors.join(", ")}`).concat(flattenedErrors.formErrors);
|
|
796
|
-
throw new Error(
|
|
797
|
-
`Invalid app configuration for ${fullPath}:
|
|
798
|
-
${errorMessages.join("\n")}`
|
|
799
|
-
);
|
|
800
|
-
}
|
|
801
|
-
throw error;
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
let watcher = global.__change_tracker_watcher__;
|
|
805
|
-
const dirsToWatch = [
|
|
806
|
-
path.join(workshopRoot$1, "playground"),
|
|
807
|
-
path.join(workshopRoot$1, "exercises"),
|
|
808
|
-
path.join(workshopRoot$1, "examples")
|
|
809
|
-
];
|
|
810
|
-
const ignoredDirs = [
|
|
811
|
-
"/.git",
|
|
812
|
-
"/node_modules",
|
|
813
|
-
"/build",
|
|
814
|
-
"/server-build",
|
|
815
|
-
"/public/build",
|
|
816
|
-
"/playwright-report",
|
|
817
|
-
"/dist",
|
|
818
|
-
"/.cache"
|
|
819
|
-
];
|
|
820
|
-
function getWatcher() {
|
|
821
|
-
if (process.env.EPICSHOP_DEPLOYED ?? process.env.EPICSHOP_ENABLE_WATCHER !== "true") {
|
|
822
|
-
return void 0;
|
|
823
|
-
}
|
|
824
|
-
if (watcher) return watcher;
|
|
825
|
-
watcher = chokidar.watch(dirsToWatch, {
|
|
826
|
-
ignoreInitial: true,
|
|
827
|
-
ignored(path2, stat) {
|
|
828
|
-
return (stat == null ? void 0 : stat.isDirectory()) ? ignoredDirs.some((dir) => path2.endsWith(dir)) : false;
|
|
829
|
-
}
|
|
830
|
-
});
|
|
831
|
-
global.__change_tracker_watcher__ = watcher;
|
|
832
|
-
return watcher;
|
|
833
|
-
}
|
|
834
|
-
let currentWithoutWatcher = null;
|
|
835
|
-
async function withoutWatcher(fn) {
|
|
836
|
-
if (!watcher) return fn();
|
|
837
|
-
let thisWithoutWatcher = currentWithoutWatcher = Symbol("withoutWatcher");
|
|
838
|
-
const eventNames = watcher.eventNames();
|
|
839
|
-
const eventNamesToListenersMap = {};
|
|
840
|
-
for (const eventName of eventNames) {
|
|
841
|
-
if (typeof eventName === "string") {
|
|
842
|
-
eventNamesToListenersMap[eventName] = watcher.listeners(eventName);
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
watcher.removeAllListeners();
|
|
846
|
-
try {
|
|
847
|
-
const result = await fn();
|
|
848
|
-
return result;
|
|
849
|
-
} finally {
|
|
850
|
-
if (currentWithoutWatcher === thisWithoutWatcher) {
|
|
851
|
-
await new Promise((r) => setTimeout(r, 100));
|
|
852
|
-
for (const eventName of eventNames) {
|
|
853
|
-
if (typeof eventName === "string") {
|
|
854
|
-
const listeners = eventNamesToListenersMap[eventName] || [];
|
|
855
|
-
for (const listener of listeners) {
|
|
856
|
-
watcher.on(eventName, listener);
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
(_a = global.__change_tracker_close_with_grace_return__) == null ? void 0 : _a.uninstall();
|
|
864
|
-
global.__change_tracker_close_with_grace_return__ = closeWithGrace(
|
|
865
|
-
() => watcher == null ? void 0 : watcher.close()
|
|
866
|
-
);
|
|
867
|
-
function trimCodeBlocks() {
|
|
868
|
-
return async function transformer(tree) {
|
|
869
|
-
visit(tree, "element", (preNode) => {
|
|
870
|
-
if (preNode.tagName !== "pre" || !preNode.children.length) {
|
|
871
|
-
return;
|
|
872
|
-
}
|
|
873
|
-
const codeNode = preNode.children[0];
|
|
874
|
-
if (!codeNode || codeNode.type !== "element" || codeNode.tagName !== "code") {
|
|
875
|
-
return;
|
|
876
|
-
}
|
|
877
|
-
const [codeStringNode] = codeNode.children;
|
|
878
|
-
if (!codeStringNode) return;
|
|
879
|
-
if (codeStringNode.type !== "text") {
|
|
880
|
-
console.warn(
|
|
881
|
-
`trimCodeBlocks: Unexpected: codeStringNode type is not "text": ${codeStringNode.type}`
|
|
882
|
-
);
|
|
883
|
-
return;
|
|
884
|
-
}
|
|
885
|
-
codeStringNode.value = codeStringNode.value.trimEnd();
|
|
886
|
-
});
|
|
887
|
-
};
|
|
888
|
-
}
|
|
889
|
-
function removePreContainerDivs() {
|
|
890
|
-
return async function preContainerDivsTransformer(tree) {
|
|
891
|
-
visit(
|
|
892
|
-
tree,
|
|
893
|
-
{ type: "element", tagName: "pre" },
|
|
894
|
-
function visitor(node, index, parent) {
|
|
895
|
-
if ((parent == null ? void 0 : parent.type) !== "element") return;
|
|
896
|
-
if (parent.tagName !== "div") return;
|
|
897
|
-
if (parent.children.length !== 1 && index === 0) return;
|
|
898
|
-
Object.assign(parent, node);
|
|
899
|
-
}
|
|
900
|
-
);
|
|
901
|
-
};
|
|
902
|
-
}
|
|
903
|
-
const rehypePlugins = [
|
|
904
|
-
trimCodeBlocks,
|
|
905
|
-
remarkCodeBlocksShiki,
|
|
906
|
-
removePreContainerDivs
|
|
907
|
-
];
|
|
908
|
-
const verboseLog = process.env.EPICSHOP_VERBOSE_LOG === "true" ? console.log : () => {
|
|
909
|
-
};
|
|
910
|
-
async function compileMdx(file, {
|
|
911
|
-
request,
|
|
912
|
-
timings,
|
|
913
|
-
forceFresh
|
|
914
|
-
} = {}) {
|
|
915
|
-
const stat = await fs$1.promises.stat(file).catch((error) => ({ error }));
|
|
916
|
-
if ("error" in stat) {
|
|
917
|
-
throw new Error(`File stat cannot be read: ${stat.error}`);
|
|
918
|
-
}
|
|
919
|
-
const key = `file:${file}`;
|
|
920
|
-
forceFresh = await shouldForceFresh({ forceFresh, request, key });
|
|
921
|
-
const existingCacheEntry = await compiledInstructionMarkdownCache.get(key);
|
|
922
|
-
if (!forceFresh && existingCacheEntry) {
|
|
923
|
-
forceFresh = stat.mtimeMs > existingCacheEntry.metadata.createdTime;
|
|
924
|
-
}
|
|
925
|
-
return cachified({
|
|
926
|
-
key,
|
|
927
|
-
cache: compiledInstructionMarkdownCache,
|
|
928
|
-
request,
|
|
929
|
-
timings,
|
|
930
|
-
forceFresh,
|
|
931
|
-
getFreshValue: () => compileMdxImpl(file)
|
|
932
|
-
});
|
|
933
|
-
}
|
|
934
|
-
async function compileMdxImpl(file) {
|
|
935
|
-
let title = null;
|
|
936
|
-
const epicVideoEmbeds = [];
|
|
937
|
-
try {
|
|
938
|
-
verboseLog(`Compiling ${file}`);
|
|
939
|
-
const bundleResult = await queuedBundleMDX({
|
|
940
|
-
file,
|
|
941
|
-
cwd: path.dirname(file),
|
|
942
|
-
mdxOptions(options) {
|
|
943
|
-
options.remarkPlugins = [
|
|
944
|
-
...options.remarkPlugins ?? [],
|
|
945
|
-
[remarkAutolinkHeadings, { behavior: "wrap" }],
|
|
946
|
-
gfm,
|
|
947
|
-
() => (tree) => {
|
|
948
|
-
visit(tree, "heading", (node) => {
|
|
949
|
-
if (title) return;
|
|
950
|
-
if (node.depth === 1) {
|
|
951
|
-
visit(node, "text", (textNode) => {
|
|
952
|
-
title = textNode.value.trim();
|
|
953
|
-
});
|
|
954
|
-
}
|
|
955
|
-
});
|
|
956
|
-
title = title ? title.replace(/^\d+\. /, "").trim() : null;
|
|
957
|
-
},
|
|
958
|
-
() => (tree) => {
|
|
959
|
-
visit(tree, "mdxJsxFlowElement", (jsxEl) => {
|
|
960
|
-
if (jsxEl.name !== "EpicVideo") return;
|
|
961
|
-
const urlAttr = jsxEl.attributes.find(
|
|
962
|
-
// @ts-expect-error no idea why this started being an issue suddenly 🤷♂️
|
|
963
|
-
(a) => a.type === "mdxJsxAttribute" && a.name === "url"
|
|
964
|
-
);
|
|
965
|
-
if (!urlAttr) return;
|
|
966
|
-
let url = urlAttr.value;
|
|
967
|
-
if (typeof url !== "string") return;
|
|
968
|
-
if (url.endsWith("/")) url = url.slice(0, -1);
|
|
969
|
-
epicVideoEmbeds.push(url);
|
|
970
|
-
});
|
|
971
|
-
},
|
|
972
|
-
emoji
|
|
973
|
-
];
|
|
974
|
-
options.rehypePlugins = [
|
|
975
|
-
...options.rehypePlugins ?? [],
|
|
976
|
-
...rehypePlugins
|
|
977
|
-
];
|
|
978
|
-
options.mdxExtensions = [".mdx", ".md"];
|
|
979
|
-
options.format = "mdx";
|
|
980
|
-
options.development = false;
|
|
981
|
-
return options;
|
|
982
|
-
}
|
|
983
|
-
});
|
|
984
|
-
if (!bundleResult) throw new Error(`Timeout for file: ${file}`);
|
|
985
|
-
const result = { code: bundleResult.code, title, epicVideoEmbeds };
|
|
986
|
-
return result;
|
|
987
|
-
} catch (error) {
|
|
988
|
-
console.error(`Compilation error for file: `, file, error);
|
|
989
|
-
throw error;
|
|
990
|
-
} finally {
|
|
991
|
-
verboseLog(`Successfully compiled ${file}`);
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
async function compileMarkdownString(markdownString) {
|
|
995
|
-
return cachified({
|
|
996
|
-
key: markdownString,
|
|
997
|
-
cache: compiledMarkdownCache,
|
|
998
|
-
ttl: 1e3 * 60 * 60 * 24,
|
|
999
|
-
getFreshValue: async () => {
|
|
1000
|
-
try {
|
|
1001
|
-
verboseLog(`Compiling string`, markdownString);
|
|
1002
|
-
const result = await queuedBundleMDX({
|
|
1003
|
-
source: markdownString,
|
|
1004
|
-
mdxOptions(options) {
|
|
1005
|
-
options.rehypePlugins = [
|
|
1006
|
-
...options.rehypePlugins ?? [],
|
|
1007
|
-
...rehypePlugins
|
|
1008
|
-
];
|
|
1009
|
-
options.development = false;
|
|
1010
|
-
return options;
|
|
1011
|
-
}
|
|
1012
|
-
});
|
|
1013
|
-
if (!result) throw new Error(`Timed out compiling markdown string`);
|
|
1014
|
-
return result.code;
|
|
1015
|
-
} catch (error) {
|
|
1016
|
-
console.error(`Compilation error for code: `, markdownString, error);
|
|
1017
|
-
throw error;
|
|
1018
|
-
} finally {
|
|
1019
|
-
verboseLog(`Successfully compiled string`, markdownString);
|
|
1020
|
-
}
|
|
971
|
+
if (error instanceof z.ZodError) {
|
|
972
|
+
const flattenedErrors = error.flatten();
|
|
973
|
+
const errorMessages = Object.entries(flattenedErrors.fieldErrors).map(([field, errors]) => `${field}: ${errors == null ? void 0 : errors.join(", ")}`).concat(flattenedErrors.formErrors);
|
|
974
|
+
throw new Error(
|
|
975
|
+
`Invalid app configuration for ${fullPath}:
|
|
976
|
+
${errorMessages.join("\n")}`
|
|
977
|
+
);
|
|
1021
978
|
}
|
|
1022
|
-
|
|
1023
|
-
}
|
|
1024
|
-
let _queue = null;
|
|
1025
|
-
async function getQueue() {
|
|
1026
|
-
if (_queue) return _queue;
|
|
1027
|
-
_queue = new PQueue({
|
|
1028
|
-
concurrency: 1,
|
|
1029
|
-
throwOnTimeout: true,
|
|
1030
|
-
timeout: 1e3 * 60
|
|
1031
|
-
});
|
|
1032
|
-
return _queue;
|
|
1033
|
-
}
|
|
1034
|
-
async function queuedBundleMDX(...args) {
|
|
1035
|
-
const queue = await getQueue();
|
|
1036
|
-
const result = await queue.add(() => bundleMDX(...args));
|
|
1037
|
-
return result;
|
|
979
|
+
throw error;
|
|
980
|
+
}
|
|
1038
981
|
}
|
|
1039
982
|
const schema = z.object({
|
|
1040
983
|
NODE_ENV: z.enum(["production", "development", "test"]).default("development"),
|
|
@@ -1061,6 +1004,64 @@ function getEnv() {
|
|
|
1061
1004
|
EPICSHOP_DEPLOYED: process.env.EPICSHOP_DEPLOYED === "true" || process.env.EPICSHOP_DEPLOYED === "1"
|
|
1062
1005
|
};
|
|
1063
1006
|
}
|
|
1007
|
+
async function getDirModifiedTime(dir, { forceFresh = false } = {}) {
|
|
1008
|
+
const result = await cachified({
|
|
1009
|
+
key: dir,
|
|
1010
|
+
cache: dirModifiedTimeCache,
|
|
1011
|
+
ttl: 200,
|
|
1012
|
+
forceFresh,
|
|
1013
|
+
getFreshValue: () => getDirModifiedTimeImpl(dir)
|
|
1014
|
+
});
|
|
1015
|
+
return result;
|
|
1016
|
+
}
|
|
1017
|
+
async function getDirModifiedTimeImpl(dir) {
|
|
1018
|
+
const isIgnored = await isGitIgnored({ cwd: dir });
|
|
1019
|
+
const files = await fs$1.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
1020
|
+
const modifiedTimes2 = [];
|
|
1021
|
+
for (const file of files) {
|
|
1022
|
+
if (isIgnored(file.name)) continue;
|
|
1023
|
+
const filePath = path$1.join(dir, file.name);
|
|
1024
|
+
if (file.isDirectory()) {
|
|
1025
|
+
modifiedTimes2.push(await getDirModifiedTime(filePath));
|
|
1026
|
+
} else {
|
|
1027
|
+
try {
|
|
1028
|
+
const { mtimeMs } = await fs$1.promises.stat(filePath);
|
|
1029
|
+
modifiedTimes2.push(mtimeMs);
|
|
1030
|
+
} catch {
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
try {
|
|
1035
|
+
const { mtimeMs } = await fs$1.promises.stat(dir);
|
|
1036
|
+
modifiedTimes2.push(mtimeMs);
|
|
1037
|
+
} catch {
|
|
1038
|
+
}
|
|
1039
|
+
return Math.max(-1, ...modifiedTimes2);
|
|
1040
|
+
}
|
|
1041
|
+
async function modifiedMoreRecentlyThan(time2, ...dirs) {
|
|
1042
|
+
const modifiedTimePromises = dirs.map((dir) => getDirModifiedTime(dir));
|
|
1043
|
+
const allFinishedPromise = Promise.all(modifiedTimePromises);
|
|
1044
|
+
const firstMoreRecentPromise = modifiedTimePromises.map(
|
|
1045
|
+
(p) => p.then((t) => t > time2 ? true : allFinishedPromise.then(() => false))
|
|
1046
|
+
);
|
|
1047
|
+
const firstMoreRecent = await Promise.race(firstMoreRecentPromise);
|
|
1048
|
+
return firstMoreRecent;
|
|
1049
|
+
}
|
|
1050
|
+
let _queue = null;
|
|
1051
|
+
function getQueue() {
|
|
1052
|
+
if (_queue) return _queue;
|
|
1053
|
+
_queue = new PQueue({
|
|
1054
|
+
concurrency: 10,
|
|
1055
|
+
throwOnTimeout: true,
|
|
1056
|
+
timeout: 1e3 * 60
|
|
1057
|
+
});
|
|
1058
|
+
return _queue;
|
|
1059
|
+
}
|
|
1060
|
+
async function queuedGetDirModifiedTime(...args) {
|
|
1061
|
+
const queue = getQueue();
|
|
1062
|
+
const result = await queue.add(() => getDirModifiedTime(...args));
|
|
1063
|
+
return result || -1;
|
|
1064
|
+
}
|
|
1064
1065
|
function getErrorMessage$1(error) {
|
|
1065
1066
|
if (typeof error === "string") return error;
|
|
1066
1067
|
if (error && typeof error === "object" && "message" in error && typeof error.message === "string") {
|
|
@@ -1073,9 +1074,9 @@ const isDeployed$1 = process.env.EPICSHOP_DEPLOYED === "true" || process.env.EPI
|
|
|
1073
1074
|
const devProcesses = remember("dev_processes", getDevProcessesMap);
|
|
1074
1075
|
const testProcesses = remember("test_processes", getTestProcessesMap);
|
|
1075
1076
|
function getDevProcessesMap() {
|
|
1076
|
-
var
|
|
1077
|
+
var _a;
|
|
1077
1078
|
const procs = /* @__PURE__ */ new Map();
|
|
1078
|
-
(
|
|
1079
|
+
(_a = global.__process_dev_close_with_grace_return__) == null ? void 0 : _a.uninstall();
|
|
1079
1080
|
global.__process_dev_close_with_grace_return__ = closeWithGrace(async () => {
|
|
1080
1081
|
for (const [name, proc] of procs.entries()) {
|
|
1081
1082
|
console.log("closing", name);
|
|
@@ -1085,9 +1086,9 @@ function getDevProcessesMap() {
|
|
|
1085
1086
|
return procs;
|
|
1086
1087
|
}
|
|
1087
1088
|
function getTestProcessesMap() {
|
|
1088
|
-
var
|
|
1089
|
+
var _a;
|
|
1089
1090
|
const procs = /* @__PURE__ */ new Map();
|
|
1090
|
-
(
|
|
1091
|
+
(_a = global.__process_test_close_with_grace_return__) == null ? void 0 : _a.uninstall();
|
|
1091
1092
|
global.__process_test_close_with_grace_return__ = closeWithGrace(async () => {
|
|
1092
1093
|
for (const [id, proc] of procs.entries()) {
|
|
1093
1094
|
if (proc.process) {
|
|
@@ -1316,7 +1317,7 @@ async function waitForPortToBeAvailable(port2) {
|
|
|
1316
1317
|
console.error("Timed out waiting for the port to become available");
|
|
1317
1318
|
}
|
|
1318
1319
|
}
|
|
1319
|
-
|
|
1320
|
+
global.__epicshop_apps_initialized__ ?? (global.__epicshop_apps_initialized__ = false);
|
|
1320
1321
|
const workshopRoot = process.env.EPICSHOP_CONTEXT_CWD = process.env.EPICSHOP_CONTEXT_CWD ?? process.cwd();
|
|
1321
1322
|
const playgroundAppNameInfoPath = path$1.join(
|
|
1322
1323
|
workshopRoot,
|
|
@@ -1434,7 +1435,7 @@ function isExerciseStepApp(app) {
|
|
|
1434
1435
|
return isProblemApp(app) || isSolutionApp(app);
|
|
1435
1436
|
}
|
|
1436
1437
|
function exists(file) {
|
|
1437
|
-
return fs.promises.access(file, fs.constants.F_OK).then(
|
|
1438
|
+
return fs$1.promises.access(file, fs$1.constants.F_OK).then(
|
|
1438
1439
|
() => true,
|
|
1439
1440
|
() => false
|
|
1440
1441
|
);
|
|
@@ -1448,27 +1449,39 @@ const modifiedTimes = remember(
|
|
|
1448
1449
|
"modified_times",
|
|
1449
1450
|
() => /* @__PURE__ */ new Map()
|
|
1450
1451
|
);
|
|
1451
|
-
function init() {
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
initialized$1 = true;
|
|
1452
|
+
async function init() {
|
|
1453
|
+
if (global.__epicshop_apps_initialized__) return;
|
|
1454
|
+
global.__epicshop_apps_initialized__ = true;
|
|
1455
1455
|
const config = getWorkshopConfig();
|
|
1456
1456
|
process.env.EPICSHOP_GITHUB_REPO = config.githubRepo;
|
|
1457
1457
|
process.env.EPICSHOP_GITHUB_ROOT = config.githubRoot;
|
|
1458
1458
|
init$1();
|
|
1459
1459
|
global.ENV = getEnv();
|
|
1460
|
-
|
|
1461
|
-
}
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1460
|
+
if (!ENV.EPICSHOP_DEPLOYED && process.env.EPICSHOP_ENABLE_WATCHER === "true") {
|
|
1461
|
+
const isIgnored = await isGitIgnored({ cwd: workshopRoot });
|
|
1462
|
+
const filesToWatch = ["README.mdx", "FINISHED.mdx", "package.json"];
|
|
1463
|
+
const chok = chokidar.watch(["examples", "playground", "exercises"], {
|
|
1464
|
+
cwd: workshopRoot,
|
|
1465
|
+
ignoreInitial: true,
|
|
1466
|
+
ignored(filePath, stats) {
|
|
1467
|
+
if (isIgnored(filePath)) return true;
|
|
1468
|
+
if (filePath.includes(".git")) return true;
|
|
1469
|
+
if (stats == null ? void 0 : stats.isDirectory()) {
|
|
1470
|
+
if (filePath.endsWith("playground")) return false;
|
|
1471
|
+
const pathParts = filePath.split(path$1.sep);
|
|
1472
|
+
if (pathParts.at(-2) === "examples") return false;
|
|
1473
|
+
if (pathParts.at(-3) === "exercises") return false;
|
|
1474
|
+
if (pathParts.at(-2) === "exercises") return false;
|
|
1475
|
+
if (pathParts.at(-1) === "exercises") return false;
|
|
1476
|
+
return true;
|
|
1477
|
+
}
|
|
1478
|
+
return (stats == null ? void 0 : stats.isFile()) ? !filesToWatch.some((file) => filePath.endsWith(file)) : false;
|
|
1479
|
+
}
|
|
1480
|
+
});
|
|
1481
|
+
chok.on("all", (_event, filePath) => {
|
|
1482
|
+
setModifiedTimesForAppDirs(path$1.join(workshopRoot, filePath));
|
|
1483
|
+
});
|
|
1484
|
+
closeWithGrace(() => chok.close());
|
|
1472
1485
|
}
|
|
1473
1486
|
}
|
|
1474
1487
|
function getForceFresh$1(cacheEntry) {
|
|
@@ -1477,6 +1490,17 @@ function getForceFresh$1(cacheEntry) {
|
|
|
1477
1490
|
if (!latestModifiedTime) return void 0;
|
|
1478
1491
|
return latestModifiedTime > cacheEntry.metadata.createdTime ? true : void 0;
|
|
1479
1492
|
}
|
|
1493
|
+
function setModifiedTimesForAppDirs(...filePaths) {
|
|
1494
|
+
const now = Date.now();
|
|
1495
|
+
for (const filePath of filePaths) {
|
|
1496
|
+
const appDir2 = getAppPathFromFilePath(filePath);
|
|
1497
|
+
if (appDir2) {
|
|
1498
|
+
modifiedTimes.set(appDir2, now);
|
|
1499
|
+
} else {
|
|
1500
|
+
console.warn(`filePath ${filePath} does not match any app dir`);
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1480
1504
|
function getForceFreshForDir(cacheEntry, ...dirs) {
|
|
1481
1505
|
const truthyDirs = dirs.filter(Boolean);
|
|
1482
1506
|
for (const d of truthyDirs) {
|
|
@@ -1494,7 +1518,7 @@ function getForceFreshForDir(cacheEntry, ...dirs) {
|
|
|
1494
1518
|
}
|
|
1495
1519
|
async function readDir(dir) {
|
|
1496
1520
|
if (await exists(dir)) {
|
|
1497
|
-
return fs.promises.readdir(dir);
|
|
1521
|
+
return fs$1.promises.readdir(dir);
|
|
1498
1522
|
}
|
|
1499
1523
|
return [];
|
|
1500
1524
|
}
|
|
@@ -1530,9 +1554,9 @@ function getAppDirInfo(appDir2) {
|
|
|
1530
1554
|
return { stepNumber, type, subtitle };
|
|
1531
1555
|
}
|
|
1532
1556
|
function extractExerciseNumber(dir) {
|
|
1533
|
-
var
|
|
1557
|
+
var _a, _b;
|
|
1534
1558
|
const regex = /^(?<number>\d+)\./;
|
|
1535
|
-
const number = (_b = (
|
|
1559
|
+
const number = (_b = (_a = regex.exec(dir)) == null ? void 0 : _a.groups) == null ? void 0 : _b.number;
|
|
1536
1560
|
if (!number) {
|
|
1537
1561
|
return null;
|
|
1538
1562
|
}
|
|
@@ -1586,7 +1610,7 @@ async function getApps({
|
|
|
1586
1610
|
request,
|
|
1587
1611
|
forceFresh
|
|
1588
1612
|
} = {}) {
|
|
1589
|
-
|
|
1613
|
+
await init();
|
|
1590
1614
|
const key = "apps";
|
|
1591
1615
|
const apps = await cachified({
|
|
1592
1616
|
key,
|
|
@@ -1599,10 +1623,24 @@ async function getApps({
|
|
|
1599
1623
|
ttl: 1e3 * 60 * 60 * 24,
|
|
1600
1624
|
forceFresh: forceFresh ?? getForceFresh$1(appsCache.get(key)),
|
|
1601
1625
|
getFreshValue: async () => {
|
|
1602
|
-
const playgroundApp = await
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1626
|
+
const [playgroundApp, problemApps, solutionApps, exampleApps] = await Promise.all([
|
|
1627
|
+
time(() => getPlaygroundApp({ request, timings }), {
|
|
1628
|
+
type: "getPlaygroundApp",
|
|
1629
|
+
timings
|
|
1630
|
+
}),
|
|
1631
|
+
time(() => getProblemApps({ request, timings }), {
|
|
1632
|
+
type: "getProblemApps",
|
|
1633
|
+
timings
|
|
1634
|
+
}),
|
|
1635
|
+
time(() => getSolutionApps({ request, timings }), {
|
|
1636
|
+
type: "getSolutionApps",
|
|
1637
|
+
timings
|
|
1638
|
+
}),
|
|
1639
|
+
time(() => getExampleApps({ request, timings }), {
|
|
1640
|
+
type: "getExampleApps",
|
|
1641
|
+
timings
|
|
1642
|
+
})
|
|
1643
|
+
]);
|
|
1606
1644
|
const sortedApps = [
|
|
1607
1645
|
playgroundApp,
|
|
1608
1646
|
...problemApps,
|
|
@@ -1654,7 +1692,7 @@ const AppIdInfoSchema = z.object({
|
|
|
1654
1692
|
type: z.union([z.literal("problem"), z.literal("solution")])
|
|
1655
1693
|
});
|
|
1656
1694
|
function extractNumbersAndTypeFromAppNameOrPath(fullPathOrAppName) {
|
|
1657
|
-
var
|
|
1695
|
+
var _a;
|
|
1658
1696
|
const info = {};
|
|
1659
1697
|
if (fullPathOrAppName.includes(path$1.sep)) {
|
|
1660
1698
|
const relativePath = fullPathOrAppName.replace(
|
|
@@ -1665,7 +1703,7 @@ function extractNumbersAndTypeFromAppNameOrPath(fullPathOrAppName) {
|
|
|
1665
1703
|
if (!exerciseNumberPart || !stepNumberPart) return null;
|
|
1666
1704
|
const exerciseNumber = exerciseNumberPart.split(".")[0];
|
|
1667
1705
|
const stepNumber = stepNumberPart.split(".")[0];
|
|
1668
|
-
const type = (
|
|
1706
|
+
const type = (_a = stepNumberPart.split(".")[1]) == null ? void 0 : _a.split(".")[0];
|
|
1669
1707
|
info.exerciseNumber = exerciseNumber;
|
|
1670
1708
|
info.stepNumber = stepNumber;
|
|
1671
1709
|
info.type = type;
|
|
@@ -1681,18 +1719,28 @@ function extractNumbersAndTypeFromAppNameOrPath(fullPathOrAppName) {
|
|
|
1681
1719
|
}
|
|
1682
1720
|
async function getProblemDirs() {
|
|
1683
1721
|
const exercisesDir = path$1.join(workshopRoot, "exercises");
|
|
1684
|
-
const problemDirs =
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1722
|
+
const problemDirs = [];
|
|
1723
|
+
const exerciseSubDirs = await readDir(exercisesDir);
|
|
1724
|
+
for (const subDir of exerciseSubDirs) {
|
|
1725
|
+
const fullSubDir = path$1.join(exercisesDir, subDir);
|
|
1726
|
+
const subDirContents = await readDir(fullSubDir).catch(() => null);
|
|
1727
|
+
if (!subDirContents) continue;
|
|
1728
|
+
const problemSubDirs = subDirContents.filter((dir) => dir.includes(".problem")).map((dir) => path$1.join(fullSubDir, dir));
|
|
1729
|
+
problemDirs.push(...problemSubDirs);
|
|
1730
|
+
}
|
|
1688
1731
|
return problemDirs;
|
|
1689
1732
|
}
|
|
1690
1733
|
async function getSolutionDirs() {
|
|
1691
1734
|
const exercisesDir = path$1.join(workshopRoot, "exercises");
|
|
1692
|
-
const solutionDirs =
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1735
|
+
const solutionDirs = [];
|
|
1736
|
+
const exerciseSubDirs = await readDir(exercisesDir);
|
|
1737
|
+
for (const subDir of exerciseSubDirs) {
|
|
1738
|
+
const fullSubDir = path$1.join(exercisesDir, subDir);
|
|
1739
|
+
const subDirContents = await readDir(fullSubDir).catch(() => null);
|
|
1740
|
+
if (!subDirContents) continue;
|
|
1741
|
+
const solutionSubDirs = subDirContents.filter((dir) => dir.includes(".solution")).map((dir) => path$1.join(fullSubDir, dir));
|
|
1742
|
+
solutionDirs.push(...solutionSubDirs);
|
|
1743
|
+
}
|
|
1696
1744
|
return solutionDirs;
|
|
1697
1745
|
}
|
|
1698
1746
|
function getPathname(fullPath) {
|
|
@@ -1746,7 +1794,7 @@ async function findSolutionDir({
|
|
|
1746
1794
|
const { stepNumber } = info;
|
|
1747
1795
|
const paddedStepNumber = stepNumber.toString().padStart(2, "0");
|
|
1748
1796
|
const parentDir = path$1.dirname(fullPath);
|
|
1749
|
-
const siblingDirs = await fs.promises.readdir(parentDir);
|
|
1797
|
+
const siblingDirs = await fs$1.promises.readdir(parentDir);
|
|
1750
1798
|
const solutionDir = siblingDirs.find(
|
|
1751
1799
|
(dir) => dir.startsWith(`${paddedStepNumber}.solution`)
|
|
1752
1800
|
);
|
|
@@ -1773,7 +1821,7 @@ async function findProblemDir({
|
|
|
1773
1821
|
const { stepNumber } = info;
|
|
1774
1822
|
const paddedStepNumber = stepNumber.toString().padStart(2, "0");
|
|
1775
1823
|
const parentDir = path$1.dirname(fullPath);
|
|
1776
|
-
const siblingDirs = await fs.promises.readdir(parentDir);
|
|
1824
|
+
const siblingDirs = await fs$1.promises.readdir(parentDir);
|
|
1777
1825
|
const problemDir = siblingDirs.find(
|
|
1778
1826
|
(dir) => dir.endsWith("problem") && dir.includes(paddedStepNumber)
|
|
1779
1827
|
);
|
|
@@ -1800,7 +1848,7 @@ async function getTestInfo({
|
|
|
1800
1848
|
return { type: "script", script: testScript };
|
|
1801
1849
|
}
|
|
1802
1850
|
const testAppFullPath = await findSolutionDir({ fullPath }) ?? fullPath;
|
|
1803
|
-
const dirList = await fs.promises.readdir(testAppFullPath);
|
|
1851
|
+
const dirList = await fs$1.promises.readdir(testAppFullPath);
|
|
1804
1852
|
const testFiles = dirList.filter((item) => item.includes(".test."));
|
|
1805
1853
|
if (testFiles.length) {
|
|
1806
1854
|
return {
|
|
@@ -1864,10 +1912,10 @@ async function getPlaygroundApp({
|
|
|
1864
1912
|
getTestInfo({ fullPath: playgroundDir }),
|
|
1865
1913
|
getDevInfo({ fullPath: playgroundDir, portNumber })
|
|
1866
1914
|
]);
|
|
1867
|
-
const appModifiedTime = await
|
|
1915
|
+
const appModifiedTime = await queuedGetDirModifiedTime(
|
|
1868
1916
|
await getFullPathFromAppName(baseAppName)
|
|
1869
1917
|
);
|
|
1870
|
-
const playgroundAppModifiedTime = await
|
|
1918
|
+
const playgroundAppModifiedTime = await queuedGetDirModifiedTime(playgroundDir);
|
|
1871
1919
|
const type = "playground";
|
|
1872
1920
|
const title = (compiledReadme == null ? void 0 : compiledReadme.title) ?? name;
|
|
1873
1921
|
return {
|
|
@@ -1928,7 +1976,9 @@ async function getExampleApps({
|
|
|
1928
1976
|
request
|
|
1929
1977
|
} = {}) {
|
|
1930
1978
|
const examplesDir = path$1.join(workshopRoot, "examples");
|
|
1931
|
-
const exampleDirs = (await
|
|
1979
|
+
const exampleDirs = (await readDir(examplesDir)).map(
|
|
1980
|
+
(p) => path$1.join(examplesDir, p)
|
|
1981
|
+
);
|
|
1932
1982
|
const exampleApps = [];
|
|
1933
1983
|
for (const exampleDir of exampleDirs) {
|
|
1934
1984
|
const index = exampleDirs.indexOf(exampleDir);
|
|
@@ -1941,10 +1991,14 @@ async function getExampleApps({
|
|
|
1941
1991
|
timingKey: exampleDir.replace(`${examplesDir}${path$1.sep}`, ""),
|
|
1942
1992
|
request,
|
|
1943
1993
|
forceFresh: getForceFreshForDir(exampleAppCache.get(key), exampleDir),
|
|
1944
|
-
getFreshValue:
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1994
|
+
getFreshValue: async () => {
|
|
1995
|
+
return getExampleAppFromPath(exampleDir, index, request).catch(
|
|
1996
|
+
(error) => {
|
|
1997
|
+
console.error(error);
|
|
1998
|
+
return null;
|
|
1999
|
+
}
|
|
2000
|
+
);
|
|
2001
|
+
}
|
|
1948
2002
|
});
|
|
1949
2003
|
if (exampleApp) exampleApps.push(exampleApp);
|
|
1950
2004
|
}
|
|
@@ -2013,10 +2067,12 @@ async function getSolutionApps({
|
|
|
2013
2067
|
solutionAppCache.get(solutionDir),
|
|
2014
2068
|
solutionDir
|
|
2015
2069
|
),
|
|
2016
|
-
getFreshValue:
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2070
|
+
getFreshValue: async () => {
|
|
2071
|
+
return getSolutionAppFromPath(solutionDir, request).catch((error) => {
|
|
2072
|
+
console.error(error);
|
|
2073
|
+
return null;
|
|
2074
|
+
});
|
|
2075
|
+
}
|
|
2020
2076
|
});
|
|
2021
2077
|
if (solutionApp) solutionApps.push(solutionApp);
|
|
2022
2078
|
}
|
|
@@ -2087,10 +2143,12 @@ async function getProblemApps({
|
|
|
2087
2143
|
problemDir,
|
|
2088
2144
|
solutionDir
|
|
2089
2145
|
),
|
|
2090
|
-
getFreshValue:
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2146
|
+
getFreshValue: async () => {
|
|
2147
|
+
return getProblemAppFromPath(problemDir).catch((error) => {
|
|
2148
|
+
console.error(error);
|
|
2149
|
+
return null;
|
|
2150
|
+
});
|
|
2151
|
+
}
|
|
2094
2152
|
});
|
|
2095
2153
|
if (problemApp) problemApps.push(problemApp);
|
|
2096
2154
|
}
|
|
@@ -2180,111 +2238,107 @@ async function getAppFromFile(filePath) {
|
|
|
2180
2238
|
return apps.find((app) => filePath.startsWith(app.fullPath));
|
|
2181
2239
|
}
|
|
2182
2240
|
async function setPlayground(srcDir, { reset } = {}) {
|
|
2183
|
-
var _a2;
|
|
2184
2241
|
const destDir = path$1.join(workshopRoot, "playground");
|
|
2185
|
-
await
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
EPICSHOP_PLAYGROUND_WAS_RUNNING: playgroundWasRunning.toString()
|
|
2207
|
-
}
|
|
2208
|
-
});
|
|
2209
|
-
}
|
|
2210
|
-
const basename2 = path$1.basename(srcDir);
|
|
2211
|
-
await fsExtra.remove(path$1.join(destDir, "node_modules"));
|
|
2212
|
-
await fsExtra.copy(srcDir, destDir, {
|
|
2213
|
-
filter: async (srcFile, destFile) => {
|
|
2214
|
-
if (srcFile.includes(`${basename2}${path$1.sep}build`) || srcFile.includes(`${basename2}${path$1.sep}public${path$1.sep}build`)) {
|
|
2215
|
-
return false;
|
|
2216
|
-
}
|
|
2217
|
-
if (srcFile === srcDir) return true;
|
|
2218
|
-
if (srcFile.includes("node_modules")) return true;
|
|
2219
|
-
if (srcFile.endsWith(".env")) return true;
|
|
2220
|
-
if (isIgnored(srcFile)) return false;
|
|
2221
|
-
try {
|
|
2222
|
-
const isDir = (await fsExtra.stat(srcFile)).isDirectory();
|
|
2223
|
-
if (isDir) return true;
|
|
2224
|
-
const destIsDir = (await fsExtra.stat(destFile)).isDirectory();
|
|
2225
|
-
if (destIsDir) return true;
|
|
2226
|
-
const currentContents = await fsExtra.readFile(destFile);
|
|
2227
|
-
const newContents = await fsExtra.readFile(srcFile);
|
|
2228
|
-
if (currentContents.equals(newContents)) return false;
|
|
2229
|
-
return true;
|
|
2230
|
-
} catch {
|
|
2231
|
-
return true;
|
|
2232
|
-
}
|
|
2242
|
+
const isIgnored = await isGitIgnored({ cwd: srcDir });
|
|
2243
|
+
const playgroundApp = await getAppByName("playground");
|
|
2244
|
+
const playgroundWasRunning = playgroundApp ? isAppRunning(playgroundApp) : false;
|
|
2245
|
+
if (playgroundApp && reset) {
|
|
2246
|
+
await closeProcess(playgroundApp.name);
|
|
2247
|
+
await fsExtra.remove(destDir);
|
|
2248
|
+
}
|
|
2249
|
+
const setPlaygroundTimestamp = Date.now();
|
|
2250
|
+
const preSetPlaygroundPath = await firstToExist(
|
|
2251
|
+
path$1.join(srcDir, "epicshop", "pre-set-playground.js"),
|
|
2252
|
+
path$1.join(workshopRoot, "epicshop", "pre-set-playground.js")
|
|
2253
|
+
);
|
|
2254
|
+
if (preSetPlaygroundPath) {
|
|
2255
|
+
await execa("node", [preSetPlaygroundPath], {
|
|
2256
|
+
cwd: workshopRoot,
|
|
2257
|
+
stdio: "inherit",
|
|
2258
|
+
env: {
|
|
2259
|
+
EPICSHOP_PLAYGROUND_TIMESTAMP: setPlaygroundTimestamp.toString(),
|
|
2260
|
+
EPICSHOP_PLAYGROUND_DEST_DIR: destDir,
|
|
2261
|
+
EPICSHOP_PLAYGROUND_SRC_DIR: srcDir,
|
|
2262
|
+
EPICSHOP_PLAYGROUND_WAS_RUNNING: playgroundWasRunning.toString()
|
|
2233
2263
|
}
|
|
2234
2264
|
});
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
})
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
(
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
);
|
|
2260
|
-
if (postSetPlaygroundPath) {
|
|
2261
|
-
await execa("node", [postSetPlaygroundPath], {
|
|
2262
|
-
cwd: workshopRoot,
|
|
2263
|
-
stdio: "inherit",
|
|
2264
|
-
env: {
|
|
2265
|
-
EPICSHOP_PLAYGROUND_TIMESTAMP: setPlaygroundTimestamp.toString(),
|
|
2266
|
-
EPICSHOP_PLAYGROUND_SRC_DIR: srcDir,
|
|
2267
|
-
EPICSHOP_PLAYGROUND_DEST_DIR: destDir,
|
|
2268
|
-
EPICSHOP_PLAYGROUND_WAS_RUNNING: playgroundWasRunning.toString(),
|
|
2269
|
-
EPICSHOP_PLAYGROUND_IS_STILL_RUNNING: playgroundIsStillRunning.toString(),
|
|
2270
|
-
EPICSHOP_PLAYGROUND_RESTART_PLAYGROUND: restartPlayground.toString()
|
|
2271
|
-
}
|
|
2272
|
-
});
|
|
2273
|
-
}
|
|
2274
|
-
modifiedTimes.set(destDir, Date.now());
|
|
2275
|
-
if (playgroundApp && restartPlayground) {
|
|
2276
|
-
await runAppDev(playgroundApp);
|
|
2277
|
-
await waitOnApp(playgroundApp);
|
|
2265
|
+
}
|
|
2266
|
+
const basename2 = path$1.basename(srcDir);
|
|
2267
|
+
await fsExtra.remove(path$1.join(destDir, "node_modules"));
|
|
2268
|
+
await fsExtra.copy(srcDir, destDir, {
|
|
2269
|
+
filter: async (srcFile, destFile) => {
|
|
2270
|
+
if (srcFile.includes(`${basename2}${path$1.sep}build`) || srcFile.includes(`${basename2}${path$1.sep}public${path$1.sep}build`)) {
|
|
2271
|
+
return false;
|
|
2272
|
+
}
|
|
2273
|
+
if (srcFile === srcDir) return true;
|
|
2274
|
+
if (srcFile.includes("node_modules")) return true;
|
|
2275
|
+
if (srcFile.endsWith(".env")) return true;
|
|
2276
|
+
if (isIgnored(srcFile)) return false;
|
|
2277
|
+
try {
|
|
2278
|
+
const isDir = (await fsExtra.stat(srcFile)).isDirectory();
|
|
2279
|
+
if (isDir) return true;
|
|
2280
|
+
const destIsDir = (await fsExtra.stat(destFile)).isDirectory();
|
|
2281
|
+
if (destIsDir) return true;
|
|
2282
|
+
const currentContents = await fsExtra.readFile(destFile);
|
|
2283
|
+
const newContents = await fsExtra.readFile(srcFile);
|
|
2284
|
+
if (currentContents.equals(newContents)) return false;
|
|
2285
|
+
return true;
|
|
2286
|
+
} catch {
|
|
2287
|
+
return true;
|
|
2288
|
+
}
|
|
2278
2289
|
}
|
|
2279
2290
|
});
|
|
2280
|
-
|
|
2291
|
+
async function getFiles(dir) {
|
|
2292
|
+
const dirPath = dir.replace(/\\/g, "/");
|
|
2293
|
+
const files = await globby([`${dirPath}/**/*`, "!**/build/**/*"], {
|
|
2294
|
+
onlyFiles: false,
|
|
2295
|
+
dot: true
|
|
2296
|
+
});
|
|
2297
|
+
return files.map((f) => f.replace(dirPath, ""));
|
|
2298
|
+
}
|
|
2299
|
+
const srcFiles = await getFiles(srcDir);
|
|
2300
|
+
const destFiles = await getFiles(destDir);
|
|
2301
|
+
const filesToDelete = destFiles.filter(
|
|
2302
|
+
(fileName) => !srcFiles.includes(fileName)
|
|
2303
|
+
);
|
|
2304
|
+
for (const fileToDelete of filesToDelete) {
|
|
2305
|
+
await fsExtra.remove(path$1.join(destDir, fileToDelete));
|
|
2306
|
+
}
|
|
2307
|
+
const appName = getAppName(srcDir);
|
|
2308
|
+
await fsExtra.ensureDir(path$1.dirname(playgroundAppNameInfoPath));
|
|
2309
|
+
await fsExtra.writeJSON(playgroundAppNameInfoPath, { appName });
|
|
2310
|
+
const playgroundIsStillRunning = playgroundApp ? isAppRunning(playgroundApp) : false;
|
|
2311
|
+
const restartPlayground = playgroundWasRunning && !playgroundIsStillRunning;
|
|
2312
|
+
const postSetPlaygroundPath = await firstToExist(
|
|
2313
|
+
path$1.join(srcDir, "epicshop", "post-set-playground.js"),
|
|
2314
|
+
path$1.join(workshopRoot, "epicshop", "post-set-playground.js")
|
|
2315
|
+
);
|
|
2316
|
+
if (postSetPlaygroundPath) {
|
|
2317
|
+
await execa("node", [postSetPlaygroundPath], {
|
|
2318
|
+
cwd: workshopRoot,
|
|
2319
|
+
stdio: "inherit",
|
|
2320
|
+
env: {
|
|
2321
|
+
EPICSHOP_PLAYGROUND_TIMESTAMP: setPlaygroundTimestamp.toString(),
|
|
2322
|
+
EPICSHOP_PLAYGROUND_SRC_DIR: srcDir,
|
|
2323
|
+
EPICSHOP_PLAYGROUND_DEST_DIR: destDir,
|
|
2324
|
+
EPICSHOP_PLAYGROUND_WAS_RUNNING: playgroundWasRunning.toString(),
|
|
2325
|
+
EPICSHOP_PLAYGROUND_IS_STILL_RUNNING: playgroundIsStillRunning.toString(),
|
|
2326
|
+
EPICSHOP_PLAYGROUND_RESTART_PLAYGROUND: restartPlayground.toString()
|
|
2327
|
+
}
|
|
2328
|
+
});
|
|
2329
|
+
}
|
|
2330
|
+
modifiedTimes.set(destDir, Date.now());
|
|
2331
|
+
if (playgroundApp && restartPlayground) {
|
|
2332
|
+
await runAppDev(playgroundApp);
|
|
2333
|
+
await waitOnApp(playgroundApp);
|
|
2334
|
+
}
|
|
2281
2335
|
}
|
|
2282
2336
|
async function getPlaygroundAppName() {
|
|
2283
2337
|
if (!await exists(playgroundAppNameInfoPath)) {
|
|
2284
2338
|
return null;
|
|
2285
2339
|
}
|
|
2286
2340
|
try {
|
|
2287
|
-
const jsonString = await fs.promises.readFile(
|
|
2341
|
+
const jsonString = await fs$1.promises.readFile(
|
|
2288
2342
|
playgroundAppNameInfoPath,
|
|
2289
2343
|
"utf8"
|
|
2290
2344
|
);
|
|
@@ -2295,27 +2349,6 @@ async function getPlaygroundAppName() {
|
|
|
2295
2349
|
return null;
|
|
2296
2350
|
}
|
|
2297
2351
|
}
|
|
2298
|
-
async function getDirModifiedTime(dir) {
|
|
2299
|
-
const isIgnored = await isGitIgnored({ cwd: dir });
|
|
2300
|
-
const files = await fs.promises.readdir(dir, { withFileTypes: true });
|
|
2301
|
-
const modifiedTimes2 = await Promise.all(
|
|
2302
|
-
files.map(async (file) => {
|
|
2303
|
-
if (isIgnored(file.name)) return 0;
|
|
2304
|
-
const filePath = path$1.join(dir, file.name);
|
|
2305
|
-
if (file.isDirectory()) {
|
|
2306
|
-
return getDirModifiedTime(filePath);
|
|
2307
|
-
} else {
|
|
2308
|
-
try {
|
|
2309
|
-
const { mtimeMs } = await fs.promises.stat(filePath);
|
|
2310
|
-
return mtimeMs;
|
|
2311
|
-
} catch {
|
|
2312
|
-
return 0;
|
|
2313
|
-
}
|
|
2314
|
-
}
|
|
2315
|
-
})
|
|
2316
|
-
);
|
|
2317
|
-
return Math.max(0, ...modifiedTimes2);
|
|
2318
|
-
}
|
|
2319
2352
|
function getAppDisplayName(a, allApps) {
|
|
2320
2353
|
let displayName = `${a.title} (${a.type})`;
|
|
2321
2354
|
if (isExerciseStepApp(a)) {
|
|
@@ -2379,6 +2412,23 @@ const playgroundPath = path$1.join(workshopRoot, "playground/");
|
|
|
2379
2412
|
function getRelativePath$1(filePath) {
|
|
2380
2413
|
return path$1.normalize(filePath).replace(playgroundPath, `playground${path$1.sep}`).replace(exercisesPath, "");
|
|
2381
2414
|
}
|
|
2415
|
+
function getAppPathFromFilePath(filePath) {
|
|
2416
|
+
const [, withinWorkshopRootHalf] = filePath.split(workshopRoot);
|
|
2417
|
+
if (!withinWorkshopRootHalf) {
|
|
2418
|
+
return null;
|
|
2419
|
+
}
|
|
2420
|
+
const [part1, part2, part3] = withinWorkshopRootHalf.split(path$1.sep).filter(Boolean);
|
|
2421
|
+
if (part1 === "playground") {
|
|
2422
|
+
return path$1.join(workshopRoot, "playground");
|
|
2423
|
+
}
|
|
2424
|
+
if (part1 === "examples" && part2) {
|
|
2425
|
+
return path$1.join(workshopRoot, "examples", part2);
|
|
2426
|
+
}
|
|
2427
|
+
if (part1 === "exercises" && part2 && part3) {
|
|
2428
|
+
return path$1.join(workshopRoot, "exercises", part2, part3);
|
|
2429
|
+
}
|
|
2430
|
+
return null;
|
|
2431
|
+
}
|
|
2382
2432
|
function Confetti({ id }) {
|
|
2383
2433
|
if (!id) return null;
|
|
2384
2434
|
return /* @__PURE__ */ jsx(ClientOnly, { children: () => /* @__PURE__ */ jsx(
|
|
@@ -2614,7 +2664,7 @@ const extendedTheme = {
|
|
|
2614
2664
|
}
|
|
2615
2665
|
};
|
|
2616
2666
|
const AnchorOrLink = React.forwardRef(function AnchorOrLink2(props, ref) {
|
|
2617
|
-
var
|
|
2667
|
+
var _a;
|
|
2618
2668
|
const {
|
|
2619
2669
|
to,
|
|
2620
2670
|
href,
|
|
@@ -2635,7 +2685,7 @@ const AnchorOrLink = React.forwardRef(function AnchorOrLink2(props, ref) {
|
|
|
2635
2685
|
}
|
|
2636
2686
|
if (!shouldUserRegularAnchor && typeof to === "object") {
|
|
2637
2687
|
toUrl = `${to.pathname ?? ""}${to.hash ? `#${to.hash}` : ""}${to.search ? `?${to.search}` : ""}`;
|
|
2638
|
-
shouldUserRegularAnchor = Boolean((
|
|
2688
|
+
shouldUserRegularAnchor = Boolean((_a = to.pathname) == null ? void 0 : _a.includes(":"));
|
|
2639
2689
|
}
|
|
2640
2690
|
if (shouldUserRegularAnchor) {
|
|
2641
2691
|
return /* @__PURE__ */ jsx("a", { ...rest, download, href: href ?? toUrl, ref, children });
|
|
@@ -2799,8 +2849,8 @@ function EpicProgress() {
|
|
|
2799
2849
|
const transition = useNavigation();
|
|
2800
2850
|
const fetchers = useFetchers().filter(
|
|
2801
2851
|
(fetcher) => {
|
|
2802
|
-
var
|
|
2803
|
-
return ((
|
|
2852
|
+
var _a;
|
|
2853
|
+
return ((_a = fetcher.formData) == null ? void 0 : _a.get("show-progress-bar")) === "true";
|
|
2804
2854
|
}
|
|
2805
2855
|
);
|
|
2806
2856
|
const states = [transition.state, ...fetchers.map((f) => f.state)];
|
|
@@ -3040,17 +3090,17 @@ function ThemeSwitch() {
|
|
|
3040
3090
|
] });
|
|
3041
3091
|
}
|
|
3042
3092
|
function useTheme() {
|
|
3043
|
-
var
|
|
3093
|
+
var _a;
|
|
3044
3094
|
const hints = useHints();
|
|
3045
3095
|
const requestInfo = useRequestInfo();
|
|
3046
3096
|
const fetchers = useFetchers();
|
|
3047
3097
|
const fetcher = fetchers.find(
|
|
3048
3098
|
(f) => {
|
|
3049
|
-
var
|
|
3050
|
-
return ((
|
|
3099
|
+
var _a2;
|
|
3100
|
+
return ((_a2 = f.formData) == null ? void 0 : _a2.get("intent")) === "update-theme";
|
|
3051
3101
|
}
|
|
3052
3102
|
);
|
|
3053
|
-
const optimisticTheme = (
|
|
3103
|
+
const optimisticTheme = (_a = fetcher == null ? void 0 : fetcher.formData) == null ? void 0 : _a.get("theme");
|
|
3054
3104
|
if (optimisticTheme === "system") return hints.theme;
|
|
3055
3105
|
if (optimisticTheme === "light" || optimisticTheme === "dark") {
|
|
3056
3106
|
return optimisticTheme;
|
|
@@ -3324,7 +3374,7 @@ function getProgressForLesson(epicLessonSlug, {
|
|
|
3324
3374
|
workshopFinished,
|
|
3325
3375
|
exercises
|
|
3326
3376
|
}) {
|
|
3327
|
-
var
|
|
3377
|
+
var _a;
|
|
3328
3378
|
const hasEmbed = (embed) => embed == null ? void 0 : embed.some((e) => e.split("/").at(-1) === epicLessonSlug);
|
|
3329
3379
|
if (workshopInstructions.compiled.status === "success" && hasEmbed(workshopInstructions.compiled.epicVideoEmbeds)) {
|
|
3330
3380
|
return { type: "workshop-instructions" };
|
|
@@ -3346,7 +3396,7 @@ function getProgressForLesson(epicLessonSlug, {
|
|
|
3346
3396
|
};
|
|
3347
3397
|
}
|
|
3348
3398
|
for (const step of exercise.steps.filter(Boolean)) {
|
|
3349
|
-
if (hasEmbed((
|
|
3399
|
+
if (hasEmbed((_a = step.problem) == null ? void 0 : _a.epicVideoEmbeds)) {
|
|
3350
3400
|
return {
|
|
3351
3401
|
type: "step",
|
|
3352
3402
|
exerciseNumber: exercise.exerciseNumber,
|
|
@@ -3444,7 +3494,7 @@ async function userHasAccessToWorkshop({
|
|
|
3444
3494
|
request,
|
|
3445
3495
|
forceFresh
|
|
3446
3496
|
}) {
|
|
3447
|
-
var
|
|
3497
|
+
var _a;
|
|
3448
3498
|
const config = getWorkshopConfig();
|
|
3449
3499
|
const {
|
|
3450
3500
|
product: { host, slug }
|
|
@@ -3454,7 +3504,7 @@ async function userHasAccessToWorkshop({
|
|
|
3454
3504
|
const cookieHeader = request.headers.get("Cookie");
|
|
3455
3505
|
if (!cookieHeader) return false;
|
|
3456
3506
|
const cookies = cookie__default.parse(cookieHeader);
|
|
3457
|
-
return ((
|
|
3507
|
+
return ((_a = cookies.skill) == null ? void 0 : _a.split(",").includes(slug)) ?? false;
|
|
3458
3508
|
}
|
|
3459
3509
|
const authInfo = await getAuthInfo();
|
|
3460
3510
|
if (!authInfo) return false;
|
|
@@ -3486,9 +3536,9 @@ async function userHasAccessToWorkshop({
|
|
|
3486
3536
|
}
|
|
3487
3537
|
const PresenceContext = createContext(null);
|
|
3488
3538
|
function usePresencePreferences() {
|
|
3489
|
-
var
|
|
3539
|
+
var _a;
|
|
3490
3540
|
const data = useRouteLoaderData("root");
|
|
3491
|
-
return ((
|
|
3541
|
+
return ((_a = data == null ? void 0 : data.preferences) == null ? void 0 : _a.presence) ?? null;
|
|
3492
3542
|
}
|
|
3493
3543
|
function useOptionalWorkshopTitle() {
|
|
3494
3544
|
const data = useRouteLoaderData("root");
|
|
@@ -3567,10 +3617,10 @@ function usePresenceSocket(user) {
|
|
|
3567
3617
|
}
|
|
3568
3618
|
function scoreUsers(location, users) {
|
|
3569
3619
|
const scoredUsers = users.map((user) => {
|
|
3570
|
-
var
|
|
3620
|
+
var _a, _b, _c, _d;
|
|
3571
3621
|
let score = 0;
|
|
3572
3622
|
const available = 4;
|
|
3573
|
-
if ((location == null ? void 0 : location.workshopTitle) === ((
|
|
3623
|
+
if ((location == null ? void 0 : location.workshopTitle) === ((_a = user.location) == null ? void 0 : _a.workshopTitle)) {
|
|
3574
3624
|
score += 1;
|
|
3575
3625
|
if (((_b = location == null ? void 0 : location.exercise) == null ? void 0 : _b.exerciseNumber) && location.exercise.exerciseNumber === ((_d = (_c = user.location) == null ? void 0 : _c.exercise) == null ? void 0 : _d.exerciseNumber)) {
|
|
3576
3626
|
score += 1;
|
|
@@ -3722,33 +3772,42 @@ async function loader$y({ request }) {
|
|
|
3722
3772
|
throw redirect("/onboarding");
|
|
3723
3773
|
}
|
|
3724
3774
|
}
|
|
3725
|
-
const preferences = await getPreferences();
|
|
3726
|
-
const progress = await getProgress({ timings }).catch((e) => {
|
|
3727
|
-
console.error("Failed to get progress", e);
|
|
3728
|
-
const emptyProgress = [];
|
|
3729
|
-
return emptyProgress;
|
|
3730
|
-
});
|
|
3731
|
-
const { toast: toast2, headers: toastHeaders } = await getToast(request);
|
|
3732
|
-
const { confettiId, headers: confettiHeaders } = getConfetti(request);
|
|
3733
|
-
const discordMember = await getDiscordMember();
|
|
3734
3775
|
const theme = getTheme(request);
|
|
3735
|
-
const
|
|
3736
|
-
const
|
|
3737
|
-
const
|
|
3738
|
-
|
|
3776
|
+
const { confettiId, headers: confettiHeaders } = getConfetti(request);
|
|
3777
|
+
const { toast: toast2, headers: toastHeaders } = await getToast(request);
|
|
3778
|
+
const asyncStuff = await promiseHash({
|
|
3779
|
+
preferences: getPreferences(),
|
|
3780
|
+
progress: getProgress({ timings }).catch((e) => {
|
|
3781
|
+
console.error("Failed to get progress", e);
|
|
3782
|
+
const emptyProgress = [];
|
|
3783
|
+
return emptyProgress;
|
|
3784
|
+
}),
|
|
3785
|
+
discordMember: getDiscordMember(),
|
|
3786
|
+
user: getUserInfo(),
|
|
3787
|
+
userHasAccess: userHasAccessToWorkshop({ request, timings }),
|
|
3788
|
+
apps: getApps({ request, timings })
|
|
3789
|
+
});
|
|
3790
|
+
const presentUsers = await getPresentUsers(asyncStuff.user, {
|
|
3791
|
+
request,
|
|
3792
|
+
timings
|
|
3793
|
+
});
|
|
3739
3794
|
return json$1(
|
|
3740
3795
|
{
|
|
3796
|
+
...asyncStuff,
|
|
3741
3797
|
workshopConfig,
|
|
3742
3798
|
workshopTitle,
|
|
3743
3799
|
workshopSubtitle,
|
|
3744
3800
|
instructor,
|
|
3745
|
-
apps: apps.map(({ name, fullPath, relativePath }) => ({
|
|
3801
|
+
apps: asyncStuff.apps.map(({ name, fullPath, relativePath }) => ({
|
|
3746
3802
|
name,
|
|
3747
3803
|
fullPath,
|
|
3748
3804
|
relativePath
|
|
3749
3805
|
})),
|
|
3750
3806
|
ENV: getEnv(),
|
|
3751
3807
|
requestInfo: {
|
|
3808
|
+
protocol: new URL(request.url).protocol,
|
|
3809
|
+
hostname: new URL(request.url).hostname,
|
|
3810
|
+
port: new URL(request.url).port,
|
|
3752
3811
|
origin: new URL(request.url).origin,
|
|
3753
3812
|
domain: getDomainUrl(request),
|
|
3754
3813
|
hints: getHints(request),
|
|
@@ -3756,11 +3815,6 @@ async function loader$y({ request }) {
|
|
|
3756
3815
|
session: { theme },
|
|
3757
3816
|
separator: path$1.sep
|
|
3758
3817
|
},
|
|
3759
|
-
progress,
|
|
3760
|
-
preferences,
|
|
3761
|
-
discordMember,
|
|
3762
|
-
user,
|
|
3763
|
-
userHasAccess,
|
|
3764
3818
|
toast: toast2,
|
|
3765
3819
|
confettiId,
|
|
3766
3820
|
presence: {
|
|
@@ -3786,11 +3840,6 @@ function Document({
|
|
|
3786
3840
|
env = {},
|
|
3787
3841
|
className
|
|
3788
3842
|
}) {
|
|
3789
|
-
const revalidator = useRevalidator();
|
|
3790
|
-
useEffect(() => {
|
|
3791
|
-
window.__epicshop ?? (window.__epicshop = {});
|
|
3792
|
-
window.__epicshop.handleFileChange = revalidator.revalidate;
|
|
3793
|
-
}, [revalidator]);
|
|
3794
3843
|
return /* @__PURE__ */ jsxs("html", { lang: "en", className, children: [
|
|
3795
3844
|
/* @__PURE__ */ jsxs("head", { children: [
|
|
3796
3845
|
/* @__PURE__ */ jsx(ClientHintCheck, {}),
|
|
@@ -3810,8 +3859,7 @@ function Document({
|
|
|
3810
3859
|
/* @__PURE__ */ jsxs("body", { className: "bg-background text-foreground scrollbar-thin scrollbar-thumb-scrollbar h-screen-safe", children: [
|
|
3811
3860
|
children,
|
|
3812
3861
|
/* @__PURE__ */ jsx(ScrollRestoration, {}),
|
|
3813
|
-
/* @__PURE__ */ jsx(Scripts, {})
|
|
3814
|
-
ENV.EPICSHOP_DEPLOYED ? null : /* @__PURE__ */ jsx("script", { dangerouslySetInnerHTML: { __html: getWebsocketJS() } })
|
|
3862
|
+
/* @__PURE__ */ jsx(Scripts, {})
|
|
3815
3863
|
] })
|
|
3816
3864
|
] });
|
|
3817
3865
|
}
|
|
@@ -3850,70 +3898,6 @@ function AppWithProviders() {
|
|
|
3850
3898
|
function ErrorBoundary$6() {
|
|
3851
3899
|
return /* @__PURE__ */ jsx(Document, { className: "h-screen-safe", children: /* @__PURE__ */ jsx(GeneralErrorBoundary, {}) });
|
|
3852
3900
|
}
|
|
3853
|
-
function getWebsocketJS() {
|
|
3854
|
-
const js = (
|
|
3855
|
-
/* javascript */
|
|
3856
|
-
`
|
|
3857
|
-
function epicLiveReloadConnect(config) {
|
|
3858
|
-
const protocol = location.protocol === "https:" ? "wss:" : "ws:";
|
|
3859
|
-
const host = location.hostname;
|
|
3860
|
-
const port = location.port;
|
|
3861
|
-
const socketPath = protocol + "//" + host + ":" + port + "/__ws";
|
|
3862
|
-
const ws = new WebSocket(socketPath);
|
|
3863
|
-
function handleFileChange(changedFiles) {
|
|
3864
|
-
console.log(
|
|
3865
|
-
['🐨 Reloading', window.frameElement?.getAttribute('title')]
|
|
3866
|
-
.filter(Boolean)
|
|
3867
|
-
.join(' '),
|
|
3868
|
-
changedFiles
|
|
3869
|
-
);
|
|
3870
|
-
if (typeof window.__epicshop?.handleFileChange === "function") {
|
|
3871
|
-
window.__epicshop?.handleFileChange();
|
|
3872
|
-
} else {
|
|
3873
|
-
setTimeout(() => window.location.reload(), 200);
|
|
3874
|
-
}
|
|
3875
|
-
}
|
|
3876
|
-
function debounce(fn, ms) {
|
|
3877
|
-
let timeout;
|
|
3878
|
-
return function debouncedFn(...args) {
|
|
3879
|
-
clearTimeout(timeout);
|
|
3880
|
-
timeout = setTimeout(() => fn(...args), ms);
|
|
3881
|
-
};
|
|
3882
|
-
}
|
|
3883
|
-
const debouncedHandleFileChange = debounce(handleFileChange, 50);
|
|
3884
|
-
ws.onmessage = (message) => {
|
|
3885
|
-
const event = JSON.parse(message.data);
|
|
3886
|
-
if (event.type !== 'epicshop:file-change') return;
|
|
3887
|
-
const { filePaths } = event.data;
|
|
3888
|
-
debouncedHandleFileChange(filePaths);
|
|
3889
|
-
};
|
|
3890
|
-
ws.onopen = () => {
|
|
3891
|
-
if (config && typeof config.onOpen === "function") {
|
|
3892
|
-
config.onOpen();
|
|
3893
|
-
}
|
|
3894
|
-
};
|
|
3895
|
-
ws.onclose = (event) => {
|
|
3896
|
-
if (event.code === 1006) {
|
|
3897
|
-
console.log("EpicShop dev server web socket closed. Reconnecting...");
|
|
3898
|
-
setTimeout(
|
|
3899
|
-
() =>
|
|
3900
|
-
epicLiveReloadConnect({
|
|
3901
|
-
onOpen: () => window.location.reload(),
|
|
3902
|
-
}),
|
|
3903
|
-
1000
|
|
3904
|
-
);
|
|
3905
|
-
}
|
|
3906
|
-
};
|
|
3907
|
-
ws.onerror = (error) => {
|
|
3908
|
-
console.log("EpicShop dev server web socket error:");
|
|
3909
|
-
console.error(error);
|
|
3910
|
-
};
|
|
3911
|
-
}
|
|
3912
|
-
epicLiveReloadConnect();
|
|
3913
|
-
`
|
|
3914
|
-
);
|
|
3915
|
-
return js;
|
|
3916
|
-
}
|
|
3917
3901
|
const route0 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
3918
3902
|
__proto__: null,
|
|
3919
3903
|
ErrorBoundary: ErrorBoundary$6,
|
|
@@ -4050,6 +4034,63 @@ function Logo({
|
|
|
4050
4034
|
}
|
|
4051
4035
|
return logoElement;
|
|
4052
4036
|
}
|
|
4037
|
+
const eventSchema = z.object({
|
|
4038
|
+
type: z.literal("epicshop:file-change"),
|
|
4039
|
+
data: z.object({
|
|
4040
|
+
filePaths: z.array(z.string())
|
|
4041
|
+
})
|
|
4042
|
+
});
|
|
4043
|
+
function useRevalidationWSImpl({ watchPaths }) {
|
|
4044
|
+
const requestInfo = useRequestInfo();
|
|
4045
|
+
const revalidator = useRevalidator();
|
|
4046
|
+
const latestRevalidatorRef = useRef(revalidator);
|
|
4047
|
+
useEffect(() => {
|
|
4048
|
+
latestRevalidatorRef.current = revalidator;
|
|
4049
|
+
}, [revalidator]);
|
|
4050
|
+
const socketParams = new URLSearchParams();
|
|
4051
|
+
for (const path2 of watchPaths) {
|
|
4052
|
+
socketParams.append("watch", path2);
|
|
4053
|
+
}
|
|
4054
|
+
const socketQuery = socketParams.toString();
|
|
4055
|
+
const protocol = requestInfo.protocol === "https:" ? "wss:" : "ws:";
|
|
4056
|
+
const host = requestInfo.hostname;
|
|
4057
|
+
const port2 = requestInfo.port;
|
|
4058
|
+
const socketPath = `${protocol}//${host}:${port2}/__ws?${socketQuery}`;
|
|
4059
|
+
useEffect(() => {
|
|
4060
|
+
if (!socketQuery) return;
|
|
4061
|
+
let ws = null;
|
|
4062
|
+
function createWebSocket() {
|
|
4063
|
+
if (ws) ws.close();
|
|
4064
|
+
ws = new WebSocket(socketPath);
|
|
4065
|
+
ws.onmessage = (message) => {
|
|
4066
|
+
const eventParsed = eventSchema.safeParse(JSON.parse(message.data));
|
|
4067
|
+
if (!eventParsed.success) return;
|
|
4068
|
+
const { data: event } = eventParsed;
|
|
4069
|
+
if (event.type !== "epicshop:file-change") return;
|
|
4070
|
+
console.log(
|
|
4071
|
+
"🐨 Revalidating due to file changes:",
|
|
4072
|
+
event.data.filePaths
|
|
4073
|
+
);
|
|
4074
|
+
latestRevalidatorRef.current.revalidate();
|
|
4075
|
+
};
|
|
4076
|
+
ws.onclose = (event) => {
|
|
4077
|
+
if (event.code === 1006) {
|
|
4078
|
+
setTimeout(() => {
|
|
4079
|
+
createWebSocket();
|
|
4080
|
+
}, 1e3);
|
|
4081
|
+
}
|
|
4082
|
+
};
|
|
4083
|
+
ws.onerror = (error) => {
|
|
4084
|
+
console.error("🐨 EpicShop WebSocket error:", error);
|
|
4085
|
+
};
|
|
4086
|
+
}
|
|
4087
|
+
createWebSocket();
|
|
4088
|
+
return () => {
|
|
4089
|
+
ws == null ? void 0 : ws.close();
|
|
4090
|
+
};
|
|
4091
|
+
}, [socketQuery, socketPath]);
|
|
4092
|
+
}
|
|
4093
|
+
const useRevalidationWS = ENV.EPICSHOP_DEPLOYED ? () => null : useRevalidationWSImpl;
|
|
4053
4094
|
const Dialog = DialogPrimitive.Root;
|
|
4054
4095
|
const DialogTrigger = DialogPrimitive.Trigger;
|
|
4055
4096
|
const DialogPortal = DialogPrimitive.Portal;
|
|
@@ -4157,14 +4198,14 @@ function useEpicProgress() {
|
|
|
4157
4198
|
const data = useRouteLoaderData("root");
|
|
4158
4199
|
const progressFetcher = useFetchers().find(
|
|
4159
4200
|
(f) => {
|
|
4160
|
-
var
|
|
4161
|
-
return f.formAction === "/progress" && ((
|
|
4201
|
+
var _a;
|
|
4202
|
+
return f.formAction === "/progress" && ((_a = f.formData) == null ? void 0 : _a.has("complete"));
|
|
4162
4203
|
}
|
|
4163
4204
|
);
|
|
4164
4205
|
if (!progressFetcher || !(data == null ? void 0 : data.progress)) return (data == null ? void 0 : data.progress) ?? null;
|
|
4165
4206
|
return data.progress.map((p) => {
|
|
4166
|
-
var
|
|
4167
|
-
const optimisticCompleted = ((
|
|
4207
|
+
var _a, _b;
|
|
4208
|
+
const optimisticCompleted = ((_a = progressFetcher.formData) == null ? void 0 : _a.get("complete")) === "true";
|
|
4168
4209
|
const optimisticLessonSlug = (_b = progressFetcher.formData) == null ? void 0 : _b.get("lessonSlug");
|
|
4169
4210
|
if (optimisticLessonSlug === p.epicLessonSlug) {
|
|
4170
4211
|
return {
|
|
@@ -4324,13 +4365,13 @@ function ProgressToggle({
|
|
|
4324
4365
|
className,
|
|
4325
4366
|
...progressItemSearch
|
|
4326
4367
|
}) {
|
|
4327
|
-
var
|
|
4368
|
+
var _a, _b, _c, _d;
|
|
4328
4369
|
const progressFetcher = useFetcher();
|
|
4329
4370
|
const peRedirectInput = usePERedirectInput();
|
|
4330
4371
|
const progressItem = useProgressItem(progressItemSearch);
|
|
4331
4372
|
const animationRef = React.useRef(null);
|
|
4332
4373
|
const buttonRef = React.useRef(null);
|
|
4333
|
-
const optimisticCompleted = ((
|
|
4374
|
+
const optimisticCompleted = ((_a = progressFetcher.formData) == null ? void 0 : _a.has("complete")) ? progressFetcher.formData.get("complete") === "true" : Boolean(progressItem == null ? void 0 : progressItem.epicCompletedAt);
|
|
4334
4375
|
const [startAnimation, setStartAnimation] = React.useState(false);
|
|
4335
4376
|
const location = useLocation();
|
|
4336
4377
|
const navigation = useNavigation();
|
|
@@ -4338,11 +4379,11 @@ function ProgressToggle({
|
|
|
4338
4379
|
const navigationLocationPathname = (_d = navigation.location) == null ? void 0 : _d.pathname;
|
|
4339
4380
|
const locationPathname = location.pathname;
|
|
4340
4381
|
React.useEffect(() => {
|
|
4341
|
-
var
|
|
4382
|
+
var _a2;
|
|
4342
4383
|
if (navigationLocationStateFrom === "continue next lesson button") {
|
|
4343
4384
|
if (locationPathname === navigationLocationPathname) {
|
|
4344
4385
|
setStartAnimation(true);
|
|
4345
|
-
(
|
|
4386
|
+
(_a2 = buttonRef.current) == null ? void 0 : _a2.focus();
|
|
4346
4387
|
}
|
|
4347
4388
|
}
|
|
4348
4389
|
}, [
|
|
@@ -4450,7 +4491,7 @@ const route36 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
4450
4491
|
useRequireEpicProgress
|
|
4451
4492
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
4452
4493
|
async function loader$w({ request }) {
|
|
4453
|
-
var
|
|
4494
|
+
var _a;
|
|
4454
4495
|
const timings = makeTimings("appLayoutLoader");
|
|
4455
4496
|
const { title: workshopTitle } = getWorkshopConfig();
|
|
4456
4497
|
const [exercises, playgroundAppName] = await Promise.all([
|
|
@@ -4460,7 +4501,7 @@ async function loader$w({ request }) {
|
|
|
4460
4501
|
const playground = {
|
|
4461
4502
|
appName: playgroundAppName,
|
|
4462
4503
|
exerciseNumber: Number(
|
|
4463
|
-
(
|
|
4504
|
+
(_a = extractNumbersAndTypeFromAppNameOrPath(playgroundAppName ?? "")) == null ? void 0 : _a.exerciseNumber
|
|
4464
4505
|
)
|
|
4465
4506
|
};
|
|
4466
4507
|
const result = json$1(
|
|
@@ -4554,7 +4595,7 @@ function FacePile({ isMenuOpened }) {
|
|
|
4554
4595
|
return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-2", children: /* @__PURE__ */ jsxs(TooltipProvider, { children: [
|
|
4555
4596
|
(shouldShowNumberOverLimit ? users.slice(0, limit) : users).map(
|
|
4556
4597
|
({ user, score }) => {
|
|
4557
|
-
var
|
|
4598
|
+
var _a, _b;
|
|
4558
4599
|
const scoreClassNames = getScoreClassNames(score);
|
|
4559
4600
|
const locationLabel = getLocationLabel(user.location);
|
|
4560
4601
|
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
@@ -4585,7 +4626,7 @@ function FacePile({ isMenuOpened }) {
|
|
|
4585
4626
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
4586
4627
|
user.name || `${displayNameShort} Dev`,
|
|
4587
4628
|
" ",
|
|
4588
|
-
locationLabel ? ` is ${((_b = (
|
|
4629
|
+
locationLabel ? ` is ${((_b = (_a = user.location) == null ? void 0 : _a.origin) == null ? void 0 : _b.includes("localhost")) ? "working" : "learning"} ${score === 1 && (loggedInUser == null ? void 0 : loggedInUser.id) !== user.id ? "with you" : ""} on` : null
|
|
4589
4630
|
] }),
|
|
4590
4631
|
(locationLabel == null ? void 0 : locationLabel.line1) ? /* @__PURE__ */ jsx("span", { children: locationLabel.line1 }) : null,
|
|
4591
4632
|
(locationLabel == null ? void 0 : locationLabel.line2) ? /* @__PURE__ */ jsx("span", { children: locationLabel.line2 }) : null
|
|
@@ -4626,6 +4667,7 @@ function App() {
|
|
|
4626
4667
|
const isWide = useIsWide();
|
|
4627
4668
|
const isHydrated = useHydrated();
|
|
4628
4669
|
const [isMenuOpened, setMenuOpened] = React.useState(false);
|
|
4670
|
+
useRevalidationWS({ watchPaths: ["./exercises/README.mdx"] });
|
|
4629
4671
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
4630
4672
|
user ? null : /* @__PURE__ */ jsx(NoUserBanner, {}),
|
|
4631
4673
|
isHydrated && isWide ? null : /* @__PURE__ */ jsx(
|
|
@@ -5462,9 +5504,9 @@ function NavToggle({
|
|
|
5462
5504
|
React.useEffect(() => {
|
|
5463
5505
|
if (!isMenuOpened) return;
|
|
5464
5506
|
function handleKeyUp(event) {
|
|
5465
|
-
var
|
|
5507
|
+
var _a;
|
|
5466
5508
|
if (event.key === "Escape") {
|
|
5467
|
-
(
|
|
5509
|
+
(_a = menuButtonRef.current) == null ? void 0 : _a.click();
|
|
5468
5510
|
}
|
|
5469
5511
|
}
|
|
5470
5512
|
document.addEventListener("keyup", handleKeyUp);
|
|
@@ -5816,7 +5858,7 @@ async function getForceFresh(filePath, cacheEntry) {
|
|
|
5816
5858
|
if (!cacheEntry) return true;
|
|
5817
5859
|
const app = await getAppFromFile(filePath);
|
|
5818
5860
|
if (!app) return true;
|
|
5819
|
-
const appModified =
|
|
5861
|
+
const appModified = await queuedGetDirModifiedTime(app.fullPath);
|
|
5820
5862
|
const cacheModified = cacheEntry.metadata.createdTime;
|
|
5821
5863
|
return !cacheModified || appModified > cacheModified || void 0;
|
|
5822
5864
|
}
|
|
@@ -5836,7 +5878,7 @@ async function compileTs(filePath, fullPath, {
|
|
|
5836
5878
|
getFreshValue: async () => {
|
|
5837
5879
|
const result = await esbuild.build({
|
|
5838
5880
|
stdin: {
|
|
5839
|
-
contents: await fs
|
|
5881
|
+
contents: await fs.promises.readFile(filePath, "utf-8"),
|
|
5840
5882
|
// NOTE: if the fileAppName is specified, then we're resolving to a different
|
|
5841
5883
|
// app than the one we're serving the file from. We do this so the tests
|
|
5842
5884
|
// can live in the solution directory, but be run against the problem
|
|
@@ -6070,6 +6112,10 @@ async function loader$r({ request, params }) {
|
|
|
6070
6112
|
return redirect(getBaseUrl({ request, port: app.dev.portNumber }));
|
|
6071
6113
|
}
|
|
6072
6114
|
const relevantPaths = Array.from(/* @__PURE__ */ new Set([app.fullPath, fileApp.fullPath]));
|
|
6115
|
+
const watchParams = new URLSearchParams();
|
|
6116
|
+
for (const path2 of relevantPaths) {
|
|
6117
|
+
watchParams.append("watch", path2);
|
|
6118
|
+
}
|
|
6073
6119
|
const js = (
|
|
6074
6120
|
/* javascript */
|
|
6075
6121
|
`
|
|
@@ -6077,20 +6123,19 @@ async function loader$r({ request, params }) {
|
|
|
6077
6123
|
const protocol = location.protocol === "https:" ? "wss:" : "ws:";
|
|
6078
6124
|
const host = location.hostname;
|
|
6079
6125
|
const port = location.port;
|
|
6080
|
-
const socketPath = protocol + "//" + host + ":" + port + "/__ws";
|
|
6126
|
+
const socketPath = protocol + "//" + host + ":" + port + "/__ws?" + ${JSON.stringify(watchParams.toString())};
|
|
6081
6127
|
const ws = new WebSocket(socketPath);
|
|
6082
6128
|
ws.onmessage = (message) => {
|
|
6083
6129
|
const event = JSON.parse(message.data);
|
|
6084
6130
|
if (event.type !== 'epicshop:file-change') return;
|
|
6085
6131
|
const { filePaths } = event.data;
|
|
6086
|
-
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
}
|
|
6132
|
+
console.log(
|
|
6133
|
+
['🐨 Reloading', window.frameElement?.getAttribute('title'), 'due to file changes:']
|
|
6134
|
+
.filter(Boolean)
|
|
6135
|
+
.join(' '),
|
|
6136
|
+
filePaths
|
|
6137
|
+
);
|
|
6138
|
+
window.location.reload();
|
|
6094
6139
|
};
|
|
6095
6140
|
ws.onopen = () => {
|
|
6096
6141
|
if (config && typeof config.onOpen === "function") {
|
|
@@ -6129,7 +6174,7 @@ const route6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
|
|
|
6129
6174
|
loader: loader$r
|
|
6130
6175
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
6131
6176
|
async function loader$q({ request, params }) {
|
|
6132
|
-
var
|
|
6177
|
+
var _a;
|
|
6133
6178
|
const timings = makeTimings("app");
|
|
6134
6179
|
const { fileApp, app } = await resolveApps({ request, params, timings });
|
|
6135
6180
|
const baseApp = isPlaygroundApp(app) ? await getAppByName(app.appName) : app;
|
|
@@ -6177,7 +6222,7 @@ async function loader$q({ request, params }) {
|
|
|
6177
6222
|
const { title: workshopTitle } = getWorkshopConfig();
|
|
6178
6223
|
const baseAppTitle = isExerciseStepApp(baseApp) ? [
|
|
6179
6224
|
`${baseApp.stepNumber.toString().padStart(2, "0")}. ${baseApp.title}`,
|
|
6180
|
-
`${baseApp.exerciseNumber.toString().padStart(2, "0")}. ${((
|
|
6225
|
+
`${baseApp.exerciseNumber.toString().padStart(2, "0")}. ${((_a = await getExercise(baseApp.exerciseNumber, { request, timings })) == null ? void 0 : _a.title) ?? "Unknown"}`,
|
|
6181
6226
|
workshopTitle
|
|
6182
6227
|
] : [(baseApp == null ? void 0 : baseApp.title) ?? "N/A"];
|
|
6183
6228
|
const title = (isExerciseStepApp(app) ? [
|
|
@@ -6217,7 +6262,7 @@ const route7 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
|
|
|
6217
6262
|
loader: loader$q
|
|
6218
6263
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
6219
6264
|
async function loader$p({ request, params }) {
|
|
6220
|
-
var
|
|
6265
|
+
var _a;
|
|
6221
6266
|
const timings = makeTimings("app_test_loader");
|
|
6222
6267
|
const userHasAccess = await userHasAccessToWorkshop({
|
|
6223
6268
|
request
|
|
@@ -6320,7 +6365,7 @@ ${testScriptTag}`;
|
|
|
6320
6365
|
const title = (isExerciseStepApp(app) ? [
|
|
6321
6366
|
isProblemApp(app) ? "🧪💪" : isSolutionApp(app) ? "🧪🏁" : null,
|
|
6322
6367
|
`${app.stepNumber.toString().padStart(2, "0")}. ${app.title}`,
|
|
6323
|
-
`${app.exerciseNumber.toString().padStart(2, "0")}. ${((
|
|
6368
|
+
`${app.exerciseNumber.toString().padStart(2, "0")}. ${((_a = await getExercise(app.exerciseNumber, { request, timings })) == null ? void 0 : _a.title) ?? "Unknown"}`,
|
|
6324
6369
|
workshopTitle
|
|
6325
6370
|
] : ["🧪", appTitle]).filter(Boolean).join(" | ");
|
|
6326
6371
|
const html = (
|
|
@@ -6501,9 +6546,9 @@ const PlaybackTimeSchema = z.object({
|
|
|
6501
6546
|
return { time: Number(data.time), expiresAt: new Date(data.expiresAt) };
|
|
6502
6547
|
});
|
|
6503
6548
|
function usePlayerPreferences() {
|
|
6504
|
-
var
|
|
6549
|
+
var _a;
|
|
6505
6550
|
const data = useRouteLoaderData("root");
|
|
6506
|
-
return ((
|
|
6551
|
+
return ((_a = data == null ? void 0 : data.preferences) == null ? void 0 : _a.player) ?? null;
|
|
6507
6552
|
}
|
|
6508
6553
|
const ignoredInputs = [
|
|
6509
6554
|
"INPUT",
|
|
@@ -6611,9 +6656,9 @@ function MuxPlayer({
|
|
|
6611
6656
|
});
|
|
6612
6657
|
}, 300);
|
|
6613
6658
|
React.useEffect(() => {
|
|
6614
|
-
var
|
|
6659
|
+
var _a, _b;
|
|
6615
6660
|
if (!metadataLoaded) return;
|
|
6616
|
-
const textTracks = (
|
|
6661
|
+
const textTracks = (_a = muxPlayerRef.current) == null ? void 0 : _a.textTracks;
|
|
6617
6662
|
if (!textTracks) return;
|
|
6618
6663
|
const subtitlePref = (_b = playerPreferencesRef.current) == null ? void 0 : _b.subtitle;
|
|
6619
6664
|
if (subtitlePref == null ? void 0 : subtitlePref.id) {
|
|
@@ -6655,11 +6700,11 @@ function MuxPlayer({
|
|
|
6655
6700
|
defaultHiddenCaptions: true,
|
|
6656
6701
|
currentTime,
|
|
6657
6702
|
onTimeUpdate: () => {
|
|
6658
|
-
var
|
|
6703
|
+
var _a;
|
|
6659
6704
|
return sessionStorage.setItem(
|
|
6660
6705
|
currentTimeSessionKey,
|
|
6661
6706
|
JSON.stringify({
|
|
6662
|
-
time: (
|
|
6707
|
+
time: (_a = muxPlayerRef.current) == null ? void 0 : _a.currentTime,
|
|
6663
6708
|
expiresAt: new Date(Date.now() + 1e3 * 60 * 30).toISOString()
|
|
6664
6709
|
})
|
|
6665
6710
|
);
|
|
@@ -6743,8 +6788,8 @@ function useInterval(callback, delay = 1e3) {
|
|
|
6743
6788
|
}, [callback]);
|
|
6744
6789
|
useEffect(() => {
|
|
6745
6790
|
function tick() {
|
|
6746
|
-
var
|
|
6747
|
-
(
|
|
6791
|
+
var _a;
|
|
6792
|
+
(_a = savedCallback.current) == null ? void 0 : _a.call(savedCallback);
|
|
6748
6793
|
}
|
|
6749
6794
|
if (delay !== null) {
|
|
6750
6795
|
const id = setInterval(tick, delay);
|
|
@@ -6872,7 +6917,7 @@ function extractEpicTitle(urlString) {
|
|
|
6872
6917
|
"useFetcherType"
|
|
6873
6918
|
];
|
|
6874
6919
|
const title = titleWords.filter(Boolean).map((word, index) => {
|
|
6875
|
-
var
|
|
6920
|
+
var _a;
|
|
6876
6921
|
const lowerWord = word.toLowerCase();
|
|
6877
6922
|
const literalWord = literalWords.find(
|
|
6878
6923
|
(w) => w.toLowerCase() === lowerWord
|
|
@@ -6881,7 +6926,7 @@ function extractEpicTitle(urlString) {
|
|
|
6881
6926
|
if (lowerCaseWords.includes(lowerWord) && index > 0) {
|
|
6882
6927
|
return lowerWord;
|
|
6883
6928
|
}
|
|
6884
|
-
return ((
|
|
6929
|
+
return ((_a = lowerWord[0]) == null ? void 0 : _a.toUpperCase()) + lowerWord.slice(1);
|
|
6885
6930
|
}).join(" ");
|
|
6886
6931
|
if (isSolution) {
|
|
6887
6932
|
return `${title} (🏁 solution)`;
|
|
@@ -7351,7 +7396,7 @@ function getArgumentsForLineNumber(editor, fileName, lineNumber, colNumber, work
|
|
|
7351
7396
|
return [fileName];
|
|
7352
7397
|
}
|
|
7353
7398
|
function guessEditor() {
|
|
7354
|
-
var
|
|
7399
|
+
var _a;
|
|
7355
7400
|
if (process.env.EPICSHOP_EDITOR) {
|
|
7356
7401
|
return shellQuote.parse(process.env.EPICSHOP_EDITOR).map((a) => String(a));
|
|
7357
7402
|
}
|
|
@@ -7372,7 +7417,7 @@ function guessEditor() {
|
|
|
7372
7417
|
).toString();
|
|
7373
7418
|
const runningProcesses = output.split("\r\n");
|
|
7374
7419
|
for (let i = 0; i < runningProcesses.length; i++) {
|
|
7375
|
-
const processPath = (
|
|
7420
|
+
const processPath = (_a = runningProcesses[i]) == null ? void 0 : _a.trim();
|
|
7376
7421
|
if (!processPath) continue;
|
|
7377
7422
|
const processName = path.basename(processPath);
|
|
7378
7423
|
if (COMMON_EDITORS_WIN.includes(processName)) {
|
|
@@ -7431,7 +7476,7 @@ async function launchEditor(pathList, lineNumber = 1, colNumber = 1) {
|
|
|
7431
7476
|
)) {
|
|
7432
7477
|
acc.errorsList.push(fileName);
|
|
7433
7478
|
} else {
|
|
7434
|
-
if (!fs
|
|
7479
|
+
if (!fs.existsSync(fileName)) {
|
|
7435
7480
|
fsExtra.ensureDirSync(path.dirname(fileName));
|
|
7436
7481
|
fsExtra.writeFileSync(fileName, "", "utf8");
|
|
7437
7482
|
}
|
|
@@ -7481,7 +7526,7 @@ File names may consist only of alphanumeric characters (all languages), periods,
|
|
|
7481
7526
|
_childProcess.kill("SIGKILL");
|
|
7482
7527
|
}
|
|
7483
7528
|
return new Promise((res) => {
|
|
7484
|
-
var
|
|
7529
|
+
var _a;
|
|
7485
7530
|
if (process.platform === "win32") {
|
|
7486
7531
|
_childProcess = child_process.spawn(
|
|
7487
7532
|
"cmd.exe",
|
|
@@ -7493,7 +7538,7 @@ File names may consist only of alphanumeric characters (all languages), periods,
|
|
|
7493
7538
|
stdio: ["inherit", "inherit", "pipe"]
|
|
7494
7539
|
});
|
|
7495
7540
|
}
|
|
7496
|
-
(
|
|
7541
|
+
(_a = _childProcess.stderr) == null ? void 0 : _a.on("data", (data) => {
|
|
7497
7542
|
const message = String(data);
|
|
7498
7543
|
if (!message.includes("Node.js environment variables are disabled")) {
|
|
7499
7544
|
process.stderr.write(data);
|
|
@@ -7663,7 +7708,7 @@ function LaunchEditorImpl({
|
|
|
7663
7708
|
children,
|
|
7664
7709
|
onUpdate
|
|
7665
7710
|
}) {
|
|
7666
|
-
var
|
|
7711
|
+
var _a;
|
|
7667
7712
|
const fetcher = useLaunchFetcher(onUpdate);
|
|
7668
7713
|
const peRedirectInput = usePERedirectInput();
|
|
7669
7714
|
const fileList = typeof appFile === "string" ? [appFile] : appFile;
|
|
@@ -7697,7 +7742,7 @@ function LaunchEditorImpl({
|
|
|
7697
7742
|
className: clsx(
|
|
7698
7743
|
"launch_button",
|
|
7699
7744
|
fetcher.state === "idle" ? null : "cursor-progress",
|
|
7700
|
-
((
|
|
7745
|
+
((_a = fetcher.data) == null ? void 0 : _a.status) === "error" ? "cursor-not-allowed" : null
|
|
7701
7746
|
),
|
|
7702
7747
|
children
|
|
7703
7748
|
}
|
|
@@ -7808,19 +7853,19 @@ function OpenInEditor({
|
|
|
7808
7853
|
"data-start": start,
|
|
7809
7854
|
"data-type": type
|
|
7810
7855
|
}) {
|
|
7811
|
-
var
|
|
7856
|
+
var _a;
|
|
7812
7857
|
const data = useLoaderData();
|
|
7813
7858
|
if (type === "other" || !buttons || !filename || !fullPath) return null;
|
|
7814
|
-
const currentAppFullPath = safePath(((
|
|
7859
|
+
const currentAppFullPath = safePath(((_a = data[data.type]) == null ? void 0 : _a.fullPath) ?? "");
|
|
7815
7860
|
const isFileFromDifferentApp = !fullPath.startsWith(currentAppFullPath);
|
|
7816
7861
|
const validButtons = ENV.EPICSHOP_DEPLOYED ? ["problem", "solution"] : ["problem", "solution", "playground"];
|
|
7817
7862
|
const buttonList = buttons.split(",");
|
|
7818
7863
|
const apps = validButtons.filter((button) => buttonList.includes(button));
|
|
7819
7864
|
return /* @__PURE__ */ jsx(Fragment, { children: apps.map((type2) => {
|
|
7820
|
-
var
|
|
7865
|
+
var _a2;
|
|
7821
7866
|
const app = data[type2];
|
|
7822
7867
|
if (type2 === "playground") {
|
|
7823
|
-
const isDifferentApp = data.playground && data.playground.appName !== ((
|
|
7868
|
+
const isDifferentApp = data.playground && data.playground.appName !== ((_a2 = data.problem) == null ? void 0 : _a2.name);
|
|
7824
7869
|
if (!app || isDifferentApp || isFileFromDifferentApp) {
|
|
7825
7870
|
return /* @__PURE__ */ jsxs(
|
|
7826
7871
|
"button",
|
|
@@ -7864,10 +7909,10 @@ function CopyButton() {
|
|
|
7864
7909
|
{
|
|
7865
7910
|
className: cn(buttonClassName, "w-12 uppercase"),
|
|
7866
7911
|
onClick: (event) => {
|
|
7867
|
-
var
|
|
7912
|
+
var _a, _b, _c;
|
|
7868
7913
|
setCopied(true);
|
|
7869
7914
|
const button = event.currentTarget;
|
|
7870
|
-
const code = ((_c = (_b = (
|
|
7915
|
+
const code = ((_c = (_b = (_a = button.parentElement) == null ? void 0 : _a.parentElement) == null ? void 0 : _b.querySelector("pre")) == null ? void 0 : _c.textContent) || "";
|
|
7871
7916
|
void navigator.clipboard.writeText(code);
|
|
7872
7917
|
},
|
|
7873
7918
|
children: copied ? "copied" : "copy"
|
|
@@ -7976,9 +8021,9 @@ const meta$4 = ({
|
|
|
7976
8021
|
data,
|
|
7977
8022
|
matches
|
|
7978
8023
|
}) => {
|
|
7979
|
-
var
|
|
8024
|
+
var _a;
|
|
7980
8025
|
const number = data == null ? void 0 : data.exercise.exerciseNumber.toString().padStart(2, "0");
|
|
7981
|
-
const rootData = (
|
|
8026
|
+
const rootData = (_a = matches.find((m) => m.id === "root")) == null ? void 0 : _a.data;
|
|
7982
8027
|
if (!data || !rootData) return [{ title: "🦉 | Error" }];
|
|
7983
8028
|
return getSeoMetaTags({
|
|
7984
8029
|
title: `📝 | ${number}. ${data.exercise.title} | ${rootData == null ? void 0 : rootData.workshopTitle}`,
|
|
@@ -8046,9 +8091,12 @@ const headers$9 = ({ loaderHeaders, parentHeaders }) => {
|
|
|
8046
8091
|
};
|
|
8047
8092
|
const mdxComponents$4 = { h1: () => null };
|
|
8048
8093
|
function ExerciseNumberRoute() {
|
|
8049
|
-
var
|
|
8094
|
+
var _a;
|
|
8050
8095
|
const data = useLoaderData();
|
|
8051
|
-
|
|
8096
|
+
useRevalidationWS({
|
|
8097
|
+
watchPaths: [data.exerciseReadme.file]
|
|
8098
|
+
});
|
|
8099
|
+
const firstStepNumber = String(((_a = data.firstStep) == null ? void 0 : _a.stepNumber) ?? "01").padStart(
|
|
8052
8100
|
2,
|
|
8053
8101
|
"0"
|
|
8054
8102
|
);
|
|
@@ -8259,11 +8307,11 @@ function diffPathToRelative(filePath) {
|
|
|
8259
8307
|
return relativePath.join(path.sep);
|
|
8260
8308
|
}
|
|
8261
8309
|
function getLanguage(ext) {
|
|
8262
|
-
var
|
|
8263
|
-
return ((
|
|
8264
|
-
var
|
|
8265
|
-
return l.id === ext || ((
|
|
8266
|
-
})) == null ? void 0 :
|
|
8310
|
+
var _a;
|
|
8311
|
+
return ((_a = bundledLanguagesInfo.find((l) => {
|
|
8312
|
+
var _a2;
|
|
8313
|
+
return l.id === ext || ((_a2 = l.aliases) == null ? void 0 : _a2.includes(ext));
|
|
8314
|
+
})) == null ? void 0 : _a.id) ?? "text";
|
|
8267
8315
|
}
|
|
8268
8316
|
function getFileCodeblocks(file, filePathApp1, filePathApp2, type) {
|
|
8269
8317
|
if (!file.chunks.length) {
|
|
@@ -8444,15 +8492,23 @@ async function getDiffIgnore(filePath) {
|
|
|
8444
8492
|
(content) => content.split("\n").map((line) => line.trim()).filter((line) => !line.startsWith("#")).filter(Boolean)
|
|
8445
8493
|
) : [];
|
|
8446
8494
|
}
|
|
8447
|
-
function getForceFreshForDiff(app1, app2, cacheEntry) {
|
|
8448
|
-
|
|
8495
|
+
async function getForceFreshForDiff(app1, app2, cacheEntry) {
|
|
8496
|
+
const cacheModified = cacheEntry == null ? void 0 : cacheEntry.metadata.createdTime;
|
|
8497
|
+
if (!cacheModified) return true;
|
|
8449
8498
|
const app1Modified = modifiedTimes.get(app1.fullPath) ?? 0;
|
|
8499
|
+
if (app1Modified > cacheModified) return true;
|
|
8450
8500
|
const app2Modified = modifiedTimes.get(app2.fullPath) ?? 0;
|
|
8451
|
-
|
|
8452
|
-
|
|
8501
|
+
if (app2Modified > cacheModified) return true;
|
|
8502
|
+
const modifiedMoreRecently = await modifiedMoreRecentlyThan(
|
|
8503
|
+
cacheModified,
|
|
8504
|
+
app1.fullPath,
|
|
8505
|
+
app2.fullPath
|
|
8506
|
+
);
|
|
8507
|
+
if (modifiedMoreRecently) return true;
|
|
8508
|
+
return void 0;
|
|
8453
8509
|
}
|
|
8454
8510
|
async function getDiffFiles(app1, app2, {
|
|
8455
|
-
forceFresh
|
|
8511
|
+
forceFresh,
|
|
8456
8512
|
timings,
|
|
8457
8513
|
request
|
|
8458
8514
|
} = {}) {
|
|
@@ -8461,7 +8517,7 @@ async function getDiffFiles(app1, app2, {
|
|
|
8461
8517
|
const result = await cachified({
|
|
8462
8518
|
key,
|
|
8463
8519
|
cache: diffFilesCache,
|
|
8464
|
-
forceFresh: forceFresh || getForceFreshForDiff(app1, app2, cacheEntry),
|
|
8520
|
+
forceFresh: forceFresh || await getForceFreshForDiff(app1, app2, cacheEntry),
|
|
8465
8521
|
timings,
|
|
8466
8522
|
request,
|
|
8467
8523
|
getFreshValue: () => getDiffFilesImpl(app1, app2)
|
|
@@ -8511,7 +8567,7 @@ async function getDiffFilesImpl(app1, app2) {
|
|
|
8511
8567
|
})).filter((file) => !testFiles.includes(file.path));
|
|
8512
8568
|
}
|
|
8513
8569
|
async function getDiffCode(app1, app2, {
|
|
8514
|
-
forceFresh
|
|
8570
|
+
forceFresh,
|
|
8515
8571
|
timings,
|
|
8516
8572
|
request
|
|
8517
8573
|
} = {}) {
|
|
@@ -8520,7 +8576,7 @@ async function getDiffCode(app1, app2, {
|
|
|
8520
8576
|
const result = await cachified({
|
|
8521
8577
|
key,
|
|
8522
8578
|
cache: diffCodeCache,
|
|
8523
|
-
forceFresh: forceFresh || getForceFreshForDiff(app1, app2, cacheEntry),
|
|
8579
|
+
forceFresh: forceFresh || await getForceFreshForDiff(app1, app2, cacheEntry),
|
|
8524
8580
|
timings,
|
|
8525
8581
|
request,
|
|
8526
8582
|
getFreshValue: () => getDiffCodeImpl(app1, app2)
|
|
@@ -8682,7 +8738,7 @@ function SetPlayground({
|
|
|
8682
8738
|
tooltipText,
|
|
8683
8739
|
...buttonProps
|
|
8684
8740
|
}) {
|
|
8685
|
-
var
|
|
8741
|
+
var _a;
|
|
8686
8742
|
const fetcher = useFetcher();
|
|
8687
8743
|
const peRedirectInput = usePERedirectInput();
|
|
8688
8744
|
const submitButton = /* @__PURE__ */ jsx(
|
|
@@ -8693,7 +8749,7 @@ function SetPlayground({
|
|
|
8693
8749
|
className: clsx(
|
|
8694
8750
|
buttonProps.className,
|
|
8695
8751
|
fetcher.state !== "idle" ? "cursor-progress" : null,
|
|
8696
|
-
((
|
|
8752
|
+
((_a = fetcher.data) == null ? void 0 : _a.status) === "error" ? "cursor-not-allowed" : null
|
|
8697
8753
|
)
|
|
8698
8754
|
}
|
|
8699
8755
|
);
|
|
@@ -8717,7 +8773,7 @@ function PlaygroundChooser({
|
|
|
8717
8773
|
playgroundAppName,
|
|
8718
8774
|
allApps
|
|
8719
8775
|
}) {
|
|
8720
|
-
var
|
|
8776
|
+
var _a;
|
|
8721
8777
|
const fetcher = useFetcher();
|
|
8722
8778
|
return /* @__PURE__ */ jsxs(
|
|
8723
8779
|
Select.Root,
|
|
@@ -8738,7 +8794,7 @@ function PlaygroundChooser({
|
|
|
8738
8794
|
className: clsx(
|
|
8739
8795
|
"flex h-full w-full items-center justify-between text-left radix-placeholder:text-gray-500 focus-visible:outline-none",
|
|
8740
8796
|
fetcher.state !== "idle" ? "cursor-progress" : null,
|
|
8741
|
-
((
|
|
8797
|
+
((_a = fetcher.data) == null ? void 0 : _a.status) === "error" ? "cursor-not-allowed" : null
|
|
8742
8798
|
),
|
|
8743
8799
|
children: [
|
|
8744
8800
|
/* @__PURE__ */ jsx("span", { className: "w-80 flex-1 overflow-hidden text-ellipsis whitespace-nowrap scrollbar-thin scrollbar-thumb-scrollbar", children: /* @__PURE__ */ jsx(
|
|
@@ -8884,10 +8940,10 @@ function DiffLink({
|
|
|
8884
8940
|
);
|
|
8885
8941
|
}
|
|
8886
8942
|
function getAppName2(input) {
|
|
8887
|
-
var
|
|
8943
|
+
var _a;
|
|
8888
8944
|
if (typeof input === "number") {
|
|
8889
8945
|
const stepIndex = data.exerciseIndex + input;
|
|
8890
|
-
return (
|
|
8946
|
+
return (_a = data.allApps[stepIndex]) == null ? void 0 : _a.name;
|
|
8891
8947
|
}
|
|
8892
8948
|
if (!input) return null;
|
|
8893
8949
|
for (const { name, stepName } of data.allApps) {
|
|
@@ -8969,7 +9025,7 @@ function LinkToApp({
|
|
|
8969
9025
|
children = /* @__PURE__ */ jsx("code", { children: appTo.toString() }),
|
|
8970
9026
|
...props
|
|
8971
9027
|
}) {
|
|
8972
|
-
var
|
|
9028
|
+
var _a;
|
|
8973
9029
|
const [searchParams] = useSearchParams();
|
|
8974
9030
|
const to = `?${withParam$1(
|
|
8975
9031
|
searchParams,
|
|
@@ -8983,7 +9039,7 @@ function LinkToApp({
|
|
|
8983
9039
|
const previewAppUrl = (app == null ? void 0 : app.dev.type) === "script" ? getBaseUrl({
|
|
8984
9040
|
domain: requestInfo.domain,
|
|
8985
9041
|
port: app.dev.portNumber
|
|
8986
|
-
}) : ((
|
|
9042
|
+
}) : ((_a = data.playground) == null ? void 0 : _a.dev.type) === "browser" ? data.playground.dev.pathname : null;
|
|
8987
9043
|
const { inBrowserBrowserRef } = useStepContext();
|
|
8988
9044
|
const href = previewAppUrl ? previewAppUrl.slice(0, -1) + appTo.toString() : null;
|
|
8989
9045
|
return /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center justify-between gap-1", children: [
|
|
@@ -8997,9 +9053,9 @@ function LinkToApp({
|
|
|
8997
9053
|
}),
|
|
8998
9054
|
title: ENV.EPICSHOP_DEPLOYED ? "Cannot link to app in deployed version" : void 0,
|
|
8999
9055
|
onClick: (event) => {
|
|
9000
|
-
var
|
|
9056
|
+
var _a2, _b;
|
|
9001
9057
|
if (ENV.EPICSHOP_DEPLOYED) event.preventDefault();
|
|
9002
|
-
(
|
|
9058
|
+
(_a2 = props.onClick) == null ? void 0 : _a2.call(props, event);
|
|
9003
9059
|
(_b = inBrowserBrowserRef.current) == null ? void 0 : _b.handleExtrnalNavigation(appTo.toString());
|
|
9004
9060
|
},
|
|
9005
9061
|
children
|
|
@@ -9026,14 +9082,14 @@ function LinkToApp({
|
|
|
9026
9082
|
function TouchedFiles({
|
|
9027
9083
|
diffFilesPromise
|
|
9028
9084
|
}) {
|
|
9029
|
-
var
|
|
9085
|
+
var _a, _b;
|
|
9030
9086
|
const data = useLoaderData();
|
|
9031
9087
|
const [open, setOpen] = React.useState(false);
|
|
9032
9088
|
const contentRef = React.useRef(null);
|
|
9033
9089
|
function handleLaunchUpdate() {
|
|
9034
9090
|
setOpen(false);
|
|
9035
9091
|
}
|
|
9036
|
-
const appName = (
|
|
9092
|
+
const appName = (_a = data.playground) == null ? void 0 : _a.appName;
|
|
9037
9093
|
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(Popover.Root, { open, onOpenChange: setOpen, children: [
|
|
9038
9094
|
/* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
9039
9095
|
"button",
|
|
@@ -9092,12 +9148,12 @@ function TouchedFiles({
|
|
|
9092
9148
|
}
|
|
9093
9149
|
) }) : null,
|
|
9094
9150
|
diffFiles.map((file) => {
|
|
9095
|
-
var
|
|
9151
|
+
var _a2;
|
|
9096
9152
|
return /* @__PURE__ */ jsx("li", { "data-state": file.status, children: /* @__PURE__ */ jsx(
|
|
9097
9153
|
LaunchEditor,
|
|
9098
9154
|
{
|
|
9099
9155
|
appFile: `${file.path},${file.line},1`,
|
|
9100
|
-
appName: ENV.EPICSHOP_DEPLOYED ? ((
|
|
9156
|
+
appName: ENV.EPICSHOP_DEPLOYED ? ((_a2 = data.problem) == null ? void 0 : _a2.name) ?? "playground" : "playground",
|
|
9101
9157
|
onUpdate: handleLaunchUpdate,
|
|
9102
9158
|
children: /* @__PURE__ */ jsx("code", { children: file.path })
|
|
9103
9159
|
}
|
|
@@ -9115,14 +9171,14 @@ function TouchedFiles({
|
|
|
9115
9171
|
] }) });
|
|
9116
9172
|
}
|
|
9117
9173
|
function pageTitle(data, workshopTitle) {
|
|
9118
|
-
var
|
|
9174
|
+
var _a;
|
|
9119
9175
|
const exerciseNumber = (data == null ? void 0 : data.exerciseStepApp.exerciseNumber.toString().padStart(2, "0")) ?? "00";
|
|
9120
9176
|
const stepNumber = (data == null ? void 0 : data.exerciseStepApp.stepNumber.toString().padStart(2, "0")) ?? "00";
|
|
9121
9177
|
const emoji2 = {
|
|
9122
9178
|
problem: "💪",
|
|
9123
9179
|
solution: "🏁"
|
|
9124
9180
|
}[(data == null ? void 0 : data.type) ?? "problem"];
|
|
9125
|
-
const title = ((
|
|
9181
|
+
const title = ((_a = data == null ? void 0 : data[data.type]) == null ? void 0 : _a.title) ?? "N/A";
|
|
9126
9182
|
return {
|
|
9127
9183
|
emoji: emoji2,
|
|
9128
9184
|
stepNumber,
|
|
@@ -9138,8 +9194,8 @@ const meta$3 = ({
|
|
|
9138
9194
|
matches,
|
|
9139
9195
|
params
|
|
9140
9196
|
}) => {
|
|
9141
|
-
var
|
|
9142
|
-
const rootData = (
|
|
9197
|
+
var _a;
|
|
9198
|
+
const rootData = (_a = matches.find((m) => m.id === "root")) == null ? void 0 : _a.data;
|
|
9143
9199
|
if (!data || !rootData) return [{ title: "🦉 | Error" }];
|
|
9144
9200
|
const { emoji: emoji2, stepNumber, title, exerciseNumber, exerciseTitle } = pageTitle(data);
|
|
9145
9201
|
return getSeoMetaTags({
|
|
@@ -9152,8 +9208,8 @@ const meta$3 = ({
|
|
|
9152
9208
|
});
|
|
9153
9209
|
};
|
|
9154
9210
|
async function loader$l({ request, params }) {
|
|
9155
|
-
var
|
|
9156
|
-
const timings = makeTimings("
|
|
9211
|
+
var _a, _b;
|
|
9212
|
+
const timings = makeTimings("exerciseStepTypeLayoutLoader");
|
|
9157
9213
|
const url = new URL(request.url);
|
|
9158
9214
|
const { title: workshopTitle } = getWorkshopConfig();
|
|
9159
9215
|
const cacheOptions = { request, timings };
|
|
@@ -9211,7 +9267,7 @@ async function loader$l({ request, params }) {
|
|
|
9211
9267
|
const exerciseId = getStepId(exerciseStepApp);
|
|
9212
9268
|
const exerciseIndex = allApps.findIndex((step) => step.stepId === exerciseId);
|
|
9213
9269
|
const exerciseApps = allAppsFull.filter(isExerciseStepApp).filter((app) => app.exerciseNumber === exerciseStepApp.exerciseNumber);
|
|
9214
|
-
const isLastStep = ((
|
|
9270
|
+
const isLastStep = ((_a = exerciseApps[exerciseApps.length - 1]) == null ? void 0 : _a.name) === exerciseStepApp.name;
|
|
9215
9271
|
const isFirstStep = ((_b = exerciseApps[0]) == null ? void 0 : _b.name) === exerciseStepApp.name;
|
|
9216
9272
|
const nextApp = await getNextExerciseApp(exerciseStepApp, cacheOptions);
|
|
9217
9273
|
const prevApp = await getPrevExerciseApp(exerciseStepApp, cacheOptions);
|
|
@@ -9287,10 +9343,13 @@ const headers$7 = ({ loaderHeaders, parentHeaders }) => {
|
|
|
9287
9343
|
return headers2;
|
|
9288
9344
|
};
|
|
9289
9345
|
function ExercisePartRoute$1() {
|
|
9290
|
-
var
|
|
9346
|
+
var _a;
|
|
9291
9347
|
const data = useLoaderData();
|
|
9292
9348
|
const inBrowserBrowserRef = useRef(null);
|
|
9293
9349
|
const titleBits = pageTitle(data);
|
|
9350
|
+
useRevalidationWS({
|
|
9351
|
+
watchPaths: [`${data.exerciseStepApp.relativePath}/README.mdx`]
|
|
9352
|
+
});
|
|
9294
9353
|
return /* @__PURE__ */ jsx("div", { className: "flex max-w-full flex-grow flex-col", children: /* @__PURE__ */ jsxs("main", { className: "flex flex-grow flex-col sm:grid sm:h-full sm:min-h-[800px] sm:grid-cols-1 sm:grid-rows-2 md:min-h-[unset] lg:grid-cols-2 lg:grid-rows-1", children: [
|
|
9295
9354
|
/* @__PURE__ */ jsxs("div", { className: "relative flex flex-col sm:col-span-1 sm:row-span-1 sm:h-full lg:border-r", children: [
|
|
9296
9355
|
/* @__PURE__ */ jsx("h1", { className: "h-14 border-b pl-10 pr-5 text-sm font-medium leading-tight", children: /* @__PURE__ */ jsxs("div", { className: "flex h-14 flex-wrap items-center justify-between gap-x-2 py-2", children: [
|
|
@@ -9319,7 +9378,7 @@ function ExercisePartRoute$1() {
|
|
|
9319
9378
|
")"
|
|
9320
9379
|
] })
|
|
9321
9380
|
] }),
|
|
9322
|
-
data.problem && ((
|
|
9381
|
+
data.problem && ((_a = data.playground) == null ? void 0 : _a.appName) !== data.problem.name ? /* @__PURE__ */ jsx("div", { className: "hidden md:block", children: /* @__PURE__ */ jsx(SetAppToPlayground, { appName: data.problem.name }) }) : null
|
|
9323
9382
|
] }) }),
|
|
9324
9383
|
/* @__PURE__ */ jsxs(
|
|
9325
9384
|
"article",
|
|
@@ -9497,10 +9556,10 @@ async function action$4({ request }) {
|
|
|
9497
9556
|
throw new Error(`Unknown intent: ${intent}`);
|
|
9498
9557
|
}
|
|
9499
9558
|
function AppStopper({ name }) {
|
|
9500
|
-
var
|
|
9559
|
+
var _a;
|
|
9501
9560
|
const fetcher = useFetcher();
|
|
9502
9561
|
const peRedirectInput = usePERedirectInput();
|
|
9503
|
-
const inFlightIntent = (
|
|
9562
|
+
const inFlightIntent = (_a = fetcher.formData) == null ? void 0 : _a.get("intent");
|
|
9504
9563
|
const inFlightState = inFlightIntent === "stop" ? "Stopping App" : inFlightIntent === "restart" ? "Restarting App" : null;
|
|
9505
9564
|
const altDown = useAltDown();
|
|
9506
9565
|
return /* @__PURE__ */ jsxs(fetcher.Form, { method: "POST", action: "/start", children: [
|
|
@@ -9530,10 +9589,10 @@ function PortStopper({ port: port2 }) {
|
|
|
9530
9589
|
] });
|
|
9531
9590
|
}
|
|
9532
9591
|
function AppStarter({ name }) {
|
|
9533
|
-
var
|
|
9592
|
+
var _a;
|
|
9534
9593
|
const fetcher = useFetcher();
|
|
9535
9594
|
const peRedirectInput = usePERedirectInput();
|
|
9536
|
-
if (((
|
|
9595
|
+
if (((_a = fetcher.data) == null ? void 0 : _a.status) === "app-not-started") {
|
|
9537
9596
|
if (fetcher.data.error === "port-unavailable") {
|
|
9538
9597
|
return /* @__PURE__ */ jsxs("div", { children: [
|
|
9539
9598
|
"The port is unavailable. Would you like to stop whatever is running on that port and try again?",
|
|
@@ -9659,8 +9718,8 @@ function InBrowserBrowserForRealzImpl({ baseUrl, id, name, initialRoute }, ref)
|
|
|
9659
9718
|
});
|
|
9660
9719
|
useEffect(() => {
|
|
9661
9720
|
function handleMessage(messageEvent) {
|
|
9662
|
-
var
|
|
9663
|
-
if (messageEvent.source !== ((
|
|
9721
|
+
var _a;
|
|
9722
|
+
if (messageEvent.source !== ((_a = iframeRef.current) == null ? void 0 : _a.contentWindow)) return;
|
|
9664
9723
|
const result = messageSchema.safeParse(messageEvent.data, {
|
|
9665
9724
|
path: ["messageEvent", "data"]
|
|
9666
9725
|
});
|
|
@@ -9761,7 +9820,7 @@ function InBrowserBrowserForRealzImpl({ baseUrl, id, name, initialRoute }, ref)
|
|
|
9761
9820
|
}
|
|
9762
9821
|
}, [iframePathname]);
|
|
9763
9822
|
const navigateChild = (...params) => {
|
|
9764
|
-
var
|
|
9823
|
+
var _a, _b;
|
|
9765
9824
|
const to = params[0];
|
|
9766
9825
|
if (typeof to === "number") {
|
|
9767
9826
|
lastDirectionRef.current = to > 0 ? "forward" : "back";
|
|
@@ -9774,7 +9833,7 @@ function InBrowserBrowserForRealzImpl({ baseUrl, id, name, initialRoute }, ref)
|
|
|
9774
9833
|
lastDirectionTimeout.current = setTimeout(() => {
|
|
9775
9834
|
lastDirectionRef.current = "new";
|
|
9776
9835
|
}, 100);
|
|
9777
|
-
(_b = (
|
|
9836
|
+
(_b = (_a = iframeRef.current) == null ? void 0 : _a.contentWindow) == null ? void 0 : _b.postMessage(
|
|
9778
9837
|
{ type: "epicshop:navigate-call", params },
|
|
9779
9838
|
"*"
|
|
9780
9839
|
);
|
|
@@ -10172,6 +10231,18 @@ const mdxComponents$3 = {
|
|
|
10172
10231
|
// override the pre-with-buttons
|
|
10173
10232
|
pre
|
|
10174
10233
|
};
|
|
10234
|
+
function RevalidateApps({
|
|
10235
|
+
app1: app1Name,
|
|
10236
|
+
app2: app2Name
|
|
10237
|
+
}) {
|
|
10238
|
+
const apps = useApps();
|
|
10239
|
+
const app1 = apps.find((app) => app.name === app1Name);
|
|
10240
|
+
const app2 = apps.find((app) => app.name === app2Name);
|
|
10241
|
+
useRevalidationWS({
|
|
10242
|
+
watchPaths: [app1 == null ? void 0 : app1.fullPath, app2 == null ? void 0 : app2.fullPath].filter(Boolean)
|
|
10243
|
+
});
|
|
10244
|
+
return null;
|
|
10245
|
+
}
|
|
10175
10246
|
function Diff({
|
|
10176
10247
|
diff,
|
|
10177
10248
|
allApps
|
|
@@ -10260,7 +10331,8 @@ function Diff({
|
|
|
10260
10331
|
`${diff2.app1}${diff2.app2}`
|
|
10261
10332
|
)
|
|
10262
10333
|
] }),
|
|
10263
|
-
/* @__PURE__ */ jsx("div", { className: "flex-grow overflow-y-scroll scrollbar-thin scrollbar-thumb-scrollbar", children: diff2.diffCode ? /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Accordion.Root, { className: "w-full", type: "multiple", children: /* @__PURE__ */ jsx(Mdx, { code: diff2.diffCode, components: mdxComponents$3 }) }) }) : diff2.app1 && diff2.app2 ? /* @__PURE__ */ jsx("p", { className: "m-5 inline-flex items-center justify-center bg-foreground px-1 py-0.5 font-mono text-sm uppercase text-background", children: "There was a problem generating the diff" }) : /* @__PURE__ */ jsx("p", { className: "m-5 inline-flex items-center justify-center bg-foreground px-1 py-0.5 font-mono text-sm uppercase text-background", children: "Select two apps to compare" }) })
|
|
10334
|
+
/* @__PURE__ */ jsx("div", { className: "flex-grow overflow-y-scroll scrollbar-thin scrollbar-thumb-scrollbar", children: diff2.diffCode ? /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Accordion.Root, { className: "w-full", type: "multiple", children: /* @__PURE__ */ jsx(Mdx, { code: diff2.diffCode, components: mdxComponents$3 }) }) }) : diff2.app1 && diff2.app2 ? /* @__PURE__ */ jsx("p", { className: "m-5 inline-flex items-center justify-center bg-foreground px-1 py-0.5 font-mono text-sm uppercase text-background", children: "There was a problem generating the diff" }) : /* @__PURE__ */ jsx("p", { className: "m-5 inline-flex items-center justify-center bg-foreground px-1 py-0.5 font-mono text-sm uppercase text-background", children: "Select two apps to compare" }) }),
|
|
10335
|
+
/* @__PURE__ */ jsx(RevalidateApps, { app1: diff2.app1, app2: diff2.app2 })
|
|
10264
10336
|
] })
|
|
10265
10337
|
}
|
|
10266
10338
|
)
|
|
@@ -10400,13 +10472,13 @@ const EpicForumResponseSchema = z.object({
|
|
|
10400
10472
|
})
|
|
10401
10473
|
);
|
|
10402
10474
|
async function fetchDiscordPosts({ request }) {
|
|
10403
|
-
var
|
|
10475
|
+
var _a;
|
|
10404
10476
|
const config = getWorkshopConfig();
|
|
10405
10477
|
const forceFresh = await shouldForceFresh({ request });
|
|
10406
10478
|
const searchParams = new URLSearchParams({
|
|
10407
10479
|
channelId: config.product.discordChannelId
|
|
10408
10480
|
});
|
|
10409
|
-
if ((
|
|
10481
|
+
if ((_a = config.product.discordTags) == null ? void 0 : _a.length) {
|
|
10410
10482
|
for (const tag of config.product.discordTags) {
|
|
10411
10483
|
searchParams.append("tagId", tag);
|
|
10412
10484
|
}
|
|
@@ -10744,8 +10816,8 @@ function InBrowserTestRunner({
|
|
|
10744
10816
|
const [testSteps, setTestSteps] = useState([]);
|
|
10745
10817
|
useEffect(() => {
|
|
10746
10818
|
function handleMessage(messageEvent) {
|
|
10747
|
-
var
|
|
10748
|
-
if (messageEvent.source !== ((
|
|
10819
|
+
var _a;
|
|
10820
|
+
if (messageEvent.source !== ((_a = iframeRef.current) == null ? void 0 : _a.contentWindow)) return;
|
|
10749
10821
|
if ("request" in messageEvent.data) return;
|
|
10750
10822
|
const result = testRunnerDataSchema.safeParse(messageEvent.data, {
|
|
10751
10823
|
path: ["messageEvent", "data"]
|
|
@@ -10850,8 +10922,8 @@ function InBrowserTestRunner({
|
|
|
10850
10922
|
"button",
|
|
10851
10923
|
{
|
|
10852
10924
|
onClick: () => {
|
|
10853
|
-
var
|
|
10854
|
-
return (_b = (
|
|
10925
|
+
var _a, _b;
|
|
10926
|
+
return (_b = (_a = iframeRef.current) == null ? void 0 : _a.contentWindow) == null ? void 0 : _b.location.reload();
|
|
10855
10927
|
},
|
|
10856
10928
|
className: "border-r p-3",
|
|
10857
10929
|
children: /* @__PURE__ */ jsx(Icon, { name: "Refresh", "aria-label": "Rerun Tests" })
|
|
@@ -10927,7 +10999,7 @@ async function loader$j({ request }) {
|
|
|
10927
10999
|
return json$1({ error: "App is not running tests" }, { status: 404 });
|
|
10928
11000
|
}
|
|
10929
11001
|
return eventStream(request.signal, function setup(send) {
|
|
10930
|
-
var
|
|
11002
|
+
var _a, _b;
|
|
10931
11003
|
let queue = [];
|
|
10932
11004
|
function sendEvent(event) {
|
|
10933
11005
|
queue.push(event);
|
|
@@ -10969,18 +11041,18 @@ async function loader$j({ request }) {
|
|
|
10969
11041
|
});
|
|
10970
11042
|
}
|
|
10971
11043
|
function handleExit(code) {
|
|
10972
|
-
var
|
|
10973
|
-
(
|
|
11044
|
+
var _a2, _b2;
|
|
11045
|
+
(_a2 = testProcess == null ? void 0 : testProcess.stdout) == null ? void 0 : _a2.off("data", handleStdOutData);
|
|
10974
11046
|
(_b2 = testProcess == null ? void 0 : testProcess.stderr) == null ? void 0 : _b2.off("data", handleStdErrData);
|
|
10975
11047
|
testProcess == null ? void 0 : testProcess.off("exit", handleExit);
|
|
10976
11048
|
sendEvent({ type: "exit", isRunning: false, code });
|
|
10977
11049
|
}
|
|
10978
|
-
(
|
|
11050
|
+
(_a = testProcess.stdout) == null ? void 0 : _a.on("data", handleStdOutData);
|
|
10979
11051
|
(_b = testProcess.stderr) == null ? void 0 : _b.on("data", handleStdErrData);
|
|
10980
11052
|
testProcess.on("exit", handleExit);
|
|
10981
11053
|
return function cleanup() {
|
|
10982
|
-
var
|
|
10983
|
-
(
|
|
11054
|
+
var _a2, _b2;
|
|
11055
|
+
(_a2 = testProcess.stdout) == null ? void 0 : _a2.off("data", handleStdOutData);
|
|
10984
11056
|
(_b2 = testProcess.stderr) == null ? void 0 : _b2.off("data", handleStdErrData);
|
|
10985
11057
|
testProcess.off("exit", handleExit);
|
|
10986
11058
|
clearInterval(interval);
|
|
@@ -10988,7 +11060,7 @@ async function loader$j({ request }) {
|
|
|
10988
11060
|
});
|
|
10989
11061
|
}
|
|
10990
11062
|
async function action$3({ request }) {
|
|
10991
|
-
var
|
|
11063
|
+
var _a;
|
|
10992
11064
|
ensureUndeployed();
|
|
10993
11065
|
const formData = await request.formData();
|
|
10994
11066
|
const userHasAccess = await userHasAccessToWorkshop({
|
|
@@ -11037,7 +11109,7 @@ async function action$3({ request }) {
|
|
|
11037
11109
|
case "stop": {
|
|
11038
11110
|
const processEntry = getTestProcessEntry(app);
|
|
11039
11111
|
if (processEntry) {
|
|
11040
|
-
(
|
|
11112
|
+
(_a = processEntry.process) == null ? void 0 : _a.kill();
|
|
11041
11113
|
}
|
|
11042
11114
|
return jsonWithPE(formData, { success: true });
|
|
11043
11115
|
}
|
|
@@ -11160,8 +11232,8 @@ function TestRunner({
|
|
|
11160
11232
|
latestOnRun.current = onRun;
|
|
11161
11233
|
}, [onRun]);
|
|
11162
11234
|
useEffect(() => {
|
|
11163
|
-
var
|
|
11164
|
-
if ((
|
|
11235
|
+
var _a, _b;
|
|
11236
|
+
if ((_a = fetcher.data) == null ? void 0 : _a.success) {
|
|
11165
11237
|
(_b = latestOnRun.current) == null ? void 0 : _b.call(latestOnRun);
|
|
11166
11238
|
}
|
|
11167
11239
|
}, [fetcher.data]);
|
|
@@ -11197,8 +11269,8 @@ function ClearTest({
|
|
|
11197
11269
|
latestOnClear.current = onClear;
|
|
11198
11270
|
}, [onClear]);
|
|
11199
11271
|
useEffect(() => {
|
|
11200
|
-
var
|
|
11201
|
-
if ((
|
|
11272
|
+
var _a, _b;
|
|
11273
|
+
if ((_a = fetcher.data) == null ? void 0 : _a.success) {
|
|
11202
11274
|
(_b = latestOnClear.current) == null ? void 0 : _b.call(latestOnClear);
|
|
11203
11275
|
}
|
|
11204
11276
|
}, [fetcher.data]);
|
|
@@ -11234,8 +11306,8 @@ function StopTest({
|
|
|
11234
11306
|
latestOnStop.current = onStop;
|
|
11235
11307
|
}, [onStop]);
|
|
11236
11308
|
useEffect(() => {
|
|
11237
|
-
var
|
|
11238
|
-
if ((
|
|
11309
|
+
var _a, _b;
|
|
11310
|
+
if ((_a = fetcher.data) == null ? void 0 : _a.success) {
|
|
11239
11311
|
(_b = latestOnStop.current) == null ? void 0 : _b.call(latestOnStop);
|
|
11240
11312
|
}
|
|
11241
11313
|
}, [fetcher.data]);
|
|
@@ -11335,7 +11407,7 @@ function TestUI({
|
|
|
11335
11407
|
return /* @__PURE__ */ jsx("div", { className: "flex h-full items-center justify-center text-lg", children: /* @__PURE__ */ jsx("p", { children: "No tests here 😢 Sorry." }) });
|
|
11336
11408
|
}
|
|
11337
11409
|
async function loader$i({ request, params }) {
|
|
11338
|
-
const timings = makeTimings("
|
|
11410
|
+
const timings = makeTimings("exerciseStepTypeIndexLoader");
|
|
11339
11411
|
const userHasAccess = await userHasAccessToWorkshop({
|
|
11340
11412
|
request,
|
|
11341
11413
|
timings
|
|
@@ -11497,7 +11569,7 @@ function withParam(searchParams, key, value) {
|
|
|
11497
11569
|
return newSearchParams;
|
|
11498
11570
|
}
|
|
11499
11571
|
function ExercisePartRoute() {
|
|
11500
|
-
var
|
|
11572
|
+
var _a, _b, _c, _d, _e, _f;
|
|
11501
11573
|
const data = useLoaderData();
|
|
11502
11574
|
const [searchParams] = useSearchParams();
|
|
11503
11575
|
const preview = searchParams.get("preview");
|
|
@@ -11505,12 +11577,12 @@ function ExercisePartRoute() {
|
|
|
11505
11577
|
const altDown = useAltDown();
|
|
11506
11578
|
const navigate = useNavigate();
|
|
11507
11579
|
function shouldHideTab(tab) {
|
|
11508
|
-
var
|
|
11580
|
+
var _a2, _b2, _c2;
|
|
11509
11581
|
if (tab === "tests") {
|
|
11510
11582
|
return ENV.EPICSHOP_DEPLOYED || !data.playground || data.playground.test.type === "none";
|
|
11511
11583
|
}
|
|
11512
11584
|
if (tab === "problem" || tab === "solution") {
|
|
11513
|
-
if (((
|
|
11585
|
+
if (((_a2 = data[tab]) == null ? void 0 : _a2.dev.type) === "none") return true;
|
|
11514
11586
|
if (ENV.EPICSHOP_DEPLOYED) {
|
|
11515
11587
|
return ((_b2 = data[tab]) == null ? void 0 : _b2.dev.type) !== "browser" && !((_c2 = data[tab]) == null ? void 0 : _c2.stackBlitzUrl);
|
|
11516
11588
|
}
|
|
@@ -11520,7 +11592,7 @@ function ExercisePartRoute() {
|
|
|
11520
11592
|
}
|
|
11521
11593
|
const activeTab = isValidPreview(preview) ? preview : tabs.find((t) => !shouldHideTab(t));
|
|
11522
11594
|
const altDiffUrl = `/diff?${new URLSearchParams({
|
|
11523
|
-
app1: ((
|
|
11595
|
+
app1: ((_a = data.problem) == null ? void 0 : _a.name) ?? "",
|
|
11524
11596
|
app2: ((_b = data.solution) == null ? void 0 : _b.name) ?? ""
|
|
11525
11597
|
})}`;
|
|
11526
11598
|
function handleDiffTabClick(event) {
|
|
@@ -11712,9 +11784,9 @@ const meta$2 = ({
|
|
|
11712
11784
|
data,
|
|
11713
11785
|
matches
|
|
11714
11786
|
}) => {
|
|
11715
|
-
var
|
|
11787
|
+
var _a;
|
|
11716
11788
|
const number = data == null ? void 0 : data.exercise.exerciseNumber.toString().padStart(2, "0");
|
|
11717
|
-
const rootData = (
|
|
11789
|
+
const rootData = (_a = matches.find((m) => m.id === "root")) == null ? void 0 : _a.data;
|
|
11718
11790
|
if (!data || !rootData) return [{ title: "🦉 | Error" }];
|
|
11719
11791
|
return getSeoMetaTags({
|
|
11720
11792
|
title: `🦉 | ${number}. ${data.exercise.title} | ${rootData == null ? void 0 : rootData.workshopTitle}`,
|
|
@@ -11762,10 +11834,10 @@ async function loader$f({ request, params }) {
|
|
|
11762
11834
|
exercise.finishedEpicVideoEmbeds,
|
|
11763
11835
|
{ request }
|
|
11764
11836
|
),
|
|
11765
|
-
exerciseFinished:
|
|
11837
|
+
exerciseFinished: {
|
|
11766
11838
|
file: finishedFilepath,
|
|
11767
11839
|
relativePath: `exercises/${exercise.dirName}/FINISHED.mdx`
|
|
11768
|
-
}
|
|
11840
|
+
},
|
|
11769
11841
|
prevStepLink: prevApp ? {
|
|
11770
11842
|
to: getAppPageRoute(prevApp),
|
|
11771
11843
|
"aria-label": `${prevApp.title} (${prevApp.type})`
|
|
@@ -11796,6 +11868,9 @@ const mdxComponents$2 = { h1: () => null };
|
|
|
11796
11868
|
function ExerciseFinished$1() {
|
|
11797
11869
|
const data = useLoaderData();
|
|
11798
11870
|
const exerciseNumber = data.exercise.exerciseNumber.toString().padStart(2, "0");
|
|
11871
|
+
useRevalidationWS({
|
|
11872
|
+
watchPaths: [`./exercises/${exerciseNumber}/FINISHED.mdx`]
|
|
11873
|
+
});
|
|
11799
11874
|
return /* @__PURE__ */ jsx("div", { className: "flex max-w-full flex-grow flex-col", children: /* @__PURE__ */ jsxs("main", { className: "flex flex-grow flex-col sm:grid sm:h-full sm:min-h-[800px] sm:grid-cols-1 sm:grid-rows-2 md:min-h-[unset] lg:grid-cols-2 lg:grid-rows-1", children: [
|
|
11800
11875
|
/* @__PURE__ */ jsxs("div", { className: "relative flex flex-col sm:col-span-1 sm:row-span-1 sm:h-full lg:border-r", children: [
|
|
11801
11876
|
/* @__PURE__ */ jsx("h1", { className: "h-14 border-b pl-10 pr-5 text-sm font-medium leading-tight", children: /* @__PURE__ */ jsx("div", { className: "flex h-14 flex-wrap items-center justify-between gap-x-2 py-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-start gap-x-2", children: [
|
|
@@ -11837,13 +11912,13 @@ function ExerciseFinished$1() {
|
|
|
11837
11912
|
),
|
|
11838
11913
|
/* @__PURE__ */ jsxs("div", { className: "flex h-16 justify-between border-b-4 border-t lg:border-b-0", children: [
|
|
11839
11914
|
/* @__PURE__ */ jsx("div", {}),
|
|
11840
|
-
|
|
11915
|
+
/* @__PURE__ */ jsx(
|
|
11841
11916
|
EditFileOnGitHub,
|
|
11842
11917
|
{
|
|
11843
11918
|
file: data.exerciseFinished.file,
|
|
11844
11919
|
relativePath: data.exerciseFinished.relativePath
|
|
11845
11920
|
}
|
|
11846
|
-
)
|
|
11921
|
+
),
|
|
11847
11922
|
/* @__PURE__ */ jsx(NavChevrons, { prev: data.prevStepLink, next: data.nextStepLink })
|
|
11848
11923
|
] })
|
|
11849
11924
|
] }),
|
|
@@ -11895,8 +11970,8 @@ const handle$4 = {
|
|
|
11895
11970
|
const meta$1 = ({
|
|
11896
11971
|
matches
|
|
11897
11972
|
}) => {
|
|
11898
|
-
var
|
|
11899
|
-
const rootData = (
|
|
11973
|
+
var _a;
|
|
11974
|
+
const rootData = (_a = matches.find((m) => m.id === "root")) == null ? void 0 : _a.data;
|
|
11900
11975
|
if (!rootData) return [];
|
|
11901
11976
|
return getSeoMetaTags({
|
|
11902
11977
|
title: `🎉 ${rootData == null ? void 0 : rootData.workshopTitle}`,
|
|
@@ -11958,6 +12033,7 @@ const headers$2 = ({ loaderHeaders, parentHeaders }) => {
|
|
|
11958
12033
|
const mdxComponents$1 = { h1: () => null };
|
|
11959
12034
|
function ExerciseFinished() {
|
|
11960
12035
|
const data = useLoaderData();
|
|
12036
|
+
useRevalidationWS({ watchPaths: ["./exercises/FINISHED.mdx"] });
|
|
11961
12037
|
return /* @__PURE__ */ jsx("div", { className: "flex h-full flex-grow flex-col", children: /* @__PURE__ */ jsxs("main", { className: "grid h-full flex-grow grid-cols-1 grid-rows-2 lg:grid-cols-2 lg:grid-rows-1", children: [
|
|
11962
12038
|
/* @__PURE__ */ jsxs("div", { className: "relative col-span-1 row-span-1 flex h-full flex-col lg:border-r", children: [
|
|
11963
12039
|
/* @__PURE__ */ jsx("h1", { className: "h-14 border-b pl-10 pr-5 text-sm font-medium uppercase leading-none", children: /* @__PURE__ */ jsx("div", { className: "flex h-14 flex-wrap items-center justify-between gap-x-2 py-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-start gap-x-2", children: [
|
|
@@ -12290,7 +12366,7 @@ async function action$2() {
|
|
|
12290
12366
|
return json$1({ status: "pending" });
|
|
12291
12367
|
}
|
|
12292
12368
|
function Login() {
|
|
12293
|
-
var
|
|
12369
|
+
var _a;
|
|
12294
12370
|
const {
|
|
12295
12371
|
product: { displayName }
|
|
12296
12372
|
} = useWorkshopConfig();
|
|
@@ -12384,7 +12460,7 @@ function Login() {
|
|
|
12384
12460
|
"."
|
|
12385
12461
|
] })
|
|
12386
12462
|
] }),
|
|
12387
|
-
/* @__PURE__ */ jsx(loginFetcher.Form, { method: "POST", children: /* @__PURE__ */ jsx(Button, { varient: "primary", type: "submit", children: loginFetcher.state === "idle" && ((
|
|
12463
|
+
/* @__PURE__ */ jsx(loginFetcher.Form, { method: "POST", children: /* @__PURE__ */ jsx(Button, { varient: "primary", type: "submit", children: loginFetcher.state === "idle" && ((_a = loginFetcher.data) == null ? void 0 : _a.status) !== "pending" ? `Retrieve Auth Code` : `Retrieving Auth Code...` }) })
|
|
12388
12464
|
] }),
|
|
12389
12465
|
authError ? /* @__PURE__ */ jsxs("div", { className: "mt-4 text-red-500", children: [
|
|
12390
12466
|
"There was an error: ",
|
|
@@ -12404,10 +12480,10 @@ const handle$2 = {
|
|
|
12404
12480
|
getSitemapEntries: () => null
|
|
12405
12481
|
};
|
|
12406
12482
|
function Support() {
|
|
12407
|
-
var
|
|
12408
|
-
const repoGroups = (
|
|
12483
|
+
var _a;
|
|
12484
|
+
const repoGroups = (_a = ENV.EPICSHOP_GITHUB_REPO.match(
|
|
12409
12485
|
/github\.com\/(?<org>[^/?]+)\/(?<repo>[^/?]+)/
|
|
12410
|
-
)) == null ? void 0 :
|
|
12486
|
+
)) == null ? void 0 : _a.groups;
|
|
12411
12487
|
let repoUrl = ENV.EPICSHOP_GITHUB_REPO;
|
|
12412
12488
|
let repoIssuesUrl = repoUrl;
|
|
12413
12489
|
if ((repoGroups == null ? void 0 : repoGroups.org) && repoGroups.repo) {
|
|
@@ -12492,8 +12568,8 @@ const handle$1 = {
|
|
|
12492
12568
|
const meta = ({
|
|
12493
12569
|
matches
|
|
12494
12570
|
}) => {
|
|
12495
|
-
var
|
|
12496
|
-
const rootData = (
|
|
12571
|
+
var _a;
|
|
12572
|
+
const rootData = (_a = matches.find((m) => m.id === "root")) == null ? void 0 : _a.data;
|
|
12497
12573
|
return [{ title: `👷 | ${rootData == null ? void 0 : rootData.workshopTitle}` }];
|
|
12498
12574
|
};
|
|
12499
12575
|
async function loader$a({ request }) {
|
|
@@ -12576,11 +12652,11 @@ function linkProgress(progress) {
|
|
|
12576
12652
|
}
|
|
12577
12653
|
}
|
|
12578
12654
|
function AdminLayout() {
|
|
12579
|
-
var
|
|
12655
|
+
var _a, _b;
|
|
12580
12656
|
const data = useLoaderData();
|
|
12581
12657
|
const navigation = useNavigation();
|
|
12582
12658
|
const epicProgress = useEpicProgress();
|
|
12583
|
-
const isStartingInspector = ((
|
|
12659
|
+
const isStartingInspector = ((_a = navigation.formData) == null ? void 0 : _a.get("intent")) === "inspect";
|
|
12584
12660
|
const isStoppingInspector = ((_b = navigation.formData) == null ? void 0 : _b.get("intent")) === "stop-inspect";
|
|
12585
12661
|
const progressStatus = {
|
|
12586
12662
|
completed: "bg-blue-500",
|
|
@@ -12739,7 +12815,7 @@ const route27 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
12739
12815
|
loader: loader$7
|
|
12740
12816
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
12741
12817
|
async function loader$6({ request }) {
|
|
12742
|
-
var
|
|
12818
|
+
var _a, _b, _c, _d;
|
|
12743
12819
|
const reqUrl = new URL(request.url);
|
|
12744
12820
|
const searchParams = reqUrl.searchParams;
|
|
12745
12821
|
const timings = makeTimings("diffLoader");
|
|
@@ -12783,7 +12859,7 @@ async function loader$6({ request }) {
|
|
|
12783
12859
|
const prevApp2Index = prevApp1Index + 1;
|
|
12784
12860
|
const nextApp1Index = usingDefaultApp1 ? 0 : app1Index + 1 < allApps.length ? app1Index + 1 : -2;
|
|
12785
12861
|
const nextApp2Index = nextApp1Index + 1;
|
|
12786
|
-
const prevApp1 = (
|
|
12862
|
+
const prevApp1 = (_a = allAppsFull[prevApp1Index]) == null ? void 0 : _a.name;
|
|
12787
12863
|
const prevApp2 = (_b = allAppsFull[prevApp2Index]) == null ? void 0 : _b.name;
|
|
12788
12864
|
const nextApp1 = (_c = allAppsFull[nextApp1Index]) == null ? void 0 : _c.name;
|
|
12789
12865
|
const nextApp2 = (_d = allAppsFull[nextApp2Index]) == null ? void 0 : _d.name;
|
|
@@ -13267,7 +13343,7 @@ const route39 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
13267
13343
|
__proto__: null,
|
|
13268
13344
|
loader
|
|
13269
13345
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
13270
|
-
const serverManifest = { "entry": { "module": "/assets/entry.client-3M2p-8I3.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js"], "css": [] }, "routes": { "root": { "id": "root", "parentId": void 0, "path": "", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/root-9wVBEzOq.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/request-info-CEhUGODY.js", "/assets/tooltip-kD4kSf1i.js", "/assets/pe-CUZaIcdt.js", "/assets/error-boundary-COkPRBOZ.js", "/assets/progress-bar-D3kudPcr.js", "/assets/index-B-hHvmeV.js", "/assets/index-YNIH4TH8.js", "/assets/presence-Cr--lRCr.js", "/assets/seo-pBpFCWsy.js"], "css": [] }, "routes/$": { "id": "routes/$", "parentId": "root", "path": "*", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_-D0Tgngwe.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/error-boundary-COkPRBOZ.js"], "css": [] }, "routes/_app+/_layout": { "id": "routes/_app+/_layout", "parentId": "root", "path": void 0, "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-BPwIOXxN.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/request-info-CEhUGODY.js", "/assets/tooltip-kD4kSf1i.js", "/assets/pe-CUZaIcdt.js", "/assets/index-YNIH4TH8.js", "/assets/workshop-config-CL4F08kr.js", "/assets/product-BAWG1Vut.js", "/assets/index-CXyf3Reb.js", "/assets/user-DvujSs-t.js", "/assets/presence-Cr--lRCr.js", "/assets/progress-BFm2U-l5.js"], "css": [] }, "routes/_app+/account": { "id": "routes/_app+/account", "parentId": "routes/_app+/_layout", "path": "account", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/account-BatJhmSV.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/request-info-CEhUGODY.js", "/assets/button-EE0aPg10.js", "/assets/tooltip-kD4kSf1i.js", "/assets/user-DvujSs-t.js", "/assets/presence-Cr--lRCr.js"], "css": [] }, "routes/_app+/app.$appName+/$": { "id": "routes/_app+/app.$appName+/$", "parentId": "routes/_app+/_layout", "path": "app/:appName/*", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/api.$": { "id": "routes/_app+/app.$appName+/api.$", "parentId": "routes/_app+/_layout", "path": "app/:appName/api/*", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/api._-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/epic_ws[.js]": { "id": "routes/_app+/app.$appName+/epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/:appName/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/index": { "id": "routes/_app+/app.$appName+/index", "parentId": "routes/_app+/_layout", "path": "app/:appName/", "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-K6Dvbx-E.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/test.$testName": { "id": "routes/_app+/app.$appName+/test.$testName", "parentId": "routes/_app+/_layout", "path": "app/:appName/test/:testName", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test._testName-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/test.epic_ws[.js]": { "id": "routes/_app+/app.$appName+/test.epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/:appName/test/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test.epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/discord": { "id": "routes/_app+/discord", "parentId": "routes/_app+/_layout", "path": "discord", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/discord-BhzUjmbI.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/user-DvujSs-t.js", "/assets/discord-BRTW4Rnh.js"], "css": [] }, "routes/_app+/exercise+/_layout": { "id": "routes/_app+/exercise+/_layout", "parentId": "routes/_app+/_layout", "path": "exercise", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-BUs3av-e.js", "imports": ["/assets/index-1cKOJFpX.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber": { "id": "routes/_app+/exercise+/$exerciseNumber", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_exerciseNumber-1JworToC.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/request-info-CEhUGODY.js", "/assets/tooltip-kD4kSf1i.js", "/assets/pe-CUZaIcdt.js", "/assets/index-YNIH4TH8.js", "/assets/loading-sXkYDMsx.js", "/assets/user-DvujSs-t.js", "/assets/workshop-config-CL4F08kr.js", "/assets/epic-video-yrWoJVFy.js", "/assets/progress-bar-D3kudPcr.js", "/assets/index-Dx5GmdYq.js", "/assets/mdx-CpyquP9i.js", "/assets/progress-BFm2U-l5.js", "/assets/seo-pBpFCWsy.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber/:stepNumber", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_exerciseNumber_._stepNumber-7kSd_6hH.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "path": ":type", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_layout-CKnDy_9Z.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/request-info-CEhUGODY.js", "/assets/tooltip-kD4kSf1i.js", "/assets/pe-CUZaIcdt.js", "/assets/index-YNIH4TH8.js", "/assets/loading-sXkYDMsx.js", "/assets/user-DvujSs-t.js", "/assets/workshop-config-CL4F08kr.js", "/assets/epic-video-yrWoJVFy.js", "/assets/progress-bar-D3kudPcr.js", "/assets/index-CXyf3Reb.js", "/assets/index-BwhlO_gF.js", "/assets/index-Dx5GmdYq.js", "/assets/error-boundary-COkPRBOZ.js", "/assets/nav-chevrons-g-C0ilNz.js", "/assets/mdx-CpyquP9i.js", "/assets/progress-BFm2U-l5.js", "/assets/set-playground-DW0yVaNn.js", "/assets/seo-pBpFCWsy.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/app": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/app", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": "app", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/app-CJ9ElQg6.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/request-info-CEhUGODY.js", "/assets/tooltip-kD4kSf1i.js", "/assets/pe-CUZaIcdt.js", "/assets/index-YNIH4TH8.js", "/assets/button-EE0aPg10.js", "/assets/loading-sXkYDMsx.js", "/assets/progress-bar-D3kudPcr.js", "/assets/preview-C7dtR2VR.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/index-Ccssehd9.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/tooltip-kD4kSf1i.js", "/assets/index-CXyf3Reb.js", "/assets/index-BwhlO_gF.js", "/assets/request-info-CEhUGODY.js", "/assets/pe-CUZaIcdt.js", "/assets/index-YNIH4TH8.js", "/assets/loading-sXkYDMsx.js", "/assets/user-DvujSs-t.js", "/assets/workshop-config-CL4F08kr.js", "/assets/epic-video-yrWoJVFy.js", "/assets/progress-bar-D3kudPcr.js", "/assets/accordion-OfO-5m5D.js", "/assets/mdx-CpyquP9i.js", "/assets/use-event-source-A_0lEOPX.js", "/assets/set-playground-DW0yVaNn.js", "/assets/button-EE0aPg10.js", "/assets/diff-jgZ_RGra.js", "/assets/error-boundary-COkPRBOZ.js", "/assets/discord-BRTW4Rnh.js", "/assets/index-B-hHvmeV.js", "/assets/tests-BR7RFlr5.js", "/assets/preview-C7dtR2VR.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/test": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/test", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": "test", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test-DbZkv25C.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/request-info-CEhUGODY.js", "/assets/tooltip-kD4kSf1i.js", "/assets/pe-CUZaIcdt.js", "/assets/index-YNIH4TH8.js", "/assets/loading-sXkYDMsx.js", "/assets/user-DvujSs-t.js", "/assets/workshop-config-CL4F08kr.js", "/assets/index-CXyf3Reb.js", "/assets/index-BwhlO_gF.js", "/assets/progress-bar-D3kudPcr.js", "/assets/epic-video-yrWoJVFy.js", "/assets/accordion-OfO-5m5D.js", "/assets/use-event-source-A_0lEOPX.js", "/assets/set-playground-DW0yVaNn.js", "/assets/tests-BR7RFlr5.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.index": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.index", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_exerciseNumber_._stepNumber.index-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.finished": { "id": "routes/_app+/exercise+/$exerciseNumber_.finished", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber/finished", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_exerciseNumber_.finished-B4D2ZAmj.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/request-info-CEhUGODY.js", "/assets/tooltip-kD4kSf1i.js", "/assets/pe-CUZaIcdt.js", "/assets/index-YNIH4TH8.js", "/assets/loading-sXkYDMsx.js", "/assets/user-DvujSs-t.js", "/assets/workshop-config-CL4F08kr.js", "/assets/epic-video-yrWoJVFy.js", "/assets/progress-bar-D3kudPcr.js", "/assets/index-Dx5GmdYq.js", "/assets/nav-chevrons-g-C0ilNz.js", "/assets/mdx-CpyquP9i.js", "/assets/progress-BFm2U-l5.js", "/assets/seo-pBpFCWsy.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/finished": { "id": "routes/_app+/finished", "parentId": "routes/_app+/_layout", "path": "finished", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/finished-Ct6I1SZV.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/request-info-CEhUGODY.js", "/assets/tooltip-kD4kSf1i.js", "/assets/pe-CUZaIcdt.js", "/assets/index-YNIH4TH8.js", "/assets/loading-sXkYDMsx.js", "/assets/user-DvujSs-t.js", "/assets/workshop-config-CL4F08kr.js", "/assets/epic-video-yrWoJVFy.js", "/assets/progress-bar-D3kudPcr.js", "/assets/index-Dx5GmdYq.js", "/assets/nav-chevrons-g-C0ilNz.js", "/assets/mdx-CpyquP9i.js", "/assets/seo-pBpFCWsy.js", "/assets/progress-BFm2U-l5.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/index": { "id": "routes/_app+/index", "parentId": "routes/_app+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/index-R-sUGQfT.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/request-info-CEhUGODY.js", "/assets/tooltip-kD4kSf1i.js", "/assets/pe-CUZaIcdt.js", "/assets/index-YNIH4TH8.js", "/assets/loading-sXkYDMsx.js", "/assets/user-DvujSs-t.js", "/assets/workshop-config-CL4F08kr.js", "/assets/epic-video-yrWoJVFy.js", "/assets/progress-bar-D3kudPcr.js", "/assets/index-Dx5GmdYq.js", "/assets/error-boundary-COkPRBOZ.js", "/assets/mdx-CpyquP9i.js", "/assets/progress-BFm2U-l5.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/login": { "id": "routes/_app+/login", "parentId": "routes/_app+/_layout", "path": "login", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/login-Cc73KLYm.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/request-info-CEhUGODY.js", "/assets/tooltip-kD4kSf1i.js", "/assets/pe-CUZaIcdt.js", "/assets/index-YNIH4TH8.js", "/assets/workshop-config-CL4F08kr.js", "/assets/use-event-source-A_0lEOPX.js", "/assets/button-EE0aPg10.js", "/assets/loading-sXkYDMsx.js", "/assets/product-BAWG1Vut.js"], "css": [] }, "routes/_app+/support": { "id": "routes/_app+/support", "parentId": "routes/_app+/_layout", "path": "support", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/support-hcqGIpir.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js"], "css": [] }, "routes/admin+/_layout": { "id": "routes/admin+/_layout", "parentId": "root", "path": "admin", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-BwzhY4NI.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/pe-CUZaIcdt.js", "/assets/tooltip-kD4kSf1i.js", "/assets/progress-BFm2U-l5.js"], "css": [] }, "routes/admin+/apps": { "id": "routes/admin+/apps", "parentId": "routes/admin+/_layout", "path": "apps", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/apps-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/admin+/cache": { "id": "routes/admin+/cache", "parentId": "routes/admin+/_layout", "path": "cache", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/cache-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/apps": { "id": "routes/apps", "parentId": "root", "path": "apps", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/apps-DP2rzg_V.js", "imports": [], "css": [] }, "routes/diff": { "id": "routes/diff", "parentId": "root", "path": "diff", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/diff-Cvtc-qzL.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/tooltip-kD4kSf1i.js", "/assets/index-CXyf3Reb.js", "/assets/index-BwhlO_gF.js", "/assets/request-info-CEhUGODY.js", "/assets/pe-CUZaIcdt.js", "/assets/index-YNIH4TH8.js", "/assets/loading-sXkYDMsx.js", "/assets/user-DvujSs-t.js", "/assets/workshop-config-CL4F08kr.js", "/assets/epic-video-yrWoJVFy.js", "/assets/progress-bar-D3kudPcr.js", "/assets/accordion-OfO-5m5D.js", "/assets/mdx-CpyquP9i.js", "/assets/diff-jgZ_RGra.js", "/assets/nav-chevrons-g-C0ilNz.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/discord.callback": { "id": "routes/discord.callback", "parentId": "root", "path": "discord/callback", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/discord.callback-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/exercises": { "id": "routes/exercises", "parentId": "root", "path": "exercises", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/exercises-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/launch-editor": { "id": "routes/launch-editor", "parentId": "root", "path": "launch-editor", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/launch-editor-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/login-sse": { "id": "routes/login-sse", "parentId": "root", "path": "login-sse", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/login-sse-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/og": { "id": "routes/og", "parentId": "root", "path": "og", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/og-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/onboarding": { "id": "routes/onboarding", "parentId": "root", "path": "onboarding", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/onboarding-B7TLVi2l.js", "imports": ["/assets/index-1cKOJFpX.js", "/assets/components-CME-nGId.js", "/assets/misc-CxCgA-_O.js", "/assets/request-info-CEhUGODY.js", "/assets/tooltip-kD4kSf1i.js", "/assets/pe-CUZaIcdt.js", "/assets/index-YNIH4TH8.js", "/assets/loading-sXkYDMsx.js", "/assets/user-DvujSs-t.js", "/assets/workshop-config-CL4F08kr.js", "/assets/button-EE0aPg10.js", "/assets/epic-video-yrWoJVFy.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/processes": { "id": "routes/processes", "parentId": "root", "path": "processes", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/processes-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/progress": { "id": "routes/progress", "parentId": "root", "path": "progress", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/progress-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/robots[.]txt": { "id": "routes/robots[.]txt", "parentId": "root", "path": "robots.txt", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/robots_._txt-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/set-playground": { "id": "routes/set-playground", "parentId": "root", "path": "set-playground", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/set-playground-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/sitemap[.]xml": { "id": "routes/sitemap[.]xml", "parentId": "root", "path": "sitemap.xml", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/sitemap_._xml-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/start": { "id": "routes/start", "parentId": "root", "path": "start", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/start-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/test": { "id": "routes/test", "parentId": "root", "path": "test", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/theme/index": { "id": "routes/theme/index", "parentId": "root", "path": "theme", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-DP2rzg_V.js", "imports": [], "css": [] }, "routes/video-player/index": { "id": "routes/video-player/index", "parentId": "root", "path": "video-player", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-l0sNRNKZ.js", "imports": [], "css": [] } }, "url": "/assets/manifest-f5f44d87.js", "version": "f5f44d87" };
|
|
13346
|
+
const serverManifest = { "entry": { "module": "/assets/entry.client-CW5CUf_W.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js"], "css": [] }, "routes": { "root": { "id": "root", "parentId": void 0, "path": "", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/root-Cl86OUog.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/request-info-DGnmXtfj.js", "/assets/tooltip-6-WS-Xux.js", "/assets/pe-CvPIToj6.js", "/assets/error-boundary-BcGxKpte.js", "/assets/progress-bar-F8_2mvYp.js", "/assets/index-YtpQLUzj.js", "/assets/index-BvihEwfB.js", "/assets/presence-Dd98AJ_5.js", "/assets/seo-pBpFCWsy.js"], "css": [] }, "routes/$": { "id": "routes/$", "parentId": "root", "path": "*", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_-ZHCWB__B.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/error-boundary-BcGxKpte.js"], "css": [] }, "routes/_app+/_layout": { "id": "routes/_app+/_layout", "parentId": "root", "path": void 0, "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-frPHZWgR.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/request-info-DGnmXtfj.js", "/assets/tooltip-6-WS-Xux.js", "/assets/pe-CvPIToj6.js", "/assets/index-BvihEwfB.js", "/assets/workshop-config-Ce9sSc3I.js", "/assets/product-mjsTrqXs.js", "/assets/revalidation-ws-DcvYvzyj.js", "/assets/index-BjNhezSK.js", "/assets/user-Boua6jiU.js", "/assets/presence-Dd98AJ_5.js", "/assets/progress-Co-59mG2.js"], "css": [] }, "routes/_app+/account": { "id": "routes/_app+/account", "parentId": "routes/_app+/_layout", "path": "account", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/account-DDuV9rZX.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/request-info-DGnmXtfj.js", "/assets/button-CMkJ8p0a.js", "/assets/tooltip-6-WS-Xux.js", "/assets/user-Boua6jiU.js", "/assets/presence-Dd98AJ_5.js"], "css": [] }, "routes/_app+/app.$appName+/$": { "id": "routes/_app+/app.$appName+/$", "parentId": "routes/_app+/_layout", "path": "app/:appName/*", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/api.$": { "id": "routes/_app+/app.$appName+/api.$", "parentId": "routes/_app+/_layout", "path": "app/:appName/api/*", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/api._-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/epic_ws[.js]": { "id": "routes/_app+/app.$appName+/epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/:appName/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/index": { "id": "routes/_app+/app.$appName+/index", "parentId": "routes/_app+/_layout", "path": "app/:appName/", "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-K6Dvbx-E.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/test.$testName": { "id": "routes/_app+/app.$appName+/test.$testName", "parentId": "routes/_app+/_layout", "path": "app/:appName/test/:testName", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test._testName-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/test.epic_ws[.js]": { "id": "routes/_app+/app.$appName+/test.epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/:appName/test/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test.epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/discord": { "id": "routes/_app+/discord", "parentId": "routes/_app+/_layout", "path": "discord", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/discord-DYeU0QX6.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/user-Boua6jiU.js", "/assets/discord-C9bVfiZ6.js"], "css": [] }, "routes/_app+/exercise+/_layout": { "id": "routes/_app+/exercise+/_layout", "parentId": "routes/_app+/_layout", "path": "exercise", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-Cfbi6StB.js", "imports": ["/assets/index-DF_XBInP.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber": { "id": "routes/_app+/exercise+/$exerciseNumber", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_exerciseNumber-BFTlBdr4.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/request-info-DGnmXtfj.js", "/assets/tooltip-6-WS-Xux.js", "/assets/pe-CvPIToj6.js", "/assets/index-BvihEwfB.js", "/assets/loading-Br41_Pbf.js", "/assets/user-Boua6jiU.js", "/assets/workshop-config-Ce9sSc3I.js", "/assets/epic-video-bs7WmhbC.js", "/assets/progress-bar-F8_2mvYp.js", "/assets/index-DBrRQJxF.js", "/assets/revalidation-ws-DcvYvzyj.js", "/assets/mdx-CRxPouxB.js", "/assets/progress-Co-59mG2.js", "/assets/seo-pBpFCWsy.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber/:stepNumber", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_exerciseNumber_._stepNumber-_687iGFh.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "path": ":type", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_layout-BriOqd2R.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/request-info-DGnmXtfj.js", "/assets/tooltip-6-WS-Xux.js", "/assets/pe-CvPIToj6.js", "/assets/index-BvihEwfB.js", "/assets/loading-Br41_Pbf.js", "/assets/user-Boua6jiU.js", "/assets/workshop-config-Ce9sSc3I.js", "/assets/epic-video-bs7WmhbC.js", "/assets/progress-bar-F8_2mvYp.js", "/assets/index-BjNhezSK.js", "/assets/index-BczhSZ3e.js", "/assets/index-DBrRQJxF.js", "/assets/error-boundary-BcGxKpte.js", "/assets/nav-chevrons-DYiI8EMU.js", "/assets/revalidation-ws-DcvYvzyj.js", "/assets/mdx-CRxPouxB.js", "/assets/progress-Co-59mG2.js", "/assets/set-playground-pMKmtPtz.js", "/assets/seo-pBpFCWsy.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/app": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/app", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": "app", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/app-wbMCZEiv.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/request-info-DGnmXtfj.js", "/assets/tooltip-6-WS-Xux.js", "/assets/pe-CvPIToj6.js", "/assets/index-BvihEwfB.js", "/assets/button-CMkJ8p0a.js", "/assets/loading-Br41_Pbf.js", "/assets/progress-bar-F8_2mvYp.js", "/assets/preview-DZcdG4kw.js"], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/index", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/index-C2yr7Uiu.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/tooltip-6-WS-Xux.js", "/assets/index-BjNhezSK.js", "/assets/index-BczhSZ3e.js", "/assets/request-info-DGnmXtfj.js", "/assets/pe-CvPIToj6.js", "/assets/index-BvihEwfB.js", "/assets/loading-Br41_Pbf.js", "/assets/user-Boua6jiU.js", "/assets/workshop-config-Ce9sSc3I.js", "/assets/epic-video-bs7WmhbC.js", "/assets/progress-bar-F8_2mvYp.js", "/assets/accordion-DuE9VejZ.js", "/assets/mdx-CRxPouxB.js", "/assets/revalidation-ws-DcvYvzyj.js", "/assets/use-event-source-CCGBLG92.js", "/assets/set-playground-pMKmtPtz.js", "/assets/button-CMkJ8p0a.js", "/assets/diff-B6thd_Sf.js", "/assets/error-boundary-BcGxKpte.js", "/assets/discord-C9bVfiZ6.js", "/assets/index-YtpQLUzj.js", "/assets/tests-BeAEgPAw.js", "/assets/preview-DZcdG4kw.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/test": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/test", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/_layout", "path": "test", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test-B6zIK2V6.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/request-info-DGnmXtfj.js", "/assets/tooltip-6-WS-Xux.js", "/assets/pe-CvPIToj6.js", "/assets/index-BvihEwfB.js", "/assets/loading-Br41_Pbf.js", "/assets/user-Boua6jiU.js", "/assets/workshop-config-Ce9sSc3I.js", "/assets/index-BjNhezSK.js", "/assets/index-BczhSZ3e.js", "/assets/progress-bar-F8_2mvYp.js", "/assets/epic-video-bs7WmhbC.js", "/assets/accordion-DuE9VejZ.js", "/assets/use-event-source-CCGBLG92.js", "/assets/set-playground-pMKmtPtz.js", "/assets/tests-BeAEgPAw.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.index": { "id": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber.index", "parentId": "routes/_app+/exercise+/$exerciseNumber_.$stepNumber", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_exerciseNumber_._stepNumber.index-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/exercise+/$exerciseNumber_.finished": { "id": "routes/_app+/exercise+/$exerciseNumber_.finished", "parentId": "routes/_app+/exercise+/_layout", "path": ":exerciseNumber/finished", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_exerciseNumber_.finished-BEfn-nJi.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/request-info-DGnmXtfj.js", "/assets/tooltip-6-WS-Xux.js", "/assets/pe-CvPIToj6.js", "/assets/index-BvihEwfB.js", "/assets/loading-Br41_Pbf.js", "/assets/user-Boua6jiU.js", "/assets/workshop-config-Ce9sSc3I.js", "/assets/epic-video-bs7WmhbC.js", "/assets/progress-bar-F8_2mvYp.js", "/assets/index-DBrRQJxF.js", "/assets/nav-chevrons-DYiI8EMU.js", "/assets/revalidation-ws-DcvYvzyj.js", "/assets/mdx-CRxPouxB.js", "/assets/progress-Co-59mG2.js", "/assets/seo-pBpFCWsy.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/finished": { "id": "routes/_app+/finished", "parentId": "routes/_app+/_layout", "path": "finished", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/finished-C2dgX1d-.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/request-info-DGnmXtfj.js", "/assets/tooltip-6-WS-Xux.js", "/assets/pe-CvPIToj6.js", "/assets/index-BvihEwfB.js", "/assets/loading-Br41_Pbf.js", "/assets/user-Boua6jiU.js", "/assets/workshop-config-Ce9sSc3I.js", "/assets/epic-video-bs7WmhbC.js", "/assets/progress-bar-F8_2mvYp.js", "/assets/index-DBrRQJxF.js", "/assets/nav-chevrons-DYiI8EMU.js", "/assets/revalidation-ws-DcvYvzyj.js", "/assets/mdx-CRxPouxB.js", "/assets/seo-pBpFCWsy.js", "/assets/progress-Co-59mG2.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/index": { "id": "routes/_app+/index", "parentId": "routes/_app+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/index-CuV1bRbu.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/request-info-DGnmXtfj.js", "/assets/tooltip-6-WS-Xux.js", "/assets/pe-CvPIToj6.js", "/assets/index-BvihEwfB.js", "/assets/loading-Br41_Pbf.js", "/assets/user-Boua6jiU.js", "/assets/workshop-config-Ce9sSc3I.js", "/assets/epic-video-bs7WmhbC.js", "/assets/progress-bar-F8_2mvYp.js", "/assets/index-DBrRQJxF.js", "/assets/error-boundary-BcGxKpte.js", "/assets/mdx-CRxPouxB.js", "/assets/progress-Co-59mG2.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/login": { "id": "routes/_app+/login", "parentId": "routes/_app+/_layout", "path": "login", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/login-kjV7hrVt.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/request-info-DGnmXtfj.js", "/assets/tooltip-6-WS-Xux.js", "/assets/pe-CvPIToj6.js", "/assets/index-BvihEwfB.js", "/assets/workshop-config-Ce9sSc3I.js", "/assets/use-event-source-CCGBLG92.js", "/assets/button-CMkJ8p0a.js", "/assets/loading-Br41_Pbf.js", "/assets/product-mjsTrqXs.js"], "css": [] }, "routes/_app+/support": { "id": "routes/_app+/support", "parentId": "routes/_app+/_layout", "path": "support", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/support-B0E_F4Zh.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js"], "css": [] }, "routes/admin+/_layout": { "id": "routes/admin+/_layout", "parentId": "root", "path": "admin", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-BLJr2x2F.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/pe-CvPIToj6.js", "/assets/tooltip-6-WS-Xux.js", "/assets/progress-Co-59mG2.js"], "css": [] }, "routes/admin+/apps": { "id": "routes/admin+/apps", "parentId": "routes/admin+/_layout", "path": "apps", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/apps-DP2rzg_V.js", "imports": [], "css": [] }, "routes/admin+/cache": { "id": "routes/admin+/cache", "parentId": "routes/admin+/_layout", "path": "cache", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/cache-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/apps": { "id": "routes/apps", "parentId": "root", "path": "apps", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/apps-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/diff": { "id": "routes/diff", "parentId": "root", "path": "diff", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/diff-BEk79KPK.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/tooltip-6-WS-Xux.js", "/assets/index-BjNhezSK.js", "/assets/index-BczhSZ3e.js", "/assets/request-info-DGnmXtfj.js", "/assets/pe-CvPIToj6.js", "/assets/index-BvihEwfB.js", "/assets/loading-Br41_Pbf.js", "/assets/user-Boua6jiU.js", "/assets/workshop-config-Ce9sSc3I.js", "/assets/epic-video-bs7WmhbC.js", "/assets/progress-bar-F8_2mvYp.js", "/assets/accordion-DuE9VejZ.js", "/assets/mdx-CRxPouxB.js", "/assets/revalidation-ws-DcvYvzyj.js", "/assets/diff-B6thd_Sf.js", "/assets/nav-chevrons-DYiI8EMU.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/discord.callback": { "id": "routes/discord.callback", "parentId": "root", "path": "discord/callback", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/discord.callback-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/exercises": { "id": "routes/exercises", "parentId": "root", "path": "exercises", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/exercises-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/launch-editor": { "id": "routes/launch-editor", "parentId": "root", "path": "launch-editor", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/launch-editor-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/login-sse": { "id": "routes/login-sse", "parentId": "root", "path": "login-sse", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/login-sse-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/og": { "id": "routes/og", "parentId": "root", "path": "og", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/og-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/onboarding": { "id": "routes/onboarding", "parentId": "root", "path": "onboarding", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/onboarding-B4Z_yevk.js", "imports": ["/assets/index-DF_XBInP.js", "/assets/components-DZ8XIeZ3.js", "/assets/misc-BE75ioh8.js", "/assets/request-info-DGnmXtfj.js", "/assets/tooltip-6-WS-Xux.js", "/assets/pe-CvPIToj6.js", "/assets/index-BvihEwfB.js", "/assets/loading-Br41_Pbf.js", "/assets/user-Boua6jiU.js", "/assets/workshop-config-Ce9sSc3I.js", "/assets/button-CMkJ8p0a.js", "/assets/epic-video-bs7WmhbC.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/processes": { "id": "routes/processes", "parentId": "root", "path": "processes", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/processes-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/progress": { "id": "routes/progress", "parentId": "root", "path": "progress", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/progress-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/robots[.]txt": { "id": "routes/robots[.]txt", "parentId": "root", "path": "robots.txt", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/robots_._txt-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/set-playground": { "id": "routes/set-playground", "parentId": "root", "path": "set-playground", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/set-playground-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/sitemap[.]xml": { "id": "routes/sitemap[.]xml", "parentId": "root", "path": "sitemap.xml", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/sitemap_._xml-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/start": { "id": "routes/start", "parentId": "root", "path": "start", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/start-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/test": { "id": "routes/test", "parentId": "root", "path": "test", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/theme/index": { "id": "routes/theme/index", "parentId": "root", "path": "theme", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/video-player/index": { "id": "routes/video-player/index", "parentId": "root", "path": "video-player", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-DP2rzg_V.js", "imports": [], "css": [] } }, "url": "/assets/manifest-d7c89645.js", "version": "d7c89645" };
|
|
13271
13347
|
const mode = "production";
|
|
13272
13348
|
const assetsBuildDirectory = "build/client";
|
|
13273
13349
|
const basename = "/";
|