@epic-web/workshop-app 5.4.1 → 5.5.0
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/_exerciseNumber-DCSM0NCG.js.map +1 -1
- package/build/client/assets/_exerciseNumber_.finished-nbpk1ToO.js.map +1 -1
- package/build/client/assets/_layout-B8j0pWoF.js +6 -0
- package/build/client/assets/_layout-B8j0pWoF.js.map +1 -0
- package/build/client/assets/_layout-DTAM9xh5.js.map +1 -1
- package/build/client/assets/{account-C4Piztoz.js → account-DPP4rKOb.js} +2 -2
- package/build/client/assets/{account-C4Piztoz.js.map → account-DPP4rKOb.js.map} +1 -1
- package/build/client/assets/epic-video-Bp4BOD2R.js.map +1 -1
- package/build/client/assets/finished-C0cpfAFL.js.map +1 -1
- package/build/client/assets/index-Bi1TbRTj.js.map +1 -1
- package/build/client/assets/index-Ca4vBON4.js.map +1 -1
- package/build/client/assets/{manifest-e5b2a6e1.js → manifest-a8336fab.js} +1 -1
- package/build/client/assets/onboarding-C2YNq60k.js.map +1 -1
- package/build/client/assets/presence-8FPJKg_8.js +28 -0
- package/build/client/assets/presence-8FPJKg_8.js.map +1 -0
- package/build/client/assets/progress-DQt_Bn9o.js.map +1 -1
- package/build/client/assets/{root-a3d3Qwip.js → root-D12XnE1S.js} +2 -2
- package/build/client/assets/{root-a3d3Qwip.js.map → root-D12XnE1S.js.map} +1 -1
- package/build/client/assets/tests-DbuyD2cI.js.map +1 -1
- package/build/server/index.js +159 -573
- package/build/server/index.js.map +1 -1
- package/package.json +3 -3
- package/build/client/assets/_layout-Cbz7Qt-S.js +0 -6
- package/build/client/assets/_layout-Cbz7Qt-S.js.map +0 -1
- package/build/client/assets/presence-DJGFvdDh.js +0 -28
- package/build/client/assets/presence-DJGFvdDh.js.map +0 -1
package/build/server/index.js
CHANGED
|
@@ -5,11 +5,13 @@ import { RemixServer, Link, useRouteError, useParams, isRouteErrorResponse, useN
|
|
|
5
5
|
import { isbot } from "isbot";
|
|
6
6
|
import { renderToPipeableStream, renderToStaticMarkup } from "react-dom/server";
|
|
7
7
|
import path from "node:path";
|
|
8
|
-
import { makeSingletonCache, cachified,
|
|
9
|
-
import { getPreferences, getAuthInfo, readOnboardingData, requireAuthInfo, deleteDb, setPresencePreferences, PlayerPreferencesSchema, setPlayerPreferences, setAuthInfo, markOnboardingVideoWatched } from "@epic-web/workshop-utils/db.server";
|
|
10
|
-
import { z } from "zod";
|
|
11
|
-
import { getWorkshopInstructions, getWorkshopFinished, getExercises, getApps, getPlaygroundAppName, extractNumbersAndTypeFromAppNameOrPath, getAppFromFile, getAppByName, isProblemApp, isPlaygroundApp, isExerciseStepApp, getExercise, isSolutionApp, isExampleApp, getRelativePath as getRelativePath$1, workshopRoot, modifiedTimes, getForceFreshForDir, setPlayground, requireExerciseApp, requireExercise, getExerciseApp, getAppDisplayName, getNextExerciseApp, getPrevExerciseApp, getAppPageRoute } from "@epic-web/workshop-utils/apps.server";
|
|
8
|
+
import { makeSingletonCache, cachified, deleteCache, compiledCodeCache, diffFilesCache, diffCodeCache, shouldForceFresh, fsCache, getAllFileCacheEntries, ogCache } from "@epic-web/workshop-utils/cache.server";
|
|
12
9
|
import { getWorkshopConfig } from "@epic-web/workshop-utils/config.server";
|
|
10
|
+
import { getAuthInfo, getPreferences, readOnboardingData, requireAuthInfo, deleteDb, setPresencePreferences, PlayerPreferencesSchema, setPlayerPreferences, setAuthInfo, markOnboardingVideoWatched } from "@epic-web/workshop-utils/db.server";
|
|
11
|
+
import { getUserInfo, userHasAccessToWorkshop, getProgress, updateProgress, getEpicVideoInfos } from "@epic-web/workshop-utils/epic-api.server";
|
|
12
|
+
import { getUserId, getSetClientIdCookieHeader } from "@epic-web/workshop-utils/user.server";
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
import { getApps, getExercises, getPlaygroundAppName, extractNumbersAndTypeFromAppNameOrPath, getAppFromFile, getAppByName, isProblemApp, isPlaygroundApp, isExerciseStepApp, getExercise, isSolutionApp, isExampleApp, getRelativePath as getRelativePath$1, workshopRoot, modifiedTimes, getForceFreshForDir, setPlayground, requireExerciseApp, requireExercise, getExerciseApp, getAppDisplayName, getNextExerciseApp, getPrevExerciseApp, getAppPageRoute, getWorkshopFinished, getWorkshopInstructions } from "@epic-web/workshop-utils/apps.server";
|
|
13
15
|
import { getEnv } from "@epic-web/workshop-utils/env.server";
|
|
14
16
|
import { makeTimings, getServerTimeHeader, combineServerTimings, time } from "@epic-web/workshop-utils/timing.server";
|
|
15
17
|
import { cssBundleHref } from "@remix-run/css-bundle";
|
|
@@ -20,7 +22,7 @@ import { ClientOnly } from "remix-utils/client-only";
|
|
|
20
22
|
import slugify from "@sindresorhus/slugify";
|
|
21
23
|
import clsx$1, { clsx } from "clsx";
|
|
22
24
|
import * as React from "react";
|
|
23
|
-
import React__default, { useRef, useEffect, useMemo, useState, createContext, useContext, useSyncExternalStore, forwardRef, useImperativeHandle, Suspense, useReducer } from "react";
|
|
25
|
+
import React__default, { useRef, useEffect, useMemo, useState, createContext, useContext, useCallback, useSyncExternalStore, forwardRef, useImperativeHandle, Suspense, useReducer } from "react";
|
|
24
26
|
import { extendTailwindMerge } from "tailwind-merge";
|
|
25
27
|
import { Toaster, toast } from "sonner";
|
|
26
28
|
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
@@ -33,10 +35,8 @@ import { clientHint as clientHint$1 } from "@epic-web/client-hints/time-zone";
|
|
|
33
35
|
import { safeRedirect } from "remix-utils/safe-redirect";
|
|
34
36
|
import { ServerOnly } from "remix-utils/server-only";
|
|
35
37
|
import * as cookie from "cookie";
|
|
36
|
-
import cookie__default from "cookie";
|
|
37
|
-
import md5 from "md5-hex";
|
|
38
|
-
import { createId } from "@paralleldrive/cuid2";
|
|
39
38
|
import { usePartySocket } from "partysocket/react";
|
|
39
|
+
import { createId } from "@paralleldrive/cuid2";
|
|
40
40
|
import { motion, useAnimationControls } from "framer-motion";
|
|
41
41
|
import { useHydrated } from "remix-utils/use-hydrated";
|
|
42
42
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
@@ -74,6 +74,7 @@ import { useEventSource } from "remix-utils/sse/react";
|
|
|
74
74
|
import { eventStream } from "remix-utils/sse/server";
|
|
75
75
|
import { EventEmitter } from "events";
|
|
76
76
|
import { remember } from "@epic-web/remember";
|
|
77
|
+
import md5 from "md5-hex";
|
|
77
78
|
import { Issuer } from "openid-client";
|
|
78
79
|
import inspector from "node:inspector";
|
|
79
80
|
import { getCommitInfo, getLatestWorkshopAppVersion } from "@epic-web/workshop-utils/git.server";
|
|
@@ -148,15 +149,18 @@ const MessageSchema = z.object({
|
|
|
148
149
|
);
|
|
149
150
|
const PresenceSchema = z.object({ users: z.array(UserSchema) });
|
|
150
151
|
const presenceCache = makeSingletonCache("PresenceCache");
|
|
151
|
-
async function getPresentUsers(
|
|
152
|
-
|
|
152
|
+
async function getPresentUsers({
|
|
153
|
+
timings,
|
|
154
|
+
request
|
|
155
|
+
} = {}) {
|
|
156
|
+
const presence = await cachified({
|
|
153
157
|
key: "presence",
|
|
154
158
|
cache: presenceCache,
|
|
155
159
|
timings,
|
|
156
160
|
request,
|
|
157
|
-
ttl: 1e3 *
|
|
161
|
+
ttl: 1e3 * 2,
|
|
158
162
|
swr: 1e3 * 60 * 60 * 24,
|
|
159
|
-
checkValue:
|
|
163
|
+
checkValue: PresenceSchema,
|
|
160
164
|
async getFreshValue(context) {
|
|
161
165
|
try {
|
|
162
166
|
const response = await Promise.race([
|
|
@@ -175,20 +179,53 @@ async function getPresentUsers(user, { timings, request } = {}) {
|
|
|
175
179
|
`Unexpected response from partykit: ${response.status} ${response.statusText}`
|
|
176
180
|
);
|
|
177
181
|
}
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
const users = presence.users;
|
|
181
|
-
if ((preferences == null ? void 0 : preferences.presence.optOut) ?? !user) {
|
|
182
|
-
return uniqueUsers(users.filter((u) => u.id !== (user == null ? void 0 : user.id)));
|
|
183
|
-
} else {
|
|
184
|
-
return uniqueUsers([...users, user]);
|
|
185
|
-
}
|
|
182
|
+
const presence2 = PresenceSchema.parse(await response.json());
|
|
183
|
+
return presence2;
|
|
186
184
|
} catch {
|
|
187
185
|
context.metadata.ttl = 300;
|
|
188
|
-
return [];
|
|
186
|
+
return { users: [] };
|
|
189
187
|
}
|
|
190
188
|
}
|
|
191
189
|
});
|
|
190
|
+
const { users } = presence;
|
|
191
|
+
const authInfo = await getAuthInfo();
|
|
192
|
+
const userId = request ? (await getUserId({ request })).id : (authInfo == null ? void 0 : authInfo.id) ?? null;
|
|
193
|
+
const preferences = await getPreferences();
|
|
194
|
+
if ((preferences == null ? void 0 : preferences.presence.optOut) || !userId) {
|
|
195
|
+
return uniqueUsers(users.filter((u) => u.id !== userId));
|
|
196
|
+
} else {
|
|
197
|
+
const user = { id: userId };
|
|
198
|
+
const config = getWorkshopConfig();
|
|
199
|
+
const url = request ? new URL(request.url) : void 0;
|
|
200
|
+
user.location = {
|
|
201
|
+
workshopTitle: config.title,
|
|
202
|
+
origin: url ? url.origin : void 0
|
|
203
|
+
};
|
|
204
|
+
if (url) {
|
|
205
|
+
if (url.pathname.startsWith("/exercise/")) {
|
|
206
|
+
const [exerciseNumber, stepNumber, type] = url.pathname.split("/").slice(2);
|
|
207
|
+
user.location.exercise = {
|
|
208
|
+
exerciseNumber: isNaN(Number(exerciseNumber)) ? null : Number(exerciseNumber),
|
|
209
|
+
stepNumber: isNaN(Number(stepNumber)) ? null : Number(stepNumber),
|
|
210
|
+
type: type === "problem" ? "problem" : type === "solution" ? "solution" : null
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (authInfo) {
|
|
215
|
+
const [userInfo, hasAccess] = await Promise.all([
|
|
216
|
+
getUserInfo({ request, timings }),
|
|
217
|
+
userHasAccessToWorkshop({ request, timings })
|
|
218
|
+
]);
|
|
219
|
+
Object.assign(user, {
|
|
220
|
+
name: userInfo == null ? void 0 : userInfo.name,
|
|
221
|
+
avatarUrl: userInfo == null ? void 0 : userInfo.imageUrlLarge,
|
|
222
|
+
imageUrlSmall: userInfo == null ? void 0 : userInfo.imageUrlSmall,
|
|
223
|
+
imageUrlLarge: userInfo == null ? void 0 : userInfo.imageUrlLarge,
|
|
224
|
+
hasAccess
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
return uniqueUsers([...users, user]);
|
|
228
|
+
}
|
|
192
229
|
}
|
|
193
230
|
function uniqueUsers(users) {
|
|
194
231
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -903,495 +940,6 @@ function createConfettiHeaders(value = String(Date.now())) {
|
|
|
903
940
|
})
|
|
904
941
|
});
|
|
905
942
|
}
|
|
906
|
-
const Transcript = z.string().nullable().optional().transform((s) => s ?? "Transcripts not available");
|
|
907
|
-
const EpicVideoInfoSchema = z.object({
|
|
908
|
-
transcript: Transcript,
|
|
909
|
-
muxPlaybackId: z.string()
|
|
910
|
-
});
|
|
911
|
-
const EpicVideoRegionRestrictedErrorSchema = z.object({
|
|
912
|
-
requestCountry: z.string(),
|
|
913
|
-
restrictedCountry: z.string(),
|
|
914
|
-
isRegionRestricted: z.literal(true)
|
|
915
|
-
});
|
|
916
|
-
const CachedEpicVideoInfoSchema = z.object({
|
|
917
|
-
transcript: Transcript,
|
|
918
|
-
muxPlaybackId: z.string(),
|
|
919
|
-
status: z.literal("success"),
|
|
920
|
-
statusCode: z.number(),
|
|
921
|
-
statusText: z.string()
|
|
922
|
-
}).or(
|
|
923
|
-
z.object({
|
|
924
|
-
status: z.literal("error"),
|
|
925
|
-
statusCode: z.number(),
|
|
926
|
-
statusText: z.string(),
|
|
927
|
-
type: z.literal("unknown")
|
|
928
|
-
})
|
|
929
|
-
).or(
|
|
930
|
-
z.object({
|
|
931
|
-
status: z.literal("error"),
|
|
932
|
-
statusCode: z.number(),
|
|
933
|
-
statusText: z.string(),
|
|
934
|
-
type: z.literal("region-restricted"),
|
|
935
|
-
requestCountry: z.string(),
|
|
936
|
-
restrictedCountry: z.string()
|
|
937
|
-
})
|
|
938
|
-
).or(z.null());
|
|
939
|
-
async function getEpicVideoInfos(epicWebUrls, { request, timings } = {}) {
|
|
940
|
-
if (!epicWebUrls) return {};
|
|
941
|
-
const authInfo = await getAuthInfo();
|
|
942
|
-
if (ENV.EPICSHOP_DEPLOYED) return {};
|
|
943
|
-
const epicVideoInfos = {};
|
|
944
|
-
for (const epicVideoEmbed of epicWebUrls) {
|
|
945
|
-
const epicVideoInfo = await getEpicVideoInfo({
|
|
946
|
-
epicVideoEmbed,
|
|
947
|
-
accessToken: authInfo == null ? void 0 : authInfo.tokenSet.access_token,
|
|
948
|
-
request,
|
|
949
|
-
timings
|
|
950
|
-
});
|
|
951
|
-
if (epicVideoInfo) {
|
|
952
|
-
epicVideoInfos[epicVideoEmbed] = epicVideoInfo;
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
return epicVideoInfos;
|
|
956
|
-
}
|
|
957
|
-
async function getEpicVideoInfo({
|
|
958
|
-
epicVideoEmbed,
|
|
959
|
-
accessToken,
|
|
960
|
-
request,
|
|
961
|
-
timings
|
|
962
|
-
}) {
|
|
963
|
-
const tokenPortion = accessToken ? md5(accessToken) : "unauthenticated";
|
|
964
|
-
const key = `epic-video-info:${tokenPortion}:${epicVideoEmbed}`;
|
|
965
|
-
return cachified({
|
|
966
|
-
key,
|
|
967
|
-
request,
|
|
968
|
-
cache: fsCache,
|
|
969
|
-
timings,
|
|
970
|
-
ttl: 1e3 * 60 * 60,
|
|
971
|
-
swr: 1e3 * 60 * 60 * 24 * 30,
|
|
972
|
-
checkValue: CachedEpicVideoInfoSchema,
|
|
973
|
-
async getFreshValue(context) {
|
|
974
|
-
const epicUrl = new URL(epicVideoEmbed);
|
|
975
|
-
if (epicUrl.host !== "www.epicweb.dev" && epicUrl.host !== "www.epicreact.dev") {
|
|
976
|
-
return null;
|
|
977
|
-
}
|
|
978
|
-
if (epicUrl.pathname.startsWith("/tutorials/")) {
|
|
979
|
-
epicUrl.pathname = epicUrl.pathname.replace(
|
|
980
|
-
/^\/tutorials\//,
|
|
981
|
-
"/workshops/"
|
|
982
|
-
);
|
|
983
|
-
}
|
|
984
|
-
const infoResponse = await fetch(
|
|
985
|
-
`https://${epicUrl.host}/api${epicUrl.pathname}`,
|
|
986
|
-
accessToken ? { headers: { authorization: `Bearer ${accessToken}` } } : void 0
|
|
987
|
-
);
|
|
988
|
-
const { status, statusText } = infoResponse;
|
|
989
|
-
if (infoResponse.status >= 200 && infoResponse.status < 300) {
|
|
990
|
-
const rawInfo = await infoResponse.json();
|
|
991
|
-
const infoResult = EpicVideoInfoSchema.safeParse(rawInfo);
|
|
992
|
-
if (infoResult.success) {
|
|
993
|
-
return {
|
|
994
|
-
status: "success",
|
|
995
|
-
statusCode: status,
|
|
996
|
-
statusText,
|
|
997
|
-
...infoResult.data
|
|
998
|
-
};
|
|
999
|
-
} else {
|
|
1000
|
-
context.metadata.ttl = 1e3 * 2;
|
|
1001
|
-
context.metadata.swr = 0;
|
|
1002
|
-
const restrictedResult = EpicVideoRegionRestrictedErrorSchema.safeParse(rawInfo);
|
|
1003
|
-
if (restrictedResult.success) {
|
|
1004
|
-
return {
|
|
1005
|
-
status: "error",
|
|
1006
|
-
statusCode: status,
|
|
1007
|
-
statusText,
|
|
1008
|
-
type: "region-restricted",
|
|
1009
|
-
...restrictedResult.data
|
|
1010
|
-
};
|
|
1011
|
-
} else {
|
|
1012
|
-
console.warn(
|
|
1013
|
-
`Response from EpicWeb for "${epicUrl.pathname}" does not match expectation`,
|
|
1014
|
-
infoResult.error
|
|
1015
|
-
);
|
|
1016
|
-
return {
|
|
1017
|
-
status: "error",
|
|
1018
|
-
statusCode: 500,
|
|
1019
|
-
statusText: "API Data Type Mismatch",
|
|
1020
|
-
type: "unknown"
|
|
1021
|
-
};
|
|
1022
|
-
}
|
|
1023
|
-
}
|
|
1024
|
-
} else {
|
|
1025
|
-
context.metadata.ttl = 1e3 * 2;
|
|
1026
|
-
context.metadata.swr = 0;
|
|
1027
|
-
return {
|
|
1028
|
-
status: "error",
|
|
1029
|
-
statusCode: status,
|
|
1030
|
-
statusText,
|
|
1031
|
-
type: "unknown"
|
|
1032
|
-
};
|
|
1033
|
-
}
|
|
1034
|
-
}
|
|
1035
|
-
}).catch((e) => {
|
|
1036
|
-
console.error(`Failed to fetch epic video info for ${epicVideoEmbed}`, e);
|
|
1037
|
-
throw e;
|
|
1038
|
-
});
|
|
1039
|
-
}
|
|
1040
|
-
async function getEpicProgress({
|
|
1041
|
-
timings,
|
|
1042
|
-
request,
|
|
1043
|
-
forceFresh
|
|
1044
|
-
} = {}) {
|
|
1045
|
-
if (ENV.EPICSHOP_DEPLOYED) return [];
|
|
1046
|
-
const authInfo = await getAuthInfo();
|
|
1047
|
-
const {
|
|
1048
|
-
product: { host }
|
|
1049
|
-
} = getWorkshopConfig();
|
|
1050
|
-
if (!authInfo) return [];
|
|
1051
|
-
const tokenPart = md5(authInfo.tokenSet.access_token);
|
|
1052
|
-
const EpicProgressSchema = z.array(
|
|
1053
|
-
z.object({
|
|
1054
|
-
lessonId: z.string(),
|
|
1055
|
-
completedAt: z.string().nullable()
|
|
1056
|
-
})
|
|
1057
|
-
);
|
|
1058
|
-
return cachified({
|
|
1059
|
-
key: `epic-progress:${host}:${tokenPart}`,
|
|
1060
|
-
cache: fsCache,
|
|
1061
|
-
request,
|
|
1062
|
-
timings,
|
|
1063
|
-
forceFresh,
|
|
1064
|
-
ttl: 1e3 * 2,
|
|
1065
|
-
swr: 1e3 * 60 * 60 * 24 * 30,
|
|
1066
|
-
checkValue: EpicProgressSchema,
|
|
1067
|
-
async getFreshValue(context) {
|
|
1068
|
-
const response = await fetch(`https://${host}/api/progress`, {
|
|
1069
|
-
headers: {
|
|
1070
|
-
authorization: `Bearer ${authInfo.tokenSet.access_token}`
|
|
1071
|
-
}
|
|
1072
|
-
}).catch((e) => new Response(getErrorMessage(e), { status: 500 }));
|
|
1073
|
-
if (response.status < 200 || response.status >= 300) {
|
|
1074
|
-
console.error(
|
|
1075
|
-
`Failed to fetch progress from EpicWeb: ${response.status} ${response.statusText}`
|
|
1076
|
-
);
|
|
1077
|
-
context.metadata.ttl = 1e3 * 2;
|
|
1078
|
-
context.metadata.swr = 0;
|
|
1079
|
-
return [];
|
|
1080
|
-
}
|
|
1081
|
-
return EpicProgressSchema.parse(await response.json());
|
|
1082
|
-
}
|
|
1083
|
-
});
|
|
1084
|
-
}
|
|
1085
|
-
async function getProgress({
|
|
1086
|
-
timings,
|
|
1087
|
-
request
|
|
1088
|
-
} = {}) {
|
|
1089
|
-
if (ENV.EPICSHOP_DEPLOYED) return [];
|
|
1090
|
-
const authInfo = await getAuthInfo();
|
|
1091
|
-
if (!authInfo) return [];
|
|
1092
|
-
const {
|
|
1093
|
-
product: { slug, host }
|
|
1094
|
-
} = getWorkshopConfig();
|
|
1095
|
-
if (!slug) return [];
|
|
1096
|
-
const [
|
|
1097
|
-
workshopData,
|
|
1098
|
-
epicProgress,
|
|
1099
|
-
workshopInstructions,
|
|
1100
|
-
workshopFinished,
|
|
1101
|
-
exercises
|
|
1102
|
-
] = await Promise.all([
|
|
1103
|
-
getWorkshopData(slug, { request, timings }),
|
|
1104
|
-
getEpicProgress({ request, timings }),
|
|
1105
|
-
getWorkshopInstructions({ request }),
|
|
1106
|
-
getWorkshopFinished({ request }),
|
|
1107
|
-
getExercises({ request, timings })
|
|
1108
|
-
]);
|
|
1109
|
-
const progress = [];
|
|
1110
|
-
for (const resource of workshopData.resources) {
|
|
1111
|
-
const lessons = resource._type === "section" ? resource.lessons : [resource];
|
|
1112
|
-
for (const lesson of lessons) {
|
|
1113
|
-
const epicLessonSlug = lesson.slug;
|
|
1114
|
-
const lessonProgress = epicProgress.find(
|
|
1115
|
-
({ lessonId }) => lessonId === lesson._id
|
|
1116
|
-
);
|
|
1117
|
-
const epicCompletedAt = lessonProgress ? lessonProgress.completedAt : null;
|
|
1118
|
-
const progressForLesson = getProgressForLesson(epicLessonSlug, {
|
|
1119
|
-
workshopInstructions,
|
|
1120
|
-
workshopFinished,
|
|
1121
|
-
exercises
|
|
1122
|
-
});
|
|
1123
|
-
const epicLessonUrl = `https://${host}/workshops/${slug}/${epicLessonSlug}`;
|
|
1124
|
-
if (progressForLesson) {
|
|
1125
|
-
progress.push({
|
|
1126
|
-
...progressForLesson,
|
|
1127
|
-
epicLessonUrl,
|
|
1128
|
-
epicLessonSlug,
|
|
1129
|
-
epicCompletedAt
|
|
1130
|
-
});
|
|
1131
|
-
} else {
|
|
1132
|
-
progress.push({
|
|
1133
|
-
type: "unknown",
|
|
1134
|
-
epicLessonUrl,
|
|
1135
|
-
epicLessonSlug,
|
|
1136
|
-
epicCompletedAt
|
|
1137
|
-
});
|
|
1138
|
-
}
|
|
1139
|
-
}
|
|
1140
|
-
}
|
|
1141
|
-
return progress;
|
|
1142
|
-
}
|
|
1143
|
-
function getProgressForLesson(epicLessonSlug, {
|
|
1144
|
-
workshopInstructions,
|
|
1145
|
-
workshopFinished,
|
|
1146
|
-
exercises
|
|
1147
|
-
}) {
|
|
1148
|
-
var _a;
|
|
1149
|
-
const hasEmbed = (embed) => embed == null ? void 0 : embed.some((e) => e.split("/").at(-1) === epicLessonSlug);
|
|
1150
|
-
if (workshopInstructions.compiled.status === "success" && hasEmbed(workshopInstructions.compiled.epicVideoEmbeds)) {
|
|
1151
|
-
return { type: "workshop-instructions" };
|
|
1152
|
-
}
|
|
1153
|
-
if (workshopFinished.compiled.status === "success" && hasEmbed(workshopFinished.compiled.epicVideoEmbeds)) {
|
|
1154
|
-
return { type: "workshop-finished" };
|
|
1155
|
-
}
|
|
1156
|
-
for (const exercise of exercises) {
|
|
1157
|
-
if (hasEmbed(exercise.instructionsEpicVideoEmbeds)) {
|
|
1158
|
-
return {
|
|
1159
|
-
type: "instructions",
|
|
1160
|
-
exerciseNumber: exercise.exerciseNumber
|
|
1161
|
-
};
|
|
1162
|
-
}
|
|
1163
|
-
if (hasEmbed(exercise.finishedEpicVideoEmbeds)) {
|
|
1164
|
-
return {
|
|
1165
|
-
type: "finished",
|
|
1166
|
-
exerciseNumber: exercise.exerciseNumber
|
|
1167
|
-
};
|
|
1168
|
-
}
|
|
1169
|
-
for (const step of exercise.steps.filter(Boolean)) {
|
|
1170
|
-
if (hasEmbed((_a = step.problem) == null ? void 0 : _a.epicVideoEmbeds)) {
|
|
1171
|
-
return {
|
|
1172
|
-
type: "step",
|
|
1173
|
-
exerciseNumber: exercise.exerciseNumber,
|
|
1174
|
-
stepNumber: step.stepNumber
|
|
1175
|
-
};
|
|
1176
|
-
}
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
}
|
|
1180
|
-
async function updateProgress({ lessonSlug, complete }, {
|
|
1181
|
-
timings,
|
|
1182
|
-
request
|
|
1183
|
-
} = {}) {
|
|
1184
|
-
if (ENV.EPICSHOP_DEPLOYED) {
|
|
1185
|
-
return {
|
|
1186
|
-
status: "error",
|
|
1187
|
-
error: "cannot update progress when deployed"
|
|
1188
|
-
};
|
|
1189
|
-
}
|
|
1190
|
-
const authInfo = await getAuthInfo();
|
|
1191
|
-
if (!authInfo) {
|
|
1192
|
-
return { status: "error", error: "not authenticated" };
|
|
1193
|
-
}
|
|
1194
|
-
const {
|
|
1195
|
-
product: { host }
|
|
1196
|
-
} = getWorkshopConfig();
|
|
1197
|
-
const response = await fetch(`https://${host}/api/progress`, {
|
|
1198
|
-
method: "POST",
|
|
1199
|
-
headers: {
|
|
1200
|
-
authorization: `Bearer ${authInfo.tokenSet.access_token}`,
|
|
1201
|
-
"content-type": "application/json"
|
|
1202
|
-
},
|
|
1203
|
-
body: JSON.stringify(
|
|
1204
|
-
complete ? { lessonSlug } : { lessonSlug, remove: true }
|
|
1205
|
-
)
|
|
1206
|
-
}).catch((e) => new Response(getErrorMessage(e), { status: 500 }));
|
|
1207
|
-
await getEpicProgress({ forceFresh: true, request, timings });
|
|
1208
|
-
if (response.status < 200 || response.status >= 300) {
|
|
1209
|
-
return {
|
|
1210
|
-
status: "error",
|
|
1211
|
-
error: `${response.status} ${response.statusText}`
|
|
1212
|
-
};
|
|
1213
|
-
}
|
|
1214
|
-
return { status: "success" };
|
|
1215
|
-
}
|
|
1216
|
-
const ModuleSchema = z.object({
|
|
1217
|
-
resources: z.array(
|
|
1218
|
-
z.union([
|
|
1219
|
-
z.object({
|
|
1220
|
-
_type: z.literal("lesson"),
|
|
1221
|
-
_id: z.string(),
|
|
1222
|
-
slug: z.string()
|
|
1223
|
-
}),
|
|
1224
|
-
z.object({
|
|
1225
|
-
_type: z.literal("section"),
|
|
1226
|
-
lessons: z.array(z.object({ _id: z.string(), slug: z.string() }))
|
|
1227
|
-
})
|
|
1228
|
-
])
|
|
1229
|
-
)
|
|
1230
|
-
});
|
|
1231
|
-
async function getWorkshopData(slug, {
|
|
1232
|
-
timings,
|
|
1233
|
-
request,
|
|
1234
|
-
forceFresh
|
|
1235
|
-
} = {}) {
|
|
1236
|
-
if (ENV.EPICSHOP_DEPLOYED) return { resources: [] };
|
|
1237
|
-
const authInfo = await getAuthInfo();
|
|
1238
|
-
if (!authInfo) return { resources: [] };
|
|
1239
|
-
const {
|
|
1240
|
-
product: { host }
|
|
1241
|
-
} = getWorkshopConfig();
|
|
1242
|
-
return cachified({
|
|
1243
|
-
key: `epic-workshop-data:${host}:${slug}`,
|
|
1244
|
-
cache: fsCache,
|
|
1245
|
-
request,
|
|
1246
|
-
forceFresh,
|
|
1247
|
-
timings,
|
|
1248
|
-
checkValue: ModuleSchema,
|
|
1249
|
-
async getFreshValue() {
|
|
1250
|
-
const response = await fetch(
|
|
1251
|
-
`https://${host}/api/workshops/${encodeURIComponent(slug)}`
|
|
1252
|
-
).catch((e) => new Response(getErrorMessage(e), { status: 500 }));
|
|
1253
|
-
if (response.status < 200 || response.status >= 300) {
|
|
1254
|
-
console.error(
|
|
1255
|
-
`Failed to fetch workshop data from EpicWeb for ${slug}: ${response.status} ${response.statusText}`
|
|
1256
|
-
);
|
|
1257
|
-
return { resources: [] };
|
|
1258
|
-
}
|
|
1259
|
-
return ModuleSchema.parse(await response.json());
|
|
1260
|
-
}
|
|
1261
|
-
});
|
|
1262
|
-
}
|
|
1263
|
-
async function userHasAccessToWorkshop({
|
|
1264
|
-
timings,
|
|
1265
|
-
request,
|
|
1266
|
-
forceFresh
|
|
1267
|
-
}) {
|
|
1268
|
-
var _a;
|
|
1269
|
-
const config = getWorkshopConfig();
|
|
1270
|
-
const {
|
|
1271
|
-
product: { host, slug }
|
|
1272
|
-
} = config;
|
|
1273
|
-
if (!slug) return true;
|
|
1274
|
-
if (ENV.EPICSHOP_DEPLOYED) {
|
|
1275
|
-
const cookieHeader = request.headers.get("Cookie");
|
|
1276
|
-
if (!cookieHeader) return false;
|
|
1277
|
-
const cookies = cookie__default.parse(cookieHeader);
|
|
1278
|
-
return ((_a = cookies.skill) == null ? void 0 : _a.split(",").includes(slug)) ?? false;
|
|
1279
|
-
}
|
|
1280
|
-
const authInfo = await getAuthInfo();
|
|
1281
|
-
if (!authInfo) return false;
|
|
1282
|
-
return cachified({
|
|
1283
|
-
key: `user-has-access-to-workshop:${host}:${slug}`,
|
|
1284
|
-
cache: fsCache,
|
|
1285
|
-
request,
|
|
1286
|
-
forceFresh,
|
|
1287
|
-
timings,
|
|
1288
|
-
ttl: 1e3 * 5,
|
|
1289
|
-
checkValue: z.boolean(),
|
|
1290
|
-
async getFreshValue(context) {
|
|
1291
|
-
const response = await fetch(
|
|
1292
|
-
`https://${host}/api/workshops/${encodeURIComponent(slug)}/access`,
|
|
1293
|
-
{
|
|
1294
|
-
headers: {
|
|
1295
|
-
authorization: `Bearer ${authInfo.tokenSet.access_token}`
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
).catch((e) => new Response(getErrorMessage(e), { status: 500 }));
|
|
1299
|
-
const hasAccess = response.ok ? await response.json() === true : false;
|
|
1300
|
-
if (hasAccess) {
|
|
1301
|
-
context.metadata.ttl = 1e3 * 60 * 60 * 24 * 30;
|
|
1302
|
-
context.metadata.swr = 1e3 * 60 * 60 * 24 * 30;
|
|
1303
|
-
}
|
|
1304
|
-
return hasAccess;
|
|
1305
|
-
}
|
|
1306
|
-
});
|
|
1307
|
-
}
|
|
1308
|
-
const UserInfoSchema = z.object({
|
|
1309
|
-
id: z.string(),
|
|
1310
|
-
name: z.string().nullable(),
|
|
1311
|
-
email: z.string().email(),
|
|
1312
|
-
image: z.string().nullable(),
|
|
1313
|
-
discordProfile: z.object({
|
|
1314
|
-
nick: z.string().nullable(),
|
|
1315
|
-
user: z.object({
|
|
1316
|
-
id: z.string(),
|
|
1317
|
-
username: z.string(),
|
|
1318
|
-
avatar: z.string().nullable().optional(),
|
|
1319
|
-
global_name: z.string().nullable().optional()
|
|
1320
|
-
})
|
|
1321
|
-
}).nullable().optional()
|
|
1322
|
-
}).transform((data) => {
|
|
1323
|
-
var _a, _b;
|
|
1324
|
-
return {
|
|
1325
|
-
...data,
|
|
1326
|
-
imageUrlSmall: resizeImageUrl(data.image, { size: 64 }) ?? resolveDiscordAvatar((_a = data.discordProfile) == null ? void 0 : _a.user, {
|
|
1327
|
-
size: 64
|
|
1328
|
-
}) ?? resolveGravatarUrl(data.email, { size: 64 }),
|
|
1329
|
-
imageUrlLarge: resizeImageUrl(data.image, { size: 512 }) ?? resolveDiscordAvatar((_b = data.discordProfile) == null ? void 0 : _b.user, {
|
|
1330
|
-
size: 512
|
|
1331
|
-
}) ?? resolveGravatarUrl(data.email, { size: 512 })
|
|
1332
|
-
};
|
|
1333
|
-
});
|
|
1334
|
-
function resizeImageUrl(url, { size }) {
|
|
1335
|
-
if (!url) return null;
|
|
1336
|
-
const urlObj = new URL(url);
|
|
1337
|
-
urlObj.searchParams.set("size", size.toString());
|
|
1338
|
-
return urlObj.toString();
|
|
1339
|
-
}
|
|
1340
|
-
function resolveGravatarUrl(email, { size }) {
|
|
1341
|
-
if (!email) return null;
|
|
1342
|
-
const hash = md5(email.toLowerCase());
|
|
1343
|
-
const gravatarOptions = new URLSearchParams({
|
|
1344
|
-
size: size.toString(),
|
|
1345
|
-
default: "identicon"
|
|
1346
|
-
});
|
|
1347
|
-
return `https://www.gravatar.com/avatar/${hash}?${gravatarOptions.toString()}`;
|
|
1348
|
-
}
|
|
1349
|
-
function resolveDiscordAvatar(user, { size }) {
|
|
1350
|
-
if (!user) return null;
|
|
1351
|
-
const { avatar, id: userId } = user;
|
|
1352
|
-
if (!avatar) return null;
|
|
1353
|
-
const isGif = avatar.startsWith("a_");
|
|
1354
|
-
const url = new URL(
|
|
1355
|
-
`/avatars/${userId}/${avatar}.${isGif ? "gif" : "png"}`,
|
|
1356
|
-
"https://cdn.discordapp.com"
|
|
1357
|
-
);
|
|
1358
|
-
url.searchParams.set("size", size.toString());
|
|
1359
|
-
return url.toString();
|
|
1360
|
-
}
|
|
1361
|
-
async function getUserInfo({
|
|
1362
|
-
timings,
|
|
1363
|
-
request,
|
|
1364
|
-
forceFresh
|
|
1365
|
-
} = {}) {
|
|
1366
|
-
const authInfo = await getAuthInfo();
|
|
1367
|
-
if (!authInfo) return null;
|
|
1368
|
-
const { tokenSet } = authInfo;
|
|
1369
|
-
const {
|
|
1370
|
-
product: { host }
|
|
1371
|
-
} = getWorkshopConfig();
|
|
1372
|
-
const accessToken = tokenSet.access_token;
|
|
1373
|
-
const url = `https://${host}/oauth/userinfo`;
|
|
1374
|
-
return cachified({
|
|
1375
|
-
key: `${url}:${md5(accessToken)}`,
|
|
1376
|
-
cache: fsCache,
|
|
1377
|
-
request,
|
|
1378
|
-
forceFresh,
|
|
1379
|
-
timings,
|
|
1380
|
-
ttl: 1e3 * 60 * 1,
|
|
1381
|
-
swr: 1e3 * 60 * 60 * 24 * 365,
|
|
1382
|
-
checkValue: UserInfoSchema,
|
|
1383
|
-
async getFreshValue() {
|
|
1384
|
-
const response = await fetch(url, {
|
|
1385
|
-
headers: { authorization: `Bearer ${accessToken}` }
|
|
1386
|
-
});
|
|
1387
|
-
if (!response.ok) {
|
|
1388
|
-
throw new Error(`Failed to fetch user info: ${response.statusText}`);
|
|
1389
|
-
}
|
|
1390
|
-
const data = await response.json();
|
|
1391
|
-
return UserInfoSchema.parse(data);
|
|
1392
|
-
}
|
|
1393
|
-
});
|
|
1394
|
-
}
|
|
1395
943
|
const PresenceContext = createContext(null);
|
|
1396
944
|
function usePresencePreferences() {
|
|
1397
945
|
var _a;
|
|
@@ -1407,35 +955,51 @@ const ExerciseAppParamsSchema = z.object({
|
|
|
1407
955
|
exerciseNumber: z.coerce.number().finite(),
|
|
1408
956
|
stepNumber: z.coerce.number().finite().optional()
|
|
1409
957
|
});
|
|
958
|
+
function useFirstCallDelayedCallback(cb, delay) {
|
|
959
|
+
const [timedPromise] = useState(
|
|
960
|
+
() => new Promise((resolve) => setTimeout(resolve, delay))
|
|
961
|
+
);
|
|
962
|
+
const mounted = useRef(true);
|
|
963
|
+
const currentCallRef = useRef(null);
|
|
964
|
+
const lastCbRef = useRef(cb);
|
|
965
|
+
useEffect(() => {
|
|
966
|
+
lastCbRef.current = cb;
|
|
967
|
+
}, [cb]);
|
|
968
|
+
const delayedCb = useCallback(
|
|
969
|
+
(...args) => {
|
|
970
|
+
const thisOne = Symbol();
|
|
971
|
+
currentCallRef.current = thisOne;
|
|
972
|
+
void timedPromise.then(() => {
|
|
973
|
+
if (!mounted.current) return;
|
|
974
|
+
if (currentCallRef.current !== thisOne) {
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
lastCbRef.current(...args);
|
|
978
|
+
});
|
|
979
|
+
},
|
|
980
|
+
[timedPromise]
|
|
981
|
+
);
|
|
982
|
+
return delayedCb;
|
|
983
|
+
}
|
|
1410
984
|
function usePresenceSocket(user) {
|
|
1411
985
|
const workshopTitle = useOptionalWorkshopTitle();
|
|
1412
|
-
const { userHasAccess = false } = useRouteLoaderData("root") ?? {};
|
|
986
|
+
const { userHasAccess = false, userId } = useRouteLoaderData("root") ?? {};
|
|
1413
987
|
const requestInfo = useRequestInfo();
|
|
1414
988
|
const rawParams = useParams();
|
|
1415
989
|
const prefs = usePresencePreferences();
|
|
1416
990
|
const data = useRouteLoaderData("root");
|
|
1417
991
|
const [users, setUsers] = useState((data == null ? void 0 : data.presence.users) ?? []);
|
|
1418
|
-
const
|
|
1419
|
-
|
|
1420
|
-
if (
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
return newClientId;
|
|
1426
|
-
});
|
|
992
|
+
const handleMessage = useFirstCallDelayedCallback((evt) => {
|
|
993
|
+
const messageResult = MessageSchema.safeParse(JSON.parse(String(evt.data)));
|
|
994
|
+
if (!messageResult.success) return;
|
|
995
|
+
if (messageResult.data.type === "presence") {
|
|
996
|
+
setUsers(messageResult.data.payload.users);
|
|
997
|
+
}
|
|
998
|
+
}, 2e3);
|
|
1427
999
|
const socket = usePartySocket({
|
|
1428
1000
|
host: new URL(partykitBaseUrl).host,
|
|
1429
1001
|
room: partykitRoom,
|
|
1430
|
-
onMessage
|
|
1431
|
-
const messageResult = MessageSchema.safeParse(
|
|
1432
|
-
JSON.parse(String(evt.data))
|
|
1433
|
-
);
|
|
1434
|
-
if (!messageResult.success) return;
|
|
1435
|
-
if (messageResult.data.type === "presence") {
|
|
1436
|
-
setUsers(messageResult.data.payload.users);
|
|
1437
|
-
}
|
|
1438
|
-
}
|
|
1002
|
+
onMessage: handleMessage
|
|
1439
1003
|
});
|
|
1440
1004
|
const paramsResult = ExerciseAppParamsSchema.safeParse(rawParams);
|
|
1441
1005
|
const params = paramsResult.success ? paramsResult.data : null;
|
|
@@ -1451,54 +1015,58 @@ function usePresenceSocket(user) {
|
|
|
1451
1015
|
} : null
|
|
1452
1016
|
};
|
|
1453
1017
|
let message = null;
|
|
1454
|
-
if (
|
|
1455
|
-
if (
|
|
1018
|
+
if (user) {
|
|
1019
|
+
if (prefs == null ? void 0 : prefs.optOut) {
|
|
1456
1020
|
message = { type: "remove-user", payload: { id: user.id } };
|
|
1021
|
+
} else {
|
|
1022
|
+
message = {
|
|
1023
|
+
type: "add-user",
|
|
1024
|
+
payload: {
|
|
1025
|
+
id: user.id,
|
|
1026
|
+
name: user.name,
|
|
1027
|
+
hasAccess: userHasAccess,
|
|
1028
|
+
imageUrlSmall: user.imageUrlSmall,
|
|
1029
|
+
imageUrlLarge: user.imageUrlLarge,
|
|
1030
|
+
location
|
|
1031
|
+
}
|
|
1032
|
+
};
|
|
1457
1033
|
}
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
message = {
|
|
1461
|
-
type: "add-user",
|
|
1462
|
-
payload: {
|
|
1463
|
-
id: user.id,
|
|
1464
|
-
name: user.name,
|
|
1465
|
-
hasAccess: userHasAccess,
|
|
1466
|
-
imageUrlSmall: user.imageUrlSmall,
|
|
1467
|
-
imageUrlLarge: user.imageUrlLarge,
|
|
1468
|
-
location
|
|
1469
|
-
}
|
|
1470
|
-
};
|
|
1034
|
+
} else if (userId == null ? void 0 : userId.id) {
|
|
1035
|
+
message = { type: "add-user", payload: { id: userId.id, location } };
|
|
1471
1036
|
}
|
|
1472
1037
|
const messageJson = message ? JSON.stringify(message) : null;
|
|
1473
1038
|
useEffect(() => {
|
|
1474
1039
|
if (messageJson) socket.send(messageJson);
|
|
1475
1040
|
}, [messageJson, socket]);
|
|
1476
|
-
const scoredUsers = scoreUsers(location, users);
|
|
1041
|
+
const scoredUsers = scoreUsers({ id: userId == null ? void 0 : userId.id, location }, users);
|
|
1477
1042
|
return { users: scoredUsers };
|
|
1478
1043
|
}
|
|
1479
|
-
function scoreUsers(
|
|
1480
|
-
const
|
|
1044
|
+
function scoreUsers(user, users) {
|
|
1045
|
+
const { location } = user;
|
|
1046
|
+
const scoredUsers = users.map((user2) => {
|
|
1481
1047
|
var _a, _b, _c, _d;
|
|
1482
1048
|
let score = 0;
|
|
1483
1049
|
const available = 5;
|
|
1484
|
-
if (
|
|
1050
|
+
if (user2.hasAccess) {
|
|
1485
1051
|
score += 1;
|
|
1486
1052
|
}
|
|
1487
|
-
if ((location == null ? void 0 : location.workshopTitle) === ((_a =
|
|
1053
|
+
if ((location == null ? void 0 : location.workshopTitle) === ((_a = user2.location) == null ? void 0 : _a.workshopTitle)) {
|
|
1488
1054
|
score += 1;
|
|
1489
|
-
if (((_b = location == null ? void 0 : location.exercise) == null ? void 0 : _b.exerciseNumber) && location.exercise.exerciseNumber === ((_d = (_c =
|
|
1055
|
+
if (((_b = location == null ? void 0 : location.exercise) == null ? void 0 : _b.exerciseNumber) && location.exercise.exerciseNumber === ((_d = (_c = user2.location) == null ? void 0 : _c.exercise) == null ? void 0 : _d.exerciseNumber)) {
|
|
1490
1056
|
score += 1;
|
|
1491
|
-
if (location.exercise.stepNumber && location.exercise.stepNumber ===
|
|
1057
|
+
if (location.exercise.stepNumber && location.exercise.stepNumber === user2.location.exercise.stepNumber) {
|
|
1492
1058
|
score += 1;
|
|
1493
|
-
if (location.exercise.type && location.exercise.type ===
|
|
1059
|
+
if (location.exercise.type && location.exercise.type === user2.location.exercise.type) {
|
|
1494
1060
|
score += 1;
|
|
1495
1061
|
}
|
|
1496
1062
|
}
|
|
1497
1063
|
}
|
|
1498
1064
|
}
|
|
1499
|
-
return { user, score: Math.floor(score / available * 10) / 10 };
|
|
1065
|
+
return { user: user2, score: Math.floor(score / available * 10) / 10 };
|
|
1500
1066
|
});
|
|
1501
1067
|
return scoredUsers.sort((a, b) => {
|
|
1068
|
+
if (a.user.id === (user == null ? void 0 : user.id)) return -1;
|
|
1069
|
+
if (b.user.id === (user == null ? void 0 : user.id)) return 1;
|
|
1502
1070
|
if (a.score === b.score) return 0;
|
|
1503
1071
|
return a.score > b.score ? -1 : 1;
|
|
1504
1072
|
});
|
|
@@ -1622,6 +1190,7 @@ const meta$6 = ({ data: data2 }) => {
|
|
|
1622
1190
|
});
|
|
1623
1191
|
};
|
|
1624
1192
|
async function loader$x({ request }) {
|
|
1193
|
+
var _a;
|
|
1625
1194
|
const timings = makeTimings("rootLoader");
|
|
1626
1195
|
const workshopConfig = getWorkshopConfig();
|
|
1627
1196
|
const {
|
|
@@ -1640,6 +1209,7 @@ async function loader$x({ request }) {
|
|
|
1640
1209
|
const { confettiId, headers: confettiHeaders } = getConfetti(request);
|
|
1641
1210
|
const { toast: toast2, headers: toastHeaders } = await getToast(request);
|
|
1642
1211
|
const asyncStuff = await promiseHash({
|
|
1212
|
+
userId: getUserId({ request }),
|
|
1643
1213
|
preferences: getPreferences(),
|
|
1644
1214
|
progress: getProgress({ timings }).catch((e) => {
|
|
1645
1215
|
console.error("Failed to get progress", e);
|
|
@@ -1650,7 +1220,7 @@ async function loader$x({ request }) {
|
|
|
1650
1220
|
userHasAccess: userHasAccessToWorkshop({ request, timings }),
|
|
1651
1221
|
apps: getApps({ request, timings })
|
|
1652
1222
|
});
|
|
1653
|
-
const presentUsers = await getPresentUsers(
|
|
1223
|
+
const presentUsers = await getPresentUsers({
|
|
1654
1224
|
request,
|
|
1655
1225
|
timings
|
|
1656
1226
|
});
|
|
@@ -1685,19 +1255,15 @@ async function loader$x({ request }) {
|
|
|
1685
1255
|
}
|
|
1686
1256
|
},
|
|
1687
1257
|
{
|
|
1688
|
-
headers: combineHeaders(
|
|
1689
|
-
|
|
1690
|
-
|
|
1258
|
+
headers: combineHeaders(
|
|
1259
|
+
toastHeaders,
|
|
1260
|
+
confettiHeaders,
|
|
1261
|
+
{ "Server-Timing": timings.toString() },
|
|
1262
|
+
((_a = asyncStuff.userId) == null ? void 0 : _a.type) === "cookie.randomId" ? { "Set-Cookie": getSetClientIdCookieHeader(asyncStuff.userId.id) } : void 0
|
|
1263
|
+
)
|
|
1691
1264
|
}
|
|
1692
1265
|
);
|
|
1693
1266
|
}
|
|
1694
|
-
const headers$c = ({ loaderHeaders }) => {
|
|
1695
|
-
const headers2 = {
|
|
1696
|
-
"Cache-Control": loaderHeaders.get("Cache-Control") ?? "",
|
|
1697
|
-
"Server-Timing": loaderHeaders.get("Server-Timing") ?? ""
|
|
1698
|
-
};
|
|
1699
|
-
return headers2;
|
|
1700
|
-
};
|
|
1701
1267
|
function Document({
|
|
1702
1268
|
children,
|
|
1703
1269
|
env = {},
|
|
@@ -1765,7 +1331,6 @@ const route0 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
|
|
|
1765
1331
|
__proto__: null,
|
|
1766
1332
|
ErrorBoundary: ErrorBoundary$6,
|
|
1767
1333
|
default: AppWithProviders,
|
|
1768
|
-
headers: headers$c,
|
|
1769
1334
|
links,
|
|
1770
1335
|
loader: loader$x,
|
|
1771
1336
|
meta: meta$6
|
|
@@ -2359,7 +1924,7 @@ const route38 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
2359
1924
|
useRequireEpicProgress
|
|
2360
1925
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2361
1926
|
async function loader$v({ request }) {
|
|
2362
|
-
var _a;
|
|
1927
|
+
var _a, _b;
|
|
2363
1928
|
const timings = makeTimings("appLayoutLoader");
|
|
2364
1929
|
const { title: workshopTitle } = getWorkshopConfig();
|
|
2365
1930
|
const [exercises, playgroundAppName] = await Promise.all([
|
|
@@ -2394,7 +1959,8 @@ async function loader$v({ request }) {
|
|
|
2394
1959
|
name: (problem == null ? void 0 : problem.name) ?? (solution == null ? void 0 : solution.name) ?? "Unknown"
|
|
2395
1960
|
}))
|
|
2396
1961
|
})),
|
|
2397
|
-
playground
|
|
1962
|
+
playground,
|
|
1963
|
+
isMenuOpened: ((_b = request.headers.get("cookie")) == null ? void 0 : _b.includes("es_menu_open=true")) ?? false
|
|
2398
1964
|
},
|
|
2399
1965
|
{
|
|
2400
1966
|
headers: {
|
|
@@ -2540,11 +2106,16 @@ function FacePile({ isMenuOpened }) {
|
|
|
2540
2106
|
}
|
|
2541
2107
|
const useIsWide = makeMediaQueryStore("(min-width: 640px)", true);
|
|
2542
2108
|
function App() {
|
|
2109
|
+
const data2 = useLoaderData();
|
|
2543
2110
|
const user = useOptionalUser();
|
|
2544
2111
|
const isWide = useIsWide();
|
|
2545
2112
|
const isHydrated = useHydrated();
|
|
2546
|
-
const [isMenuOpened,
|
|
2113
|
+
const [isMenuOpened, setMenuOpenedState] = React.useState(data2.isMenuOpened);
|
|
2547
2114
|
useRevalidationWS({ watchPaths: ["./exercises/README.mdx"] });
|
|
2115
|
+
function setMenuOpened(value) {
|
|
2116
|
+
setMenuOpenedState(value);
|
|
2117
|
+
document.cookie = `es_menu_open=${value.toString()}; path=/; SameSite=Lax;`;
|
|
2118
|
+
}
|
|
2548
2119
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
2549
2120
|
user ? null : /* @__PURE__ */ jsx(NoUserBanner, {}),
|
|
2550
2121
|
isHydrated && isWide ? null : /* @__PURE__ */ jsx(
|
|
@@ -2599,6 +2170,7 @@ function NoUserBanner() {
|
|
|
2599
2170
|
const {
|
|
2600
2171
|
product: { host, displayName }
|
|
2601
2172
|
} = useWorkshopConfig();
|
|
2173
|
+
const userHasAccess = useUserHasAccess();
|
|
2602
2174
|
const details = /* @__PURE__ */ jsx("div", { children: ENV.EPICSHOP_DEPLOYED ? /* @__PURE__ */ jsxs("div", { children: [
|
|
2603
2175
|
`This is the deployed version. `,
|
|
2604
2176
|
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -2646,7 +2218,7 @@ function NoUserBanner() {
|
|
|
2646
2218
|
details
|
|
2647
2219
|
] })
|
|
2648
2220
|
] }),
|
|
2649
|
-
/* @__PURE__ */ jsxs("div", { className: "hidden h-full flex-col items-center sm:flex md:flex-row", children: [
|
|
2221
|
+
userHasAccess ? null : /* @__PURE__ */ jsxs("div", { className: "hidden h-full flex-col items-center sm:flex md:flex-row", children: [
|
|
2650
2222
|
/* @__PURE__ */ jsxs(
|
|
2651
2223
|
Link,
|
|
2652
2224
|
{
|
|
@@ -3353,6 +2925,7 @@ function NavToggle({
|
|
|
3353
2925
|
setMenuOpened,
|
|
3354
2926
|
menuControls
|
|
3355
2927
|
}) {
|
|
2928
|
+
const initialOpenRef = React.useRef(isMenuOpened);
|
|
3356
2929
|
const menuButtonRef = React.useRef(null);
|
|
3357
2930
|
const path01Variants = {
|
|
3358
2931
|
open: { d: "M3.06061 2.99999L21.0606 21" },
|
|
@@ -3410,7 +2983,7 @@ function NavToggle({
|
|
|
3410
2983
|
/* @__PURE__ */ jsx(
|
|
3411
2984
|
motion.path,
|
|
3412
2985
|
{
|
|
3413
|
-
...path01Variants.closed,
|
|
2986
|
+
...path01Variants[initialOpenRef.current ? "open" : "closed"],
|
|
3414
2987
|
animate: path01Controls,
|
|
3415
2988
|
transition: { duration: 0.2 },
|
|
3416
2989
|
stroke: "currentColor",
|
|
@@ -3420,7 +2993,7 @@ function NavToggle({
|
|
|
3420
2993
|
/* @__PURE__ */ jsx(
|
|
3421
2994
|
motion.path,
|
|
3422
2995
|
{
|
|
3423
|
-
...path02Variants.closed,
|
|
2996
|
+
...path02Variants[initialOpenRef.current ? "open" : "closed"],
|
|
3424
2997
|
animate: path02Controls,
|
|
3425
2998
|
transition: { duration: 0.2 },
|
|
3426
2999
|
stroke: "currentColor",
|
|
@@ -10110,7 +9683,20 @@ async function registerDevice() {
|
|
|
10110
9683
|
return;
|
|
10111
9684
|
}
|
|
10112
9685
|
const userinfo = await client.userinfo(tokenSet);
|
|
10113
|
-
|
|
9686
|
+
let id;
|
|
9687
|
+
if (typeof userinfo.id === "string") {
|
|
9688
|
+
id = userinfo.id;
|
|
9689
|
+
} else {
|
|
9690
|
+
console.warn("[UNEXPECTED] User ID is not a string:", userinfo.id);
|
|
9691
|
+
id = userinfo.email ? md5(userinfo.email) : createId();
|
|
9692
|
+
}
|
|
9693
|
+
await setAuthInfo({
|
|
9694
|
+
id,
|
|
9695
|
+
tokenSet,
|
|
9696
|
+
email: userinfo.email,
|
|
9697
|
+
name: userinfo.name
|
|
9698
|
+
});
|
|
9699
|
+
await getUserInfo({ forceFresh: true });
|
|
10114
9700
|
authEmitter.emit(EVENTS.AUTH_RESOLVED);
|
|
10115
9701
|
} catch (error) {
|
|
10116
9702
|
authEmitter.emit(EVENTS.AUTH_REJECTED, {
|
|
@@ -11299,7 +10885,7 @@ const route41 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
11299
10885
|
__proto__: null,
|
|
11300
10886
|
loader
|
|
11301
10887
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
11302
|
-
const serverManifest = { "entry": { "module": "/assets/entry.client-DqIWuxf8.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.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-a3d3Qwip.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/pe-ChIwTk8v.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/index-C9Hx0Dey.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-Bdg3v8tC.js", "/assets/presence-DJGFvdDh.js", "/assets/seo-pBpFCWsy.js", "/assets/request-info-ByUEfOil.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/_-BrkpfnBb.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/misc-DUy_whwE.js", "/assets/components-Be92gVxW.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-Cbz7Qt-S.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/pe-ChIwTk8v.js", "/assets/product-DIAmCwmZ.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-BCTr8uu6.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/presence-DJGFvdDh.js", "/assets/progress-DQt_Bn9o.js", "/assets/index-Bdg3v8tC.js", "/assets/components-Be92gVxW.js", "/assets/request-info-ByUEfOil.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-C4Piztoz.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/button-_qPvcoqR.js", "/assets/misc-DUy_whwE.js", "/assets/tooltip-DO9uwurQ.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/presence-DJGFvdDh.js", "/assets/components-Be92gVxW.js", "/assets/request-info-ByUEfOil.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-l0sNRNKZ.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+/app.epic_ws[.js]": { "id": "routes/_app+/app.epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/app.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": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/discord-Bdnx7fu-.js", "imports": ["/assets/discord-BUWZUTEC.js", "/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/components-Be92gVxW.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.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-88n0To1b.js", "imports": ["/assets/index-BFGhCX_U.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-DCSM0NCG.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/progress-DQt_Bn9o.js", "/assets/misc-DUy_whwE.js", "/assets/seo-pBpFCWsy.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.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-BIMJh_sg.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/components-Be92gVxW.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-DTAM9xh5.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/progress-DQt_Bn9o.js", "/assets/set-playground-CBHBA46B.js", "/assets/seo-pBpFCWsy.js", "/assets/misc-DUy_whwE.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/tooltip-DO9uwurQ.js", "/assets/request-info-ByUEfOil.js", "/assets/components-Be92gVxW.js", "/assets/index-BCTr8uu6.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/pe-ChIwTk8v.js", "/assets/index-DZDhtMuq.js", "/assets/index-Bdg3v8tC.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.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-DgTXXO8s.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/preview-DaZd0wMb.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/request-info-ByUEfOil.js", "/assets/button-_qPvcoqR.js", "/assets/loading-XhMtj4mp.js", "/assets/index-Bdg3v8tC.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/progress-bar-BaTU3Yx_.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-Bi1TbRTj.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-DZDhtMuq.js", "/assets/misc-DUy_whwE.js", "/assets/diff-8nlDkmpc.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/loading-XhMtj4mp.js", "/assets/discord-BUWZUTEC.js", "/assets/components-Be92gVxW.js", "/assets/index-C9Hx0Dey.js", "/assets/set-playground-CBHBA46B.js", "/assets/tests-DbuyD2cI.js", "/assets/preview-DaZd0wMb.js", "/assets/index-BCTr8uu6.js", "/assets/accordion-D9-D-n9p.js", "/assets/mdx-CEjzXoEx.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/pe-ChIwTk8v.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/use-event-source-x59d4R2Z.js", "/assets/button-_qPvcoqR.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-DoKJvNug.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/tests-DbuyD2cI.js", "/assets/components-Be92gVxW.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/misc-DUy_whwE.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/accordion-D9-D-n9p.js", "/assets/index-DZDhtMuq.js", "/assets/index-BCTr8uu6.js", "/assets/use-event-source-x59d4R2Z.js", "/assets/set-playground-CBHBA46B.js", "/assets/progress-bar-BaTU3Yx_.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-nbpk1ToO.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/loading-XhMtj4mp.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/progress-DQt_Bn9o.js", "/assets/misc-DUy_whwE.js", "/assets/seo-pBpFCWsy.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.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-C0cpfAFL.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/loading-XhMtj4mp.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/misc-DUy_whwE.js", "/assets/seo-pBpFCWsy.js", "/assets/progress-DQt_Bn9o.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.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-Ca4vBON4.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/mdx-CEjzXoEx.js", "/assets/misc-DUy_whwE.js", "/assets/progress-DQt_Bn9o.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.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-C1oOgi98.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/use-event-source-x59d4R2Z.js", "/assets/button-_qPvcoqR.js", "/assets/loading-XhMtj4mp.js", "/assets/product-DIAmCwmZ.js", "/assets/workshop-config-WVltG_BV.js", "/assets/request-info-ByUEfOil.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/index-Bdg3v8tC.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.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-CIz02V_r.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/admin+/_layout": { "id": "routes/admin+/_layout", "parentId": "root", "path": "admin", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-Dfmv2zcn.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.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/admin+/index": { "id": "routes/admin+/index", "parentId": "routes/admin+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-pkiQppkK.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/tooltip-DO9uwurQ.js", "/assets/progress-DQt_Bn9o.js", "/assets/components-Be92gVxW.js", "/assets/pe-ChIwTk8v.js"], "css": [] }, "routes/admin+/version": { "id": "routes/admin+/version", "parentId": "routes/admin+/_layout", "path": "version", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/version-lxUUxt3s.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/workshop-config-WVltG_BV.js", "/assets/components-Be92gVxW.js"], "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-BhRAIPKc.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/diff-8nlDkmpc.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/components-Be92gVxW.js", "/assets/accordion-D9-D-n9p.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-DZDhtMuq.js", "/assets/index-BCTr8uu6.js", "/assets/mdx-CEjzXoEx.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/revalidation-ws-dUa9CAqr.js"], "css": ["/assets/epic-video-DUnRvy1A.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-C2YNq60k.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/button-_qPvcoqR.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.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-K6Dvbx-E.js", "imports": [], "css": [] } }, "url": "/assets/manifest-e5b2a6e1.js", "version": "e5b2a6e1" };
|
|
10888
|
+
const serverManifest = { "entry": { "module": "/assets/entry.client-DqIWuxf8.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.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-D12XnE1S.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/pe-ChIwTk8v.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/index-C9Hx0Dey.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-Bdg3v8tC.js", "/assets/presence-8FPJKg_8.js", "/assets/seo-pBpFCWsy.js", "/assets/request-info-ByUEfOil.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/_-BrkpfnBb.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/misc-DUy_whwE.js", "/assets/components-Be92gVxW.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-B8j0pWoF.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/pe-ChIwTk8v.js", "/assets/product-DIAmCwmZ.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-BCTr8uu6.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/presence-8FPJKg_8.js", "/assets/progress-DQt_Bn9o.js", "/assets/index-Bdg3v8tC.js", "/assets/components-Be92gVxW.js", "/assets/request-info-ByUEfOil.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-DPP4rKOb.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/button-_qPvcoqR.js", "/assets/misc-DUy_whwE.js", "/assets/tooltip-DO9uwurQ.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/presence-8FPJKg_8.js", "/assets/components-Be92gVxW.js", "/assets/request-info-ByUEfOil.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-l0sNRNKZ.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+/app.epic_ws[.js]": { "id": "routes/_app+/app.epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/app.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": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/discord-Bdnx7fu-.js", "imports": ["/assets/discord-BUWZUTEC.js", "/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/components-Be92gVxW.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.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-88n0To1b.js", "imports": ["/assets/index-BFGhCX_U.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-DCSM0NCG.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/progress-DQt_Bn9o.js", "/assets/misc-DUy_whwE.js", "/assets/seo-pBpFCWsy.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.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-BIMJh_sg.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/components-Be92gVxW.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-DTAM9xh5.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/progress-DQt_Bn9o.js", "/assets/set-playground-CBHBA46B.js", "/assets/seo-pBpFCWsy.js", "/assets/misc-DUy_whwE.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/tooltip-DO9uwurQ.js", "/assets/request-info-ByUEfOil.js", "/assets/components-Be92gVxW.js", "/assets/index-BCTr8uu6.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/pe-ChIwTk8v.js", "/assets/index-DZDhtMuq.js", "/assets/index-Bdg3v8tC.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.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-DgTXXO8s.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/preview-DaZd0wMb.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/request-info-ByUEfOil.js", "/assets/button-_qPvcoqR.js", "/assets/loading-XhMtj4mp.js", "/assets/index-Bdg3v8tC.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/progress-bar-BaTU3Yx_.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-Bi1TbRTj.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-DZDhtMuq.js", "/assets/misc-DUy_whwE.js", "/assets/diff-8nlDkmpc.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/loading-XhMtj4mp.js", "/assets/discord-BUWZUTEC.js", "/assets/components-Be92gVxW.js", "/assets/index-C9Hx0Dey.js", "/assets/set-playground-CBHBA46B.js", "/assets/tests-DbuyD2cI.js", "/assets/preview-DaZd0wMb.js", "/assets/index-BCTr8uu6.js", "/assets/accordion-D9-D-n9p.js", "/assets/mdx-CEjzXoEx.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/pe-ChIwTk8v.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/use-event-source-x59d4R2Z.js", "/assets/button-_qPvcoqR.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-DoKJvNug.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/tests-DbuyD2cI.js", "/assets/components-Be92gVxW.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/misc-DUy_whwE.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/accordion-D9-D-n9p.js", "/assets/index-DZDhtMuq.js", "/assets/index-BCTr8uu6.js", "/assets/use-event-source-x59d4R2Z.js", "/assets/set-playground-CBHBA46B.js", "/assets/progress-bar-BaTU3Yx_.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-nbpk1ToO.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/loading-XhMtj4mp.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/progress-DQt_Bn9o.js", "/assets/misc-DUy_whwE.js", "/assets/seo-pBpFCWsy.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.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-C0cpfAFL.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/loading-XhMtj4mp.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/revalidation-ws-dUa9CAqr.js", "/assets/mdx-CEjzXoEx.js", "/assets/misc-DUy_whwE.js", "/assets/seo-pBpFCWsy.js", "/assets/progress-DQt_Bn9o.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.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-Ca4vBON4.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/index-BCxBKsqT.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/error-boundary-BZA-ffa8.js", "/assets/mdx-CEjzXoEx.js", "/assets/misc-DUy_whwE.js", "/assets/progress-DQt_Bn9o.js", "/assets/components-Be92gVxW.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.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-C1oOgi98.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/use-event-source-x59d4R2Z.js", "/assets/button-_qPvcoqR.js", "/assets/loading-XhMtj4mp.js", "/assets/product-DIAmCwmZ.js", "/assets/workshop-config-WVltG_BV.js", "/assets/request-info-ByUEfOil.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/index-Bdg3v8tC.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.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-CIz02V_r.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.js"], "css": [] }, "routes/admin+/_layout": { "id": "routes/admin+/_layout", "parentId": "root", "path": "admin", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-Dfmv2zcn.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/components-Be92gVxW.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/admin+/index": { "id": "routes/admin+/index", "parentId": "routes/admin+/_layout", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-pkiQppkK.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/tooltip-DO9uwurQ.js", "/assets/progress-DQt_Bn9o.js", "/assets/components-Be92gVxW.js", "/assets/pe-ChIwTk8v.js"], "css": [] }, "routes/admin+/version": { "id": "routes/admin+/version", "parentId": "routes/admin+/_layout", "path": "version", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/version-lxUUxt3s.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/workshop-config-WVltG_BV.js", "/assets/components-Be92gVxW.js"], "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-BhRAIPKc.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/misc-DUy_whwE.js", "/assets/diff-8nlDkmpc.js", "/assets/nav-chevrons-DnR25VLp.js", "/assets/components-Be92gVxW.js", "/assets/accordion-D9-D-n9p.js", "/assets/tooltip-DO9uwurQ.js", "/assets/index-DZDhtMuq.js", "/assets/index-BCTr8uu6.js", "/assets/mdx-CEjzXoEx.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.js", "/assets/progress-bar-BaTU3Yx_.js", "/assets/revalidation-ws-dUa9CAqr.js"], "css": ["/assets/epic-video-DUnRvy1A.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-C2YNq60k.js", "imports": ["/assets/index-BFGhCX_U.js", "/assets/button-_qPvcoqR.js", "/assets/epic-video-Bp4BOD2R.js", "/assets/components-Be92gVxW.js", "/assets/misc-DUy_whwE.js", "/assets/index-Bdg3v8tC.js", "/assets/request-info-ByUEfOil.js", "/assets/tooltip-DO9uwurQ.js", "/assets/pe-ChIwTk8v.js", "/assets/loading-XhMtj4mp.js", "/assets/user-Bv6wYhQP.js", "/assets/workshop-config-WVltG_BV.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-K6Dvbx-E.js", "imports": [], "css": [] } }, "url": "/assets/manifest-a8336fab.js", "version": "a8336fab" };
|
|
11303
10889
|
const mode = "production";
|
|
11304
10890
|
const assetsBuildDirectory = "build/client";
|
|
11305
10891
|
const basename = "/";
|