@epic-web/workshop-app 4.5.0 → 4.6.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.
Files changed (333) hide show
  1. package/bin/epicshop.js +3 -3
  2. package/build/client/assets/{_-CGn-2XfF.js → _-COWH0sBh.js} +2 -2
  3. package/build/client/assets/{_-CGn-2XfF.js.map → _-COWH0sBh.js.map} +1 -1
  4. package/build/client/assets/_exerciseNumber-rfzZiDNa.js +2 -0
  5. package/build/client/assets/_exerciseNumber-rfzZiDNa.js.map +1 -0
  6. package/build/client/assets/{_exerciseNumber_._stepNumber-D00x64Vg.js → _exerciseNumber_._stepNumber-C37pli7_.js} +2 -2
  7. package/build/client/assets/_exerciseNumber_._stepNumber-C37pli7_.js.map +1 -0
  8. package/build/client/assets/_exerciseNumber_.finished-B7SgnqdS.js +2 -0
  9. package/build/client/assets/_exerciseNumber_.finished-B7SgnqdS.js.map +1 -0
  10. package/build/client/assets/_layout-BG1Jwh7V.js +2 -0
  11. package/build/client/assets/_layout-BG1Jwh7V.js.map +1 -0
  12. package/build/client/assets/{_layout-Caqk73Ed.js → _layout-CNgYirUN.js} +2 -2
  13. package/build/client/assets/_layout-CNgYirUN.js.map +1 -0
  14. package/build/client/assets/{_layout-MFX35ekR.js → _layout-D0zbQZjf.js} +2 -2
  15. package/build/client/assets/_layout-D0zbQZjf.js.map +1 -0
  16. package/build/client/assets/{account-Cp6A7SfU.js → account-DesvwOeg.js} +2 -2
  17. package/build/client/assets/{account-Cp6A7SfU.js.map → account-DesvwOeg.js.map} +1 -1
  18. package/build/client/assets/diff-BKsbFB6w.js +42 -0
  19. package/build/client/assets/diff-BKsbFB6w.js.map +1 -0
  20. package/build/client/assets/{diff-Ddyuc0-s.js → diff-KDzcgGYL.js} +2 -2
  21. package/build/client/assets/diff-KDzcgGYL.js.map +1 -0
  22. package/build/client/assets/{discord-DZWTKMPn.js → discord-0kv66Q6F.js} +2 -2
  23. package/build/client/assets/{discord-DZWTKMPn.js.map → discord-0kv66Q6F.js.map} +1 -1
  24. package/build/client/assets/discord-Xp0X4-Fl.js +2 -0
  25. package/build/client/assets/discord-Xp0X4-Fl.js.map +1 -0
  26. package/build/client/assets/epic-video-BwtXsHGU.js +2988 -0
  27. package/build/client/assets/epic-video-BwtXsHGU.js.map +1 -0
  28. package/build/client/assets/{error-boundary-BUV7xD2e.js → error-boundary-Bcric_4t.js} +2 -2
  29. package/build/client/assets/error-boundary-Bcric_4t.js.map +1 -0
  30. package/build/client/assets/finished-BI2-0Ykt.js +2 -0
  31. package/build/client/assets/finished-BI2-0Ykt.js.map +1 -0
  32. package/build/client/assets/{index-CVJowtf6.js → index-BQRtqn3g.js} +2 -2
  33. package/build/client/assets/index-BQRtqn3g.js.map +1 -0
  34. package/build/client/assets/index-Bg9MMnnf.js +2 -0
  35. package/build/client/assets/index-Bg9MMnnf.js.map +1 -0
  36. package/build/client/assets/{login-BCM4kJTm.js → login-D8zyjBAb.js} +2 -2
  37. package/build/client/assets/{login-BCM4kJTm.js.map → login-D8zyjBAb.js.map} +1 -1
  38. package/build/client/assets/manifest-c65c0481.js +1 -0
  39. package/build/client/assets/{mdx-BVZ4sNxQ.js → mdx-BYvGbvEr.js} +2 -2
  40. package/build/client/assets/mdx-BYvGbvEr.js.map +1 -0
  41. package/build/client/assets/{misc-DBBsMyAP.js → misc-DNgC2Frq.js} +2 -2
  42. package/build/client/assets/{misc-DBBsMyAP.js.map → misc-DNgC2Frq.js.map} +1 -1
  43. package/build/client/assets/{nav-chevrons-DnG58Hov.js → nav-chevrons-DOYtx9XE.js} +2 -2
  44. package/build/client/assets/{nav-chevrons-DnG58Hov.js.map → nav-chevrons-DOYtx9XE.js.map} +1 -1
  45. package/build/client/assets/og-l0sNRNKZ.js +2 -0
  46. package/build/client/assets/og-l0sNRNKZ.js.map +1 -0
  47. package/build/client/assets/{onboarding-oSo74A5L.js → onboarding-euWyXpCL.js} +2 -2
  48. package/build/client/assets/{onboarding-oSo74A5L.js.map → onboarding-euWyXpCL.js.map} +1 -1
  49. package/build/client/assets/presence-BJPzwbUy.js.map +1 -1
  50. package/build/client/assets/progress-CF9Xwfxf.js +2 -0
  51. package/build/client/assets/progress-CF9Xwfxf.js.map +1 -0
  52. package/build/client/assets/{progress-bar-TRgQ8YZ8.js → progress-bar-7LK87ZMh.js} +2 -2
  53. package/build/client/assets/progress-bar-7LK87ZMh.js.map +1 -0
  54. package/build/client/assets/{root-CxuwYUpK.js → root-BXq0yevS.js} +4 -4
  55. package/build/client/assets/root-BXq0yevS.js.map +1 -0
  56. package/build/client/assets/seo-CHrqghsC.js +2 -0
  57. package/build/client/assets/seo-CHrqghsC.js.map +1 -0
  58. package/build/client/assets/support-DUAHYT3r.js.map +1 -1
  59. package/build/client/assets/tooltip-Kw0lYWBI.js +2 -0
  60. package/build/client/assets/tooltip-Kw0lYWBI.js.map +1 -0
  61. package/build/client/img/epicweb-og-background.png +0 -0
  62. package/build/server/index.js +1816 -1472
  63. package/build/server/index.js.map +1 -1
  64. package/dist/server/index.js +0 -2
  65. package/node_modules/@babel/runtime/helpers/AwaitValue.js +2 -2
  66. package/node_modules/@babel/runtime/helpers/OverloadYield.js +2 -2
  67. package/node_modules/@babel/runtime/helpers/applyDecoratedDescriptor.js +7 -22
  68. package/node_modules/@babel/runtime/helpers/applyDecs2311.js +9 -9
  69. package/node_modules/@babel/runtime/helpers/arrayLikeToArray.js +4 -4
  70. package/node_modules/@babel/runtime/helpers/arrayWithHoles.js +2 -2
  71. package/node_modules/@babel/runtime/helpers/arrayWithoutHoles.js +2 -2
  72. package/node_modules/@babel/runtime/helpers/assertThisInitialized.js +3 -5
  73. package/node_modules/@babel/runtime/helpers/asyncToGenerator.js +16 -21
  74. package/node_modules/@babel/runtime/helpers/checkPrivateRedeclaration.js +2 -4
  75. package/node_modules/@babel/runtime/helpers/classApplyDescriptorDestructureSet.js +7 -15
  76. package/node_modules/@babel/runtime/helpers/classApplyDescriptorGet.js +2 -5
  77. package/node_modules/@babel/runtime/helpers/classApplyDescriptorSet.js +4 -8
  78. package/node_modules/@babel/runtime/helpers/classCallCheck.js +2 -4
  79. package/node_modules/@babel/runtime/helpers/classCheckPrivateStaticAccess.js +2 -2
  80. package/node_modules/@babel/runtime/helpers/classCheckPrivateStaticFieldDescriptor.js +2 -4
  81. package/node_modules/@babel/runtime/helpers/classExtractFieldDescriptor.js +2 -2
  82. package/node_modules/@babel/runtime/helpers/classNameTDZError.js +2 -2
  83. package/node_modules/@babel/runtime/helpers/classPrivateFieldDestructureSet.js +3 -3
  84. package/node_modules/@babel/runtime/helpers/classPrivateFieldGet.js +3 -3
  85. package/node_modules/@babel/runtime/helpers/classPrivateFieldInitSpec.js +2 -3
  86. package/node_modules/@babel/runtime/helpers/classPrivateFieldLooseBase.js +3 -5
  87. package/node_modules/@babel/runtime/helpers/classPrivateFieldLooseKey.js +2 -2
  88. package/node_modules/@babel/runtime/helpers/classPrivateFieldSet.js +3 -4
  89. package/node_modules/@babel/runtime/helpers/classPrivateMethodGet.js +2 -3
  90. package/node_modules/@babel/runtime/helpers/classPrivateMethodInitSpec.js +2 -3
  91. package/node_modules/@babel/runtime/helpers/classStaticPrivateFieldDestructureSet.js +2 -4
  92. package/node_modules/@babel/runtime/helpers/classStaticPrivateFieldSpecGet.js +2 -4
  93. package/node_modules/@babel/runtime/helpers/classStaticPrivateFieldSpecSet.js +2 -5
  94. package/node_modules/@babel/runtime/helpers/classStaticPrivateMethodGet.js +2 -3
  95. package/node_modules/@babel/runtime/helpers/construct.js +1 -1
  96. package/node_modules/@babel/runtime/helpers/createClass.js +8 -14
  97. package/node_modules/@babel/runtime/helpers/createForOfIteratorHelper.js +24 -27
  98. package/node_modules/@babel/runtime/helpers/createForOfIteratorHelperLoose.js +11 -12
  99. package/node_modules/@babel/runtime/helpers/createSuper.js +10 -12
  100. package/node_modules/@babel/runtime/helpers/decorate.js +185 -278
  101. package/node_modules/@babel/runtime/helpers/defaults.js +6 -9
  102. package/node_modules/@babel/runtime/helpers/defineEnumerableProperties.js +8 -16
  103. package/node_modules/@babel/runtime/helpers/defineProperty.js +7 -13
  104. package/node_modules/@babel/runtime/helpers/esm/AsyncGenerator.js +3 -2
  105. package/node_modules/@babel/runtime/helpers/esm/AwaitValue.js +4 -3
  106. package/node_modules/@babel/runtime/helpers/esm/OverloadYield.js +4 -3
  107. package/node_modules/@babel/runtime/helpers/esm/applyDecoratedDescriptor.js +9 -23
  108. package/node_modules/@babel/runtime/helpers/esm/applyDecs.js +3 -2
  109. package/node_modules/@babel/runtime/helpers/esm/applyDecs2203.js +3 -2
  110. package/node_modules/@babel/runtime/helpers/esm/applyDecs2203R.js +3 -2
  111. package/node_modules/@babel/runtime/helpers/esm/applyDecs2301.js +3 -2
  112. package/node_modules/@babel/runtime/helpers/esm/applyDecs2305.js +3 -2
  113. package/node_modules/@babel/runtime/helpers/esm/applyDecs2311.js +12 -11
  114. package/node_modules/@babel/runtime/helpers/esm/arrayLikeToArray.js +6 -5
  115. package/node_modules/@babel/runtime/helpers/esm/arrayWithHoles.js +4 -3
  116. package/node_modules/@babel/runtime/helpers/esm/arrayWithoutHoles.js +4 -3
  117. package/node_modules/@babel/runtime/helpers/esm/assertClassBrand.js +3 -2
  118. package/node_modules/@babel/runtime/helpers/esm/assertThisInitialized.js +5 -6
  119. package/node_modules/@babel/runtime/helpers/esm/asyncGeneratorDelegate.js +3 -2
  120. package/node_modules/@babel/runtime/helpers/esm/asyncIterator.js +3 -2
  121. package/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js +18 -22
  122. package/node_modules/@babel/runtime/helpers/esm/awaitAsyncGenerator.js +3 -2
  123. package/node_modules/@babel/runtime/helpers/esm/callSuper.js +3 -2
  124. package/node_modules/@babel/runtime/helpers/esm/checkInRHS.js +3 -2
  125. package/node_modules/@babel/runtime/helpers/esm/checkPrivateRedeclaration.js +4 -5
  126. package/node_modules/@babel/runtime/helpers/esm/classApplyDescriptorDestructureSet.js +9 -16
  127. package/node_modules/@babel/runtime/helpers/esm/classApplyDescriptorGet.js +4 -6
  128. package/node_modules/@babel/runtime/helpers/esm/classApplyDescriptorSet.js +6 -9
  129. package/node_modules/@babel/runtime/helpers/esm/classCallCheck.js +4 -5
  130. package/node_modules/@babel/runtime/helpers/esm/classCheckPrivateStaticAccess.js +4 -3
  131. package/node_modules/@babel/runtime/helpers/esm/classCheckPrivateStaticFieldDescriptor.js +4 -5
  132. package/node_modules/@babel/runtime/helpers/esm/classExtractFieldDescriptor.js +4 -3
  133. package/node_modules/@babel/runtime/helpers/esm/classNameTDZError.js +4 -3
  134. package/node_modules/@babel/runtime/helpers/esm/classPrivateFieldDestructureSet.js +5 -4
  135. package/node_modules/@babel/runtime/helpers/esm/classPrivateFieldGet.js +5 -4
  136. package/node_modules/@babel/runtime/helpers/esm/classPrivateFieldGet2.js +3 -2
  137. package/node_modules/@babel/runtime/helpers/esm/classPrivateFieldInitSpec.js +4 -4
  138. package/node_modules/@babel/runtime/helpers/esm/classPrivateFieldLooseBase.js +5 -6
  139. package/node_modules/@babel/runtime/helpers/esm/classPrivateFieldLooseKey.js +4 -3
  140. package/node_modules/@babel/runtime/helpers/esm/classPrivateFieldSet.js +5 -5
  141. package/node_modules/@babel/runtime/helpers/esm/classPrivateFieldSet2.js +3 -2
  142. package/node_modules/@babel/runtime/helpers/esm/classPrivateGetter.js +3 -2
  143. package/node_modules/@babel/runtime/helpers/esm/classPrivateMethodGet.js +4 -4
  144. package/node_modules/@babel/runtime/helpers/esm/classPrivateMethodInitSpec.js +4 -4
  145. package/node_modules/@babel/runtime/helpers/esm/classPrivateMethodSet.js +3 -2
  146. package/node_modules/@babel/runtime/helpers/esm/classPrivateSetter.js +3 -2
  147. package/node_modules/@babel/runtime/helpers/esm/classStaticPrivateFieldDestructureSet.js +4 -5
  148. package/node_modules/@babel/runtime/helpers/esm/classStaticPrivateFieldSpecGet.js +4 -5
  149. package/node_modules/@babel/runtime/helpers/esm/classStaticPrivateFieldSpecSet.js +4 -6
  150. package/node_modules/@babel/runtime/helpers/esm/classStaticPrivateMethodGet.js +4 -4
  151. package/node_modules/@babel/runtime/helpers/esm/classStaticPrivateMethodSet.js +3 -2
  152. package/node_modules/@babel/runtime/helpers/esm/construct.js +4 -3
  153. package/node_modules/@babel/runtime/helpers/esm/createClass.js +10 -15
  154. package/node_modules/@babel/runtime/helpers/esm/createForOfIteratorHelper.js +26 -28
  155. package/node_modules/@babel/runtime/helpers/esm/createForOfIteratorHelperLoose.js +13 -13
  156. package/node_modules/@babel/runtime/helpers/esm/createSuper.js +12 -13
  157. package/node_modules/@babel/runtime/helpers/esm/decorate.js +187 -279
  158. package/node_modules/@babel/runtime/helpers/esm/defaults.js +8 -10
  159. package/node_modules/@babel/runtime/helpers/esm/defineAccessor.js +3 -2
  160. package/node_modules/@babel/runtime/helpers/esm/defineEnumerableProperties.js +10 -17
  161. package/node_modules/@babel/runtime/helpers/esm/defineProperty.js +9 -14
  162. package/node_modules/@babel/runtime/helpers/esm/dispose.js +3 -2
  163. package/node_modules/@babel/runtime/helpers/esm/extends.js +9 -13
  164. package/node_modules/@babel/runtime/helpers/esm/get.js +10 -16
  165. package/node_modules/@babel/runtime/helpers/esm/getPrototypeOf.js +6 -6
  166. package/node_modules/@babel/runtime/helpers/esm/identity.js +4 -3
  167. package/node_modules/@babel/runtime/helpers/esm/importDeferProxy.js +3 -2
  168. package/node_modules/@babel/runtime/helpers/esm/inherits.js +11 -14
  169. package/node_modules/@babel/runtime/helpers/esm/inheritsLoose.js +4 -5
  170. package/node_modules/@babel/runtime/helpers/esm/initializerDefineProperty.js +8 -8
  171. package/node_modules/@babel/runtime/helpers/esm/initializerWarningHelper.js +4 -3
  172. package/node_modules/@babel/runtime/helpers/esm/instanceof.js +4 -7
  173. package/node_modules/@babel/runtime/helpers/esm/interopRequireDefault.js +5 -4
  174. package/node_modules/@babel/runtime/helpers/esm/interopRequireWildcard.js +3 -2
  175. package/node_modules/@babel/runtime/helpers/esm/isNativeFunction.js +6 -5
  176. package/node_modules/@babel/runtime/helpers/esm/isNativeReflectConstruct.js +3 -2
  177. package/node_modules/@babel/runtime/helpers/esm/iterableToArray.js +4 -3
  178. package/node_modules/@babel/runtime/helpers/esm/iterableToArrayLimit.js +3 -2
  179. package/node_modules/@babel/runtime/helpers/esm/iterableToArrayLimitLoose.js +3 -2
  180. package/node_modules/@babel/runtime/helpers/esm/jsx.js +3 -2
  181. package/node_modules/@babel/runtime/helpers/esm/maybeArrayLike.js +7 -6
  182. package/node_modules/@babel/runtime/helpers/esm/newArrowCheck.js +4 -5
  183. package/node_modules/@babel/runtime/helpers/esm/nonIterableRest.js +3 -2
  184. package/node_modules/@babel/runtime/helpers/esm/nonIterableSpread.js +3 -2
  185. package/node_modules/@babel/runtime/helpers/esm/nullishReceiverError.js +3 -2
  186. package/node_modules/@babel/runtime/helpers/esm/objectDestructuringEmpty.js +4 -3
  187. package/node_modules/@babel/runtime/helpers/esm/objectSpread.js +11 -13
  188. package/node_modules/@babel/runtime/helpers/esm/objectSpread2.js +3 -2
  189. package/node_modules/@babel/runtime/helpers/esm/objectWithoutProperties.js +10 -13
  190. package/node_modules/@babel/runtime/helpers/esm/objectWithoutPropertiesLoose.js +9 -10
  191. package/node_modules/@babel/runtime/helpers/esm/possibleConstructorReturn.js +6 -8
  192. package/node_modules/@babel/runtime/helpers/esm/readOnlyError.js +4 -3
  193. package/node_modules/@babel/runtime/helpers/esm/regeneratorRuntime.js +3 -2
  194. package/node_modules/@babel/runtime/helpers/esm/set.js +19 -37
  195. package/node_modules/@babel/runtime/helpers/esm/setFunctionName.js +3 -2
  196. package/node_modules/@babel/runtime/helpers/esm/setPrototypeOf.js +6 -7
  197. package/node_modules/@babel/runtime/helpers/esm/skipFirstGeneratorNext.js +5 -5
  198. package/node_modules/@babel/runtime/helpers/esm/slicedToArray.js +4 -3
  199. package/node_modules/@babel/runtime/helpers/esm/slicedToArrayLoose.js +4 -3
  200. package/node_modules/@babel/runtime/helpers/esm/superPropBase.js +5 -7
  201. package/node_modules/@babel/runtime/helpers/esm/taggedTemplateLiteral.js +5 -7
  202. package/node_modules/@babel/runtime/helpers/esm/taggedTemplateLiteralLoose.js +4 -7
  203. package/node_modules/@babel/runtime/helpers/esm/tdz.js +4 -3
  204. package/node_modules/@babel/runtime/helpers/esm/temporalRef.js +6 -5
  205. package/node_modules/@babel/runtime/helpers/esm/temporalUndefined.js +2 -1
  206. package/node_modules/@babel/runtime/helpers/esm/toArray.js +4 -3
  207. package/node_modules/@babel/runtime/helpers/esm/toConsumableArray.js +4 -3
  208. package/node_modules/@babel/runtime/helpers/esm/toPrimitive.js +3 -2
  209. package/node_modules/@babel/runtime/helpers/esm/toPropertyKey.js +3 -2
  210. package/node_modules/@babel/runtime/helpers/esm/toSetter.js +3 -2
  211. package/node_modules/@babel/runtime/helpers/esm/typeof.js +3 -2
  212. package/node_modules/@babel/runtime/helpers/esm/unsupportedIterableToArray.js +8 -8
  213. package/node_modules/@babel/runtime/helpers/esm/using.js +3 -2
  214. package/node_modules/@babel/runtime/helpers/esm/usingCtx.js +3 -2
  215. package/node_modules/@babel/runtime/helpers/esm/wrapAsyncGenerator.js +4 -3
  216. package/node_modules/@babel/runtime/helpers/esm/wrapNativeSuper.js +17 -20
  217. package/node_modules/@babel/runtime/helpers/esm/wrapRegExp.js +3 -2
  218. package/node_modules/@babel/runtime/helpers/esm/writeOnlyError.js +4 -3
  219. package/node_modules/@babel/runtime/helpers/extends.js +6 -11
  220. package/node_modules/@babel/runtime/helpers/get.js +7 -14
  221. package/node_modules/@babel/runtime/helpers/getPrototypeOf.js +4 -5
  222. package/node_modules/@babel/runtime/helpers/identity.js +2 -2
  223. package/node_modules/@babel/runtime/helpers/inherits.js +9 -13
  224. package/node_modules/@babel/runtime/helpers/inheritsLoose.js +2 -4
  225. package/node_modules/@babel/runtime/helpers/initializerDefineProperty.js +6 -7
  226. package/node_modules/@babel/runtime/helpers/initializerWarningHelper.js +2 -2
  227. package/node_modules/@babel/runtime/helpers/instanceof.js +2 -6
  228. package/node_modules/@babel/runtime/helpers/interopRequireDefault.js +3 -3
  229. package/node_modules/@babel/runtime/helpers/isNativeFunction.js +4 -4
  230. package/node_modules/@babel/runtime/helpers/iterableToArray.js +2 -2
  231. package/node_modules/@babel/runtime/helpers/maybeArrayLike.js +5 -5
  232. package/node_modules/@babel/runtime/helpers/newArrowCheck.js +2 -4
  233. package/node_modules/@babel/runtime/helpers/objectDestructuringEmpty.js +2 -2
  234. package/node_modules/@babel/runtime/helpers/objectSpread.js +9 -12
  235. package/node_modules/@babel/runtime/helpers/objectWithoutProperties.js +8 -12
  236. package/node_modules/@babel/runtime/helpers/objectWithoutPropertiesLoose.js +7 -9
  237. package/node_modules/@babel/runtime/helpers/possibleConstructorReturn.js +4 -7
  238. package/node_modules/@babel/runtime/helpers/readOnlyError.js +2 -2
  239. package/node_modules/@babel/runtime/helpers/set.js +17 -36
  240. package/node_modules/@babel/runtime/helpers/setPrototypeOf.js +4 -6
  241. package/node_modules/@babel/runtime/helpers/skipFirstGeneratorNext.js +3 -4
  242. package/node_modules/@babel/runtime/helpers/slicedToArray.js +2 -2
  243. package/node_modules/@babel/runtime/helpers/slicedToArrayLoose.js +2 -2
  244. package/node_modules/@babel/runtime/helpers/superPropBase.js +3 -6
  245. package/node_modules/@babel/runtime/helpers/taggedTemplateLiteral.js +3 -6
  246. package/node_modules/@babel/runtime/helpers/taggedTemplateLiteralLoose.js +2 -6
  247. package/node_modules/@babel/runtime/helpers/tdz.js +2 -2
  248. package/node_modules/@babel/runtime/helpers/temporalRef.js +2 -2
  249. package/node_modules/@babel/runtime/helpers/toArray.js +2 -2
  250. package/node_modules/@babel/runtime/helpers/toConsumableArray.js +2 -2
  251. package/node_modules/@babel/runtime/helpers/unsupportedIterableToArray.js +6 -7
  252. package/node_modules/@babel/runtime/helpers/wrapAsyncGenerator.js +2 -2
  253. package/node_modules/@babel/runtime/helpers/wrapNativeSuper.js +15 -19
  254. package/node_modules/@babel/runtime/helpers/writeOnlyError.js +2 -2
  255. package/node_modules/@babel/runtime/package.json +587 -587
  256. package/node_modules/@conform-to/dom/form.js +1 -1
  257. package/node_modules/@conform-to/dom/form.mjs +1 -1
  258. package/node_modules/@conform-to/dom/formdata.d.ts +2 -2
  259. package/node_modules/@conform-to/dom/formdata.js +12 -34
  260. package/node_modules/@conform-to/dom/formdata.mjs +12 -34
  261. package/node_modules/@conform-to/dom/intent.d.ts +82 -0
  262. package/node_modules/@conform-to/dom/intent.js +136 -0
  263. package/node_modules/@conform-to/dom/intent.mjs +126 -0
  264. package/node_modules/@conform-to/dom/package.json +58 -59
  265. package/node_modules/@conform-to/dom/parse.d.ts +30 -0
  266. package/node_modules/@conform-to/dom/parse.js +43 -0
  267. package/node_modules/@conform-to/dom/parse.mjs +37 -0
  268. package/node_modules/@conform-to/dom/submission.d.ts +2 -2
  269. package/node_modules/@conform-to/dom/submission.js +23 -21
  270. package/node_modules/@conform-to/dom/submission.mjs +23 -21
  271. package/node_modules/@conform-to/dom/types.d.ts +20 -0
  272. package/node_modules/@conform-to/react/helpers.js +1 -1
  273. package/node_modules/@conform-to/react/helpers.mjs +1 -1
  274. package/node_modules/@conform-to/react/package.json +68 -69
  275. package/node_modules/@conform-to/zod/package.json +60 -61
  276. package/node_modules/framer-motion/dist/cjs/{dom-entry-fJy-kji5.js → dom-entry-DSxBucW4.js} +115 -107
  277. package/node_modules/framer-motion/dist/cjs/dom-entry.js +1 -1
  278. package/node_modules/framer-motion/dist/cjs/index.js +43 -10
  279. package/node_modules/framer-motion/dist/dom-entry.d.ts +1 -1
  280. package/node_modules/framer-motion/dist/dom.js +1 -1
  281. package/node_modules/framer-motion/dist/es/animation/GroupPlaybackControls.mjs +2 -3
  282. package/node_modules/framer-motion/dist/es/animation/interfaces/motion-value.mjs +4 -1
  283. package/node_modules/framer-motion/dist/es/animation/interfaces/visual-element-target.mjs +2 -3
  284. package/node_modules/framer-motion/dist/es/animation/optimized-appear/get-appear-id.mjs +7 -0
  285. package/node_modules/framer-motion/dist/es/projection/node/create-projection-node.mjs +43 -9
  286. package/node_modules/framer-motion/dist/es/render/dom/DOMKeyframesResolver.mjs +11 -8
  287. package/node_modules/framer-motion/dist/es/render/utils/motion-values.mjs +1 -1
  288. package/node_modules/framer-motion/dist/es/value/index.mjs +1 -1
  289. package/node_modules/framer-motion/dist/framer-motion.dev.js +156 -116
  290. package/node_modules/framer-motion/dist/framer-motion.js +1 -1
  291. package/node_modules/framer-motion/dist/index.d.ts +2 -1
  292. package/node_modules/framer-motion/dist/projection.dev.js +163 -20
  293. package/node_modules/framer-motion/dist/three-entry.d.ts +1 -0
  294. package/node_modules/framer-motion/package.json +8 -8
  295. package/node_modules/remix-utils/node_modules/type-fest/package.json +1 -1
  296. package/node_modules/remix-utils/node_modules/type-fest/source/conditional-keys.d.ts +5 -3
  297. package/node_modules/tslib/package.json +1 -1
  298. package/node_modules/tslib/tslib.d.ts +1 -1
  299. package/node_modules/tslib/tslib.es6.js +7 -3
  300. package/node_modules/tslib/tslib.es6.mjs +10 -7
  301. package/node_modules/tslib/tslib.js +7 -4
  302. package/package.json +8 -6
  303. package/start.js +6 -4
  304. package/build/client/assets/_exerciseNumber-D6YNCQoj.js +0 -2
  305. package/build/client/assets/_exerciseNumber-D6YNCQoj.js.map +0 -1
  306. package/build/client/assets/_exerciseNumber_._stepNumber-D00x64Vg.js.map +0 -1
  307. package/build/client/assets/_exerciseNumber_.finished-DR3gQ1pK.js +0 -2
  308. package/build/client/assets/_exerciseNumber_.finished-DR3gQ1pK.js.map +0 -1
  309. package/build/client/assets/_layout-Caqk73Ed.js.map +0 -1
  310. package/build/client/assets/_layout-DXegGcTM.js +0 -2
  311. package/build/client/assets/_layout-DXegGcTM.js.map +0 -1
  312. package/build/client/assets/_layout-MFX35ekR.js.map +0 -1
  313. package/build/client/assets/diff-Ddyuc0-s.js.map +0 -1
  314. package/build/client/assets/diff-ZJmYghvh.js +0 -42
  315. package/build/client/assets/diff-ZJmYghvh.js.map +0 -1
  316. package/build/client/assets/discord-fsySDDKv.js +0 -2
  317. package/build/client/assets/discord-fsySDDKv.js.map +0 -1
  318. package/build/client/assets/epic-video-BKzHxm70.js +0 -2985
  319. package/build/client/assets/epic-video-BKzHxm70.js.map +0 -1
  320. package/build/client/assets/error-boundary-BUV7xD2e.js.map +0 -1
  321. package/build/client/assets/finished-gQ-B3k8j.js +0 -2
  322. package/build/client/assets/finished-gQ-B3k8j.js.map +0 -1
  323. package/build/client/assets/index-CVJowtf6.js.map +0 -1
  324. package/build/client/assets/index-Drecz7hr.js +0 -2
  325. package/build/client/assets/index-Drecz7hr.js.map +0 -1
  326. package/build/client/assets/manifest-0b01450d.js +0 -1
  327. package/build/client/assets/mdx-BVZ4sNxQ.js.map +0 -1
  328. package/build/client/assets/progress-HmjERaPh.js +0 -2
  329. package/build/client/assets/progress-HmjERaPh.js.map +0 -1
  330. package/build/client/assets/progress-bar-TRgQ8YZ8.js.map +0 -1
  331. package/build/client/assets/root-CxuwYUpK.js.map +0 -1
  332. package/build/client/assets/tooltip-BdTNdCYE.js +0 -2
  333. package/build/client/assets/tooltip-BdTNdCYE.js.map +0 -1
@@ -1,10 +1,10 @@
1
1
  var _a, _b;
2
2
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
3
3
  import { PassThrough } from "stream";
4
- import "@total-typescript/ts-reset";
5
- import fs$1 from "fs";
6
- import path from "path";
4
+ import fs from "node:fs";
5
+ import path$1 from "node:path";
7
6
  import { remember } from "@epic-web/remember";
7
+ import "@total-typescript/ts-reset";
8
8
  import { execaCommand, execa } from "execa";
9
9
  import fsExtra from "fs-extra";
10
10
  import { glob } from "glob";
@@ -12,12 +12,14 @@ import { isGitIgnored, globby } from "globby";
12
12
  import * as z from "zod";
13
13
  import { z as z$1 } from "zod";
14
14
  import os from "os";
15
+ import path from "path";
15
16
  import * as C from "@epic-web/cachified";
16
17
  import { verboseReporter, cachified as cachified$1 } from "@epic-web/cachified";
17
18
  import { LRUCache } from "lru-cache";
18
19
  import md5 from "md5-hex";
19
20
  import chokidar from "chokidar";
20
21
  import closeWithGrace from "close-with-grace";
22
+ import fs$1 from "fs";
21
23
  import { remarkCodeBlocksShiki } from "@kentcdodds/md-temp";
22
24
  import { bundleMDX } from "mdx-bundler";
23
25
  import PQueue from "p-queue";
@@ -25,8 +27,6 @@ import remarkAutolinkHeadings from "remark-autolink-headings";
25
27
  import emoji from "remark-emoji";
26
28
  import gfm from "remark-gfm";
27
29
  import { visit } from "unist-util-visit";
28
- import fs from "node:fs";
29
- import path$1 from "node:path";
30
30
  import { createProcessor } from "@mdx-js/mdx";
31
31
  import { removePosition } from "unist-util-remove-position";
32
32
  import child_process, { spawn } from "child_process";
@@ -35,12 +35,12 @@ import chalk from "chalk";
35
35
  import fkill from "fkill";
36
36
  import { promises } from "node:dns";
37
37
  import { createReadableStreamFromReadable, redirect, json, createCookieSessionStorage, defer } from "@remix-run/node";
38
- import { RemixServer, Link, useRouteError, useParams, isRouteErrorResponse, useNavigation, useFetchers, useRouteLoaderData, useRevalidator, useFetcher, useLoaderData, Outlet, Meta, Links, ScrollRestoration, Scripts, useLocation, NavLink, Await, useSearchParams, Form, useSubmit, useNavigate } from "@remix-run/react";
38
+ import { RemixServer, Link, useRouteError, useParams, isRouteErrorResponse, useNavigation, useFetchers, useRouteLoaderData, useRevalidator, useFetcher, useLoaderData, Outlet, Meta, Links, ScrollRestoration, Scripts, useLocation, NavLink, Await, useSubmit, useSearchParams, Form, useNavigate } from "@remix-run/react";
39
39
  import { isbot } from "isbot";
40
40
  import { renderToPipeableStream } from "react-dom/server";
41
41
  import { cssBundleHref } from "@remix-run/css-bundle";
42
42
  import * as React from "react";
43
- import React__default, { useRef, useEffect, useMemo, useState, createContext, useContext, forwardRef, useImperativeHandle, useReducer, Suspense } from "react";
43
+ import React__default, { useRef, useEffect, useMemo, useState, createContext, useContext, Suspense, forwardRef, useImperativeHandle, useReducer } from "react";
44
44
  import { useSpinDelay } from "spin-delay";
45
45
  import { Index as Index$1 } from "confetti-react";
46
46
  import { ClientOnly } from "remix-utils/client-only";
@@ -52,11 +52,11 @@ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
52
52
  import { useForm, getFormProps } from "@conform-to/react";
53
53
  import { parseWithZod } from "@conform-to/zod";
54
54
  import { safeRedirect } from "remix-utils/safe-redirect";
55
- import * as cookie from "cookie";
56
55
  import { getHintUtils } from "@epic-web/client-hints";
57
56
  import { clientHint, subscribeToSchemeChange } from "@epic-web/client-hints/color-scheme";
58
57
  import { clientHint as clientHint$2, subscribeToMotionChange } from "@epic-web/client-hints/reduced-motion";
59
58
  import { clientHint as clientHint$1 } from "@epic-web/client-hints/time-zone";
59
+ import * as cookie from "cookie";
60
60
  import { createId } from "@paralleldrive/cuid2";
61
61
  import { usePartySocket } from "partysocket/react";
62
62
  import { motion, useAnimationControls } from "framer-motion";
@@ -66,15 +66,15 @@ import RealMuxPlayer from "@mux/mux-player-react";
66
66
  import shellQuote from "shell-quote";
67
67
  import * as mdxBundler from "mdx-bundler/client/index.js";
68
68
  import * as Tabs from "@radix-ui/react-tabs";
69
- import dayjs from "dayjs";
70
- import "dayjs/plugin/relativeTime.js";
71
- import "dayjs/plugin/timezone.js";
72
- import "dayjs/plugin/utc.js";
69
+ import * as Accordion from "@radix-ui/react-accordion";
73
70
  import * as Select from "@radix-ui/react-select";
74
71
  import ignore from "ignore";
75
72
  import parseGitDiff from "parse-git-diff";
76
73
  import { bundledLanguagesInfo } from "shiki/langs";
77
- import * as Accordion from "@radix-ui/react-accordion";
74
+ import dayjs from "dayjs";
75
+ import "dayjs/plugin/relativeTime.js";
76
+ import "dayjs/plugin/timezone.js";
77
+ import "dayjs/plugin/utc.js";
78
78
  import AnsiToHTML from "ansi-to-html";
79
79
  import escapeHtml from "lodash.escape";
80
80
  import { useEventSource } from "remix-utils/sse/react";
@@ -86,6 +86,7 @@ import * as esbuild from "esbuild";
86
86
  import { EventEmitter } from "events";
87
87
  import { Issuer } from "openid-client";
88
88
  import inspector from "node:inspector";
89
+ import { ImageResponse } from "@vercel/og";
89
90
  function makeTimings(type, desc) {
90
91
  const timings = {
91
92
  [type]: [{ desc, start: performance.now() }]
@@ -353,7 +354,7 @@ async function getFileContent(filePath) {
353
354
  const fileContent = content.split("\n");
354
355
  fileContentCache.set(filePath, fileContent);
355
356
  return fileContent;
356
- } catch (error) {
357
+ } catch {
357
358
  console.warn(
358
359
  `@epic-web/workshop-app - invalid CodeFile.
359
360
  Could not read file: ${filePath}
@@ -405,7 +406,9 @@ async function validateProps(props, appDir2) {
405
406
  }, "Highlight range must be within defined range").transform(() => props.highlight).optional(),
406
407
  nonumber: BooleanSchema,
407
408
  nocopy: BooleanSchema,
408
- buttons: z.string().optional().transform((str) => str ? str.split(",") : []).refine((arr) => arr.every((item) => APP_TYPES.includes(item)), {
409
+ buttons: z.string().optional().transform(
410
+ (str) => str ? str.split(",") : []
411
+ ).refine((arr) => arr.every((item) => APP_TYPES.includes(item)), {
409
412
  message: `Buttons can only be any of ${APP_TYPES.join(",")}`
410
413
  })
411
414
  }).strict();
@@ -869,7 +872,7 @@ async function getEmbeddedFilesCache() {
869
872
  await fs$1.promises.readFile(embeddedFilesLocation, "utf-8")
870
873
  );
871
874
  }
872
- } catch (error) {
875
+ } catch {
873
876
  console.error(`Unable to read 'embeddedFiles.json' from: `, cacheDir);
874
877
  }
875
878
  return void 0;
@@ -1193,7 +1196,7 @@ async function getPkgProp(fullPath, prop, defaultValue) {
1193
1196
  }
1194
1197
  (_b = process.env).NODE_ENV ?? (_b.NODE_ENV = "development");
1195
1198
  const workshopRoot = getWorkshopRoot();
1196
- const playgroundAppNameInfoPath = path.join(
1199
+ const playgroundAppNameInfoPath = path$1.join(
1197
1200
  getWorkshopRoot(),
1198
1201
  "node_modules",
1199
1202
  ".cache",
@@ -1308,7 +1311,7 @@ function isExerciseStepApp(app) {
1308
1311
  return isProblemApp(app) || isSolutionApp(app);
1309
1312
  }
1310
1313
  function exists(file) {
1311
- return fs$1.promises.access(file, fs$1.constants.F_OK).then(
1314
+ return fs.promises.access(file, fs.constants.F_OK).then(
1312
1315
  () => true,
1313
1316
  () => false
1314
1317
  );
@@ -1348,7 +1351,7 @@ function setModifiedTimesForDir(dir) {
1348
1351
  modifiedTimes.set(dir, Date.now());
1349
1352
  }
1350
1353
  function getForceFreshForDir(dir, cacheEntry) {
1351
- if (!path.isAbsolute(dir)) {
1354
+ if (!path$1.isAbsolute(dir)) {
1352
1355
  throw new Error(`Trying to get force fresh for non-absolute path: ${dir}`);
1353
1356
  }
1354
1357
  if (!cacheEntry)
@@ -1360,7 +1363,7 @@ function getForceFreshForDir(dir, cacheEntry) {
1360
1363
  }
1361
1364
  async function readDir(dir) {
1362
1365
  if (await exists(dir)) {
1363
- return fs$1.promises.readdir(dir);
1366
+ return fs.promises.readdir(dir);
1364
1367
  }
1365
1368
  return [];
1366
1369
  }
@@ -1409,18 +1412,18 @@ async function getExercises({
1409
1412
  request
1410
1413
  } = {}) {
1411
1414
  const apps = await getApps({ request, timings });
1412
- const exerciseDirs = await readDir(path.join(workshopRoot, "exercises"));
1415
+ const exerciseDirs = await readDir(path$1.join(workshopRoot, "exercises"));
1413
1416
  const exercises = [];
1414
1417
  for (const dirName of exerciseDirs) {
1415
1418
  const exerciseNumber = extractExerciseNumber(dirName);
1416
1419
  if (!exerciseNumber)
1417
1420
  continue;
1418
1421
  const compiledReadme = await compileMdxIfExists(
1419
- path.join(workshopRoot, "exercises", dirName, "README.mdx"),
1422
+ path$1.join(workshopRoot, "exercises", dirName, "README.mdx"),
1420
1423
  { request }
1421
1424
  );
1422
1425
  const compiledFinished = await compileMdxIfExists(
1423
- path.join(workshopRoot, "exercises", dirName, "FINISHED.mdx"),
1426
+ path$1.join(workshopRoot, "exercises", dirName, "FINISHED.mdx"),
1424
1427
  { request }
1425
1428
  );
1426
1429
  const steps = [];
@@ -1528,12 +1531,12 @@ const AppIdInfoSchema = z$1.object({
1528
1531
  function extractNumbersAndTypeFromAppNameOrPath(fullPathOrAppName) {
1529
1532
  var _a2;
1530
1533
  const info = {};
1531
- if (fullPathOrAppName.includes(path.sep)) {
1534
+ if (fullPathOrAppName.includes(path$1.sep)) {
1532
1535
  const relativePath = fullPathOrAppName.replace(
1533
- path.join(workshopRoot, "exercises", path.sep),
1536
+ path$1.join(workshopRoot, "exercises", path$1.sep),
1534
1537
  ""
1535
1538
  );
1536
- const [exerciseNumberPart, stepNumberPart] = relativePath.split(path.sep);
1539
+ const [exerciseNumberPart, stepNumberPart] = relativePath.split(path$1.sep);
1537
1540
  if (!exerciseNumberPart || !stepNumberPart)
1538
1541
  return null;
1539
1542
  const exerciseNumber = exerciseNumberPart.split(".")[0];
@@ -1554,19 +1557,19 @@ function extractNumbersAndTypeFromAppNameOrPath(fullPathOrAppName) {
1554
1557
  return null;
1555
1558
  }
1556
1559
  async function getProblemDirs() {
1557
- const exercisesDir = path.join(workshopRoot, "exercises");
1560
+ const exercisesDir = path$1.join(workshopRoot, "exercises");
1558
1561
  const problemDirs = (await glob("**/*.problem*", {
1559
1562
  cwd: exercisesDir,
1560
1563
  ignore: "node_modules/**"
1561
- })).map((p) => path.join(exercisesDir, p));
1564
+ })).map((p) => path$1.join(exercisesDir, p));
1562
1565
  return problemDirs;
1563
1566
  }
1564
1567
  async function getSolutionDirs() {
1565
- const exercisesDir = path.join(workshopRoot, "exercises");
1568
+ const exercisesDir = path$1.join(workshopRoot, "exercises");
1566
1569
  const solutionDirs = (await glob("**/*.solution*", {
1567
1570
  cwd: exercisesDir,
1568
1571
  ignore: "node_modules/**"
1569
- })).map((p) => path.join(exercisesDir, p));
1572
+ })).map((p) => path$1.join(exercisesDir, p));
1570
1573
  return solutionDirs;
1571
1574
  }
1572
1575
  function getPathname(fullPath) {
@@ -1578,30 +1581,30 @@ function getAppName(fullPath) {
1578
1581
  return "playground";
1579
1582
  if (/examples\/.+\/?$/.test(fullPath)) {
1580
1583
  const restOfPath = fullPath.replace(
1581
- `${getWorkshopRoot()}${path.sep}examples${path.sep}`,
1584
+ `${getWorkshopRoot()}${path$1.sep}examples${path$1.sep}`,
1582
1585
  ""
1583
1586
  );
1584
- return `example.${restOfPath.split(path.sep).join("__sep__")}`;
1587
+ return `example.${restOfPath.split(path$1.sep).join("__sep__")}`;
1585
1588
  }
1586
1589
  const appIdInfo = extractNumbersAndTypeFromAppNameOrPath(fullPath);
1587
1590
  if (appIdInfo) {
1588
1591
  const { exerciseNumber, stepNumber, type } = appIdInfo;
1589
1592
  return `${exerciseNumber}.${stepNumber}.${type}`;
1590
1593
  } else {
1591
- const relativePath = fullPath.replace(`${workshopRoot}${path.sep}`, "");
1592
- return relativePath.split(path.sep).join("__sep__");
1594
+ const relativePath = fullPath.replace(`${workshopRoot}${path$1.sep}`, "");
1595
+ return relativePath.split(path$1.sep).join("__sep__");
1593
1596
  }
1594
1597
  }
1595
1598
  async function getFullPathFromAppName(appName) {
1596
1599
  if (appName === "playground")
1597
- return path.join(workshopRoot, "playground");
1600
+ return path$1.join(workshopRoot, "playground");
1598
1601
  if (appName.startsWith(".example")) {
1599
- const relativePath = appName.replace(".example", "").split("__sep__").join(path.sep);
1600
- return path.join(workshopRoot, "examples", relativePath);
1602
+ const relativePath = appName.replace(".example", "").split("__sep__").join(path$1.sep);
1603
+ return path$1.join(workshopRoot, "examples", relativePath);
1601
1604
  }
1602
1605
  if (appName.includes("__sep__")) {
1603
- const relativePath = appName.replaceAll("__sep__", path.sep);
1604
- return path.join(workshopRoot, relativePath);
1606
+ const relativePath = appName.replaceAll("__sep__", path$1.sep);
1607
+ return path$1.join(workshopRoot, relativePath);
1605
1608
  }
1606
1609
  const [exerciseNumber, stepNumber, type] = appName.split(".");
1607
1610
  const appDirs = type === "problem" ? await getProblemDirs() : type === "solution" ? await getSolutionDirs() : [];
@@ -1616,20 +1619,20 @@ async function getFullPathFromAppName(appName) {
1616
1619
  async function findSolutionDir({
1617
1620
  fullPath
1618
1621
  }) {
1619
- const dirName = path.basename(fullPath);
1622
+ const dirName = path$1.basename(fullPath);
1620
1623
  if (dirName.includes(".problem")) {
1621
1624
  const info = getAppDirInfo(dirName);
1622
1625
  if (!info)
1623
1626
  return null;
1624
1627
  const { stepNumber } = info;
1625
1628
  const paddedStepNumber = stepNumber.toString().padStart(2, "0");
1626
- const parentDir = path.dirname(fullPath);
1627
- const siblingDirs = await fs$1.promises.readdir(parentDir);
1629
+ const parentDir = path$1.dirname(fullPath);
1630
+ const siblingDirs = await fs.promises.readdir(parentDir);
1628
1631
  const solutionDir = siblingDirs.find(
1629
1632
  (dir) => dir.startsWith(`${paddedStepNumber}.solution`)
1630
1633
  );
1631
1634
  if (solutionDir) {
1632
- return path.join(parentDir, solutionDir);
1635
+ return path$1.join(parentDir, solutionDir);
1633
1636
  }
1634
1637
  } else if (fullPath.endsWith("playground")) {
1635
1638
  const appName = await getPlaygroundAppName();
@@ -1644,20 +1647,20 @@ async function findSolutionDir({
1644
1647
  async function findProblemDir({
1645
1648
  fullPath
1646
1649
  }) {
1647
- const dirName = path.basename(fullPath);
1650
+ const dirName = path$1.basename(fullPath);
1648
1651
  if (dirName.includes(".solution")) {
1649
1652
  const info = getAppDirInfo(dirName);
1650
1653
  if (!info)
1651
1654
  return null;
1652
1655
  const { stepNumber } = info;
1653
1656
  const paddedStepNumber = stepNumber.toString().padStart(2, "0");
1654
- const parentDir = path.dirname(fullPath);
1655
- const siblingDirs = await fs$1.promises.readdir(parentDir);
1657
+ const parentDir = path$1.dirname(fullPath);
1658
+ const siblingDirs = await fs.promises.readdir(parentDir);
1656
1659
  const problemDir = siblingDirs.find(
1657
1660
  (dir) => dir.endsWith("problem") && dir.includes(paddedStepNumber)
1658
1661
  );
1659
1662
  if (problemDir) {
1660
- return path.join(parentDir, problemDir);
1663
+ return path$1.join(parentDir, problemDir);
1661
1664
  }
1662
1665
  } else if (fullPath.endsWith("playground")) {
1663
1666
  const appName = await getPlaygroundAppName();
@@ -1670,13 +1673,13 @@ async function findProblemDir({
1670
1673
  async function getTestInfo({
1671
1674
  fullPath
1672
1675
  }) {
1673
- const hasPkgJson = await exists(path.join(fullPath, "package.json"));
1676
+ const hasPkgJson = await exists(path$1.join(fullPath, "package.json"));
1674
1677
  const testScript = hasPkgJson ? await getPkgProp(fullPath, "epicshop.scripts.test", "") : null;
1675
1678
  if (testScript) {
1676
1679
  return { type: "script", script: testScript };
1677
1680
  }
1678
1681
  const testAppFullPath = await findSolutionDir({ fullPath }) ?? fullPath;
1679
- const dirList = await fs$1.promises.readdir(testAppFullPath);
1682
+ const dirList = await fs.promises.readdir(testAppFullPath);
1680
1683
  const testFiles = dirList.filter((item) => item.includes(".test."));
1681
1684
  if (testFiles.length) {
1682
1685
  return {
@@ -1691,7 +1694,7 @@ async function getDevInfo({
1691
1694
  fullPath,
1692
1695
  portNumber
1693
1696
  }) {
1694
- const hasPkgJson = await exists(path.join(fullPath, "package.json"));
1697
+ const hasPkgJson = await exists(path$1.join(fullPath, "package.json"));
1695
1698
  const hasDevScript = hasPkgJson ? Boolean(await getPkgProp(fullPath, "scripts.dev", "")) : false;
1696
1699
  if (hasDevScript) {
1697
1700
  const initialRoute = (hasPkgJson ? await getPkgProp(fullPath, "epicshop.initialRoute", "") : "") || await getPkgProp(workshopRoot, "epicshop.initialRoute", "/");
@@ -1710,7 +1713,7 @@ async function getPlaygroundApp({
1710
1713
  timings,
1711
1714
  request
1712
1715
  } = {}) {
1713
- const playgroundDir = path.join(workshopRoot, "playground");
1716
+ const playgroundDir = path$1.join(workshopRoot, "playground");
1714
1717
  const baseAppName = await getPlaygroundAppName();
1715
1718
  const key = `playground-${baseAppName}`;
1716
1719
  const baseAppFullPath = baseAppName ? await getFullPathFromAppName(baseAppName) : null;
@@ -1722,7 +1725,7 @@ async function getPlaygroundApp({
1722
1725
  cache: playgroundAppCache,
1723
1726
  ttl: 1e3 * 60 * 60 * 24,
1724
1727
  timings,
1725
- timingKey: playgroundDir.replace(`${playgroundDir}${path.sep}`, ""),
1728
+ timingKey: playgroundDir.replace(`${playgroundDir}${path$1.sep}`, ""),
1726
1729
  request,
1727
1730
  forceFresh: forceFreshPlaygroundDir || forceFreshBaseApp,
1728
1731
  getFreshValue: async () => {
@@ -1730,11 +1733,11 @@ async function getPlaygroundApp({
1730
1733
  return null;
1731
1734
  if (!baseAppName)
1732
1735
  return null;
1733
- const dirName = path.basename(playgroundDir);
1736
+ const dirName = path$1.basename(playgroundDir);
1734
1737
  const name = getAppName(playgroundDir);
1735
1738
  const portNumber = 4e3;
1736
1739
  const [compiledReadme, test, dev] = await Promise.all([
1737
- compileMdxIfExists(path.join(playgroundDir, "README.mdx"), { request }),
1740
+ compileMdxIfExists(path$1.join(playgroundDir, "README.mdx"), { request }),
1738
1741
  getTestInfo({ fullPath: playgroundDir }),
1739
1742
  getDevInfo({ fullPath: playgroundDir, portNumber })
1740
1743
  ]);
@@ -1749,7 +1752,7 @@ async function getPlaygroundApp({
1749
1752
  isUpToDate: appModifiedTime <= playgroundAppModifiedTime,
1750
1753
  fullPath: playgroundDir,
1751
1754
  relativePath: playgroundDir.replace(
1752
- `${getWorkshopRoot()}${path.sep}`,
1755
+ `${getWorkshopRoot()}${path$1.sep}`,
1753
1756
  ""
1754
1757
  ),
1755
1758
  title: (compiledReadme == null ? void 0 : compiledReadme.title) ?? name,
@@ -1766,9 +1769,9 @@ async function getPlaygroundApp({
1766
1769
  });
1767
1770
  }
1768
1771
  async function getExampleAppFromPath(fullPath, index, request) {
1769
- const dirName = path.basename(fullPath);
1772
+ const dirName = path$1.basename(fullPath);
1770
1773
  const compiledReadme = await compileMdxIfExists(
1771
- path.join(fullPath, "README.mdx"),
1774
+ path$1.join(fullPath, "README.mdx"),
1772
1775
  { request }
1773
1776
  );
1774
1777
  const name = getAppName(fullPath);
@@ -1777,7 +1780,7 @@ async function getExampleAppFromPath(fullPath, index, request) {
1777
1780
  name,
1778
1781
  type: "example",
1779
1782
  fullPath,
1780
- relativePath: fullPath.replace(`${getWorkshopRoot()}${path.sep}`, ""),
1783
+ relativePath: fullPath.replace(`${getWorkshopRoot()}${path$1.sep}`, ""),
1781
1784
  title: (compiledReadme == null ? void 0 : compiledReadme.title) ?? name,
1782
1785
  epicVideoEmbeds: compiledReadme == null ? void 0 : compiledReadme.epicVideoEmbeds,
1783
1786
  dirName,
@@ -1790,8 +1793,8 @@ async function getExampleApps({
1790
1793
  timings,
1791
1794
  request
1792
1795
  } = {}) {
1793
- const examplesDir = path.join(workshopRoot, "examples");
1794
- const exampleDirs = (await glob("*", { cwd: examplesDir, ignore: "node_modules/**" })).map((p) => path.join(examplesDir, p));
1796
+ const examplesDir = path$1.join(workshopRoot, "examples");
1797
+ const exampleDirs = (await glob("*", { cwd: examplesDir, ignore: "node_modules/**" })).map((p) => path$1.join(examplesDir, p));
1795
1798
  const exampleApps = [];
1796
1799
  for (const exampleDir of exampleDirs) {
1797
1800
  const index = exampleDirs.indexOf(exampleDir);
@@ -1801,7 +1804,7 @@ async function getExampleApps({
1801
1804
  cache: exampleAppCache,
1802
1805
  ttl: 1e3 * 60 * 60 * 24,
1803
1806
  timings,
1804
- timingKey: exampleDir.replace(`${examplesDir}${path.sep}`, ""),
1807
+ timingKey: exampleDir.replace(`${examplesDir}${path$1.sep}`, ""),
1805
1808
  request,
1806
1809
  forceFresh: getForceFreshForDir(exampleDir, exampleAppCache.get(key)),
1807
1810
  getFreshValue: () => getExampleAppFromPath(exampleDir, index, request).catch((error) => {
@@ -1815,8 +1818,8 @@ async function getExampleApps({
1815
1818
  return exampleApps;
1816
1819
  }
1817
1820
  async function getSolutionAppFromPath(fullPath, request) {
1818
- const dirName = path.basename(fullPath);
1819
- const parentDirName = path.basename(path.dirname(fullPath));
1821
+ const dirName = path$1.basename(fullPath);
1822
+ const parentDirName = path$1.basename(path$1.dirname(fullPath));
1820
1823
  const exerciseNumber = extractExerciseNumber(parentDirName);
1821
1824
  if (!exerciseNumber)
1822
1825
  return null;
@@ -1827,7 +1830,7 @@ async function getSolutionAppFromPath(fullPath, request) {
1827
1830
  const { stepNumber } = info;
1828
1831
  const portNumber = 7e3 + (exerciseNumber - 1) * 10 + stepNumber;
1829
1832
  const compiledReadme = await compileMdxIfExists(
1830
- path.join(fullPath, "README.mdx"),
1833
+ path$1.join(fullPath, "README.mdx"),
1831
1834
  { request }
1832
1835
  );
1833
1836
  const problemDir = await findProblemDir({
@@ -1848,7 +1851,7 @@ async function getSolutionAppFromPath(fullPath, request) {
1848
1851
  stepNumber,
1849
1852
  dirName,
1850
1853
  fullPath,
1851
- relativePath: fullPath.replace(`${getWorkshopRoot()}${path.sep}`, ""),
1854
+ relativePath: fullPath.replace(`${getWorkshopRoot()}${path$1.sep}`, ""),
1852
1855
  instructionsCode: compiledReadme == null ? void 0 : compiledReadme.code,
1853
1856
  test,
1854
1857
  dev
@@ -1858,7 +1861,7 @@ async function getSolutionApps({
1858
1861
  timings,
1859
1862
  request
1860
1863
  } = {}) {
1861
- const exercisesDir = path.join(workshopRoot, "exercises");
1864
+ const exercisesDir = path$1.join(workshopRoot, "exercises");
1862
1865
  const solutionDirs = await getSolutionDirs();
1863
1866
  const solutionApps = [];
1864
1867
  for (const solutionDir of solutionDirs) {
@@ -1866,7 +1869,7 @@ async function getSolutionApps({
1866
1869
  key: solutionDir,
1867
1870
  cache: solutionAppCache,
1868
1871
  timings,
1869
- timingKey: solutionDir.replace(`${exercisesDir}${path.sep}`, ""),
1872
+ timingKey: solutionDir.replace(`${exercisesDir}${path$1.sep}`, ""),
1870
1873
  request,
1871
1874
  ttl: 1e3 * 60 * 60 * 24,
1872
1875
  forceFresh: getForceFreshForDir(
@@ -1884,8 +1887,8 @@ async function getSolutionApps({
1884
1887
  return solutionApps;
1885
1888
  }
1886
1889
  async function getProblemAppFromPath(fullPath, request) {
1887
- const dirName = path.basename(fullPath);
1888
- const parentDirName = path.basename(path.dirname(fullPath));
1890
+ const dirName = path$1.basename(fullPath);
1891
+ const parentDirName = path$1.basename(path$1.dirname(fullPath));
1889
1892
  const exerciseNumber = extractExerciseNumber(parentDirName);
1890
1893
  if (!exerciseNumber)
1891
1894
  return null;
@@ -1896,7 +1899,7 @@ async function getProblemAppFromPath(fullPath, request) {
1896
1899
  const { stepNumber } = info;
1897
1900
  const portNumber = 6e3 + (exerciseNumber - 1) * 10 + stepNumber;
1898
1901
  const compiledReadme = await compileMdxIfExists(
1899
- path.join(fullPath, "README.mdx"),
1902
+ path$1.join(fullPath, "README.mdx"),
1900
1903
  { request }
1901
1904
  );
1902
1905
  const solutionDir = await findSolutionDir({
@@ -1917,7 +1920,7 @@ async function getProblemAppFromPath(fullPath, request) {
1917
1920
  stepNumber,
1918
1921
  dirName,
1919
1922
  fullPath,
1920
- relativePath: fullPath.replace(`${getWorkshopRoot()}${path.sep}`, ""),
1923
+ relativePath: fullPath.replace(`${getWorkshopRoot()}${path$1.sep}`, ""),
1921
1924
  instructionsCode: compiledReadme == null ? void 0 : compiledReadme.code,
1922
1925
  test,
1923
1926
  dev
@@ -1927,7 +1930,7 @@ async function getProblemApps({
1927
1930
  timings,
1928
1931
  request
1929
1932
  } = {}) {
1930
- const exercisesDir = path.join(workshopRoot, "exercises");
1933
+ const exercisesDir = path$1.join(workshopRoot, "exercises");
1931
1934
  const problemDirs = await getProblemDirs();
1932
1935
  const problemApps = [];
1933
1936
  for (const problemDir of problemDirs) {
@@ -1935,7 +1938,7 @@ async function getProblemApps({
1935
1938
  key: problemDir,
1936
1939
  cache: problemAppCache,
1937
1940
  timings,
1938
- timingKey: problemDir.replace(`${exercisesDir}${path.sep}`, ""),
1941
+ timingKey: problemDir.replace(`${exercisesDir}${path$1.sep}`, ""),
1939
1942
  request,
1940
1943
  ttl: 1e3 * 60 * 60 * 24,
1941
1944
  forceFresh: getForceFreshForDir(
@@ -2030,8 +2033,8 @@ async function setPlayground(srcDir, { reset } = {}) {
2030
2033
  var _a2, _b2;
2031
2034
  const isIgnored = await isGitIgnored({ cwd: srcDir });
2032
2035
  const workshopRoot2 = getWorkshopRoot();
2033
- const destDir = path.join(workshopRoot2, "playground");
2034
- const playgroundFiles = path.join(destDir, "**");
2036
+ const destDir = path$1.join(workshopRoot2, "playground");
2037
+ const playgroundFiles = path$1.join(destDir, "**");
2035
2038
  (_a2 = getOptionalWatcher()) == null ? void 0 : _a2.unwatch(playgroundFiles);
2036
2039
  const playgroundApp = await getAppByName("playground");
2037
2040
  const playgroundWasRunning = playgroundApp ? isAppRunning(playgroundApp) : false;
@@ -2041,14 +2044,13 @@ async function setPlayground(srcDir, { reset } = {}) {
2041
2044
  }
2042
2045
  const setPlaygroundTimestamp = Date.now();
2043
2046
  const preSetPlaygroundPath = await firstToExist(
2044
- path.join(srcDir, "epicshop", "pre-set-playground.js"),
2045
- path.join(workshopRoot2, "epicshop", "pre-set-playground.js")
2047
+ path$1.join(srcDir, "epicshop", "pre-set-playground.js"),
2048
+ path$1.join(workshopRoot2, "epicshop", "pre-set-playground.js")
2046
2049
  );
2047
2050
  if (preSetPlaygroundPath) {
2048
2051
  await execa("node", [preSetPlaygroundPath], {
2049
2052
  cwd: workshopRoot2,
2050
2053
  stdio: "inherit",
2051
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
2052
2054
  env: {
2053
2055
  EPICSHOP_PLAYGROUND_TIMESTAMP: setPlaygroundTimestamp.toString(),
2054
2056
  EPICSHOP_PLAYGROUND_DEST_DIR: destDir,
@@ -2057,11 +2059,11 @@ async function setPlayground(srcDir, { reset } = {}) {
2057
2059
  }
2058
2060
  });
2059
2061
  }
2060
- const basename2 = path.basename(srcDir);
2061
- await fsExtra.remove(path.join(destDir, "node_modules"));
2062
+ const basename2 = path$1.basename(srcDir);
2063
+ await fsExtra.remove(path$1.join(destDir, "node_modules"));
2062
2064
  await fsExtra.copy(srcDir, destDir, {
2063
2065
  filter: async (srcFile, destFile) => {
2064
- if (srcFile.includes(`${basename2}${path.sep}build`) || srcFile.includes(`${basename2}${path.sep}public${path.sep}build`)) {
2066
+ if (srcFile.includes(`${basename2}${path$1.sep}build`) || srcFile.includes(`${basename2}${path$1.sep}public${path$1.sep}build`)) {
2065
2067
  return false;
2066
2068
  }
2067
2069
  if (srcFile === srcDir)
@@ -2103,22 +2105,21 @@ async function setPlayground(srcDir, { reset } = {}) {
2103
2105
  (fileName) => !srcFiles.includes(fileName)
2104
2106
  );
2105
2107
  for (const fileToDelete of filesToDelete) {
2106
- await fsExtra.remove(path.join(destDir, fileToDelete));
2108
+ await fsExtra.remove(path$1.join(destDir, fileToDelete));
2107
2109
  }
2108
2110
  const appName = getAppName(srcDir);
2109
- await fsExtra.ensureDir(path.dirname(playgroundAppNameInfoPath));
2111
+ await fsExtra.ensureDir(path$1.dirname(playgroundAppNameInfoPath));
2110
2112
  await fsExtra.writeJSON(playgroundAppNameInfoPath, { appName });
2111
2113
  const playgroundIsStillRunning = playgroundApp ? isAppRunning(playgroundApp) : false;
2112
2114
  const restartPlayground = playgroundWasRunning && !playgroundIsStillRunning;
2113
2115
  const postSetPlaygroundPath = await firstToExist(
2114
- path.join(srcDir, "epicshop", "post-set-playground.js"),
2115
- path.join(workshopRoot2, "epicshop", "post-set-playground.js")
2116
+ path$1.join(srcDir, "epicshop", "post-set-playground.js"),
2117
+ path$1.join(workshopRoot2, "epicshop", "post-set-playground.js")
2116
2118
  );
2117
2119
  if (postSetPlaygroundPath) {
2118
2120
  await execa("node", [postSetPlaygroundPath], {
2119
2121
  cwd: workshopRoot2,
2120
2122
  stdio: "inherit",
2121
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
2122
2123
  env: {
2123
2124
  EPICSHOP_PLAYGROUND_TIMESTAMP: setPlaygroundTimestamp.toString(),
2124
2125
  EPICSHOP_PLAYGROUND_SRC_DIR: srcDir,
@@ -2141,7 +2142,7 @@ async function getPlaygroundAppName() {
2141
2142
  return null;
2142
2143
  }
2143
2144
  try {
2144
- const jsonString = await fs$1.promises.readFile(
2145
+ const jsonString = await fs.promises.readFile(
2145
2146
  playgroundAppNameInfoPath,
2146
2147
  "utf8"
2147
2148
  );
@@ -2155,17 +2156,17 @@ async function getPlaygroundAppName() {
2155
2156
  }
2156
2157
  async function getDirModifiedTime(dir) {
2157
2158
  const isIgnored = await isGitIgnored({ cwd: dir });
2158
- const files = await fs$1.promises.readdir(dir, { withFileTypes: true });
2159
+ const files = await fs.promises.readdir(dir, { withFileTypes: true });
2159
2160
  const modifiedTimes2 = await Promise.all(
2160
2161
  files.map(async (file) => {
2161
2162
  if (isIgnored(file.name))
2162
2163
  return 0;
2163
- const filePath = path.join(dir, file.name);
2164
+ const filePath = path$1.join(dir, file.name);
2164
2165
  if (file.isDirectory()) {
2165
2166
  return getDirModifiedTime(filePath);
2166
2167
  } else {
2167
2168
  try {
2168
- const { mtimeMs } = await fs$1.promises.stat(filePath);
2169
+ const { mtimeMs } = await fs.promises.stat(filePath);
2169
2170
  return mtimeMs;
2170
2171
  } catch {
2171
2172
  return 0;
@@ -2204,6 +2205,20 @@ async function getWorkshopTitle() {
2204
2205
  }
2205
2206
  return title;
2206
2207
  }
2208
+ async function getWorkshopSubtitle() {
2209
+ return await getPkgProp(workshopRoot, "epicshop.subtitle");
2210
+ }
2211
+ async function getWorkshopInstructor() {
2212
+ const InstructorSchema = z$1.object({
2213
+ name: z$1.string().optional(),
2214
+ avatar: z$1.string().optional(),
2215
+ "𝕏": z$1.string().optional()
2216
+ }).optional();
2217
+ const instructor = InstructorSchema.parse(
2218
+ await getPkgProp(getWorkshopRoot(), "epicshop.instructor")
2219
+ );
2220
+ return instructor;
2221
+ }
2207
2222
  async function getEpicWorkshopSlug() {
2208
2223
  const epicWorkshopSlug = await getPkgProp(
2209
2224
  workshopRoot,
@@ -2218,7 +2233,7 @@ function getWorkshopRoot() {
2218
2233
  async function getWorkshopInstructions({
2219
2234
  request
2220
2235
  } = {}) {
2221
- const readmeFilepath = path.join(workshopRoot, "exercises", "README.mdx");
2236
+ const readmeFilepath = path$1.join(workshopRoot, "exercises", "README.mdx");
2222
2237
  const compiled = await compileMdx(readmeFilepath, { request }).then(
2223
2238
  (r) => ({ ...r, status: "success" }),
2224
2239
  (e) => {
@@ -2235,7 +2250,7 @@ async function getWorkshopInstructions({
2235
2250
  async function getWorkshopFinished({
2236
2251
  request
2237
2252
  } = {}) {
2238
- const finishedFilepath = path.join(workshopRoot, "exercises", "FINISHED.mdx");
2253
+ const finishedFilepath = path$1.join(workshopRoot, "exercises", "FINISHED.mdx");
2239
2254
  const compiled = await compileMdx(finishedFilepath, { request }).then(
2240
2255
  (r) => ({ ...r, status: "success" }),
2241
2256
  (e) => {
@@ -2253,10 +2268,10 @@ async function getWorkshopFinished({
2253
2268
  relativePath: "exercises/finished.mdx"
2254
2269
  };
2255
2270
  }
2256
- const exercisesPath = path.join(workshopRoot, "exercises/");
2257
- const playgroundPath = path.join(workshopRoot, "playground/");
2271
+ const exercisesPath = path$1.join(workshopRoot, "exercises/");
2272
+ const playgroundPath = path$1.join(workshopRoot, "playground/");
2258
2273
  function getRelativePath$1(filePath) {
2259
- return path.normalize(filePath).replace(playgroundPath, `playground${path.sep}`).replace(exercisesPath, "");
2274
+ return path$1.normalize(filePath).replace(playgroundPath, `playground${path$1.sep}`).replace(exercisesPath, "");
2260
2275
  }
2261
2276
  z$1.object({
2262
2277
  NODE_ENV: z$1.enum(["production", "development", "test"]).default("development"),
@@ -2588,6 +2603,83 @@ function Confetti({ id }) {
2588
2603
  id
2589
2604
  ) });
2590
2605
  }
2606
+ function AnimatedBars({
2607
+ title,
2608
+ size = 16,
2609
+ ...props
2610
+ }) {
2611
+ return /* @__PURE__ */ jsxs(
2612
+ "svg",
2613
+ {
2614
+ width: size,
2615
+ height: size,
2616
+ viewBox: "0 0 16 16",
2617
+ "aria-hidden": !title,
2618
+ ...props,
2619
+ children: [
2620
+ title ? /* @__PURE__ */ jsx("title", { children: title }) : null,
2621
+ /* @__PURE__ */ jsxs("g", { fill: "currentColor", children: [
2622
+ /* @__PURE__ */ jsxs("g", { className: "nc-loop-dots-16-icon-f", children: [
2623
+ /* @__PURE__ */ jsx("circle", { cx: "3", cy: "8", fill: "currentColor", r: "2" }),
2624
+ /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "2" }),
2625
+ /* @__PURE__ */ jsx("circle", { cx: "13", cy: "8", fill: "currentColor", r: "2" })
2626
+ ] }),
2627
+ /* @__PURE__ */ jsx("style", { children: `.nc-loop-dots-16-icon-f{--animation-duration:1s}.nc-loop-dots-16-icon-f *{opacity:.4;transform:scale(.7)}.nc-loop-dots-16-icon-f :nth-child(1),.nc-loop-dots-16-icon-f :nth-child(3){animation:nc-loop-dots-anim-2b var(--animation-duration) infinite linear}.nc-loop-dots-16-icon-f :nth-child(1){transform-origin:3px 8px}.nc-loop-dots-16-icon-f :nth-child(2){animation:nc-loop-dots-anim-1b calc(var(--animation-duration)/2) infinite linear;animation-delay:calc(var(--animation-duration)/4);transform-origin:8px 8px}.nc-loop-dots-16-icon-f :nth-child(3){animation-delay:calc(var(--animation-duration)/2);transform-origin:13px 8px}@keyframes nc-loop-dots-anim-1b{0%,100%{opacity:.4;transform:scale(.7)}50%{opacity:1;transform:scale(1)}}@keyframes nc-loop-dots-anim-2b{0%,100%,66%{opacity:.4;transform:scale(.7)}33%{opacity:1;transform:scale(1)}}` })
2628
+ ] })
2629
+ ]
2630
+ }
2631
+ );
2632
+ }
2633
+ const sizeClassName = {
2634
+ font: "w-[1em] h-[1em]",
2635
+ xs: "w-3 h-3",
2636
+ sm: "w-4 h-4",
2637
+ md: "w-5 h-5",
2638
+ lg: "w-6 h-6",
2639
+ xl: "w-7 h-7",
2640
+ "2xl": "w-8 h-8"
2641
+ };
2642
+ const childrenSizeClassName = {
2643
+ font: "gap-1.5",
2644
+ xs: "gap-1.5",
2645
+ sm: "gap-1.5",
2646
+ md: "gap-2",
2647
+ lg: "gap-2",
2648
+ xl: "gap-3",
2649
+ "2xl": "gap-4"
2650
+ };
2651
+ function Icon({
2652
+ name,
2653
+ size = "font",
2654
+ title,
2655
+ className,
2656
+ children,
2657
+ ...props
2658
+ }) {
2659
+ if (children) {
2660
+ return /* @__PURE__ */ jsxs(
2661
+ "span",
2662
+ {
2663
+ className: `inline-flex items-center ${childrenSizeClassName[size]}`,
2664
+ children: [
2665
+ /* @__PURE__ */ jsx(Icon, { name, size, className, ...props }),
2666
+ children
2667
+ ]
2668
+ }
2669
+ );
2670
+ }
2671
+ return /* @__PURE__ */ jsxs(
2672
+ "svg",
2673
+ {
2674
+ ...props,
2675
+ className: cn(sizeClassName[size], "inline self-center", className),
2676
+ children: [
2677
+ title ? /* @__PURE__ */ jsx("title", { children: title }) : null,
2678
+ /* @__PURE__ */ jsx("use", { href: `/icons.svg#${name}`, fill: "transparent" })
2679
+ ]
2680
+ }
2681
+ );
2682
+ }
2591
2683
  const removeProseMargin = {
2592
2684
  "> ul > li > *:first-child": {
2593
2685
  marginTop: "unset"
@@ -2730,89 +2822,11 @@ const extendedTheme = {
2730
2822
  "accordion-up": "accordion-up 0.2s ease-out"
2731
2823
  }
2732
2824
  };
2733
- function AnimatedBars({
2734
- title,
2735
- size = 16,
2736
- ...props
2737
- }) {
2738
- return /* @__PURE__ */ jsxs(
2739
- "svg",
2740
- {
2741
- width: size,
2742
- height: size,
2743
- viewBox: "0 0 16 16",
2744
- "aria-hidden": !title,
2745
- ...props,
2746
- children: [
2747
- title ? /* @__PURE__ */ jsx("title", { children: title }) : null,
2748
- /* @__PURE__ */ jsxs("g", { fill: "currentColor", children: [
2749
- /* @__PURE__ */ jsxs("g", { className: "nc-loop-dots-16-icon-f", children: [
2750
- /* @__PURE__ */ jsx("circle", { cx: "3", cy: "8", fill: "currentColor", r: "2" }),
2751
- /* @__PURE__ */ jsx("circle", { cx: "8", cy: "8", r: "2" }),
2752
- /* @__PURE__ */ jsx("circle", { cx: "13", cy: "8", fill: "currentColor", r: "2" })
2753
- ] }),
2754
- /* @__PURE__ */ jsx("style", { children: `.nc-loop-dots-16-icon-f{--animation-duration:1s}.nc-loop-dots-16-icon-f *{opacity:.4;transform:scale(.7)}.nc-loop-dots-16-icon-f :nth-child(1),.nc-loop-dots-16-icon-f :nth-child(3){animation:nc-loop-dots-anim-2b var(--animation-duration) infinite linear}.nc-loop-dots-16-icon-f :nth-child(1){transform-origin:3px 8px}.nc-loop-dots-16-icon-f :nth-child(2){animation:nc-loop-dots-anim-1b calc(var(--animation-duration)/2) infinite linear;animation-delay:calc(var(--animation-duration)/4);transform-origin:8px 8px}.nc-loop-dots-16-icon-f :nth-child(3){animation-delay:calc(var(--animation-duration)/2);transform-origin:13px 8px}@keyframes nc-loop-dots-anim-1b{0%,100%{opacity:.4;transform:scale(.7)}50%{opacity:1;transform:scale(1)}}@keyframes nc-loop-dots-anim-2b{0%,100%,66%{opacity:.4;transform:scale(.7)}33%{opacity:1;transform:scale(1)}}` })
2755
- ] })
2756
- ]
2757
- }
2758
- );
2759
- }
2760
- const sizeClassName = {
2761
- font: "w-[1em] h-[1em]",
2762
- xs: "w-3 h-3",
2763
- sm: "w-4 h-4",
2764
- md: "w-5 h-5",
2765
- lg: "w-6 h-6",
2766
- xl: "w-7 h-7",
2767
- "2xl": "w-8 h-8"
2768
- };
2769
- const childrenSizeClassName = {
2770
- font: "gap-1.5",
2771
- xs: "gap-1.5",
2772
- sm: "gap-1.5",
2773
- md: "gap-2",
2774
- lg: "gap-2",
2775
- xl: "gap-3",
2776
- "2xl": "gap-4"
2777
- };
2778
- function Icon({
2779
- name,
2780
- size = "font",
2781
- title,
2782
- className,
2783
- children,
2784
- ...props
2785
- }) {
2786
- if (children) {
2787
- return /* @__PURE__ */ jsxs(
2788
- "span",
2789
- {
2790
- className: `inline-flex items-center ${childrenSizeClassName[size]}`,
2791
- children: [
2792
- /* @__PURE__ */ jsx(Icon, { name, size, className, ...props }),
2793
- children
2794
- ]
2795
- }
2796
- );
2797
- }
2798
- return /* @__PURE__ */ jsxs(
2799
- "svg",
2800
- {
2801
- ...props,
2802
- className: cn(sizeClassName[size], "inline self-center", className),
2803
- children: [
2804
- title ? /* @__PURE__ */ jsx("title", { children: title }) : null,
2805
- /* @__PURE__ */ jsx("use", { href: `/icons.svg#${name}`, fill: "transparent" })
2806
- ]
2807
- }
2808
- );
2809
- }
2810
2825
  const AnchorOrLink = React.forwardRef(function AnchorOrLink2(props, ref) {
2811
2826
  var _a2;
2812
2827
  const {
2813
2828
  to,
2814
2829
  href,
2815
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
2816
2830
  download,
2817
2831
  reload = false,
2818
2832
  prefetch,
@@ -2833,10 +2847,7 @@ const AnchorOrLink = React.forwardRef(function AnchorOrLink2(props, ref) {
2833
2847
  shouldUserRegularAnchor = Boolean((_a2 = to.pathname) == null ? void 0 : _a2.includes(":"));
2834
2848
  }
2835
2849
  if (shouldUserRegularAnchor) {
2836
- return (
2837
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
2838
- /* @__PURE__ */ jsx("a", { ...rest, download, href: href ?? toUrl, ref, children })
2839
- );
2850
+ return /* @__PURE__ */ jsx("a", { ...rest, download, href: href ?? toUrl, ref, children });
2840
2851
  } else {
2841
2852
  return /* @__PURE__ */ jsx(Link, { prefetch, to: to ?? href ?? "", ...rest, ref, children });
2842
2853
  }
@@ -3091,20 +3102,6 @@ function SimpleTooltip({
3091
3102
  /* @__PURE__ */ jsx(TooltipContent, { children: content })
3092
3103
  ] });
3093
3104
  }
3094
- const cookieName$1 = "EpicShop_theme";
3095
- function getTheme(request) {
3096
- const cookieHeader = request.headers.get("cookie");
3097
- const parsed = cookieHeader ? cookie.parse(cookieHeader)[cookieName$1] : null;
3098
- if (parsed === "light" || parsed === "dark")
3099
- return parsed;
3100
- return null;
3101
- }
3102
- function setTheme(theme) {
3103
- return cookie.serialize(cookieName$1, theme, {
3104
- path: "/",
3105
- maxAge: theme === "system" ? 0 : 60 * 60 * 365 * 100
3106
- });
3107
- }
3108
3105
  function useRequestInfo() {
3109
3106
  const data = useRouteLoaderData("root");
3110
3107
  return data.requestInfo;
@@ -3159,6 +3156,20 @@ function ErrorList({
3159
3156
  return null;
3160
3157
  return /* @__PURE__ */ jsx("ul", { id, className: "space-y-1", children: errorsToRender.map((e) => /* @__PURE__ */ jsx("li", { className: "text-danger text-[10px]", children: e }, e)) });
3161
3158
  }
3159
+ const cookieName$1 = "EpicShop_theme";
3160
+ function getTheme(request) {
3161
+ const cookieHeader = request.headers.get("cookie");
3162
+ const parsed = cookieHeader ? cookie.parse(cookieHeader)[cookieName$1] : null;
3163
+ if (parsed === "light" || parsed === "dark")
3164
+ return parsed;
3165
+ return null;
3166
+ }
3167
+ function setTheme(theme) {
3168
+ return cookie.serialize(cookieName$1, theme, {
3169
+ path: "/",
3170
+ maxAge: theme === "system" ? 0 : 60 * 60 * 365 * 100
3171
+ });
3172
+ }
3162
3173
  const ROUTE_PATH = "/theme";
3163
3174
  const ThemeFormSchema = z$1.object({
3164
3175
  redirectTo: z$1.string().optional(),
@@ -3243,7 +3254,7 @@ function useTheme() {
3243
3254
  }
3244
3255
  return requestInfo.session.theme ?? hints.theme;
3245
3256
  }
3246
- const route34 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3257
+ const route35 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3247
3258
  __proto__: null,
3248
3259
  ThemeSwitch,
3249
3260
  action: action$c,
@@ -3736,6 +3747,40 @@ function usePresence() {
3736
3747
  }
3737
3748
  return presence;
3738
3749
  }
3750
+ function getSeoMetaTags({
3751
+ title,
3752
+ description,
3753
+ instructor,
3754
+ requestInfo,
3755
+ ogTitle = title,
3756
+ ogDescription = description,
3757
+ ogImageUrl = requestInfo.domain + "/og?" + new URLSearchParams({
3758
+ title: ogTitle,
3759
+ subtitle: ogDescription ?? "",
3760
+ urlPathname: requestInfo.path,
3761
+ // to make cache busting possible, whenever the og image changes, we can change the version
3762
+ // note if the inputs change, then the cache will be busted automatically
3763
+ // it's only if the image changes that we need to change the version
3764
+ version: "v1"
3765
+ }).toString(),
3766
+ ogImageAlt = title
3767
+ }) {
3768
+ return [
3769
+ { title },
3770
+ description ? { description } : null,
3771
+ (instructor == null ? void 0 : instructor.name) ? { name: "author", content: instructor.name } : null,
3772
+ { name: "og:site_name", content: title },
3773
+ { name: "twitter:card", content: "summary_large_image" },
3774
+ { name: "twitter:creator", content: instructor == null ? void 0 : instructor["𝕏"] },
3775
+ { name: "og:title", content: ogTitle },
3776
+ description ? { name: "og:description", content: ogDescription } : null,
3777
+ { name: "og:type", content: "website" },
3778
+ { name: "og:image:width", content: "1200" },
3779
+ { name: "og:image:height", content: "630" },
3780
+ { name: "og:image:alt", content: ogImageAlt },
3781
+ { name: "og:image", content: ogImageUrl }
3782
+ ].filter(Boolean);
3783
+ }
3739
3784
  const toastKey = "toast";
3740
3785
  const TypeSchema = z$1.enum(["message", "success", "error"]);
3741
3786
  const ToastSchema = z$1.object({
@@ -3800,9 +3845,16 @@ const links = () => {
3800
3845
  ];
3801
3846
  };
3802
3847
  const meta$5 = ({ data }) => {
3803
- return [{ title: data == null ? void 0 : data.workshopTitle }];
3848
+ if (!data)
3849
+ return [];
3850
+ return getSeoMetaTags({
3851
+ instructor: data.instructor,
3852
+ title: data.workshopTitle,
3853
+ description: data.workshopSubtitle,
3854
+ requestInfo: data.requestInfo
3855
+ });
3804
3856
  };
3805
- async function loader$r({ request }) {
3857
+ async function loader$s({ request }) {
3806
3858
  const timings = makeTimings("rootLoader");
3807
3859
  const onboarding = await readOnboardingData();
3808
3860
  if (!ENV.EPICSHOP_DEPLOYED && !(onboarding == null ? void 0 : onboarding.finishedTourVideo)) {
@@ -3815,6 +3867,16 @@ async function loader$r({ request }) {
3815
3867
  desc: "getWorkshopTitle in root",
3816
3868
  timings
3817
3869
  });
3870
+ const workshopSubtitle = await time(() => getWorkshopSubtitle(), {
3871
+ type: "getWorkshopSubtitle",
3872
+ desc: "getWorkshopSubtitle in root",
3873
+ timings
3874
+ });
3875
+ const instructor = await time(() => getWorkshopInstructor(), {
3876
+ type: "getInstructor",
3877
+ desc: "getInstructor in root",
3878
+ timings
3879
+ });
3818
3880
  const preferences = await getPreferences();
3819
3881
  const progress = await getProgress({ timings }).catch((e) => {
3820
3882
  console.error("Failed to get progress", e);
@@ -3831,6 +3893,8 @@ async function loader$r({ request }) {
3831
3893
  return json(
3832
3894
  {
3833
3895
  workshopTitle,
3896
+ workshopSubtitle,
3897
+ instructor,
3834
3898
  apps: apps.map(({ name, fullPath, relativePath }) => ({
3835
3899
  name,
3836
3900
  fullPath,
@@ -4008,10 +4072,10 @@ const route0 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
4008
4072
  default: AppWithProviders,
4009
4073
  headers: headers$8,
4010
4074
  links,
4011
- loader: loader$r,
4075
+ loader: loader$s,
4012
4076
  meta: meta$5
4013
4077
  }, Symbol.toStringTag, { value: "Module" }));
4014
- async function loader$q() {
4078
+ async function loader$r() {
4015
4079
  throw new Response("Not found", { status: 404 });
4016
4080
  }
4017
4081
  function NotFound() {
@@ -4038,8 +4102,25 @@ const route1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
4038
4102
  __proto__: null,
4039
4103
  ErrorBoundary: ErrorBoundary$4,
4040
4104
  default: NotFound,
4041
- loader: loader$q
4105
+ loader: loader$r
4042
4106
  }, Symbol.toStringTag, { value: "Module" }));
4107
+ function useOptionalUser() {
4108
+ const data = useRouteLoaderData("root");
4109
+ return data == null ? void 0 : data.user;
4110
+ }
4111
+ function useUser() {
4112
+ const user = useOptionalUser();
4113
+ if (!user) {
4114
+ throw new Error(
4115
+ "useUser requires a user. If the user is optional, use useOptionalUser instead."
4116
+ );
4117
+ }
4118
+ return user;
4119
+ }
4120
+ function useOptionalDiscordMember() {
4121
+ const data = useRouteLoaderData("root");
4122
+ return data == null ? void 0 : data.discordMember;
4123
+ }
4043
4124
  function useEpicProgress() {
4044
4125
  const data = useRouteLoaderData("root");
4045
4126
  const progressFetcher = useFetchers().find(
@@ -4205,7 +4286,9 @@ async function action$b({ request }) {
4205
4286
  const otherExerciseLessons = beforeProgress.filter(
4206
4287
  (p) => (p.type === "step" || p.type === "instructions" || p.type === "finished") && p.exerciseNumber === exerciseNumber && p.epicLessonSlug !== lessonSlug
4207
4288
  );
4208
- const otherAreFinished = otherExerciseLessons.every((p) => p.epicCompletedAt);
4289
+ const otherAreFinished = otherExerciseLessons.every(
4290
+ (p) => p.epicCompletedAt
4291
+ );
4209
4292
  return otherAreFinished ? `You completed exercise ${exerciseNumber}!` : null;
4210
4293
  }
4211
4294
  const announcement = getCompletionAnnouncement();
@@ -4331,7 +4414,7 @@ function ProgressToggle({
4331
4414
  )
4332
4415
  ] });
4333
4416
  }
4334
- const route30 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
4417
+ const route31 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
4335
4418
  __proto__: null,
4336
4419
  ProgressToggle,
4337
4420
  action: action$b,
@@ -4342,24 +4425,7 @@ const route30 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
4342
4425
  useProgressItemClassName,
4343
4426
  useRequireEpicProgress
4344
4427
  }, Symbol.toStringTag, { value: "Module" }));
4345
- function useOptionalUser() {
4346
- const data = useRouteLoaderData("root");
4347
- return data == null ? void 0 : data.user;
4348
- }
4349
- function useUser() {
4350
- const user = useOptionalUser();
4351
- if (!user) {
4352
- throw new Error(
4353
- "useUser requires a user. If the user is optional, use useOptionalUser instead."
4354
- );
4355
- }
4356
- return user;
4357
- }
4358
- function useOptionalDiscordMember() {
4359
- const data = useRouteLoaderData("root");
4360
- return data == null ? void 0 : data.discordMember;
4361
- }
4362
- async function loader$p({ request }) {
4428
+ async function loader$q({ request }) {
4363
4429
  var _a2;
4364
4430
  const timings = makeTimings("stepLoader");
4365
4431
  const [exercises, workshopTitle, playgroundAppName] = await Promise.all([
@@ -5057,7 +5123,7 @@ const route2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
5057
5123
  __proto__: null,
5058
5124
  default: App,
5059
5125
  headers: headers$7,
5060
- loader: loader$p
5126
+ loader: loader$q
5061
5127
  }, Symbol.toStringTag, { value: "Module" }));
5062
5128
  function ExercisesLayout() {
5063
5129
  return /* @__PURE__ */ jsx("div", { className: "flex h-full flex-grow", children: /* @__PURE__ */ jsx(Outlet, {}) });
@@ -5066,56 +5132,6 @@ const route3 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
5066
5132
  __proto__: null,
5067
5133
  default: ExercisesLayout
5068
5134
  }, Symbol.toStringTag, { value: "Module" }));
5069
- function Loading({
5070
- children = "Loading"
5071
- }) {
5072
- const { reducedMotion } = useHints();
5073
- if (reducedMotion === "reduce") {
5074
- return /* @__PURE__ */ jsx("div", { className: "animate-pulse", children });
5075
- }
5076
- return /* @__PURE__ */ jsxs(
5077
- "div",
5078
- {
5079
- className: "flex items-center gap-2 font-mono text-sm font-medium uppercase",
5080
- role: "status",
5081
- children: [
5082
- /* @__PURE__ */ jsx("div", { "aria-hidden": "true", children: /* @__PURE__ */ jsx(Characters, {}) }),
5083
- children,
5084
- /* @__PURE__ */ jsx("div", { "aria-hidden": "true", children: /* @__PURE__ */ jsx(Characters, {}) })
5085
- ]
5086
- }
5087
- );
5088
- }
5089
- const characters = "█<▓█ ▒░/▒░ █░>▒▓/ █▒▒ ▓▒▓/█<░▒ ▓/░>";
5090
- const randomCharacter = () => characters[Math.floor(Math.random() * characters.length)];
5091
- function Characters() {
5092
- const [char1, setChar1] = useState(characters[0]);
5093
- const [char2, setChar2] = useState(characters[1]);
5094
- useInterval(() => {
5095
- setChar1(randomCharacter());
5096
- setChar2(randomCharacter());
5097
- }, 80);
5098
- return /* @__PURE__ */ jsxs("span", { children: [
5099
- char1,
5100
- char2
5101
- ] });
5102
- }
5103
- function useInterval(callback, delay = 1e3) {
5104
- const savedCallback = useRef(null);
5105
- useEffect(() => {
5106
- savedCallback.current = callback;
5107
- }, [callback]);
5108
- useEffect(() => {
5109
- function tick() {
5110
- var _a2;
5111
- (_a2 = savedCallback.current) == null ? void 0 : _a2.call(savedCallback);
5112
- }
5113
- if (delay !== null) {
5114
- const id = setInterval(tick, delay);
5115
- return () => clearInterval(id);
5116
- }
5117
- }, [delay]);
5118
- }
5119
5135
  const PlaybackTimeSchema = z$1.object({
5120
5136
  time: z$1.number(),
5121
5137
  expiresAt: z$1.string()
@@ -5321,12 +5337,62 @@ function isDeepEqual(obj1, obj2) {
5321
5337
  }
5322
5338
  return true;
5323
5339
  }
5324
- const route36 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
5340
+ const route37 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
5325
5341
  __proto__: null,
5326
5342
  MuxPlayer,
5327
5343
  action: action$a,
5328
5344
  usePlayerPreferences
5329
5345
  }, Symbol.toStringTag, { value: "Module" }));
5346
+ function Loading({
5347
+ children = "Loading"
5348
+ }) {
5349
+ const { reducedMotion } = useHints();
5350
+ if (reducedMotion === "reduce") {
5351
+ return /* @__PURE__ */ jsx("div", { className: "animate-pulse", children });
5352
+ }
5353
+ return /* @__PURE__ */ jsxs(
5354
+ "div",
5355
+ {
5356
+ className: "flex items-center gap-2 font-mono text-sm font-medium uppercase",
5357
+ role: "status",
5358
+ children: [
5359
+ /* @__PURE__ */ jsx("div", { "aria-hidden": "true", children: /* @__PURE__ */ jsx(Characters, {}) }),
5360
+ children,
5361
+ /* @__PURE__ */ jsx("div", { "aria-hidden": "true", children: /* @__PURE__ */ jsx(Characters, {}) })
5362
+ ]
5363
+ }
5364
+ );
5365
+ }
5366
+ const characters = "█<▓█ ▒░/▒░ █░>▒▓/ █▒▒ ▓▒▓/█<░▒ ▓/░>";
5367
+ const randomCharacter = () => characters[Math.floor(Math.random() * characters.length)];
5368
+ function Characters() {
5369
+ const [char1, setChar1] = useState(characters[0]);
5370
+ const [char2, setChar2] = useState(characters[1]);
5371
+ useInterval(() => {
5372
+ setChar1(randomCharacter());
5373
+ setChar2(randomCharacter());
5374
+ }, 80);
5375
+ return /* @__PURE__ */ jsxs("span", { children: [
5376
+ char1,
5377
+ char2
5378
+ ] });
5379
+ }
5380
+ function useInterval(callback, delay = 1e3) {
5381
+ const savedCallback = useRef(null);
5382
+ useEffect(() => {
5383
+ savedCallback.current = callback;
5384
+ }, [callback]);
5385
+ useEffect(() => {
5386
+ function tick() {
5387
+ var _a2;
5388
+ (_a2 = savedCallback.current) == null ? void 0 : _a2.call(savedCallback);
5389
+ }
5390
+ if (delay !== null) {
5391
+ const id = setInterval(tick, delay);
5392
+ return () => clearInterval(id);
5393
+ }
5394
+ }, [delay]);
5395
+ }
5330
5396
  const EpicVideoInfoContext = React.createContext(null);
5331
5397
  function EpicVideoInfoProvider({
5332
5398
  children,
@@ -5451,7 +5517,9 @@ function extractEpicTitle(urlString) {
5451
5517
  const title = titleWords.filter(Boolean).map((word, index) => {
5452
5518
  var _a2;
5453
5519
  const lowerWord = word.toLowerCase();
5454
- const literalWord = literalWords.find((w) => w.toLowerCase() === lowerWord);
5520
+ const literalWord = literalWords.find(
5521
+ (w) => w.toLowerCase() === lowerWord
5522
+ );
5455
5523
  if (literalWord)
5456
5524
  return literalWord;
5457
5525
  if (lowerCaseWords.includes(lowerWord) && index > 0) {
@@ -5953,7 +6021,7 @@ function guessEditor() {
5953
6021
  }
5954
6022
  }
5955
6023
  }
5956
- } catch (error) {
6024
+ } catch {
5957
6025
  }
5958
6026
  if (process.env.VISUAL) {
5959
6027
  return [process.env.VISUAL];
@@ -6463,7 +6531,6 @@ function PreWithButtons({ children, ...props }) {
6463
6531
  ...props,
6464
6532
  className: clsx(
6465
6533
  "scrollbar-thin scrollbar-thumb-scrollbar",
6466
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
6467
6534
  props.className ?? ""
6468
6535
  ),
6469
6536
  ...updateFilename(),
@@ -6489,7 +6556,6 @@ const mdxComponents$5 = {
6489
6556
  ...props,
6490
6557
  className: clsx(
6491
6558
  "scrollbar-thin scrollbar-thumb-scrollbar",
6492
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
6493
6559
  props.className ?? ""
6494
6560
  )
6495
6561
  }
@@ -6539,18 +6605,20 @@ const meta$4 = ({
6539
6605
  matches
6540
6606
  }) => {
6541
6607
  var _a2;
6542
- if (!data) {
6543
- return [{ title: "📝 | Error" }];
6544
- }
6545
- const number = data.exercise.exerciseNumber.toString().padStart(2, "0");
6608
+ const number = data == null ? void 0 : data.exercise.exerciseNumber.toString().padStart(2, "0");
6546
6609
  const rootData = (_a2 = matches.find((m) => m.id === "root")) == null ? void 0 : _a2.data;
6547
- return [
6548
- {
6549
- title: `📝 | ${number}. ${data.exercise.title} | ${rootData == null ? void 0 : rootData.workshopTitle}`
6550
- }
6551
- ];
6610
+ if (!data || !rootData)
6611
+ return [{ title: "🦉 | Error" }];
6612
+ return getSeoMetaTags({
6613
+ title: `📝 | ${number}. ${data.exercise.title} | ${rootData == null ? void 0 : rootData.workshopTitle}`,
6614
+ description: `Elaboration for ${number}. ${data.exercise.title}`,
6615
+ ogTitle: data.exercise.title,
6616
+ ogDescription: `Elaboration for exercise ${Number(number)}`,
6617
+ instructor: rootData.instructor,
6618
+ requestInfo: rootData.requestInfo
6619
+ });
6552
6620
  };
6553
- async function loader$o({ request, params }) {
6621
+ async function loader$p({ request, params }) {
6554
6622
  const timings = makeTimings("exerciseNumberLoader");
6555
6623
  invariantResponse(params.exerciseNumber, "exerciseNumber is required");
6556
6624
  const [exercises, workshopTitle] = await Promise.all([
@@ -6694,10 +6762,10 @@ const route4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
6694
6762
  ErrorBoundary: ErrorBoundary$3,
6695
6763
  default: ExerciseNumberRoute,
6696
6764
  headers: headers$6,
6697
- loader: loader$o,
6765
+ loader: loader$p,
6698
6766
  meta: meta$4
6699
6767
  }, Symbol.toStringTag, { value: "Module" }));
6700
- async function loader$n({ request, params }) {
6768
+ async function loader$o({ request, params }) {
6701
6769
  const timings = makeTimings("stepLoader");
6702
6770
  invariantResponse(params.exerciseNumber, "exerciseNumber is required");
6703
6771
  const [exercises, workshopTitle] = await Promise.all([
@@ -6754,428 +6822,427 @@ const route5 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
6754
6822
  ErrorBoundary: ErrorBoundary$2,
6755
6823
  default: StepRoute,
6756
6824
  headers: headers$5,
6757
- loader: loader$n
6825
+ loader: loader$o
6758
6826
  }, Symbol.toStringTag, { value: "Module" }));
6759
- const EmojiDataSchema = z$1.union([
6760
- z$1.object({
6761
- emojiName: z$1.never().optional(),
6762
- emojiUrl: z$1.string()
6763
- }),
6764
- z$1.object({
6765
- emojiName: z$1.string(),
6766
- emojiUrl: z$1.never().optional()
6767
- }),
6768
- z$1.object({
6769
- emojiName: z$1.never().optional(),
6770
- emojiUrl: z$1.never().optional()
6771
- })
6772
- ]);
6773
- const ThreadItemSchema = z$1.object({
6774
- id: z$1.string(),
6775
- tags: z$1.array(
6776
- z$1.object({
6777
- name: z$1.string()
6778
- }).and(EmojiDataSchema)
6779
- ),
6780
- name: z$1.string(),
6781
- link: z$1.string(),
6782
- authorDisplayName: z$1.string(),
6783
- authorHexAccentColor: z$1.string().nullable().optional(),
6784
- authorAvatarUrl: z$1.string().nullable(),
6785
- messagePreview: z$1.string(),
6786
- messageCount: z$1.number(),
6787
- lastUpdated: z$1.string(),
6788
- previewImageUrl: z$1.string().nullable(),
6789
- reactions: z$1.array(
6790
- z$1.object({
6791
- count: z$1.number()
6792
- }).and(EmojiDataSchema)
6793
- )
6794
- });
6795
- const ThreadDataSchema = z$1.array(ThreadItemSchema);
6796
- const EpicForumResponseSchema = z$1.object({
6797
- status: z$1.literal("error"),
6798
- error: z$1.string()
6799
- }).or(
6800
- z$1.object({
6801
- status: z$1.literal("success"),
6802
- threadData: ThreadDataSchema
6803
- })
6804
- );
6805
- async function fetchDiscordPosts({ request }) {
6806
- return cachified({
6807
- key: "fetchDiscordPosts",
6808
- request,
6809
- cache: fsCache,
6810
- ttl: 1e3 * 60 * 2,
6811
- swr: 1e3 * 60 * 60 * 24 * 7,
6812
- checkValue: ThreadDataSchema,
6813
- async getFreshValue() {
6814
- const forceFresh = await shouldForceFresh({ request });
6815
- const searchParams = new URLSearchParams(
6816
- forceFresh ? { fresh: "true" } : {}
6817
- );
6818
- const result = await fetch(
6819
- // `http://localhost:3000/resources/epic-web-forum?${searchParams}`,
6820
- `https://kcd-discord-bot-v2.fly.dev/resources/epic-web-forum?${searchParams}`,
6821
- {
6822
- method: "POST",
6823
- headers: { "content-type": "application/json" }
6824
- }
6825
- );
6826
- if (!result.ok) {
6827
- console.error(`There was an error communicating with discord`);
6828
- try {
6829
- console.error(await result.text());
6830
- } catch {
6831
- }
6832
- return [];
6833
- }
6834
- const jsonResult = await result.json();
6835
- const epicForumResponseResult = EpicForumResponseSchema.safeParse(jsonResult);
6836
- if (epicForumResponseResult.success) {
6837
- if (epicForumResponseResult.data.status === "error") {
6838
- console.error(`There was an error communicating with discord`);
6839
- console.error(epicForumResponseResult.data.error);
6840
- return [];
6841
- } else {
6842
- return epicForumResponseResult.data.threadData;
6843
- }
6844
- } else {
6845
- console.error(`There was an error parsing the discord response`);
6846
- console.error(epicForumResponseResult.error.flatten());
6847
- return [];
6848
- }
6849
- }
6850
- });
6851
- }
6852
- const port = process.env.PORT || "5639";
6853
- const scope = "guilds.join identify messages.read";
6854
- const DiscordApiResponseSchema = z$1.object({
6855
- status: z$1.literal("error"),
6856
- error: z$1.string()
6857
- }).or(
6858
- z$1.object({
6859
- status: z$1.literal("success"),
6860
- member: DiscordMemberSchema
6861
- })
6862
- );
6863
- function getDiscordAuthURL() {
6864
- const discordAuthUrl = new URL("https://discord.com/oauth2/authorize");
6865
- discordAuthUrl.searchParams.append("client_id", "738096608440483870");
6866
- discordAuthUrl.searchParams.append(
6867
- "redirect_uri",
6868
- `http://localhost:${port}/discord/callback`
6869
- );
6870
- discordAuthUrl.searchParams.append("response_type", "code");
6871
- discordAuthUrl.searchParams.append("scope", scope);
6872
- return discordAuthUrl.toString();
6873
- }
6874
- async function loader$m({ request }) {
6875
- const authInfo = await requireAuthInfo({ request });
6876
- const discordCode = new URL(request.url).searchParams.get("code");
6877
- invariantResponse(discordCode, "Missing code");
6878
- const result = await fetch(
6879
- // 'http://localhost:3000/resources/connect-epic-web',
6880
- "https://kcd-discord-bot-v2.fly.dev/resources/connect-epic-web",
6881
- {
6882
- method: "POST",
6883
- headers: { "content-type": "application/json" },
6884
- body: JSON.stringify({
6885
- deviceToken: authInfo.tokenSet.access_token,
6886
- discordCode,
6887
- port,
6888
- scope
6889
- })
6890
- }
6891
- );
6892
- if (!result.ok) {
6893
- console.error(`There was an error connecting Discord`);
6894
- try {
6895
- console.error(await result.text());
6896
- } catch {
6827
+ const AccordionComponent = ({
6828
+ title,
6829
+ children,
6830
+ variant,
6831
+ icon,
6832
+ forceMount = false
6833
+ }) => {
6834
+ const getVariantIcon = () => {
6835
+ switch (variant) {
6836
+ case "changed":
6837
+ return /* @__PURE__ */ jsx(
6838
+ Icon,
6839
+ {
6840
+ name: "Modified",
6841
+ "aria-label": "Modified",
6842
+ className: "text-[#fb923c]"
6843
+ }
6844
+ );
6845
+ case "renamed":
6846
+ return /* @__PURE__ */ jsx(
6847
+ Icon,
6848
+ {
6849
+ name: "Renamed",
6850
+ "aria-label": "Renamed",
6851
+ className: "text-[#fb923c]"
6852
+ }
6853
+ );
6854
+ case "added":
6855
+ return /* @__PURE__ */ jsx(Icon, { name: "Added", "aria-label": "Added", className: "text-[#10b981]" });
6856
+ case "deleted":
6857
+ return /* @__PURE__ */ jsx(
6858
+ Icon,
6859
+ {
6860
+ name: "Deleted",
6861
+ "aria-label": "Deleted",
6862
+ className: "text-[#ef4444]"
6863
+ }
6864
+ );
6865
+ default:
6866
+ return /* @__PURE__ */ jsx(
6867
+ Icon,
6868
+ {
6869
+ name: "Modified",
6870
+ "aria-label": "Modified",
6871
+ className: "text-[#fb923c]"
6872
+ }
6873
+ );
6897
6874
  }
6898
- return redirectWithToast("/account", {
6899
- type: "error",
6900
- title: "Error",
6901
- description: `There was an error connecting your Discord account (details in terminal output). Please try again.`
6902
- });
6903
- }
6904
- const parseResult = DiscordApiResponseSchema.safeParse(await result.json());
6905
- if (!parseResult.success) {
6906
- console.error(`There was an error connecting Discord`);
6907
- console.error(parseResult.error);
6908
- return redirectWithToast("/account", {
6909
- type: "error",
6910
- title: "Error",
6911
- description: `There was an error connecting your Discord account (details in terminal output). Please try again.`
6912
- });
6913
- }
6914
- if (parseResult.data.status === "error") {
6915
- console.error(`There was an error connecting Discord`);
6916
- console.error(parseResult.data.error);
6917
- return redirect("/account?error");
6918
- }
6919
- const member = parseResult.data.member;
6920
- await setDiscordMember(member);
6921
- return redirectWithToast("/account", {
6922
- type: "success",
6923
- title: "Success",
6924
- description: `Your Discord account "${member.displayName}" has been connected!`
6925
- });
6926
- }
6927
- const route24 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
6928
- __proto__: null,
6929
- getDiscordAuthURL,
6930
- loader: loader$m
6931
- }, Symbol.toStringTag, { value: "Module" }));
6932
- async function loader$l() {
6933
- return json({ discordAuthUrl: getDiscordAuthURL() });
6934
- }
6935
- function useDiscordCTALink({
6936
- discordAuthUrl
6937
- }) {
6938
- const user = useOptionalUser();
6939
- const discordMember = useOptionalDiscordMember();
6940
- if (!user) {
6941
- return "/login";
6942
- }
6943
- if (!discordMember) {
6944
- return discordAuthUrl;
6945
- }
6946
- return "https://discord.com/channels/715220730605731931/1161045224907341972";
6947
- }
6948
- function DiscordCTA({ discordAuthUrl }) {
6949
- const user = useOptionalUser();
6950
- const discordMember = useOptionalDiscordMember();
6951
- if (!user) {
6952
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2 text-xl", children: [
6953
- /* @__PURE__ */ jsxs(Link, { to: "/login", className: "inline-flex items-center gap-2 underline", children: [
6954
- /* @__PURE__ */ jsx(Icon, { name: "Discord", size: "2xl" }),
6955
- "Login"
6956
- ] }),
6957
- " ",
6958
- /* @__PURE__ */ jsxs("span", { children: [
6959
- "to get access to the exclusive",
6960
- " ",
6961
- /* @__PURE__ */ jsx(Link, { to: "/discord", className: "underline", children: "discord channel" }),
6962
- "."
6963
- ] })
6964
- ] });
6965
- }
6966
- if (!discordMember) {
6967
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2 text-xl", children: [
6968
- /* @__PURE__ */ jsxs(Link, { to: discordAuthUrl, className: "flex items-center gap-2 underline", children: [
6969
- /* @__PURE__ */ jsx(Icon, { name: "Discord", size: "2xl" }),
6970
- "Connect Discord"
6971
- ] }),
6875
+ };
6876
+ const getVariantLabel = () => {
6877
+ switch (variant) {
6878
+ case "changed":
6879
+ return "modified";
6880
+ default:
6881
+ return variant;
6882
+ }
6883
+ };
6884
+ const fixedTitle = title.replace(/\\\\/g, "\\");
6885
+ return /* @__PURE__ */ jsxs(Accordion.Item, { value: title, children: [
6886
+ /* @__PURE__ */ jsxs(AccordionTrigger, { variant: getVariantLabel(), children: [
6887
+ icon ? icon : getVariantIcon(),
6972
6888
  " ",
6973
- /* @__PURE__ */ jsxs("span", { children: [
6974
- "to get access to the exclusive",
6975
- " ",
6976
- /* @__PURE__ */ jsx(Link, { to: "/discord", className: "underline", children: "discord channel" }),
6977
- "."
6978
- ] })
6979
- ] });
6980
- }
6981
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2 text-xl underline", children: [
6982
- /* @__PURE__ */ jsx(Link, { to: "discord://discord.com/channels/715220730605731931/1161045224907341972", children: /* @__PURE__ */ jsx(Icon, { name: "Discord", size: "2xl" }) }),
6889
+ fixedTitle
6890
+ ] }),
6983
6891
  /* @__PURE__ */ jsx(
6984
- Link,
6892
+ AccordionContent,
6985
6893
  {
6986
- to: "https://discord.com/channels/715220730605731931/1161045224907341972",
6987
- target: "_blank",
6988
- rel: "noreferrer noopener",
6989
- children: "Open Discord"
6894
+ forceMount,
6895
+ className: clsx(
6896
+ "prose max-w-none whitespace-pre-wrap dark:prose-invert prose-pre:m-0 prose-pre:mb-1 prose-pre:rounded-none",
6897
+ {
6898
+ "radix-state-closed:hidden": forceMount
6899
+ }
6900
+ ),
6901
+ children
6990
6902
  }
6991
6903
  )
6992
6904
  ] });
6993
- }
6994
- function DiscordRoute() {
6995
- const data = useLoaderData();
6996
- return /* @__PURE__ */ jsxs("div", { className: "container flex h-full max-w-3xl flex-col items-center justify-center gap-4 p-12", children: [
6997
- /* @__PURE__ */ jsx(DiscordCTA, { discordAuthUrl: data.discordAuthUrl }),
6998
- /* @__PURE__ */ jsxs("p", { children: [
6999
- "The",
7000
- " ",
7001
- /* @__PURE__ */ jsx(
7002
- Link,
7003
- {
7004
- target: "_blank",
7005
- rel: "noreferrer noopener",
7006
- className: "underline",
7007
- to: "https://kentcdodds.com/discord",
7008
- children: "Epic Web Community on Discord"
7009
- }
6905
+ };
6906
+ const AccordionTrigger = React.forwardRef(
6907
+ ({ children, className, variant, ...props }, forwardedRef) => /* @__PURE__ */ jsx(Accordion.Header, { className: "flex", asChild: true, children: /* @__PURE__ */ jsxs(
6908
+ Accordion.Trigger,
6909
+ {
6910
+ className: clsx(
6911
+ "group flex w-full items-center justify-between border-b p-4 pr-3 font-mono text-sm font-medium leading-none hover:bg-foreground/20",
6912
+ className
7010
6913
  ),
7011
- " ",
7012
- "is a great place to hang out with other developers who are working through this workshop. You can ask questions, get help, and solidify what you're learning by helping others."
7013
- ] }),
7014
- /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsxs("small", { className: "text-sm", children: [
7015
- "If you've not joined the Epic Web Community on Discord yet, you'll be required to go through a short onboarding process first. A friendly bot will explain the process when you",
7016
- " ",
7017
- /* @__PURE__ */ jsx(
7018
- Link,
6914
+ ...props,
6915
+ ref: forwardedRef,
6916
+ children: [
6917
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5", children }),
6918
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
6919
+ /* @__PURE__ */ jsx("span", { className: "font-mono text-xs font-normal uppercase text-muted-foreground", children: variant }),
6920
+ /* @__PURE__ */ jsx(
6921
+ Icon,
6922
+ {
6923
+ name: "TriangleDownSmall",
6924
+ className: "transition group-radix-state-open:rotate-180",
6925
+ "aria-hidden": true
6926
+ }
6927
+ )
6928
+ ] })
6929
+ ]
6930
+ }
6931
+ ) })
6932
+ );
6933
+ const AccordionContent = React.forwardRef(
6934
+ ({ children, className, ...props }, forwardedRef) => /* @__PURE__ */ jsx(
6935
+ Accordion.Content,
6936
+ {
6937
+ className: clsx("", className),
6938
+ ...props,
6939
+ ref: forwardedRef,
6940
+ children: /* @__PURE__ */ jsx("div", { children })
6941
+ }
6942
+ )
6943
+ );
6944
+ const pre = (props) => /* @__PURE__ */ jsx("pre", { ...props });
6945
+ const mdxComponents$3 = {
6946
+ Accordion: AccordionComponent,
6947
+ // override the pre-with-buttons
6948
+ pre
6949
+ };
6950
+ function Diff({
6951
+ diff,
6952
+ allApps
6953
+ }) {
6954
+ const submit = useSubmit();
6955
+ const [params] = useSearchParams();
6956
+ const paramsWithForcedRefresh = new URLSearchParams(params);
6957
+ paramsWithForcedRefresh.set("forceFresh", "diff");
6958
+ const navigation = useNavigation();
6959
+ const spinnerNavigating = useSpinDelay(navigation.state !== "idle", {
6960
+ delay: 0,
6961
+ minDuration: 1e3
6962
+ });
6963
+ const hiddenInputs = [];
6964
+ for (const [key, value] of params.entries()) {
6965
+ if (key === "app1" || key === "app2")
6966
+ continue;
6967
+ hiddenInputs.push(
6968
+ /* @__PURE__ */ jsx("input", { type: "hidden", name: key, value }, key)
6969
+ );
6970
+ }
6971
+ return /* @__PURE__ */ jsx(
6972
+ Suspense,
6973
+ {
6974
+ fallback: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center p-8", children: /* @__PURE__ */ jsx(SimpleTooltip, { content: "Loading diff", children: /* @__PURE__ */ jsx(Icon, { name: "Refresh", className: "animate-spin" }) }) }),
6975
+ children: /* @__PURE__ */ jsx(
6976
+ Await,
7019
6977
  {
7020
- to: "https://kcd.im/discord",
7021
- target: "_blank",
7022
- rel: "noreferrer noopener",
7023
- className: "underline",
7024
- children: "join"
6978
+ resolve: diff,
6979
+ errorElement: /* @__PURE__ */ jsx("p", { className: "p-6 text-foreground-danger", children: "There was an error calculating the diff. Sorry." }),
6980
+ children: (diff2) => /* @__PURE__ */ jsxs("div", { className: "flex h-full w-full flex-col", children: [
6981
+ /* @__PURE__ */ jsxs("div", { className: "flex h-14 min-h-14 w-full overflow-x-hidden border-b", children: [
6982
+ /* @__PURE__ */ jsx("div", { className: "border-r", children: /* @__PURE__ */ jsx(SimpleTooltip, { content: "Reload diff", children: /* @__PURE__ */ jsx(
6983
+ Link,
6984
+ {
6985
+ to: `.?${paramsWithForcedRefresh}`,
6986
+ className: "flex h-full w-14 items-center justify-center",
6987
+ children: /* @__PURE__ */ jsx(
6988
+ Icon,
6989
+ {
6990
+ name: "Refresh",
6991
+ className: cn({ "animate-spin": spinnerNavigating })
6992
+ }
6993
+ )
6994
+ }
6995
+ ) }) }),
6996
+ /* @__PURE__ */ jsxs(
6997
+ Form,
6998
+ {
6999
+ onChange: (e) => submit(e.currentTarget),
7000
+ className: "flex h-full flex-1 items-center overflow-x-auto scrollbar-thin scrollbar-thumb-scrollbar",
7001
+ children: [
7002
+ hiddenInputs,
7003
+ /* @__PURE__ */ jsx(
7004
+ SelectFileToDiff,
7005
+ {
7006
+ name: "app1",
7007
+ label: "App 1",
7008
+ className: "border-r",
7009
+ allApps,
7010
+ defaultValue: diff2.app1
7011
+ }
7012
+ ),
7013
+ /* @__PURE__ */ jsx(
7014
+ SelectFileToDiff,
7015
+ {
7016
+ name: "app2",
7017
+ label: "App 2",
7018
+ allApps,
7019
+ defaultValue: diff2.app2
7020
+ }
7021
+ )
7022
+ ]
7023
+ },
7024
+ `${diff2.app1}${diff2.app2}`
7025
+ )
7026
+ ] }),
7027
+ /* @__PURE__ */ jsx("div", { className: "flex-grow overflow-y-scroll scrollbar-thin scrollbar-thumb-scrollbar", children: diff2.diffCode ? /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Accordion.Root, { className: "w-full", type: "multiple", children: /* @__PURE__ */ jsx(Mdx, { code: diff2.diffCode, components: mdxComponents$3 }) }) }) : diff2.app1 && diff2.app2 ? /* @__PURE__ */ jsx("p", { className: "m-5 inline-flex items-center justify-center bg-foreground px-1 py-0.5 font-mono text-sm uppercase text-background", children: "There was a problem generating the diff" }) : /* @__PURE__ */ jsx("p", { className: "m-5 inline-flex items-center justify-center bg-foreground px-1 py-0.5 font-mono text-sm uppercase text-background", children: "Select two apps to compare" }) })
7028
+ ] })
7025
7029
  }
7026
- ),
7027
- "."
7028
- ] }) })
7029
- ] });
7030
+ )
7031
+ }
7032
+ );
7030
7033
  }
7031
- const route15 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
7032
- __proto__: null,
7033
- DiscordCTA,
7034
- default: DiscordRoute,
7035
- loader: loader$l,
7036
- useDiscordCTALink
7037
- }, Symbol.toStringTag, { value: "Module" }));
7038
- function DiscordChat() {
7039
- const data = useLoaderData();
7040
- return /* @__PURE__ */ jsxs("div", { className: "flex h-full w-full flex-col gap-4 pt-4", children: [
7041
- /* @__PURE__ */ jsx("div", { className: "text-center", children: /* @__PURE__ */ jsx(DiscordCTA, { discordAuthUrl: data.discordAuthUrl }) }),
7042
- /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-scroll bg-accent pb-4 scrollbar-thin scrollbar-thumb-scrollbar", children: /* @__PURE__ */ jsx(DiscordPosts, {}) })
7034
+ function SelectFileToDiff({
7035
+ name,
7036
+ label,
7037
+ className,
7038
+ allApps,
7039
+ defaultValue
7040
+ }) {
7041
+ return /* @__PURE__ */ jsxs(Select.Root, { name, defaultValue, children: [
7042
+ /* @__PURE__ */ jsxs(
7043
+ Select.Trigger,
7044
+ {
7045
+ className: clsx(
7046
+ "flex h-full w-full max-w-[50%] items-center justify-between px-3 text-left radix-placeholder:text-gray-500 focus-visible:outline-none",
7047
+ className
7048
+ ),
7049
+ "aria-label": `Select ${label} for git Diff`,
7050
+ children: [
7051
+ /* @__PURE__ */ jsxs("span", { className: "overflow-hidden text-ellipsis whitespace-nowrap", children: [
7052
+ label,
7053
+ ":",
7054
+ " ",
7055
+ /* @__PURE__ */ jsx(
7056
+ SelectValue,
7057
+ {
7058
+ placeholder: `Select ${label}`,
7059
+ className: "inline-block w-40 text-ellipsis"
7060
+ }
7061
+ )
7062
+ ] }),
7063
+ /* @__PURE__ */ jsx(Select.Icon, { className: "", children: /* @__PURE__ */ jsx(Icon, { name: "TriangleDownSmall" }) })
7064
+ ]
7065
+ }
7066
+ ),
7067
+ /* @__PURE__ */ jsx(Select.Portal, { children: /* @__PURE__ */ jsxs(
7068
+ Select.Content,
7069
+ {
7070
+ position: "popper",
7071
+ align: "start",
7072
+ className: "z-20 max-h-[50vh] bg-black text-white lg:max-h-[70vh]",
7073
+ children: [
7074
+ /* @__PURE__ */ jsx(Select.ScrollUpButton, { className: "flex h-5 cursor-default items-center justify-center ", children: /* @__PURE__ */ jsx(Icon, { name: "ChevronUp" }) }),
7075
+ /* @__PURE__ */ jsx(Select.Viewport, { className: "p-3", children: /* @__PURE__ */ jsxs(Select.Group, { children: [
7076
+ /* @__PURE__ */ jsx(Select.Label, { className: "px-5 pb-3 font-mono uppercase", children: label }),
7077
+ allApps.map((app) => {
7078
+ return /* @__PURE__ */ jsx(SelectItem$1, { value: app.name, children: app.displayName }, app.name);
7079
+ })
7080
+ ] }) }),
7081
+ /* @__PURE__ */ jsx(Select.ScrollDownButton, { className: "flex h-5 cursor-default items-center justify-center ", children: /* @__PURE__ */ jsx(Icon, { name: "ChevronDown" }) })
7082
+ ]
7083
+ }
7084
+ ) })
7043
7085
  ] });
7044
7086
  }
7045
- function DiscordPosts() {
7046
- const data = useLoaderData();
7047
- const ctaLink = useDiscordCTALink({ discordAuthUrl: data.discordAuthUrl });
7048
- const altDown = useAltDown();
7049
- return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col items-center justify-between", children: [
7050
- /* @__PURE__ */ jsx(
7051
- React.Suspense,
7087
+ const SelectItem$1 = React__default.forwardRef(
7088
+ ({ children, className, ...props }, forwardedRef) => {
7089
+ return /* @__PURE__ */ jsxs(
7090
+ Select.Item,
7052
7091
  {
7053
- fallback: /* @__PURE__ */ jsx("div", { className: "flex h-full w-full flex-col items-center justify-center", children: /* @__PURE__ */ jsx(Loading, { children: "Loading Discord Posts" }) }),
7054
- children: /* @__PURE__ */ jsx(
7055
- Await,
7056
- {
7057
- resolve: data.discordPostsPromise,
7058
- errorElement: /* @__PURE__ */ jsx("div", { className: "text-red-500", children: "There was a problem loading the discord posts" }),
7059
- children: (posts) => /* @__PURE__ */ jsx("ul", { className: "flex w-full flex-col gap-4 p-3 xl:p-12", children: posts.map((post) => /* @__PURE__ */ jsx(
7060
- "li",
7061
- {
7062
- className: "rounded-xl border bg-background transition-all duration-200 focus-within:-translate-y-1 focus-within:shadow-lg hover:-translate-y-1 hover:shadow-lg",
7063
- children: /* @__PURE__ */ jsx(DiscordPost, { thread: post })
7064
- },
7065
- post.id
7066
- )) })
7067
- }
7068
- )
7092
+ className: clsx(
7093
+ "relative flex cursor-pointer select-none items-center rounded px-10 py-2 leading-none opacity-80 radix-disabled:text-red-500 radix-highlighted:opacity-100 radix-highlighted:outline-none radix-state-checked:opacity-100",
7094
+ className
7095
+ ),
7096
+ ...props,
7097
+ ref: forwardedRef,
7098
+ children: [
7099
+ /* @__PURE__ */ jsx(Select.ItemText, { children }),
7100
+ /* @__PURE__ */ jsx(Select.ItemIndicator, { className: "absolute left-0 inline-flex w-[25px] items-center justify-center", children: /* @__PURE__ */ jsx(Icon, { name: "CheckSmall" }) })
7101
+ ]
7102
+ }
7103
+ );
7104
+ }
7105
+ );
7106
+ const SelectValue = React__default.forwardRef(
7107
+ ({ children, className, ...props }, forwardedRef) => {
7108
+ return /* @__PURE__ */ jsx(Select.Value, { ...props, ref: forwardedRef, children: props.value });
7109
+ }
7110
+ );
7111
+ function NavChevrons({
7112
+ prev,
7113
+ next
7114
+ }) {
7115
+ return /* @__PURE__ */ jsxs("div", { className: "relative flex h-full overflow-hidden", children: [
7116
+ prev ? /* @__PURE__ */ jsx(
7117
+ Link,
7118
+ {
7119
+ prefetch: "intent",
7120
+ ...prev,
7121
+ className: "group flex h-full items-center justify-center border-l px-7",
7122
+ children: /* @__PURE__ */ jsxs(Fragment, { children: [
7123
+ /* @__PURE__ */ jsx(
7124
+ Icon,
7125
+ {
7126
+ name: "ChevronLeft",
7127
+ className: "absolute opacity-100 transition duration-300 ease-in-out group-hover:translate-y-10 group-hover:opacity-0"
7128
+ }
7129
+ ),
7130
+ /* @__PURE__ */ jsx(
7131
+ Icon,
7132
+ {
7133
+ name: "ChevronLeft",
7134
+ className: "absolute -translate-y-10 opacity-0 transition duration-300 ease-in-out group-hover:translate-y-0 group-hover:opacity-100"
7135
+ }
7136
+ )
7137
+ ] })
7069
7138
  }
7070
- ),
7071
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
7139
+ ) : null,
7140
+ next ? /* @__PURE__ */ jsx(
7072
7141
  Link,
7073
7142
  {
7074
- to: altDown && !ctaLink.includes("oauth") ? ctaLink.replace(/^https/, "discord") : ctaLink,
7075
- target: ctaLink.includes("oauth") ? void 0 : "_blank",
7076
- rel: "noreferrer noopener",
7077
- onClick: altDown ? (e) => {
7078
- e.preventDefault();
7079
- window.open(
7080
- e.currentTarget.href,
7081
- "_blank",
7082
- "noreferrer noopener"
7083
- );
7084
- } : void 0,
7085
- className: "flex items-center gap-2 p-2 text-xl hover:underline",
7086
- children: [
7087
- "Create Post ",
7088
- /* @__PURE__ */ jsx(Icon, { name: "ExternalLink" })
7089
- ]
7143
+ prefetch: "intent",
7144
+ ...next,
7145
+ className: "group flex h-full items-center justify-center border-l px-7",
7146
+ children: /* @__PURE__ */ jsxs(Fragment, { children: [
7147
+ /* @__PURE__ */ jsx(
7148
+ Icon,
7149
+ {
7150
+ name: "ChevronRight",
7151
+ className: "absolute opacity-100 transition duration-300 ease-in-out group-hover:translate-y-10 group-hover:opacity-0"
7152
+ }
7153
+ ),
7154
+ /* @__PURE__ */ jsx(
7155
+ Icon,
7156
+ {
7157
+ name: "ChevronRight",
7158
+ className: "absolute -translate-y-10 opacity-0 transition duration-300 ease-in-out group-hover:translate-y-0 group-hover:opacity-100"
7159
+ }
7160
+ )
7161
+ ] })
7090
7162
  }
7091
- ) })
7163
+ ) : null
7092
7164
  ] });
7093
7165
  }
7094
- function DiscordPost({ thread }) {
7095
- const reactionsWithCounts = thread.reactions.filter((r) => r.count);
7096
- const hints = useHints();
7097
- return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 p-4", children: [
7098
- /* @__PURE__ */ jsxs("div", { className: "flex gap-4", children: [
7099
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
7100
- thread.tags.length ? /* @__PURE__ */ jsx("div", { className: "flex gap-2", children: thread.tags.map((t) => /* @__PURE__ */ jsxs(
7101
- "div",
7102
- {
7103
- className: "flex items-center justify-center gap-1 rounded-full bg-accent px-2 py-1 text-sm",
7104
- children: [
7105
- /* @__PURE__ */ jsx("span", { className: "h-3 w-3 leading-3", children: /* @__PURE__ */ jsx(Emoji, { name: t.emojiName, url: t.emojiUrl }) }),
7106
- /* @__PURE__ */ jsx("span", { children: t.name })
7107
- ]
7108
- },
7109
- t.name
7110
- )) }) : null,
7111
- /* @__PURE__ */ jsx("strong", { className: "text-xl font-bold", children: thread.name }),
7112
- /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-1", children: [
7113
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
7114
- thread.authorAvatarUrl ? /* @__PURE__ */ jsx(
7115
- "img",
7116
- {
7117
- src: thread.authorAvatarUrl,
7118
- alt: "",
7119
- className: "h-6 w-6 rounded-full"
7120
- }
7121
- ) : null,
7122
- /* @__PURE__ */ jsxs("span", { children: [
7123
- /* @__PURE__ */ jsx(
7124
- "span",
7125
- {
7126
- className: "font-bold",
7127
- style: thread.authorHexAccentColor ? { color: thread.authorHexAccentColor } : {},
7128
- children: thread.authorDisplayName
7129
- }
7130
- ),
7131
- ":",
7132
- " "
7133
- ] })
7134
- ] }),
7135
- /* @__PURE__ */ jsx("span", { className: "flex-1 overflow-ellipsis text-muted-foreground", children: thread.messagePreview })
7136
- ] })
7137
- ] }),
7138
- thread.previewImageUrl ? /* @__PURE__ */ jsx(
7139
- "img",
7140
- {
7141
- src: thread.previewImageUrl,
7142
- alt: "",
7143
- className: "h-28 w-28 rounded-lg object-cover"
7144
- }
7145
- ) : null
7146
- ] }),
7147
- /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
7148
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
7149
- /* @__PURE__ */ jsx("span", { children: reactionsWithCounts.length ? /* @__PURE__ */ jsx("ul", { className: "flex items-center gap-2", children: reactionsWithCounts.map((r, i) => /* @__PURE__ */ jsxs(
7150
- "li",
7151
- {
7152
- className: "flex items-center gap-1 rounded-md border border-blue-600 bg-blue-500/20 px-[5px] py-[0.5px] text-sm",
7153
- children: [
7154
- /* @__PURE__ */ jsx("span", { className: "h-3 w-3 leading-3", children: /* @__PURE__ */ jsx(Emoji, { name: r.emojiName, url: r.emojiUrl }) }),
7155
- /* @__PURE__ */ jsx("span", { children: r.count })
7156
- ]
7157
- },
7158
- i
7159
- )) }) : null }),
7160
- /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
7161
- /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1", children: [
7162
- /* @__PURE__ */ jsx(Icon, { name: "Chat" }),
7163
- " ",
7164
- thread.messageCount
7165
- ] }),
7166
- ` · ${dayjs(thread.lastUpdated).tz(hints.timeZone).fromNow()}`
7167
- ] })
7168
- ] }),
7169
- /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-4", children: [
7170
- /* @__PURE__ */ jsx("a", { href: thread.link.replace(/^https/, "discord"), children: /* @__PURE__ */ jsx(Icon, { name: "Discord" }) }),
7171
- /* @__PURE__ */ jsx("a", { href: thread.link, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ jsx(Icon, { name: "ExternalLink" }) })
7172
- ] })
7173
- ] })
7174
- ] }) });
7166
+ const port = process.env.PORT || "5639";
7167
+ const scope = "guilds.join identify messages.read";
7168
+ const DiscordApiResponseSchema = z$1.object({
7169
+ status: z$1.literal("error"),
7170
+ error: z$1.string()
7171
+ }).or(
7172
+ z$1.object({
7173
+ status: z$1.literal("success"),
7174
+ member: DiscordMemberSchema
7175
+ })
7176
+ );
7177
+ function getDiscordAuthURL() {
7178
+ const discordAuthUrl = new URL("https://discord.com/oauth2/authorize");
7179
+ discordAuthUrl.searchParams.append("client_id", "738096608440483870");
7180
+ discordAuthUrl.searchParams.append(
7181
+ "redirect_uri",
7182
+ `http://localhost:${port}/discord/callback`
7183
+ );
7184
+ discordAuthUrl.searchParams.append("response_type", "code");
7185
+ discordAuthUrl.searchParams.append("scope", scope);
7186
+ return discordAuthUrl.toString();
7175
7187
  }
7176
- function Emoji({ name, url }) {
7177
- return url ? /* @__PURE__ */ jsx("img", { src: url, alt: name, className: "h-full w-full" }) : name ? name : null;
7188
+ async function loader$n({ request }) {
7189
+ const authInfo = await requireAuthInfo({ request });
7190
+ const discordCode = new URL(request.url).searchParams.get("code");
7191
+ invariantResponse(discordCode, "Missing code");
7192
+ const result = await fetch(
7193
+ // 'http://localhost:3000/resources/connect-epic-web',
7194
+ "https://kcd-discord-bot-v2.fly.dev/resources/connect-epic-web",
7195
+ {
7196
+ method: "POST",
7197
+ headers: { "content-type": "application/json" },
7198
+ body: JSON.stringify({
7199
+ deviceToken: authInfo.tokenSet.access_token,
7200
+ discordCode,
7201
+ port,
7202
+ scope
7203
+ })
7204
+ }
7205
+ );
7206
+ if (!result.ok) {
7207
+ console.error(`There was an error connecting Discord`);
7208
+ try {
7209
+ console.error(await result.text());
7210
+ } catch {
7211
+ }
7212
+ return redirectWithToast("/account", {
7213
+ type: "error",
7214
+ title: "Error",
7215
+ description: `There was an error connecting your Discord account (details in terminal output). Please try again.`
7216
+ });
7217
+ }
7218
+ const parseResult = DiscordApiResponseSchema.safeParse(await result.json());
7219
+ if (!parseResult.success) {
7220
+ console.error(`There was an error connecting Discord`);
7221
+ console.error(parseResult.error);
7222
+ return redirectWithToast("/account", {
7223
+ type: "error",
7224
+ title: "Error",
7225
+ description: `There was an error connecting your Discord account (details in terminal output). Please try again.`
7226
+ });
7227
+ }
7228
+ if (parseResult.data.status === "error") {
7229
+ console.error(`There was an error connecting Discord`);
7230
+ console.error(parseResult.data.error);
7231
+ return redirect("/account?error");
7232
+ }
7233
+ const member = parseResult.data.member;
7234
+ await setDiscordMember(member);
7235
+ return redirectWithToast("/account", {
7236
+ type: "success",
7237
+ title: "Success",
7238
+ description: `Your Discord account "${member.displayName}" has been connected!`
7239
+ });
7178
7240
  }
7241
+ const route24 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
7242
+ __proto__: null,
7243
+ getDiscordAuthURL,
7244
+ loader: loader$n
7245
+ }, Symbol.toStringTag, { value: "Module" }));
7179
7246
  const epicshopTempDir = path.join(os.tmpdir(), "epicshop");
7180
7247
  const isDeployed = ENV.EPICSHOP_DEPLOYED;
7181
7248
  const diffTmpDir = path.join(epicshopTempDir, "diff");
@@ -7235,10 +7302,7 @@ function getFileCodeblocks(file, filePathApp1, filePathApp2, type) {
7235
7302
  type === "AddedFile" ? `Binary file added` : type === "DeletedFile" ? "Binary file deleted" : "Binary file changed"
7236
7303
  );
7237
7304
  } else {
7238
- startLine = chunk.type === "Chunk" ? chunk.fromFileRange.start : (
7239
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
7240
- chunk.type === "CombinedChunk" ? chunk.fromFileRangeA.start : 1
7241
- );
7305
+ startLine = chunk.type === "Chunk" ? chunk.fromFileRange.start : chunk.type === "CombinedChunk" ? chunk.fromFileRangeA.start : 1;
7242
7306
  toStartLine = chunk.toFileRange.start;
7243
7307
  for (let lineNumber = 0; lineNumber < chunk.changes.length; lineNumber++) {
7244
7308
  const change = chunk.changes[lineNumber];
@@ -7410,345 +7474,684 @@ async function getDiffFiles(app1, app2, {
7410
7474
  function getAppTestFiles(app) {
7411
7475
  return app.test.type === "browser" ? app.test.testFiles : [];
7412
7476
  }
7413
- async function getDiffFilesImpl(app1, app2) {
7477
+ async function getDiffFilesImpl(app1, app2) {
7478
+ if (app1.name === app2.name) {
7479
+ return [];
7480
+ }
7481
+ const { app1CopyPath, app2CopyPath } = await prepareForDiff(app1, app2);
7482
+ const { stdout: diffOutput } = await execa(
7483
+ "git",
7484
+ ["diff", "--no-index", "--ignore-blank-lines", app1CopyPath, app2CopyPath],
7485
+ { cwd: diffTmpDir }
7486
+ // --no-index implies --exit-code, so we need to use the error output
7487
+ ).catch((e) => e);
7488
+ void fsExtra.remove(app1CopyPath);
7489
+ void fsExtra.remove(app2CopyPath);
7490
+ const typesMap = {
7491
+ ChangedFile: "modified",
7492
+ AddedFile: "added",
7493
+ DeletedFile: "deleted",
7494
+ RenamedFile: "renamed"
7495
+ };
7496
+ const parsed = parseGitDiff(diffOutput, { noPrefix: true });
7497
+ const testFiles = Array.from(
7498
+ /* @__PURE__ */ new Set([...getAppTestFiles(app1), ...getAppTestFiles(app2)])
7499
+ );
7500
+ const startLine = (file) => {
7501
+ const chunk = file.type === "ChangedFile" && file.chunks[0];
7502
+ if (chunk) {
7503
+ return chunk.type === "Chunk" ? chunk.fromFileRange.start : chunk.type === "CombinedChunk" ? chunk.fromFileRangeA.start : 1;
7504
+ }
7505
+ return 1;
7506
+ };
7507
+ return parsed.files.map((file) => ({
7508
+ // prettier-ignore
7509
+ status: typesMap[file.type] ?? "unknown",
7510
+ path: diffPathToRelative(
7511
+ file.type === "RenamedFile" ? file.pathBefore : file.path
7512
+ ),
7513
+ line: startLine(file)
7514
+ })).filter((file) => !testFiles.includes(file.path));
7515
+ }
7516
+ async function getDiffCode(app1, app2, {
7517
+ forceFresh = false,
7518
+ timings,
7519
+ request
7520
+ } = {}) {
7521
+ const key = `${app1.relativePath}__vs__${app2.relativePath}`;
7522
+ const cacheEntry = diffCodeCache.get(key);
7523
+ const result = await cachified({
7524
+ key,
7525
+ cache: diffCodeCache,
7526
+ forceFresh: forceFresh || getForceFreshForDiff(app1, app2, cacheEntry),
7527
+ timings,
7528
+ request,
7529
+ getFreshValue: () => getDiffCodeImpl(app1, app2)
7530
+ });
7531
+ return result;
7532
+ }
7533
+ async function getDiffCodeImpl(app1, app2) {
7534
+ const markdownLines = [""];
7414
7535
  if (app1.name === app2.name) {
7415
- return [];
7536
+ markdownLines.push(
7537
+ '<p className="p-4 text-center">You are comparing the same app</p>'
7538
+ );
7539
+ const code2 = await compileMarkdownString(markdownLines.join("\n"));
7540
+ return code2;
7416
7541
  }
7417
7542
  const { app1CopyPath, app2CopyPath } = await prepareForDiff(app1, app2);
7418
7543
  const { stdout: diffOutput } = await execa(
7419
7544
  "git",
7420
- ["diff", "--no-index", "--ignore-blank-lines", app1CopyPath, app2CopyPath],
7545
+ [
7546
+ "diff",
7547
+ "--no-index",
7548
+ app1CopyPath,
7549
+ app2CopyPath,
7550
+ "--color=never",
7551
+ "--color-moved-ws=allow-indentation-change",
7552
+ "--no-prefix",
7553
+ "--ignore-blank-lines"
7554
+ ],
7421
7555
  { cwd: diffTmpDir }
7422
7556
  // --no-index implies --exit-code, so we need to use the error output
7423
7557
  ).catch((e) => e);
7424
7558
  void fsExtra.remove(app1CopyPath);
7425
7559
  void fsExtra.remove(app2CopyPath);
7426
- const typesMap = {
7427
- ChangedFile: "modified",
7428
- AddedFile: "added",
7429
- DeletedFile: "deleted",
7430
- RenamedFile: "renamed"
7560
+ const parsed = parseGitDiff(diffOutput);
7561
+ if (!parsed.files.length) {
7562
+ markdownLines.push(
7563
+ '<div className="m-5 inline-flex items-center justify-center bg-foreground px-1 py-0.5 font-mono text-sm uppercase text-background">No changes</div>'
7564
+ );
7565
+ }
7566
+ const app1TestFiles = getAppTestFiles(app1);
7567
+ const app2TestFiles = getAppTestFiles(app2);
7568
+ for (const file of parsed.files) {
7569
+ const pathToCopy = file.type === "RenamedFile" ? file.pathBefore : file.path;
7570
+ const relativePath = diffPathToRelative(pathToCopy);
7571
+ if (app1TestFiles.includes(relativePath))
7572
+ continue;
7573
+ const filePathApp1 = path.join(app1.fullPath, relativePath);
7574
+ const pathToApp2 = file.type === "RenamedFile" ? file.pathAfter : file.path;
7575
+ const relativePathApp2 = diffPathToRelative(pathToApp2);
7576
+ if (app2TestFiles.includes(relativePathApp2))
7577
+ continue;
7578
+ const filePathApp2 = path.join(app2.fullPath, relativePathApp2);
7579
+ switch (file.type) {
7580
+ case "ChangedFile": {
7581
+ markdownLines.push(`
7582
+
7583
+ <Accordion title=${JSON.stringify(relativePath)} variant="changed">
7584
+
7585
+ ${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join("\n")}
7586
+
7587
+ </Accordion>
7588
+
7589
+ `);
7590
+ break;
7591
+ }
7592
+ case "DeletedFile": {
7593
+ markdownLines.push(`
7594
+ <Accordion title=${JSON.stringify(relativePath)} variant="deleted">
7595
+
7596
+ ${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join("\n")}
7597
+
7598
+ </Accordion>
7599
+ `);
7600
+ break;
7601
+ }
7602
+ case "RenamedFile": {
7603
+ const relativeBefore = diffPathToRelative(file.pathBefore);
7604
+ const relativeAfter = diffPathToRelative(file.pathAfter);
7605
+ const title = JSON.stringify(`${relativeBefore} ▶️ ${relativeAfter}`);
7606
+ markdownLines.push(`
7607
+ <Accordion title=${title} variant="renamed">
7608
+
7609
+ ${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join("\n")}
7610
+
7611
+ </Accordion>
7612
+ `);
7613
+ break;
7614
+ }
7615
+ case "AddedFile": {
7616
+ markdownLines.push(`
7617
+ <Accordion title=${JSON.stringify(relativePath)} variant="added">
7618
+
7619
+ ${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join("\n")}
7620
+
7621
+ </Accordion>
7622
+ `);
7623
+ break;
7624
+ }
7625
+ default: {
7626
+ console.error(file);
7627
+ throw new Error(`Unknown file type: ${file}`);
7628
+ }
7629
+ }
7630
+ }
7631
+ const code = await compileMarkdownString(markdownLines.join("\n"));
7632
+ return code;
7633
+ }
7634
+ const SetPlaygroundSchema = z$1.object({
7635
+ appName: z$1.string(),
7636
+ reset: z$1.string().nullable().optional().transform((v) => v === "true")
7637
+ });
7638
+ async function action$8({ request }) {
7639
+ ensureUndeployed();
7640
+ const formData = await request.formData();
7641
+ const rawData = {
7642
+ appName: formData.get("appName")
7431
7643
  };
7432
- const parsed = parseGitDiff(diffOutput, { noPrefix: true });
7433
- const testFiles = Array.from(
7434
- /* @__PURE__ */ new Set([...getAppTestFiles(app1), ...getAppTestFiles(app2)])
7644
+ const result = SetPlaygroundSchema.safeParse(rawData);
7645
+ if (!result.success) {
7646
+ return json({ status: "error", error: result.error.message }, {
7647
+ status: 400
7648
+ });
7649
+ }
7650
+ const form = result.data;
7651
+ const app = await getAppByName(form.appName);
7652
+ if (!app) {
7653
+ return json(
7654
+ { status: "error", error: `App ${form.appName} not found` },
7655
+ { status: 404 }
7656
+ );
7657
+ }
7658
+ const converseApp = isProblemApp(app) && app.solutionName ? await getAppByName(app.solutionName) : isSolutionApp(app) && app.problemName ? await getAppByName(app.problemName) : void 0;
7659
+ try {
7660
+ await setPlayground(app.fullPath, { reset: form.reset });
7661
+ } catch (error) {
7662
+ const message = getErrorMessage(error);
7663
+ console.error("Error setting playground", message);
7664
+ return json({ status: "error", error: message }, {
7665
+ status: 500,
7666
+ headers: await createToastHeaders({
7667
+ type: "error",
7668
+ title: "Error",
7669
+ description: "There was an error setting the playground. Check the terminal for details."
7670
+ })
7671
+ });
7672
+ }
7673
+ const apps = await getApps({ forceFresh: true });
7674
+ const playground = apps.find(isPlaygroundApp);
7675
+ if (playground && converseApp) {
7676
+ await getDiffCode(playground, converseApp, { forceFresh: true });
7677
+ }
7678
+ return json({ status: "success" });
7679
+ }
7680
+ function SetPlayground({
7681
+ appName,
7682
+ reset = false,
7683
+ tooltipText,
7684
+ ...buttonProps
7685
+ }) {
7686
+ var _a2;
7687
+ const fetcher = useFetcher();
7688
+ const submitButton = /* @__PURE__ */ jsx(
7689
+ "button",
7690
+ {
7691
+ type: "submit",
7692
+ ...buttonProps,
7693
+ className: clsx(
7694
+ buttonProps.className,
7695
+ fetcher.state !== "idle" ? "cursor-progress" : null,
7696
+ ((_a2 = fetcher.data) == null ? void 0 : _a2.status) === "error" ? "cursor-not-allowed" : null
7697
+ )
7698
+ }
7699
+ );
7700
+ return /* @__PURE__ */ jsxs(
7701
+ fetcher.Form,
7702
+ {
7703
+ action: "/set-playground",
7704
+ method: "POST",
7705
+ className: "inline-flex items-center justify-center",
7706
+ children: [
7707
+ /* @__PURE__ */ jsx("input", { type: "hidden", name: "appName", value: appName }),
7708
+ reset ? /* @__PURE__ */ jsx("input", { type: "hidden", name: "reset", value: "true" }) : null,
7709
+ showProgressBarField,
7710
+ tooltipText ? /* @__PURE__ */ jsx(SimpleTooltip, { content: tooltipText, children: submitButton }) : submitButton
7711
+ ]
7712
+ }
7713
+ );
7714
+ }
7715
+ function PlaygroundChooser({
7716
+ playgroundAppName,
7717
+ allApps
7718
+ }) {
7719
+ var _a2;
7720
+ const fetcher = useFetcher();
7721
+ return /* @__PURE__ */ jsxs(
7722
+ Select.Root,
7723
+ {
7724
+ name: "appName",
7725
+ value: playgroundAppName,
7726
+ onValueChange: (appName) => {
7727
+ fetcher.submit(
7728
+ { appName },
7729
+ { method: "POST", action: "/set-playground" }
7730
+ );
7731
+ },
7732
+ children: [
7733
+ /* @__PURE__ */ jsxs(
7734
+ Select.Trigger,
7735
+ {
7736
+ "aria-label": "Select app for playground",
7737
+ className: clsx(
7738
+ "flex h-full w-full items-center justify-between text-left radix-placeholder:text-gray-500 focus-visible:outline-none",
7739
+ fetcher.state !== "idle" ? "cursor-progress" : null,
7740
+ ((_a2 = fetcher.data) == null ? void 0 : _a2.status) === "error" ? "cursor-not-allowed" : null
7741
+ ),
7742
+ children: [
7743
+ /* @__PURE__ */ jsx("span", { className: "w-80 flex-1 overflow-hidden text-ellipsis whitespace-nowrap scrollbar-thin scrollbar-thumb-scrollbar", children: /* @__PURE__ */ jsx(
7744
+ Select.Value,
7745
+ {
7746
+ placeholder: "Select current app",
7747
+ className: "inline-block w-40 text-ellipsis"
7748
+ }
7749
+ ) }),
7750
+ /* @__PURE__ */ jsx(Select.Icon, { children: /* @__PURE__ */ jsx(Icon, { name: "TriangleDownSmall" }) })
7751
+ ]
7752
+ }
7753
+ ),
7754
+ /* @__PURE__ */ jsx(Select.Portal, { children: /* @__PURE__ */ jsxs(
7755
+ Select.Content,
7756
+ {
7757
+ position: "popper",
7758
+ align: "start",
7759
+ className: "z-20 max-h-[50vh] bg-black text-white lg:max-h-[70vh]",
7760
+ children: [
7761
+ /* @__PURE__ */ jsx(Select.ScrollUpButton, { className: "flex h-5 cursor-default items-center justify-center ", children: /* @__PURE__ */ jsx(Icon, { name: "ChevronUp" }) }),
7762
+ /* @__PURE__ */ jsx(Select.Viewport, { className: "p-3", children: /* @__PURE__ */ jsxs(Select.Group, { children: [
7763
+ /* @__PURE__ */ jsx(Select.Label, { className: "px-5 pb-3 font-mono uppercase", children: "App" }),
7764
+ allApps.filter((app) => app.name !== "playground").map((app) => {
7765
+ return /* @__PURE__ */ jsx(SelectItem, { value: app.name, children: app.displayName }, app.name);
7766
+ })
7767
+ ] }) }),
7768
+ /* @__PURE__ */ jsx(Select.ScrollDownButton, { className: "flex h-5 cursor-default items-center justify-center ", children: /* @__PURE__ */ jsx(Icon, { name: "ChevronDown" }) })
7769
+ ]
7770
+ }
7771
+ ) })
7772
+ ]
7773
+ }
7774
+ );
7775
+ }
7776
+ function SelectItem({
7777
+ value,
7778
+ children
7779
+ }) {
7780
+ return /* @__PURE__ */ jsxs(
7781
+ Select.Item,
7782
+ {
7783
+ value,
7784
+ className: "relative flex cursor-pointer select-none items-center rounded px-10 py-2 leading-none opacity-80 radix-disabled:text-red-500 radix-highlighted:opacity-100 radix-highlighted:outline-none radix-state-checked:opacity-100",
7785
+ children: [
7786
+ /* @__PURE__ */ jsx(Select.ItemText, { children }),
7787
+ /* @__PURE__ */ jsx(Select.ItemIndicator, { className: "absolute left-0 inline-flex w-[25px] items-center justify-center", children: /* @__PURE__ */ jsx(Icon, { name: "CheckSmall" }) })
7788
+ ]
7789
+ }
7435
7790
  );
7436
- const startLine = (file) => {
7437
- const chunk = file.type === "ChangedFile" && file.chunks[0];
7438
- if (chunk) {
7439
- return chunk.type === "Chunk" ? chunk.fromFileRange.start : chunk.type === "CombinedChunk" ? chunk.fromFileRangeA.start : 1;
7791
+ }
7792
+ function SetAppToPlayground({ appName }) {
7793
+ if (ENV.EPICSHOP_DEPLOYED)
7794
+ return null;
7795
+ return /* @__PURE__ */ jsx(
7796
+ SetPlayground,
7797
+ {
7798
+ appName,
7799
+ tooltipText: "Playground is not set to the right app. Click to set Playground.",
7800
+ children: /* @__PURE__ */ jsxs("span", { className: "flex items-center justify-center gap-1 text-foreground-danger hover:underline", children: [
7801
+ /* @__PURE__ */ jsx(Icon, { name: "Unlinked", className: "animate-ping" }),
7802
+ " ",
7803
+ /* @__PURE__ */ jsx("span", { className: "uppercase", children: "Set to Playground" })
7804
+ ] })
7440
7805
  }
7441
- return 1;
7442
- };
7443
- return parsed.files.map((file) => ({
7444
- // prettier-ignore
7445
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
7446
- status: typesMap[file.type] ?? "unknown",
7447
- path: diffPathToRelative(
7448
- file.type === "RenamedFile" ? file.pathBefore : file.path
7449
- ),
7450
- line: startLine(file)
7451
- })).filter((file) => !testFiles.includes(file.path));
7806
+ );
7452
7807
  }
7453
- async function getDiffCode(app1, app2, {
7454
- forceFresh = false,
7455
- timings,
7456
- request
7457
- } = {}) {
7458
- const key = `${app1.relativePath}__vs__${app2.relativePath}`;
7459
- const cacheEntry = diffCodeCache.get(key);
7460
- const result = await cachified({
7461
- key,
7462
- cache: diffCodeCache,
7463
- forceFresh: forceFresh || getForceFreshForDiff(app1, app2, cacheEntry),
7464
- timings,
7808
+ const route32 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
7809
+ __proto__: null,
7810
+ PlaygroundChooser,
7811
+ SetAppToPlayground,
7812
+ SetPlayground,
7813
+ action: action$8
7814
+ }, Symbol.toStringTag, { value: "Module" }));
7815
+ const EmojiDataSchema = z$1.union([
7816
+ z$1.object({
7817
+ emojiName: z$1.never().optional(),
7818
+ emojiUrl: z$1.string()
7819
+ }),
7820
+ z$1.object({
7821
+ emojiName: z$1.string(),
7822
+ emojiUrl: z$1.never().optional()
7823
+ }),
7824
+ z$1.object({
7825
+ emojiName: z$1.never().optional(),
7826
+ emojiUrl: z$1.never().optional()
7827
+ })
7828
+ ]);
7829
+ const ThreadItemSchema = z$1.object({
7830
+ id: z$1.string(),
7831
+ tags: z$1.array(
7832
+ z$1.object({
7833
+ name: z$1.string()
7834
+ }).and(EmojiDataSchema)
7835
+ ),
7836
+ name: z$1.string(),
7837
+ link: z$1.string(),
7838
+ authorDisplayName: z$1.string(),
7839
+ authorHexAccentColor: z$1.string().nullable().optional(),
7840
+ authorAvatarUrl: z$1.string().nullable(),
7841
+ messagePreview: z$1.string(),
7842
+ messageCount: z$1.number(),
7843
+ lastUpdated: z$1.string(),
7844
+ previewImageUrl: z$1.string().nullable(),
7845
+ reactions: z$1.array(
7846
+ z$1.object({
7847
+ count: z$1.number()
7848
+ }).and(EmojiDataSchema)
7849
+ )
7850
+ });
7851
+ const ThreadDataSchema = z$1.array(ThreadItemSchema);
7852
+ const EpicForumResponseSchema = z$1.object({
7853
+ status: z$1.literal("error"),
7854
+ error: z$1.string()
7855
+ }).or(
7856
+ z$1.object({
7857
+ status: z$1.literal("success"),
7858
+ threadData: ThreadDataSchema
7859
+ })
7860
+ );
7861
+ async function fetchDiscordPosts({ request }) {
7862
+ return cachified({
7863
+ key: "fetchDiscordPosts",
7465
7864
  request,
7466
- getFreshValue: () => getDiffCodeImpl(app1, app2)
7467
- });
7468
- return result;
7469
- }
7470
- async function getDiffCodeImpl(app1, app2) {
7471
- const markdownLines = [""];
7472
- if (app1.name === app2.name) {
7473
- markdownLines.push(
7474
- '<p className="p-4 text-center">You are comparing the same app</p>'
7475
- );
7476
- const code2 = await compileMarkdownString(markdownLines.join("\n"));
7477
- return code2;
7478
- }
7479
- const { app1CopyPath, app2CopyPath } = await prepareForDiff(app1, app2);
7480
- const { stdout: diffOutput } = await execa(
7481
- "git",
7482
- [
7483
- "diff",
7484
- "--no-index",
7485
- app1CopyPath,
7486
- app2CopyPath,
7487
- "--color=never",
7488
- "--color-moved-ws=allow-indentation-change",
7489
- "--no-prefix",
7490
- "--ignore-blank-lines"
7491
- ],
7492
- { cwd: diffTmpDir }
7493
- // --no-index implies --exit-code, so we need to use the error output
7494
- ).catch((e) => e);
7495
- void fsExtra.remove(app1CopyPath);
7496
- void fsExtra.remove(app2CopyPath);
7497
- const parsed = parseGitDiff(diffOutput);
7498
- if (!parsed.files.length) {
7499
- markdownLines.push(
7500
- '<div className="m-5 inline-flex items-center justify-center bg-foreground px-1 py-0.5 font-mono text-sm uppercase text-background">No changes</div>'
7501
- );
7502
- }
7503
- const app1TestFiles = getAppTestFiles(app1);
7504
- const app2TestFiles = getAppTestFiles(app2);
7505
- for (const file of parsed.files) {
7506
- const pathToCopy = file.type === "RenamedFile" ? file.pathBefore : file.path;
7507
- const relativePath = diffPathToRelative(pathToCopy);
7508
- if (app1TestFiles.includes(relativePath))
7509
- continue;
7510
- const filePathApp1 = path.join(app1.fullPath, relativePath);
7511
- const pathToApp2 = file.type === "RenamedFile" ? file.pathAfter : file.path;
7512
- const relativePathApp2 = diffPathToRelative(pathToApp2);
7513
- if (app2TestFiles.includes(relativePathApp2))
7514
- continue;
7515
- const filePathApp2 = path.join(app2.fullPath, relativePathApp2);
7516
- switch (file.type) {
7517
- case "ChangedFile": {
7518
- markdownLines.push(`
7519
-
7520
- <Accordion title=${JSON.stringify(relativePath)} variant="changed">
7521
-
7522
- ${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join("\n")}
7523
-
7524
- </Accordion>
7525
-
7526
- `);
7527
- break;
7528
- }
7529
- case "DeletedFile": {
7530
- markdownLines.push(`
7531
- <Accordion title=${JSON.stringify(relativePath)} variant="deleted">
7532
-
7533
- ${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join("\n")}
7534
-
7535
- </Accordion>
7536
- `);
7537
- break;
7538
- }
7539
- case "RenamedFile": {
7540
- const relativeBefore = diffPathToRelative(file.pathBefore);
7541
- const relativeAfter = diffPathToRelative(file.pathAfter);
7542
- const title = JSON.stringify(`${relativeBefore} ▶️ ${relativeAfter}`);
7543
- markdownLines.push(`
7544
- <Accordion title=${title} variant="renamed">
7545
-
7546
- ${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join("\n")}
7547
-
7548
- </Accordion>
7549
- `);
7550
- break;
7551
- }
7552
- case "AddedFile": {
7553
- markdownLines.push(`
7554
- <Accordion title=${JSON.stringify(relativePath)} variant="added">
7555
-
7556
- ${getFileCodeblocks(file, filePathApp1, filePathApp2, file.type).join("\n")}
7557
-
7558
- </Accordion>
7559
- `);
7560
- break;
7865
+ cache: fsCache,
7866
+ ttl: 1e3 * 60 * 2,
7867
+ swr: 1e3 * 60 * 60 * 24 * 7,
7868
+ checkValue: ThreadDataSchema,
7869
+ async getFreshValue() {
7870
+ const forceFresh = await shouldForceFresh({ request });
7871
+ const searchParams = new URLSearchParams(
7872
+ forceFresh ? { fresh: "true" } : {}
7873
+ );
7874
+ const result = await fetch(
7875
+ // `http://localhost:3000/resources/epic-web-forum?${searchParams}`,
7876
+ `https://kcd-discord-bot-v2.fly.dev/resources/epic-web-forum?${searchParams}`,
7877
+ {
7878
+ method: "POST",
7879
+ headers: { "content-type": "application/json" }
7880
+ }
7881
+ );
7882
+ if (!result.ok) {
7883
+ console.error(`There was an error communicating with discord`);
7884
+ try {
7885
+ console.error(await result.text());
7886
+ } catch {
7887
+ }
7888
+ return [];
7561
7889
  }
7562
- default: {
7563
- console.error(file);
7564
- throw new Error(`Unknown file type: ${file}`);
7890
+ const jsonResult = await result.json();
7891
+ const epicForumResponseResult = EpicForumResponseSchema.safeParse(jsonResult);
7892
+ if (epicForumResponseResult.success) {
7893
+ if (epicForumResponseResult.data.status === "error") {
7894
+ console.error(`There was an error communicating with discord`);
7895
+ console.error(epicForumResponseResult.data.error);
7896
+ return [];
7897
+ } else {
7898
+ return epicForumResponseResult.data.threadData;
7899
+ }
7900
+ } else {
7901
+ console.error(`There was an error parsing the discord response`);
7902
+ console.error(epicForumResponseResult.error.flatten());
7903
+ return [];
7565
7904
  }
7566
7905
  }
7567
- }
7568
- const code = await compileMarkdownString(markdownLines.join("\n"));
7569
- return code;
7906
+ });
7570
7907
  }
7571
- const SetPlaygroundSchema = z$1.object({
7572
- appName: z$1.string(),
7573
- reset: z$1.string().nullable().optional().transform((v) => v === "true")
7574
- });
7575
- async function action$8({ request }) {
7576
- ensureUndeployed();
7577
- const formData = await request.formData();
7578
- const rawData = {
7579
- appName: formData.get("appName")
7580
- };
7581
- const result = SetPlaygroundSchema.safeParse(rawData);
7582
- if (!result.success) {
7583
- return json({ status: "error", error: result.error.message }, {
7584
- status: 400
7585
- });
7908
+ async function loader$m() {
7909
+ return json({ discordAuthUrl: getDiscordAuthURL() });
7910
+ }
7911
+ function useDiscordCTALink({
7912
+ discordAuthUrl
7913
+ }) {
7914
+ const user = useOptionalUser();
7915
+ const discordMember = useOptionalDiscordMember();
7916
+ if (!user) {
7917
+ return "/login";
7586
7918
  }
7587
- const form = result.data;
7588
- const app = await getAppByName(form.appName);
7589
- if (!app) {
7590
- return json(
7591
- { status: "error", error: `App ${form.appName} not found` },
7592
- { status: 404 }
7593
- );
7919
+ if (!discordMember) {
7920
+ return discordAuthUrl;
7594
7921
  }
7595
- const converseApp = isProblemApp(app) && app.solutionName ? await getAppByName(app.solutionName) : isSolutionApp(app) && app.problemName ? await getAppByName(app.problemName) : void 0;
7596
- try {
7597
- await setPlayground(app.fullPath, { reset: form.reset });
7598
- } catch (error) {
7599
- const message = getErrorMessage(error);
7600
- console.error("Error setting playground", message);
7601
- return json({ status: "error", error: message }, {
7602
- status: 500,
7603
- headers: await createToastHeaders({
7604
- type: "error",
7605
- title: "Error",
7606
- description: "There was an error setting the playground. Check the terminal for details."
7607
- })
7608
- });
7922
+ return "https://discord.com/channels/715220730605731931/1161045224907341972";
7923
+ }
7924
+ function DiscordCTA({ discordAuthUrl }) {
7925
+ const user = useOptionalUser();
7926
+ const discordMember = useOptionalDiscordMember();
7927
+ if (!user) {
7928
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2 text-xl", children: [
7929
+ /* @__PURE__ */ jsxs(Link, { to: "/login", className: "inline-flex items-center gap-2 underline", children: [
7930
+ /* @__PURE__ */ jsx(Icon, { name: "Discord", size: "2xl" }),
7931
+ "Login"
7932
+ ] }),
7933
+ " ",
7934
+ /* @__PURE__ */ jsxs("span", { children: [
7935
+ "to get access to the exclusive",
7936
+ " ",
7937
+ /* @__PURE__ */ jsx(Link, { to: "/discord", className: "underline", children: "discord channel" }),
7938
+ "."
7939
+ ] })
7940
+ ] });
7609
7941
  }
7610
- const apps = await getApps({ forceFresh: true });
7611
- const playground = apps.find(isPlaygroundApp);
7612
- if (playground && converseApp) {
7613
- await getDiffCode(playground, converseApp, { forceFresh: true });
7942
+ if (!discordMember) {
7943
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-center gap-2 text-xl", children: [
7944
+ /* @__PURE__ */ jsxs(Link, { to: discordAuthUrl, className: "flex items-center gap-2 underline", children: [
7945
+ /* @__PURE__ */ jsx(Icon, { name: "Discord", size: "2xl" }),
7946
+ "Connect Discord"
7947
+ ] }),
7948
+ " ",
7949
+ /* @__PURE__ */ jsxs("span", { children: [
7950
+ "to get access to the exclusive",
7951
+ " ",
7952
+ /* @__PURE__ */ jsx(Link, { to: "/discord", className: "underline", children: "discord channel" }),
7953
+ "."
7954
+ ] })
7955
+ ] });
7614
7956
  }
7615
- return json({ status: "success" });
7957
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2 text-xl underline", children: [
7958
+ /* @__PURE__ */ jsx(Link, { to: "discord://discord.com/channels/715220730605731931/1161045224907341972", children: /* @__PURE__ */ jsx(Icon, { name: "Discord", size: "2xl" }) }),
7959
+ /* @__PURE__ */ jsx(
7960
+ Link,
7961
+ {
7962
+ to: "https://discord.com/channels/715220730605731931/1161045224907341972",
7963
+ target: "_blank",
7964
+ rel: "noreferrer noopener",
7965
+ children: "Open Discord"
7966
+ }
7967
+ )
7968
+ ] });
7616
7969
  }
7617
- function SetPlayground({
7618
- appName,
7619
- reset = false,
7620
- tooltipText,
7621
- ...buttonProps
7622
- }) {
7623
- var _a2;
7624
- const fetcher = useFetcher();
7625
- const submitButton = /* @__PURE__ */ jsx(
7626
- "button",
7627
- {
7628
- type: "submit",
7629
- ...buttonProps,
7630
- className: clsx(
7631
- buttonProps.className,
7632
- fetcher.state !== "idle" ? "cursor-progress" : null,
7633
- ((_a2 = fetcher.data) == null ? void 0 : _a2.status) === "error" ? "cursor-not-allowed" : null
7634
- )
7635
- }
7636
- );
7637
- return /* @__PURE__ */ jsxs(
7638
- fetcher.Form,
7639
- {
7640
- action: "/set-playground",
7641
- method: "POST",
7642
- className: "inline-flex items-center justify-center",
7643
- children: [
7644
- /* @__PURE__ */ jsx("input", { type: "hidden", name: "appName", value: appName }),
7645
- reset ? /* @__PURE__ */ jsx("input", { type: "hidden", name: "reset", value: "true" }) : null,
7646
- showProgressBarField,
7647
- tooltipText ? /* @__PURE__ */ jsx(SimpleTooltip, { content: tooltipText, children: submitButton }) : submitButton
7648
- ]
7649
- }
7650
- );
7970
+ function DiscordRoute() {
7971
+ const data = useLoaderData();
7972
+ return /* @__PURE__ */ jsxs("div", { className: "container flex h-full max-w-3xl flex-col items-center justify-center gap-4 p-12", children: [
7973
+ /* @__PURE__ */ jsx(DiscordCTA, { discordAuthUrl: data.discordAuthUrl }),
7974
+ /* @__PURE__ */ jsxs("p", { children: [
7975
+ "The",
7976
+ " ",
7977
+ /* @__PURE__ */ jsx(
7978
+ Link,
7979
+ {
7980
+ target: "_blank",
7981
+ rel: "noreferrer noopener",
7982
+ className: "underline",
7983
+ to: "https://kentcdodds.com/discord",
7984
+ children: "Epic Web Community on Discord"
7985
+ }
7986
+ ),
7987
+ " ",
7988
+ "is a great place to hang out with other developers who are working through this workshop. You can ask questions, get help, and solidify what you're learning by helping others."
7989
+ ] }),
7990
+ /* @__PURE__ */ jsx("p", { children: /* @__PURE__ */ jsxs("small", { className: "text-sm", children: [
7991
+ "If you've not joined the Epic Web Community on Discord yet, you'll be required to go through a short onboarding process first. A friendly bot will explain the process when you",
7992
+ " ",
7993
+ /* @__PURE__ */ jsx(
7994
+ Link,
7995
+ {
7996
+ to: "https://kcd.im/discord",
7997
+ target: "_blank",
7998
+ rel: "noreferrer noopener",
7999
+ className: "underline",
8000
+ children: "join"
8001
+ }
8002
+ ),
8003
+ "."
8004
+ ] }) })
8005
+ ] });
7651
8006
  }
7652
- function PlaygroundChooser({
7653
- playgroundAppName,
7654
- allApps
7655
- }) {
7656
- var _a2;
7657
- const fetcher = useFetcher();
7658
- return /* @__PURE__ */ jsxs(
7659
- Select.Root,
7660
- {
7661
- name: "appName",
7662
- value: playgroundAppName,
7663
- onValueChange: (appName) => {
7664
- fetcher.submit(
7665
- { appName },
7666
- { method: "POST", action: "/set-playground" }
7667
- );
7668
- },
7669
- children: [
7670
- /* @__PURE__ */ jsxs(
7671
- Select.Trigger,
8007
+ const route15 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
8008
+ __proto__: null,
8009
+ DiscordCTA,
8010
+ default: DiscordRoute,
8011
+ loader: loader$m,
8012
+ useDiscordCTALink
8013
+ }, Symbol.toStringTag, { value: "Module" }));
8014
+ function DiscordChat() {
8015
+ const data = useLoaderData();
8016
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full w-full flex-col gap-4 pt-4", children: [
8017
+ /* @__PURE__ */ jsx("div", { className: "text-center", children: /* @__PURE__ */ jsx(DiscordCTA, { discordAuthUrl: data.discordAuthUrl }) }),
8018
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-scroll bg-accent pb-4 scrollbar-thin scrollbar-thumb-scrollbar", children: /* @__PURE__ */ jsx(DiscordPosts, {}) })
8019
+ ] });
8020
+ }
8021
+ function DiscordPosts() {
8022
+ const data = useLoaderData();
8023
+ const ctaLink = useDiscordCTALink({ discordAuthUrl: data.discordAuthUrl });
8024
+ const altDown = useAltDown();
8025
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-full flex-col items-center justify-between", children: [
8026
+ /* @__PURE__ */ jsx(
8027
+ React.Suspense,
8028
+ {
8029
+ fallback: /* @__PURE__ */ jsx("div", { className: "flex h-full w-full flex-col items-center justify-center", children: /* @__PURE__ */ jsx(Loading, { children: "Loading Discord Posts" }) }),
8030
+ children: /* @__PURE__ */ jsx(
8031
+ Await,
7672
8032
  {
7673
- "aria-label": "Select app for playground",
7674
- className: clsx(
7675
- "flex h-full w-full items-center justify-between text-left radix-placeholder:text-gray-500 focus-visible:outline-none",
7676
- fetcher.state !== "idle" ? "cursor-progress" : null,
7677
- ((_a2 = fetcher.data) == null ? void 0 : _a2.status) === "error" ? "cursor-not-allowed" : null
7678
- ),
8033
+ resolve: data.discordPostsPromise,
8034
+ errorElement: /* @__PURE__ */ jsx("div", { className: "text-red-500", children: "There was a problem loading the discord posts" }),
8035
+ children: (posts) => /* @__PURE__ */ jsx("ul", { className: "flex w-full flex-col gap-4 p-3 xl:p-12", children: posts.map((post) => /* @__PURE__ */ jsx(
8036
+ "li",
8037
+ {
8038
+ className: "rounded-xl border bg-background transition-all duration-200 focus-within:-translate-y-1 focus-within:shadow-lg hover:-translate-y-1 hover:shadow-lg",
8039
+ children: /* @__PURE__ */ jsx(DiscordPost, { thread: post })
8040
+ },
8041
+ post.id
8042
+ )) })
8043
+ }
8044
+ )
8045
+ }
8046
+ ),
8047
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
8048
+ Link,
8049
+ {
8050
+ to: altDown && !ctaLink.includes("oauth") ? ctaLink.replace(/^https/, "discord") : ctaLink,
8051
+ target: ctaLink.includes("oauth") ? void 0 : "_blank",
8052
+ rel: "noreferrer noopener",
8053
+ onClick: altDown ? (e) => {
8054
+ e.preventDefault();
8055
+ window.open(
8056
+ e.currentTarget.href,
8057
+ "_blank",
8058
+ "noreferrer noopener"
8059
+ );
8060
+ } : void 0,
8061
+ className: "flex items-center gap-2 p-2 text-xl hover:underline",
8062
+ children: [
8063
+ "Create Post ",
8064
+ /* @__PURE__ */ jsx(Icon, { name: "ExternalLink" })
8065
+ ]
8066
+ }
8067
+ ) })
8068
+ ] });
8069
+ }
8070
+ function DiscordPost({ thread }) {
8071
+ const reactionsWithCounts = thread.reactions.filter((r) => r.count);
8072
+ const hints = useHints();
8073
+ return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 p-4", children: [
8074
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-4", children: [
8075
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
8076
+ thread.tags.length ? /* @__PURE__ */ jsx("div", { className: "flex gap-2", children: thread.tags.map((t) => /* @__PURE__ */ jsxs(
8077
+ "div",
8078
+ {
8079
+ className: "flex items-center justify-center gap-1 rounded-full bg-accent px-2 py-1 text-sm",
7679
8080
  children: [
7680
- /* @__PURE__ */ jsx("span", { className: "w-80 flex-1 overflow-hidden text-ellipsis whitespace-nowrap scrollbar-thin scrollbar-thumb-scrollbar", children: /* @__PURE__ */ jsx(
7681
- Select.Value,
8081
+ /* @__PURE__ */ jsx("span", { className: "h-3 w-3 leading-3", children: /* @__PURE__ */ jsx(Emoji, { name: t.emojiName, url: t.emojiUrl }) }),
8082
+ /* @__PURE__ */ jsx("span", { children: t.name })
8083
+ ]
8084
+ },
8085
+ t.name
8086
+ )) }) : null,
8087
+ /* @__PURE__ */ jsx("strong", { className: "text-xl font-bold", children: thread.name }),
8088
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-1", children: [
8089
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
8090
+ thread.authorAvatarUrl ? /* @__PURE__ */ jsx(
8091
+ "img",
8092
+ {
8093
+ src: thread.authorAvatarUrl,
8094
+ alt: "",
8095
+ className: "h-6 w-6 rounded-full"
8096
+ }
8097
+ ) : null,
8098
+ /* @__PURE__ */ jsxs("span", { children: [
8099
+ /* @__PURE__ */ jsx(
8100
+ "span",
7682
8101
  {
7683
- placeholder: "Select current app",
7684
- className: "inline-block w-40 text-ellipsis"
8102
+ className: "font-bold",
8103
+ style: thread.authorHexAccentColor ? { color: thread.authorHexAccentColor } : {},
8104
+ children: thread.authorDisplayName
7685
8105
  }
7686
- ) }),
7687
- /* @__PURE__ */ jsx(Select.Icon, { children: /* @__PURE__ */ jsx(Icon, { name: "TriangleDownSmall" }) })
7688
- ]
7689
- }
7690
- ),
7691
- /* @__PURE__ */ jsx(Select.Portal, { children: /* @__PURE__ */ jsxs(
7692
- Select.Content,
8106
+ ),
8107
+ ":",
8108
+ " "
8109
+ ] })
8110
+ ] }),
8111
+ /* @__PURE__ */ jsx("span", { className: "flex-1 overflow-ellipsis text-muted-foreground", children: thread.messagePreview })
8112
+ ] })
8113
+ ] }),
8114
+ thread.previewImageUrl ? /* @__PURE__ */ jsx(
8115
+ "img",
8116
+ {
8117
+ src: thread.previewImageUrl,
8118
+ alt: "",
8119
+ className: "h-28 w-28 rounded-lg object-cover"
8120
+ }
8121
+ ) : null
8122
+ ] }),
8123
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between", children: [
8124
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
8125
+ /* @__PURE__ */ jsx("span", { children: reactionsWithCounts.length ? /* @__PURE__ */ jsx("ul", { className: "flex items-center gap-2", children: reactionsWithCounts.map((r, i) => /* @__PURE__ */ jsxs(
8126
+ "li",
7693
8127
  {
7694
- position: "popper",
7695
- align: "start",
7696
- className: "z-20 max-h-[50vh] bg-black text-white lg:max-h-[70vh]",
8128
+ className: "flex items-center gap-1 rounded-md border border-blue-600 bg-blue-500/20 px-[5px] py-[0.5px] text-sm",
7697
8129
  children: [
7698
- /* @__PURE__ */ jsx(Select.ScrollUpButton, { className: "flex h-5 cursor-default items-center justify-center ", children: /* @__PURE__ */ jsx(Icon, { name: "ChevronUp" }) }),
7699
- /* @__PURE__ */ jsx(Select.Viewport, { className: "p-3", children: /* @__PURE__ */ jsxs(Select.Group, { children: [
7700
- /* @__PURE__ */ jsx(Select.Label, { className: "px-5 pb-3 font-mono uppercase", children: "App" }),
7701
- allApps.filter((app) => app.name !== "playground").map((app) => {
7702
- return /* @__PURE__ */ jsx(SelectItem$1, { value: app.name, children: app.displayName }, app.name);
7703
- })
7704
- ] }) }),
7705
- /* @__PURE__ */ jsx(Select.ScrollDownButton, { className: "flex h-5 cursor-default items-center justify-center ", children: /* @__PURE__ */ jsx(Icon, { name: "ChevronDown" }) })
8130
+ /* @__PURE__ */ jsx("span", { className: "h-3 w-3 leading-3", children: /* @__PURE__ */ jsx(Emoji, { name: r.emojiName, url: r.emojiUrl }) }),
8131
+ /* @__PURE__ */ jsx("span", { children: r.count })
7706
8132
  ]
7707
- }
7708
- ) })
7709
- ]
7710
- }
7711
- );
7712
- }
7713
- function SelectItem$1({
7714
- value,
7715
- children
7716
- }) {
7717
- return /* @__PURE__ */ jsxs(
7718
- Select.Item,
7719
- {
7720
- value,
7721
- className: "relative flex cursor-pointer select-none items-center rounded px-10 py-2 leading-none opacity-80 radix-disabled:text-red-500 radix-highlighted:opacity-100 radix-highlighted:outline-none radix-state-checked:opacity-100",
7722
- children: [
7723
- /* @__PURE__ */ jsx(Select.ItemText, { children }),
7724
- /* @__PURE__ */ jsx(Select.ItemIndicator, { className: "absolute left-0 inline-flex w-[25px] items-center justify-center", children: /* @__PURE__ */ jsx(Icon, { name: "CheckSmall" }) })
7725
- ]
7726
- }
7727
- );
7728
- }
7729
- function SetAppToPlayground({ appName }) {
7730
- if (ENV.EPICSHOP_DEPLOYED)
7731
- return null;
7732
- return /* @__PURE__ */ jsx(
7733
- SetPlayground,
7734
- {
7735
- appName,
7736
- tooltipText: "Playground is not set to the right app. Click to set Playground.",
7737
- children: /* @__PURE__ */ jsxs("span", { className: "flex items-center justify-center gap-1 text-foreground-danger hover:underline", children: [
7738
- /* @__PURE__ */ jsx(Icon, { name: "Unlinked", className: "animate-ping" }),
7739
- " ",
7740
- /* @__PURE__ */ jsx("span", { className: "uppercase", children: "Set to Playground" })
8133
+ },
8134
+ i
8135
+ )) }) : null }),
8136
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
8137
+ /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1", children: [
8138
+ /* @__PURE__ */ jsx(Icon, { name: "Chat" }),
8139
+ " ",
8140
+ thread.messageCount
8141
+ ] }),
8142
+ ` · ${dayjs(thread.lastUpdated).tz(hints.timeZone).fromNow()}`
8143
+ ] })
8144
+ ] }),
8145
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-4", children: [
8146
+ /* @__PURE__ */ jsx("a", { href: thread.link.replace(/^https/, "discord"), children: /* @__PURE__ */ jsx(Icon, { name: "Discord" }) }),
8147
+ /* @__PURE__ */ jsx("a", { href: thread.link, target: "_blank", rel: "noreferrer noopener", children: /* @__PURE__ */ jsx(Icon, { name: "ExternalLink" }) })
7741
8148
  ] })
7742
- }
7743
- );
8149
+ ] })
8150
+ ] }) });
8151
+ }
8152
+ function Emoji({ name, url }) {
8153
+ return url ? /* @__PURE__ */ jsx("img", { src: url, alt: name, className: "h-full w-full" }) : name ? name : null;
7744
8154
  }
7745
- const route31 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
7746
- __proto__: null,
7747
- PlaygroundChooser,
7748
- SetAppToPlayground,
7749
- SetPlayground,
7750
- action: action$8
7751
- }, Symbol.toStringTag, { value: "Module" }));
7752
8155
  function PlaygroundWindow({
7753
8156
  playgroundAppName,
7754
8157
  problemAppName,
@@ -7995,7 +8398,7 @@ function AppStarter({ name }) {
7995
8398
  fetcher.state === "idle" ? /* @__PURE__ */ jsx(Button, { type: "submit", name: "intent", value: "start", varient: "mono", children: "Start App" }) : /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Loading, { children: "Starting App" }) })
7996
8399
  ] });
7997
8400
  }
7998
- const route32 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
8401
+ const route33 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
7999
8402
  __proto__: null,
8000
8403
  AppStarter,
8001
8404
  AppStopper,
@@ -8047,18 +8450,15 @@ const InBrowserBrowser = forwardRef(
8047
8450
  );
8048
8451
  function InBrowserBrowserImpl({ name, port: port2, portIsAvailable, isRunning, baseUrl, id, initialRoute }, ref) {
8049
8452
  const requestInfo = useRequestInfo();
8050
- return isRunning ? (
8051
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
8052
- /* @__PURE__ */ jsx(
8053
- InBrowserBrowserForRealz,
8054
- {
8055
- baseUrl,
8056
- id,
8057
- name,
8058
- ref,
8059
- initialRoute
8060
- }
8061
- )
8453
+ return isRunning ? /* @__PURE__ */ jsx(
8454
+ InBrowserBrowserForRealz,
8455
+ {
8456
+ baseUrl,
8457
+ id,
8458
+ name,
8459
+ ref,
8460
+ initialRoute
8461
+ }
8062
8462
  ) : portIsAvailable === false ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center", children: [
8063
8463
  /* @__PURE__ */ jsxs("p", { className: "max-w-xs pb-5 text-center", role: "status", children: [
8064
8464
  `The port for this app is unavailable. It could be that you're running it `,
@@ -8490,7 +8890,6 @@ async function action$6({ request }) {
8490
8890
  await fs.promises.readFile(cacheLocation, "utf-8")
8491
8891
  );
8492
8892
  const cachedEmbeddedFiles = new Map(
8493
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
8494
8893
  Object.entries(((_a2 = cached == null ? void 0 : cached.value) == null ? void 0 : _a2.embeddedFiles) ?? {})
8495
8894
  );
8496
8895
  if (cachedEmbeddedFiles.has(embeddedKey)) {
@@ -8535,7 +8934,7 @@ function UpdateMdxCache({
8535
8934
  )
8536
8935
  ] });
8537
8936
  }
8538
- const route35 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
8937
+ const route36 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
8539
8938
  __proto__: null,
8540
8939
  UpdateMdxCache,
8541
8940
  action: action$6
@@ -8822,129 +9221,11 @@ function LinkToApp({
8822
9221
  if (ENV.EPICSHOP_DEPLOYED)
8823
9222
  event.preventDefault();
8824
9223
  },
8825
- children: /* @__PURE__ */ jsx(Icon, { name: "ExternalLink" })
8826
- }
8827
- ) }) : null
8828
- ] });
8829
- }
8830
- const AccordionComponent = ({
8831
- title,
8832
- children,
8833
- variant,
8834
- icon,
8835
- forceMount = false
8836
- }) => {
8837
- const getVariantIcon = () => {
8838
- switch (variant) {
8839
- case "changed":
8840
- return /* @__PURE__ */ jsx(
8841
- Icon,
8842
- {
8843
- name: "Modified",
8844
- "aria-label": "Modified",
8845
- className: "text-[#fb923c]"
8846
- }
8847
- );
8848
- case "renamed":
8849
- return /* @__PURE__ */ jsx(
8850
- Icon,
8851
- {
8852
- name: "Renamed",
8853
- "aria-label": "Renamed",
8854
- className: "text-[#fb923c]"
8855
- }
8856
- );
8857
- case "added":
8858
- return /* @__PURE__ */ jsx(Icon, { name: "Added", "aria-label": "Added", className: "text-[#10b981]" });
8859
- case "deleted":
8860
- return /* @__PURE__ */ jsx(
8861
- Icon,
8862
- {
8863
- name: "Deleted",
8864
- "aria-label": "Deleted",
8865
- className: "text-[#ef4444]"
8866
- }
8867
- );
8868
- default:
8869
- return /* @__PURE__ */ jsx(
8870
- Icon,
8871
- {
8872
- name: "Modified",
8873
- "aria-label": "Modified",
8874
- className: "text-[#fb923c]"
8875
- }
8876
- );
8877
- }
8878
- };
8879
- const getVariantLabel = () => {
8880
- switch (variant) {
8881
- case "changed":
8882
- return "modified";
8883
- default:
8884
- return variant;
8885
- }
8886
- };
8887
- const fixedTitle = title.replace(/\\\\/g, "\\");
8888
- return /* @__PURE__ */ jsxs(Accordion.Item, { value: title, children: [
8889
- /* @__PURE__ */ jsxs(AccordionTrigger, { variant: getVariantLabel(), children: [
8890
- icon ? icon : getVariantIcon(),
8891
- " ",
8892
- fixedTitle
8893
- ] }),
8894
- /* @__PURE__ */ jsx(
8895
- AccordionContent,
8896
- {
8897
- forceMount,
8898
- className: clsx(
8899
- "prose max-w-none whitespace-pre-wrap dark:prose-invert prose-pre:m-0 prose-pre:mb-1 prose-pre:rounded-none",
8900
- {
8901
- "radix-state-closed:hidden": forceMount
8902
- }
8903
- ),
8904
- children
8905
- }
8906
- )
8907
- ] });
8908
- };
8909
- const AccordionTrigger = React.forwardRef(
8910
- ({ children, className, variant, ...props }, forwardedRef) => /* @__PURE__ */ jsx(Accordion.Header, { className: "flex", asChild: true, children: /* @__PURE__ */ jsxs(
8911
- Accordion.Trigger,
8912
- {
8913
- className: clsx(
8914
- "group flex w-full items-center justify-between border-b p-4 pr-3 font-mono text-sm font-medium leading-none hover:bg-foreground/20",
8915
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
8916
- className
8917
- ),
8918
- ...props,
8919
- ref: forwardedRef,
8920
- children: [
8921
- /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5", children }),
8922
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
8923
- /* @__PURE__ */ jsx("span", { className: "font-mono text-xs font-normal uppercase text-muted-foreground", children: variant }),
8924
- /* @__PURE__ */ jsx(
8925
- Icon,
8926
- {
8927
- name: "TriangleDownSmall",
8928
- className: "transition group-radix-state-open:rotate-180",
8929
- "aria-hidden": true
8930
- }
8931
- )
8932
- ] })
8933
- ]
8934
- }
8935
- ) })
8936
- );
8937
- const AccordionContent = React.forwardRef(
8938
- ({ children, className, ...props }, forwardedRef) => /* @__PURE__ */ jsx(
8939
- Accordion.Content,
8940
- {
8941
- className: clsx("", className),
8942
- ...props,
8943
- ref: forwardedRef,
8944
- children: /* @__PURE__ */ jsx("div", { children })
8945
- }
8946
- )
8947
- );
9224
+ children: /* @__PURE__ */ jsx(Icon, { name: "ExternalLink" })
9225
+ }
9226
+ ) }) : null
9227
+ ] });
9228
+ }
8948
9229
  const testRunnerStatusDataSchema = z$1.intersection(
8949
9230
  z$1.object({
8950
9231
  type: z$1.literal("epicshop:test-status-update"),
@@ -9128,7 +9409,7 @@ const testEventSchema = z$1.union([
9128
9409
  })
9129
9410
  ]);
9130
9411
  const testEventQueueSchema = z$1.array(testEventSchema);
9131
- async function loader$k({ request }) {
9412
+ async function loader$l({ request }) {
9132
9413
  ensureUndeployed();
9133
9414
  const url = new URL(request.url);
9134
9415
  const name = url.searchParams.get("name");
@@ -9448,14 +9729,14 @@ function StopTest({
9448
9729
  )
9449
9730
  ] });
9450
9731
  }
9451
- const route33 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
9732
+ const route34 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
9452
9733
  __proto__: null,
9453
9734
  ClearTest,
9454
9735
  StopTest,
9455
9736
  TestOutput,
9456
9737
  TestRunner,
9457
9738
  action: action$5,
9458
- loader: loader$k
9739
+ loader: loader$l
9459
9740
  }, Symbol.toStringTag, { value: "Module" }));
9460
9741
  function Tests({
9461
9742
  appInfo: playgroundAppInfo,
@@ -9559,266 +9840,40 @@ function TouchedFiles() {
9559
9840
  title: "You must 'Set to Playground' before opening a file",
9560
9841
  className: "not-allowed"
9561
9842
  };
9562
- return /* @__PURE__ */ jsxs("ul", { ...props, children: [
9563
- diffFiles.length > 1 && !ENV.EPICSHOP_DEPLOYED ? /* @__PURE__ */ jsx("div", { className: "mb-2 border-b border-b-gray-50 border-opacity-50 pb-2 font-sans", children: /* @__PURE__ */ jsx(
9564
- LaunchEditor,
9565
- {
9566
- appFile: diffFiles.map(
9567
- (file) => `${file.path},${file.line},1`
9568
- ),
9569
- appName: "playground",
9570
- onUpdate: handleLaunchUpdate,
9571
- children: /* @__PURE__ */ jsx("p", { children: "Open All Files" })
9572
- }
9573
- ) }) : null,
9574
- diffFiles.map((file) => {
9575
- var _a3;
9576
- return /* @__PURE__ */ jsx("li", { "data-state": file.status, children: /* @__PURE__ */ jsx(
9577
- LaunchEditor,
9578
- {
9579
- appFile: `${file.path},${file.line},1`,
9580
- appName: ENV.EPICSHOP_DEPLOYED ? ((_a3 = data.problem) == null ? void 0 : _a3.name) ?? "playground" : "playground",
9581
- onUpdate: handleLaunchUpdate,
9582
- children: /* @__PURE__ */ jsx("code", { children: file.path })
9583
- }
9584
- ) }, file.path);
9585
- })
9586
- ] });
9587
- }
9588
- }
9589
- )
9590
- }
9591
- ) })
9592
- ] })
9593
- }
9594
- ) })
9595
- ] }) });
9596
- }
9597
- const pre = (props) => /* @__PURE__ */ jsx("pre", { ...props });
9598
- const mdxComponents$3 = {
9599
- Accordion: AccordionComponent,
9600
- // override the pre-with-buttons
9601
- pre
9602
- };
9603
- function Diff({
9604
- diff,
9605
- allApps
9606
- }) {
9607
- const submit = useSubmit();
9608
- const [params] = useSearchParams();
9609
- const paramsWithForcedRefresh = new URLSearchParams(params);
9610
- paramsWithForcedRefresh.set("forceFresh", "diff");
9611
- const navigation = useNavigation();
9612
- const spinnerNavigating = useSpinDelay(navigation.state !== "idle", {
9613
- delay: 0,
9614
- minDuration: 1e3
9615
- });
9616
- const hiddenInputs = [];
9617
- for (const [key, value] of params.entries()) {
9618
- if (key === "app1" || key === "app2")
9619
- continue;
9620
- hiddenInputs.push(
9621
- /* @__PURE__ */ jsx("input", { type: "hidden", name: key, value }, key)
9622
- );
9623
- }
9624
- return /* @__PURE__ */ jsx(
9625
- Suspense,
9626
- {
9627
- fallback: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center p-8", children: /* @__PURE__ */ jsx(SimpleTooltip, { content: "Loading diff", children: /* @__PURE__ */ jsx(Icon, { name: "Refresh", className: "animate-spin" }) }) }),
9628
- children: /* @__PURE__ */ jsx(
9629
- Await,
9630
- {
9631
- resolve: diff,
9632
- errorElement: /* @__PURE__ */ jsx("p", { className: "p-6 text-foreground-danger", children: "There was an error calculating the diff. Sorry." }),
9633
- children: (diff2) => /* @__PURE__ */ jsxs("div", { className: "flex h-full w-full flex-col", children: [
9634
- /* @__PURE__ */ jsxs("div", { className: "flex h-14 min-h-14 w-full overflow-x-hidden border-b", children: [
9635
- /* @__PURE__ */ jsx("div", { className: "border-r", children: /* @__PURE__ */ jsx(SimpleTooltip, { content: "Reload diff", children: /* @__PURE__ */ jsx(
9636
- Link,
9637
- {
9638
- to: `.?${paramsWithForcedRefresh}`,
9639
- className: "flex h-full w-14 items-center justify-center",
9640
- children: /* @__PURE__ */ jsx(
9641
- Icon,
9642
- {
9643
- name: "Refresh",
9644
- className: cn({ "animate-spin": spinnerNavigating })
9645
- }
9646
- )
9647
- }
9648
- ) }) }),
9649
- /* @__PURE__ */ jsxs(
9650
- Form,
9651
- {
9652
- onChange: (e) => submit(e.currentTarget),
9653
- className: "flex h-full flex-1 items-center overflow-x-auto scrollbar-thin scrollbar-thumb-scrollbar",
9654
- children: [
9655
- hiddenInputs,
9656
- /* @__PURE__ */ jsx(
9657
- SelectFileToDiff,
9658
- {
9659
- name: "app1",
9660
- label: "App 1",
9661
- className: "border-r",
9662
- allApps,
9663
- defaultValue: diff2.app1
9664
- }
9665
- ),
9666
- /* @__PURE__ */ jsx(
9667
- SelectFileToDiff,
9668
- {
9669
- name: "app2",
9670
- label: "App 2",
9671
- allApps,
9672
- defaultValue: diff2.app2
9673
- }
9674
- )
9675
- ]
9676
- },
9677
- `${diff2.app1}${diff2.app2}`
9678
- )
9679
- ] }),
9680
- /* @__PURE__ */ jsx("div", { className: "flex-grow overflow-y-scroll scrollbar-thin scrollbar-thumb-scrollbar", children: diff2.diffCode ? /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Accordion.Root, { className: "w-full", type: "multiple", children: /* @__PURE__ */ jsx(Mdx, { code: diff2.diffCode, components: mdxComponents$3 }) }) }) : diff2.app1 && diff2.app2 ? /* @__PURE__ */ jsx("p", { className: "m-5 inline-flex items-center justify-center bg-foreground px-1 py-0.5 font-mono text-sm uppercase text-background", children: "There was a problem generating the diff" }) : /* @__PURE__ */ jsx("p", { className: "m-5 inline-flex items-center justify-center bg-foreground px-1 py-0.5 font-mono text-sm uppercase text-background", children: "Select two apps to compare" }) })
9681
- ] })
9682
- }
9683
- )
9684
- }
9685
- );
9686
- }
9687
- function SelectFileToDiff({
9688
- name,
9689
- label,
9690
- className,
9691
- allApps,
9692
- defaultValue
9693
- }) {
9694
- return /* @__PURE__ */ jsxs(Select.Root, { name, defaultValue, children: [
9695
- /* @__PURE__ */ jsxs(
9696
- Select.Trigger,
9697
- {
9698
- className: clsx(
9699
- "flex h-full w-full max-w-[50%] items-center justify-between px-3 text-left radix-placeholder:text-gray-500 focus-visible:outline-none",
9700
- className
9701
- ),
9702
- "aria-label": `Select ${label} for git Diff`,
9703
- children: [
9704
- /* @__PURE__ */ jsxs("span", { className: "overflow-hidden text-ellipsis whitespace-nowrap", children: [
9705
- label,
9706
- ":",
9707
- " ",
9708
- /* @__PURE__ */ jsx(
9709
- SelectValue,
9710
- {
9711
- placeholder: `Select ${label}`,
9712
- className: "inline-block w-40 text-ellipsis"
9713
- }
9714
- )
9715
- ] }),
9716
- /* @__PURE__ */ jsx(Select.Icon, { className: "", children: /* @__PURE__ */ jsx(Icon, { name: "TriangleDownSmall" }) })
9717
- ]
9718
- }
9719
- ),
9720
- /* @__PURE__ */ jsx(Select.Portal, { children: /* @__PURE__ */ jsxs(
9721
- Select.Content,
9722
- {
9723
- position: "popper",
9724
- align: "start",
9725
- className: "z-20 max-h-[50vh] bg-black text-white lg:max-h-[70vh]",
9726
- children: [
9727
- /* @__PURE__ */ jsx(Select.ScrollUpButton, { className: "flex h-5 cursor-default items-center justify-center ", children: /* @__PURE__ */ jsx(Icon, { name: "ChevronUp" }) }),
9728
- /* @__PURE__ */ jsx(Select.Viewport, { className: "p-3", children: /* @__PURE__ */ jsxs(Select.Group, { children: [
9729
- /* @__PURE__ */ jsx(Select.Label, { className: "px-5 pb-3 font-mono uppercase", children: label }),
9730
- allApps.map((app) => {
9731
- return (
9732
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
9733
- /* @__PURE__ */ jsx(SelectItem, { value: app.name, children: app.displayName }, app.name)
9734
- );
9735
- })
9736
- ] }) }),
9737
- /* @__PURE__ */ jsx(Select.ScrollDownButton, { className: "flex h-5 cursor-default items-center justify-center ", children: /* @__PURE__ */ jsx(Icon, { name: "ChevronDown" }) })
9738
- ]
9739
- }
9740
- ) })
9741
- ] });
9742
- }
9743
- const SelectItem = React__default.forwardRef(
9744
- ({ children, className, ...props }, forwardedRef) => {
9745
- return /* @__PURE__ */ jsxs(
9746
- Select.Item,
9747
- {
9748
- className: clsx(
9749
- "relative flex cursor-pointer select-none items-center rounded px-10 py-2 leading-none opacity-80 radix-disabled:text-red-500 radix-highlighted:opacity-100 radix-highlighted:outline-none radix-state-checked:opacity-100",
9750
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
9751
- className
9752
- ),
9753
- ...props,
9754
- ref: forwardedRef,
9755
- children: [
9756
- /* @__PURE__ */ jsx(Select.ItemText, { children }),
9757
- /* @__PURE__ */ jsx(Select.ItemIndicator, { className: "absolute left-0 inline-flex w-[25px] items-center justify-center", children: /* @__PURE__ */ jsx(Icon, { name: "CheckSmall" }) })
9758
- ]
9759
- }
9760
- );
9761
- }
9762
- );
9763
- const SelectValue = React__default.forwardRef(
9764
- ({ children, className, ...props }, forwardedRef) => {
9765
- return /* @__PURE__ */ jsx(Select.Value, { ...props, ref: forwardedRef, children: props.value });
9766
- }
9767
- );
9768
- function NavChevrons({
9769
- prev,
9770
- next
9771
- }) {
9772
- return /* @__PURE__ */ jsxs("div", { className: "relative flex h-full overflow-hidden", children: [
9773
- prev ? /* @__PURE__ */ jsx(
9774
- Link,
9775
- {
9776
- prefetch: "intent",
9777
- ...prev,
9778
- className: "group flex h-full items-center justify-center border-l px-7",
9779
- children: /* @__PURE__ */ jsxs(Fragment, { children: [
9780
- /* @__PURE__ */ jsx(
9781
- Icon,
9782
- {
9783
- name: "ChevronLeft",
9784
- className: "absolute opacity-100 transition duration-300 ease-in-out group-hover:translate-y-10 group-hover:opacity-0"
9785
- }
9786
- ),
9787
- /* @__PURE__ */ jsx(
9788
- Icon,
9789
- {
9790
- name: "ChevronLeft",
9791
- className: "absolute -translate-y-10 opacity-0 transition duration-300 ease-in-out group-hover:translate-y-0 group-hover:opacity-100"
9792
- }
9793
- )
9794
- ] })
9795
- }
9796
- ) : null,
9797
- next ? /* @__PURE__ */ jsx(
9798
- Link,
9799
- {
9800
- prefetch: "intent",
9801
- ...next,
9802
- className: "group flex h-full items-center justify-center border-l px-7",
9803
- children: /* @__PURE__ */ jsxs(Fragment, { children: [
9804
- /* @__PURE__ */ jsx(
9805
- Icon,
9806
- {
9807
- name: "ChevronRight",
9808
- className: "absolute opacity-100 transition duration-300 ease-in-out group-hover:translate-y-10 group-hover:opacity-0"
9809
- }
9810
- ),
9811
- /* @__PURE__ */ jsx(
9812
- Icon,
9813
- {
9814
- name: "ChevronRight",
9815
- className: "absolute -translate-y-10 opacity-0 transition duration-300 ease-in-out group-hover:translate-y-0 group-hover:opacity-100"
9843
+ return /* @__PURE__ */ jsxs("ul", { ...props, children: [
9844
+ diffFiles.length > 1 && !ENV.EPICSHOP_DEPLOYED ? /* @__PURE__ */ jsx("div", { className: "mb-2 border-b border-b-gray-50 border-opacity-50 pb-2 font-sans", children: /* @__PURE__ */ jsx(
9845
+ LaunchEditor,
9846
+ {
9847
+ appFile: diffFiles.map(
9848
+ (file) => `${file.path},${file.line},1`
9849
+ ),
9850
+ appName: "playground",
9851
+ onUpdate: handleLaunchUpdate,
9852
+ children: /* @__PURE__ */ jsx("p", { children: "Open All Files" })
9853
+ }
9854
+ ) }) : null,
9855
+ diffFiles.map((file) => {
9856
+ var _a3;
9857
+ return /* @__PURE__ */ jsx("li", { "data-state": file.status, children: /* @__PURE__ */ jsx(
9858
+ LaunchEditor,
9859
+ {
9860
+ appFile: `${file.path},${file.line},1`,
9861
+ appName: ENV.EPICSHOP_DEPLOYED ? ((_a3 = data.problem) == null ? void 0 : _a3.name) ?? "playground" : "playground",
9862
+ onUpdate: handleLaunchUpdate,
9863
+ children: /* @__PURE__ */ jsx("code", { children: file.path })
9864
+ }
9865
+ ) }, file.path);
9866
+ })
9867
+ ] });
9868
+ }
9869
+ }
9870
+ )
9816
9871
  }
9817
- )
9872
+ ) })
9818
9873
  ] })
9819
9874
  }
9820
- ) : null
9821
- ] });
9875
+ ) })
9876
+ ] }) });
9822
9877
  }
9823
9878
  function pageTitle(data, workshopTitle) {
9824
9879
  var _a2;
@@ -9841,18 +9896,24 @@ function pageTitle(data, workshopTitle) {
9841
9896
  }
9842
9897
  const meta$3 = ({
9843
9898
  data,
9844
- matches
9899
+ matches,
9900
+ params
9845
9901
  }) => {
9846
9902
  var _a2;
9847
9903
  const rootData = (_a2 = matches.find((m) => m.id === "root")) == null ? void 0 : _a2.data;
9904
+ if (!data || !rootData)
9905
+ return [{ title: "🦉 | Error" }];
9848
9906
  const { emoji: emoji2, stepNumber, title, exerciseNumber, exerciseTitle } = pageTitle(data);
9849
- return [
9850
- {
9851
- title: `${emoji2} | ${stepNumber}. ${title} | ${exerciseNumber}. ${exerciseTitle} | ${(rootData == null ? void 0 : rootData.workshopTitle) ?? "Epic Workshop"}`
9852
- }
9853
- ];
9907
+ return getSeoMetaTags({
9908
+ title: `${emoji2} | ${stepNumber}. ${title} | ${exerciseNumber}. ${exerciseTitle} | ${rootData.workshopTitle}`,
9909
+ description: `${params.type} step for exercise ${exerciseNumber}. ${exerciseTitle}`,
9910
+ ogTitle: title,
9911
+ ogDescription: `${exerciseTitle} step ${Number(stepNumber)} ${params.type}`,
9912
+ instructor: rootData.instructor,
9913
+ requestInfo: rootData.requestInfo
9914
+ });
9854
9915
  };
9855
- async function loader$j({ request, params }) {
9916
+ async function loader$k({ request, params }) {
9856
9917
  var _a2, _b2;
9857
9918
  const timings = makeTimings("exerciseStepTypeLoader");
9858
9919
  const workshopTitle = await getWorkshopTitle();
@@ -10286,10 +10347,10 @@ const route6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
10286
10347
  ErrorBoundary: ErrorBoundary$1,
10287
10348
  default: ExercisePartRoute,
10288
10349
  headers: headers$4,
10289
- loader: loader$j,
10350
+ loader: loader$k,
10290
10351
  meta: meta$3
10291
10352
  }, Symbol.toStringTag, { value: "Module" }));
10292
- async function loader$i({ params }) {
10353
+ async function loader$j({ params }) {
10293
10354
  const problemApp = await getExerciseApp({ ...params, type: "problem" }).then(
10294
10355
  (a) => isProblemApp(a) ? a : null
10295
10356
  );
@@ -10307,25 +10368,27 @@ async function loader$i({ params }) {
10307
10368
  }
10308
10369
  const route7 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
10309
10370
  __proto__: null,
10310
- loader: loader$i
10371
+ loader: loader$j
10311
10372
  }, Symbol.toStringTag, { value: "Module" }));
10312
10373
  const meta$2 = ({
10313
10374
  data,
10314
10375
  matches
10315
10376
  }) => {
10316
10377
  var _a2;
10317
- if (!data) {
10318
- return [{ title: "🦉 | Error" }];
10319
- }
10320
- const number = data.exercise.exerciseNumber.toString().padStart(2, "0");
10378
+ const number = data == null ? void 0 : data.exercise.exerciseNumber.toString().padStart(2, "0");
10321
10379
  const rootData = (_a2 = matches.find((m) => m.id === "root")) == null ? void 0 : _a2.data;
10322
- return [
10323
- {
10324
- title: `🦉 | ${number}. ${data.exercise.title} | ${rootData == null ? void 0 : rootData.workshopTitle}`
10325
- }
10326
- ];
10380
+ if (!data || !rootData)
10381
+ return [{ title: "🦉 | Error" }];
10382
+ return getSeoMetaTags({
10383
+ title: `🦉 | ${number}. ${data.exercise.title} | ${rootData == null ? void 0 : rootData.workshopTitle}`,
10384
+ description: `Elaboration for ${number}. ${data.exercise.title}`,
10385
+ ogTitle: `Finished: ${data.exercise.title}`,
10386
+ ogDescription: `Elaboration for exercise ${Number(number)}`,
10387
+ instructor: rootData.instructor,
10388
+ requestInfo: rootData.requestInfo
10389
+ });
10327
10390
  };
10328
- async function loader$h({ request, params }) {
10391
+ async function loader$i({ request, params }) {
10329
10392
  const timings = makeTimings("exerciseFinishedLoader");
10330
10393
  invariantResponse(params.exerciseNumber, "exerciseNumber is required");
10331
10394
  const exercise = await getExercise(params.exerciseNumber, {
@@ -10490,10 +10553,10 @@ const route8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
10490
10553
  __proto__: null,
10491
10554
  default: ExerciseFinished$1,
10492
10555
  headers: headers$3,
10493
- loader: loader$h,
10556
+ loader: loader$i,
10494
10557
  meta: meta$2
10495
10558
  }, Symbol.toStringTag, { value: "Module" }));
10496
- async function loader$g({ request }) {
10559
+ async function loader$h({ request }) {
10497
10560
  ensureUndeployed();
10498
10561
  await requireAuthInfo({ request });
10499
10562
  return json({ discordAuthUrl: getDiscordAuthURL() });
@@ -10605,26 +10668,8 @@ const route9 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
10605
10668
  __proto__: null,
10606
10669
  action: action$4,
10607
10670
  default: Account,
10608
- loader: loader$g
10671
+ loader: loader$h
10609
10672
  }, Symbol.toStringTag, { value: "Module" }));
10610
- async function resolveApps({
10611
- request,
10612
- params,
10613
- timings
10614
- }) {
10615
- const url = new URL(request.url);
10616
- const { appName } = params;
10617
- invariantResponse(appName, "appName param required");
10618
- const app = await getAppByName(appName, { request, timings });
10619
- const fileAppName = url.searchParams.get("fileAppName");
10620
- if (fileAppName) {
10621
- const apps = await getApps({ request, timings });
10622
- const fileApp = fileAppName ? apps.find((app2) => app2.name === fileAppName) : app;
10623
- return { app, fileApp };
10624
- } else {
10625
- return { app, fileApp: app };
10626
- }
10627
- }
10628
10673
  async function getForceFresh(filePath, cacheEntry) {
10629
10674
  if (!cacheEntry)
10630
10675
  return true;
@@ -10675,7 +10720,25 @@ async function compileTs(filePath, fullPath, {
10675
10720
  }
10676
10721
  });
10677
10722
  }
10678
- async function loader$f({ request, params }) {
10723
+ async function resolveApps({
10724
+ request,
10725
+ params,
10726
+ timings
10727
+ }) {
10728
+ const url = new URL(request.url);
10729
+ const { appName } = params;
10730
+ invariantResponse(appName, "appName param required");
10731
+ const app = await getAppByName(appName, { request, timings });
10732
+ const fileAppName = url.searchParams.get("fileAppName");
10733
+ if (fileAppName) {
10734
+ const apps = await getApps({ request, timings });
10735
+ const fileApp = fileAppName ? apps.find((app2) => app2.name === fileAppName) : app;
10736
+ return { app, fileApp };
10737
+ } else {
10738
+ return { app, fileApp: app };
10739
+ }
10740
+ }
10741
+ async function loader$g({ request, params }) {
10679
10742
  const timings = makeTimings("app-file");
10680
10743
  const { fileApp, app } = await resolveApps({ request, params, timings });
10681
10744
  if (!fileApp || !app) {
@@ -10731,9 +10794,9 @@ async function loader$f({ request, params }) {
10731
10794
  }
10732
10795
  const route10 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
10733
10796
  __proto__: null,
10734
- loader: loader$f
10797
+ loader: loader$g
10735
10798
  }, Symbol.toStringTag, { value: "Module" }));
10736
- async function loader$e(args) {
10799
+ async function loader$f(args) {
10737
10800
  const api = await getApiModule(args);
10738
10801
  invariantResponse(
10739
10802
  api.mod.loader,
@@ -10836,9 +10899,9 @@ async function getApiModule({ request, params }) {
10836
10899
  const route11 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
10837
10900
  __proto__: null,
10838
10901
  action: action$3,
10839
- loader: loader$e
10902
+ loader: loader$f
10840
10903
  }, Symbol.toStringTag, { value: "Module" }));
10841
- async function loader$d({ request, params }) {
10904
+ async function loader$e({ request, params }) {
10842
10905
  const timings = makeTimings("epic_ws script");
10843
10906
  const { fileApp, app } = await resolveApps({ request, params, timings });
10844
10907
  if (!fileApp || !app) {
@@ -10904,9 +10967,9 @@ async function loader$d({ request, params }) {
10904
10967
  }
10905
10968
  const route12 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
10906
10969
  __proto__: null,
10907
- loader: loader$d
10970
+ loader: loader$e
10908
10971
  }, Symbol.toStringTag, { value: "Module" }));
10909
- async function loader$c({ request, params }) {
10972
+ async function loader$d({ request, params }) {
10910
10973
  var _a2;
10911
10974
  const timings = makeTimings("app");
10912
10975
  const { fileApp, app } = await resolveApps({ request, params, timings });
@@ -10992,9 +11055,9 @@ async function loader$c({ request, params }) {
10992
11055
  }
10993
11056
  const route13 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
10994
11057
  __proto__: null,
10995
- loader: loader$c
11058
+ loader: loader$d
10996
11059
  }, Symbol.toStringTag, { value: "Module" }));
10997
- async function loader$b({ request, params }) {
11060
+ async function loader$c({ request, params }) {
10998
11061
  var _a2;
10999
11062
  const timings = makeTimings("app_test_loader");
11000
11063
  const { testName } = params;
@@ -11134,16 +11197,25 @@ import(${JSON.stringify(testScriptPath)}).then(
11134
11197
  }
11135
11198
  const route14 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
11136
11199
  __proto__: null,
11137
- loader: loader$b
11200
+ loader: loader$c
11138
11201
  }, Symbol.toStringTag, { value: "Module" }));
11139
11202
  const meta$1 = ({
11140
11203
  matches
11141
11204
  }) => {
11142
11205
  var _a2;
11143
11206
  const rootData = (_a2 = matches.find((m) => m.id === "root")) == null ? void 0 : _a2.data;
11144
- return [{ title: `🎉 ${rootData == null ? void 0 : rootData.workshopTitle}` }];
11207
+ if (!rootData)
11208
+ return [];
11209
+ return getSeoMetaTags({
11210
+ title: `🎉 ${rootData == null ? void 0 : rootData.workshopTitle}`,
11211
+ description: `Elaboration for ${rootData == null ? void 0 : rootData.workshopTitle}`,
11212
+ ogTitle: `Finished ${rootData == null ? void 0 : rootData.workshopTitle}`,
11213
+ ogDescription: `You finished! Time to submit feedback.`,
11214
+ instructor: rootData.instructor,
11215
+ requestInfo: rootData.requestInfo
11216
+ });
11145
11217
  };
11146
- async function loader$a({ request }) {
11218
+ async function loader$b({ request }) {
11147
11219
  const timings = makeTimings("finishedLoader");
11148
11220
  const exercises = await getExercises({ request, timings });
11149
11221
  const compiledFinished = await time(() => getWorkshopFinished({ request }), {
@@ -11280,10 +11352,10 @@ const route16 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
11280
11352
  __proto__: null,
11281
11353
  default: ExerciseFinished,
11282
11354
  headers: headers$2,
11283
- loader: loader$a,
11355
+ loader: loader$b,
11284
11356
  meta: meta$1
11285
11357
  }, Symbol.toStringTag, { value: "Module" }));
11286
- async function loader$9({ request }) {
11358
+ async function loader$a({ request }) {
11287
11359
  const timings = makeTimings("indexLoader");
11288
11360
  const [title, exercises, workshopReadme] = await Promise.all([
11289
11361
  time(() => getWorkshopTitle(), {
@@ -11413,7 +11485,7 @@ const route17 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
11413
11485
  ErrorBoundary,
11414
11486
  default: Index,
11415
11487
  headers: headers$1,
11416
- loader: loader$9
11488
+ loader: loader$a
11417
11489
  }, Symbol.toStringTag, { value: "Module" }));
11418
11490
  const EVENTS = {
11419
11491
  USER_CODE_RECEIVED: "USER_CODE_RECEIVED",
@@ -11475,7 +11547,7 @@ const EventSchema = z$1.union([
11475
11547
  AuthResolvedEventSchema,
11476
11548
  AuthRejectedEventSchema
11477
11549
  ]);
11478
- async function loader$8({ request }) {
11550
+ async function loader$9({ request }) {
11479
11551
  ensureUndeployed();
11480
11552
  return eventStream(request.signal, function setup(send) {
11481
11553
  function handleCodeReceived(data) {
@@ -11512,9 +11584,9 @@ async function loader$8({ request }) {
11512
11584
  const route27 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
11513
11585
  __proto__: null,
11514
11586
  EventSchema,
11515
- loader: loader$8
11587
+ loader: loader$9
11516
11588
  }, Symbol.toStringTag, { value: "Module" }));
11517
- async function loader$7() {
11589
+ async function loader$8() {
11518
11590
  ensureUndeployed();
11519
11591
  const isAuthenticated = Boolean(await getAuthInfo());
11520
11592
  if (isAuthenticated)
@@ -11637,7 +11709,7 @@ const route18 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
11637
11709
  __proto__: null,
11638
11710
  action: action$2,
11639
11711
  default: Login,
11640
- loader: loader$7
11712
+ loader: loader$8
11641
11713
  }, Symbol.toStringTag, { value: "Module" }));
11642
11714
  function Support() {
11643
11715
  var _a2;
@@ -11730,7 +11802,7 @@ const meta = ({
11730
11802
  const rootData = (_a2 = matches.find((m) => m.id === "root")) == null ? void 0 : _a2.data;
11731
11803
  return [{ title: `👷 | ${rootData == null ? void 0 : rootData.workshopTitle}` }];
11732
11804
  };
11733
- async function loader$6({ request }) {
11805
+ async function loader$7({ request }) {
11734
11806
  ensureUndeployed();
11735
11807
  const timings = makeTimings("adminLoader");
11736
11808
  const workshopSlug = await getEpicWorkshopSlug() ?? "Unkown";
@@ -11941,18 +12013,18 @@ const route20 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
11941
12013
  __proto__: null,
11942
12014
  action: action$1,
11943
12015
  default: AdminLayout,
11944
- loader: loader$6,
12016
+ loader: loader$7,
11945
12017
  meta
11946
12018
  }, Symbol.toStringTag, { value: "Module" }));
11947
- async function loader$5() {
12019
+ async function loader$6() {
11948
12020
  const apps = await getApps();
11949
12021
  return json({ apps });
11950
12022
  }
11951
12023
  const route21 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
11952
12024
  __proto__: null,
11953
- loader: loader$5
12025
+ loader: loader$6
11954
12026
  }, Symbol.toStringTag, { value: "Module" }));
11955
- async function loader$4({ request }) {
12027
+ async function loader$5({ request }) {
11956
12028
  const timings = makeTimings("appsLoader");
11957
12029
  const apps = await getApps({ request, timings });
11958
12030
  return json(
@@ -11962,9 +12034,9 @@ async function loader$4({ request }) {
11962
12034
  }
11963
12035
  const route22 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
11964
12036
  __proto__: null,
11965
- loader: loader$4
12037
+ loader: loader$5
11966
12038
  }, Symbol.toStringTag, { value: "Module" }));
11967
- async function loader$3({ request }) {
12039
+ async function loader$4({ request }) {
11968
12040
  var _a2, _b2, _c, _d;
11969
12041
  const reqUrl = new URL(request.url);
11970
12042
  const searchParams = reqUrl.searchParams;
@@ -12052,9 +12124,9 @@ function DiffViewer() {
12052
12124
  const route23 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
12053
12125
  __proto__: null,
12054
12126
  default: DiffViewer,
12055
- loader: loader$3
12127
+ loader: loader$4
12056
12128
  }, Symbol.toStringTag, { value: "Module" }));
12057
- async function loader$2({ request }) {
12129
+ async function loader$3({ request }) {
12058
12130
  const timings = makeTimings("appsLoader");
12059
12131
  const exercises = await getExercises({ request, timings });
12060
12132
  return json(
@@ -12063,6 +12135,270 @@ async function loader$2({ request }) {
12063
12135
  );
12064
12136
  }
12065
12137
  const route25 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
12138
+ __proto__: null,
12139
+ loader: loader$3
12140
+ }, Symbol.toStringTag, { value: "Module" }));
12141
+ const epicWebLogo = /* @__PURE__ */ jsxs(
12142
+ "svg",
12143
+ {
12144
+ xmlns: "http://www.w3.org/2000/svg",
12145
+ width: "212",
12146
+ height: "56",
12147
+ fill: "none",
12148
+ viewBox: "0 0 264 70",
12149
+ children: [
12150
+ /* @__PURE__ */ jsxs("g", { fill: "#FFF", children: [
12151
+ /* @__PURE__ */ jsx("path", { d: "M92.593 36.536v6.189h9.061v2.453H90V25.662h11.515v2.454h-8.922v5.994h8.225v2.426h-8.225Z" }),
12152
+ /* @__PURE__ */ jsx(
12153
+ "path",
12154
+ {
12155
+ "fill-rule": "evenodd",
12156
+ d: "M109.942 25.662h7.081c1.813 0 3.29.614 4.489 1.813 1.199 1.198 1.812 2.676 1.812 4.46 0 1.757-.613 3.262-1.812 4.461-1.199 1.199-2.676 1.812-4.489 1.812h-4.488v6.97h-2.593V25.662Zm2.593 10.12h4.488c1.088 0 1.98-.362 2.677-1.086.697-.753 1.059-1.673 1.059-2.76 0-2.231-1.589-3.848-3.736-3.848h-4.488v7.695Z",
12157
+ "clip-rule": "evenodd"
12158
+ }
12159
+ ),
12160
+ /* @__PURE__ */ jsx("path", { d: "M131.126 43.379V27.342h-3.089v-1.828h8.809v1.828h-3.127V43.38h3.127v1.828h-8.809V43.38h3.089Zm21.11 2.161c-2.955 0-5.409-.975-7.332-2.927-1.924-1.951-2.872-4.349-2.872-7.193 0-2.843.948-5.241 2.872-7.193 1.923-1.951 4.377-2.927 7.332-2.927 3.569 0 6.747 1.84 8.42 4.74l-2.259 1.31c-1.115-2.147-3.485-3.54-6.161-3.54-2.258 0-4.098.724-5.52 2.174-1.422 1.45-2.119 3.262-2.119 5.436 0 2.147.697 3.96 2.119 5.41 1.422 1.449 3.262 2.174 5.52 2.174 2.676 0 5.046-1.394 6.161-3.513l2.259 1.282c-.809 1.45-1.98 2.621-3.485 3.485-1.506.865-3.151 1.283-4.935 1.283Z" }),
12161
+ /* @__PURE__ */ jsx(
12162
+ "path",
12163
+ {
12164
+ "fill-rule": "evenodd",
12165
+ d: "M101.654 42.725v2.453H90V25.662h11.515v2.454h-8.922v5.994h8.225v2.426h-8.225v6.189h9.061Zm-8.761-.3h9.061v3.053H89.7V25.362h12.115v3.054h-8.922v5.394h8.225v3.026h-8.225v5.589Zm16.749-17.063h7.381c1.889 0 3.444.643 4.701 1.9 1.257 1.257 1.9 2.812 1.9 4.673 0 1.834-.643 3.416-1.9 4.673-1.257 1.257-2.812 1.9-4.701 1.9h-4.188v6.97h-3.193V25.362Zm2.893 19.816h-2.593V25.662h7.081c1.813 0 3.29.614 4.489 1.813 1.199 1.198 1.812 2.676 1.812 4.46 0 1.757-.613 3.262-1.812 4.461-1.199 1.199-2.676 1.812-4.489 1.812h-4.488v6.97Zm15.502-17.836v-1.828h8.809v1.828h-3.127V43.38h3.127v1.828h-8.809V43.38h3.089V27.342h-3.089Zm2.789.3h-3.089v-2.428h9.409v2.428h-3.127V43.08h3.127v2.428h-9.409V43.08h3.089V27.642Zm30.239 2.507-2.789 1.618-.145-.279c-1.059-2.038-3.32-3.379-5.895-3.379-2.188 0-3.947.7-5.306 2.085-1.362 1.388-2.033 3.123-2.033 5.226 0 2.076.671 3.81 2.033 5.199 1.359 1.386 3.118 2.085 5.306 2.085 2.575 0 4.837-1.341 5.896-3.353l.144-.274 2.787 1.583-.145.26c-.837 1.499-2.047 2.708-3.598 3.599-1.554.891-3.25 1.322-5.084 1.322-3.028 0-5.561-1.003-7.546-3.017-1.982-2.01-2.958-4.485-2.958-7.404 0-2.918.976-5.392 2.958-7.403 1.985-2.014 4.518-3.017 7.546-3.017 3.672 0 6.951 1.894 8.68 4.89l.149.259Zm-48.23 5.334h4.188c1.012 0 1.823-.334 2.459-.993.643-.696.977-1.542.977-2.555 0-2.072-1.462-3.547-3.436-3.547h-4.188v7.095Zm6.865-.787c-.697.724-1.589 1.087-2.677 1.087h-4.488v-7.695h4.488c2.147 0 3.736 1.617 3.736 3.847 0 1.088-.362 2.008-1.059 2.76Zm40.805 6.337c-.8 1.33-1.92 2.413-3.334 3.225-1.506.865-3.151 1.283-4.935 1.283-2.955 0-5.409-.976-7.332-2.928-1.924-1.951-2.872-4.349-2.872-7.193 0-2.843.948-5.241 2.872-7.193 1.923-1.951 4.377-2.927 7.332-2.927 3.462 0 6.556 1.732 8.266 4.482l.131.218.023.04-2.259 1.31a6.226 6.226 0 0 0-.144-.263c-1.168-1.997-3.451-3.278-6.017-3.278-2.258 0-4.098.725-5.52 2.175-1.422 1.45-2.119 3.262-2.119 5.436 0 2.147.697 3.96 2.119 5.41 1.422 1.449 3.262 2.174 5.52 2.174 2.565 0 4.848-1.28 6.015-3.251.051-.086.1-.173.146-.262l2.259 1.282-.07.123c-.027.046-.053.092-.081.137Z",
12166
+ "clip-rule": "evenodd"
12167
+ }
12168
+ ),
12169
+ /* @__PURE__ */ jsx("path", { d: "M174.058 45.178h-3.011l-5.604-19.516h2.732l4.461 16.06 4.739-16.06h2.621l4.74 16.06 4.46-16.06h2.733l-5.604 19.516h-3.011l-4.628-15.585-4.628 15.585Zm27.294-8.643v6.19h9.061v2.453h-11.654V25.662h11.515v2.454h-8.922v5.994h8.225v2.425h-8.225Zm28.222-1.477c1.784.864 2.928 2.509 2.928 4.6 0 1.561-.558 2.872-1.645 3.931-1.088 1.06-2.426 1.59-4.015 1.59h-8.42V25.661h7.807c1.533 0 2.815.502 3.875 1.534 1.059 1.031 1.589 2.286 1.589 3.791 0 1.729-.697 3.095-2.119 4.07Zm-3.345-6.97h-5.214v5.966h5.214c1.644 0 2.899-1.31 2.899-2.983 0-.809-.279-1.506-.864-2.091-.558-.585-1.227-.892-2.035-.892Zm-5.214 14.665h5.827c1.756 0 3.095-1.394 3.095-3.179 0-.864-.307-1.617-.92-2.23-.586-.613-1.311-.92-2.175-.92h-5.827v6.329Z" }),
12170
+ /* @__PURE__ */ jsx(
12171
+ "path",
12172
+ {
12173
+ "fill-rule": "evenodd",
12174
+ d: "M174.281 45.478h-3.46l-5.777-20.116h3.359l4.241 15.27 4.507-15.27h3.069l4.507 15.27 4.241-15.27h3.359l-5.776 20.116h-3.461l-4.404-14.83-4.405 14.83Zm-.223-.3h-3.011l-5.604-19.516h2.732l4.461 16.06 4.739-16.06h2.621l4.74 16.06 4.46-16.06h2.733l-5.604 19.516h-3.011l-4.628-15.585-4.628 15.585Zm36.655-2.753v3.053h-12.254V25.362h12.115v3.054h-8.922v5.394h8.225v3.026h-8.225v5.589h9.061Zm-9.361.3v-6.19h8.225V34.11h-8.225v-5.994h8.922v-2.454h-11.515v19.516h11.654v-2.453h-9.061Zm16.77 2.753V25.362h8.107c1.607 0 2.966.53 4.084 1.619 1.118 1.088 1.68 2.42 1.68 4.006 0 1.66-.615 3.019-1.861 4.029 1.635.957 2.67 2.6 2.67 4.642 0 1.642-.59 3.03-1.736 4.146-1.146 1.117-2.561 1.674-4.224 1.674h-8.72Zm11.752-10.264a6.066 6.066 0 0 0-.3-.156c.094-.065.185-.131.273-.2 1.238-.958 1.846-2.256 1.846-3.87 0-1.506-.53-2.76-1.589-3.792-1.06-1.032-2.342-1.534-3.875-1.534h-7.807v19.516h8.42c1.589 0 2.927-.53 4.015-1.589 1.087-1.06 1.645-2.37 1.645-3.931 0-1.971-1.017-3.546-2.628-4.444Zm-1.827-6.027c-.505-.53-1.097-.8-1.818-.8h-4.914v5.367h4.914c1.469 0 2.599-1.166 2.599-2.683 0-.73-.248-1.35-.776-1.879l-.005-.005Zm-1.818 4.867c1.644 0 2.899-1.31 2.899-2.983 0-.809-.279-1.506-.864-2.091-.558-.585-1.227-.892-2.035-.892h-5.214v5.966h5.214Zm2.575 3.502-.005-.005c-.527-.553-1.173-.827-1.957-.827h-5.527v5.729h5.527c1.582 0 2.795-1.251 2.795-2.879a2.75 2.75 0 0 0-.833-2.018Zm-7.789 5.197v-6.329h5.827c.864 0 1.589.307 2.175.92.613.613.92 1.366.92 2.23 0 1.785-1.339 3.179-3.095 3.179h-5.827Z",
12175
+ "clip-rule": "evenodd"
12176
+ }
12177
+ ),
12178
+ /* @__PURE__ */ jsx("path", { d: "M239.041 32.853a.89.89 0 0 1-1.254 0 .89.89 0 0 1 0-1.254.89.89 0 0 1 1.254 0 .889.889 0 0 1 0 1.254Zm2.753-7.187h2.904c1.003 0 1.839.355 2.508 1.055.679.7 1.013 1.567 1.013 2.6 0 1.035-.334 1.902-1.013 2.602-.669.7-1.505 1.055-2.508 1.055h-2.904v-7.313Zm1.442 5.933h1.462c.638 0 1.15-.209 1.547-.627.397-.428.595-.971.595-1.65 0-.68-.198-1.223-.595-1.64-.397-.429-.909-.637-1.547-.637h-1.462v4.554Zm8.753-1.64v1.64h3.082v1.379h-4.524v-7.313h4.471v1.38h-3.029V28.6h2.768v1.358h-2.768Zm8.997 3.019H259.2l-2.455-7.313h1.567l1.786 5.62 1.776-5.62h1.578l-2.466 7.313Z" })
12179
+ ] }),
12180
+ /* @__PURE__ */ jsx(
12181
+ "path",
12182
+ {
12183
+ fill: "url(#markGradient)",
12184
+ d: "M36.277 33.738a64.504 64.504 0 0 1-4.257 2.15c-6.333 2.912-15.383 5.86-26.228 5.981l-1.249.014-.226-1.228a31.016 31.016 0 0 1-.531-5.638C3.786 17.804 17.787 3.802 35 3.802a31.05 31.05 0 0 1 13.295 2.975l4.146-2.113A34.774 34.774 0 0 0 35 0C15.712 0 0 15.712 0 35c0 7.7 2.504 14.83 6.74 20.617 7.252-1.235 11.802-4.14 11.802-4.14s-2.905 4.544-4.14 11.798A34.803 34.803 0 0 0 35 70c19.288 0 35-15.712 35-35a34.778 34.778 0 0 0-4.652-17.42l-2.11 4.138a31.037 31.037 0 0 1 2.976 13.299C66.214 52.23 52.213 66.23 35 66.23c-1.942 0-3.804-.196-5.635-.53l-1.231-.225.014-1.251c.12-10.854 3.069-19.903 5.98-26.234a64.386 64.386 0 0 1 2.149-4.253Z"
12185
+ }
12186
+ ),
12187
+ /* @__PURE__ */ jsx(
12188
+ "path",
12189
+ {
12190
+ fill: "#FFF",
12191
+ d: "m53.235 27.155-8.03-2.344-2.345-8.047L69.5.5 53.235 27.155Z"
12192
+ }
12193
+ ),
12194
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
12195
+ "linearGradient",
12196
+ {
12197
+ id: "markGradient",
12198
+ x1: "49.496",
12199
+ x2: "20.585",
12200
+ y1: "20.504",
12201
+ y2: "49.431",
12202
+ gradientUnits: "userSpaceOnUse",
12203
+ children: [
12204
+ /* @__PURE__ */ jsx("stop", { "stop-color": "#4F75FF" }),
12205
+ /* @__PURE__ */ jsx("stop", { offset: "1", "stop-color": "#30AFFF" })
12206
+ ]
12207
+ }
12208
+ ) })
12209
+ ]
12210
+ }
12211
+ );
12212
+ const WIDTH = 1200;
12213
+ const HEIGHT = 630;
12214
+ function OgLayout({
12215
+ instructor,
12216
+ children,
12217
+ request,
12218
+ urlPathname = new URL(request.url).pathname.replace(/\/og$/, ""),
12219
+ workshopTitle
12220
+ }) {
12221
+ const domain = getDomainUrl(request);
12222
+ const protocolFreeDomain = domain.replace(/^https?:\/\//, "");
12223
+ return /* @__PURE__ */ jsxs(
12224
+ "div",
12225
+ {
12226
+ style: {
12227
+ // fontFamily: ,
12228
+ display: "flex",
12229
+ flexDirection: "column",
12230
+ width: WIDTH,
12231
+ height: HEIGHT,
12232
+ position: "relative"
12233
+ },
12234
+ children: [
12235
+ /* @__PURE__ */ jsx(
12236
+ "div",
12237
+ {
12238
+ style: {
12239
+ display: "flex",
12240
+ position: "absolute",
12241
+ top: 0,
12242
+ right: 0,
12243
+ bottom: 0,
12244
+ left: 0,
12245
+ width: "100%",
12246
+ height: "100%",
12247
+ backgroundColor: "#080B16"
12248
+ },
12249
+ children: /* @__PURE__ */ jsx(
12250
+ "img",
12251
+ {
12252
+ style: {
12253
+ width: "100%",
12254
+ height: "100%",
12255
+ objectFit: "cover",
12256
+ opacity: 0.4
12257
+ },
12258
+ src: `${domain}/img/epicweb-og-background.png`
12259
+ }
12260
+ )
12261
+ }
12262
+ ),
12263
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", position: "absolute", top: 20, left: 30 }, children: epicWebLogo }),
12264
+ instructor ? /* @__PURE__ */ jsxs(
12265
+ "div",
12266
+ {
12267
+ style: {
12268
+ display: "flex",
12269
+ gap: 8,
12270
+ justifyContent: "center",
12271
+ alignItems: "center",
12272
+ position: "absolute",
12273
+ top: 20,
12274
+ right: 30
12275
+ },
12276
+ children: [
12277
+ instructor.avatar ? /* @__PURE__ */ jsx(
12278
+ "img",
12279
+ {
12280
+ src: instructor.avatar.startsWith("/") ? `${domain}${instructor.avatar}` : instructor.avatar,
12281
+ style: { width: 56, height: 56, borderRadius: "50%" }
12282
+ }
12283
+ ) : null,
12284
+ instructor.name ? /* @__PURE__ */ jsx(
12285
+ "h2",
12286
+ {
12287
+ style: {
12288
+ margin: 0,
12289
+ opacity: 0.8,
12290
+ color: "white",
12291
+ fontSize: 30,
12292
+ fontWeight: 700
12293
+ },
12294
+ children: instructor.name
12295
+ }
12296
+ ) : null
12297
+ ]
12298
+ }
12299
+ ) : null,
12300
+ children,
12301
+ workshopTitle ? /* @__PURE__ */ jsx(
12302
+ "div",
12303
+ {
12304
+ style: {
12305
+ display: "flex",
12306
+ position: "absolute",
12307
+ bottom: 20,
12308
+ left: 30,
12309
+ color: "white",
12310
+ opacity: 0.8,
12311
+ fontSize: 20,
12312
+ fontWeight: 700
12313
+ },
12314
+ children: workshopTitle
12315
+ }
12316
+ ) : null,
12317
+ urlPathname ? /* @__PURE__ */ jsx(
12318
+ "div",
12319
+ {
12320
+ style: {
12321
+ display: "flex",
12322
+ position: "absolute",
12323
+ bottom: 20,
12324
+ right: 30,
12325
+ color: "white",
12326
+ opacity: 0.8,
12327
+ fontSize: 20,
12328
+ fontWeight: 700
12329
+ },
12330
+ children: protocolFreeDomain + urlPathname
12331
+ }
12332
+ ) : null
12333
+ ]
12334
+ }
12335
+ );
12336
+ }
12337
+ async function loader$2({ request }) {
12338
+ const url = new URL(request.url);
12339
+ const workshopTitle = await getWorkshopTitle();
12340
+ const title = url.searchParams.get("title") || workshopTitle;
12341
+ const subtitle = url.searchParams.get("subtitle") || await getWorkshopSubtitle();
12342
+ const urlPathname = url.searchParams.get("urlPathname") || url.pathname;
12343
+ const element = /* @__PURE__ */ jsx(
12344
+ OgLayout,
12345
+ {
12346
+ request,
12347
+ instructor: await getWorkshopInstructor(),
12348
+ urlPathname,
12349
+ workshopTitle: workshopTitle === title ? null : workshopTitle,
12350
+ children: /* @__PURE__ */ jsxs(
12351
+ "div",
12352
+ {
12353
+ style: {
12354
+ display: "flex",
12355
+ flexDirection: "column",
12356
+ justifyContent: "center",
12357
+ alignItems: "center",
12358
+ height: "100%",
12359
+ width: "100%",
12360
+ color: "white"
12361
+ },
12362
+ children: [
12363
+ /* @__PURE__ */ jsx(
12364
+ "h1",
12365
+ {
12366
+ style: {
12367
+ fontSize: "80px",
12368
+ fontWeight: 700,
12369
+ textWrap: "balance",
12370
+ textAlign: "center"
12371
+ },
12372
+ children: title
12373
+ }
12374
+ ),
12375
+ subtitle ? /* @__PURE__ */ jsx(
12376
+ "p",
12377
+ {
12378
+ style: {
12379
+ fontSize: "40px",
12380
+ fontWeight: 200,
12381
+ textWrap: "balance",
12382
+ textAlign: "center"
12383
+ },
12384
+ children: subtitle
12385
+ }
12386
+ ) : null
12387
+ ]
12388
+ }
12389
+ )
12390
+ }
12391
+ );
12392
+ try {
12393
+ return new ImageResponse(element, {
12394
+ width: 1200,
12395
+ height: 630
12396
+ });
12397
+ } catch (error) {
12398
+ return new Response(getErrorMessage(error), { status: 500 });
12399
+ }
12400
+ }
12401
+ const route28 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
12066
12402
  __proto__: null,
12067
12403
  loader: loader$2
12068
12404
  }, Symbol.toStringTag, { value: "Module" }));
@@ -12104,7 +12440,7 @@ function Onboarding() {
12104
12440
  /* @__PURE__ */ jsx(Form, { method: "post", className: "pb-4", children: /* @__PURE__ */ jsx(Button, { name: "intent", value: "complete", varient: "primary", children: "I've watched it. Let's go!" }) })
12105
12441
  ] });
12106
12442
  }
12107
- const route28 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
12443
+ const route29 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
12108
12444
  __proto__: null,
12109
12445
  action,
12110
12446
  default: Onboarding,
@@ -12129,11 +12465,11 @@ async function loader() {
12129
12465
  }
12130
12466
  return json({ processes, testProcesses: testProcesses2 });
12131
12467
  }
12132
- const route29 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
12468
+ const route30 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
12133
12469
  __proto__: null,
12134
12470
  loader
12135
12471
  }, Symbol.toStringTag, { value: "Module" }));
12136
- const serverManifest = { "entry": { "module": "/assets/entry.client-0j1eoieD.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/components-C5xBZAiL.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-CxuwYUpK.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/components-C5xBZAiL.js", "/assets/clsx-B-dksMZM.js", "/assets/misc-DBBsMyAP.js", "/assets/request-info-Dyls4H67.js", "/assets/tooltip-BdTNdCYE.js", "/assets/client-hints-BKxdo5Js.js", "/assets/error-boundary-BUV7xD2e.js", "/assets/progress-bar-TRgQ8YZ8.js", "/assets/index-r90CY6Wk.js", "/assets/index-Drecz7hr.js", "/assets/presence-BJPzwbUy.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/_-CGn-2XfF.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/misc-DBBsMyAP.js", "/assets/error-boundary-BUV7xD2e.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-Caqk73Ed.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/misc-DBBsMyAP.js", "/assets/request-info-Dyls4H67.js", "/assets/tooltip-BdTNdCYE.js", "/assets/client-hints-BKxdo5Js.js", "/assets/progress-HmjERaPh.js", "/assets/index-Drecz7hr.js", "/assets/user-73ocDYRe.js", "/assets/presence-BJPzwbUy.js"], "css": [] }, "routes/_app+/_exercises+/_layout": { "id": "routes/_app+/_exercises+/_layout", "parentId": "routes/_app+/_layout", "path": void 0, "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-BR-Qyofe.js", "imports": ["/assets/index-D6ygCrVn.js"], "css": [] }, "routes/_app+/_exercises+/$exerciseNumber": { "id": "routes/_app+/_exercises+/$exerciseNumber", "parentId": "routes/_app+/_exercises+/_layout", "path": ":exerciseNumber", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_exerciseNumber-D6YNCQoj.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/request-info-Dyls4H67.js", "/assets/client-hints-BKxdo5Js.js", "/assets/misc-DBBsMyAP.js", "/assets/tooltip-BdTNdCYE.js", "/assets/loading-C9f_vBoM.js", "/assets/index-Drecz7hr.js", "/assets/epic-video-BKzHxm70.js", "/assets/progress-bar-TRgQ8YZ8.js", "/assets/index-9nNr0Zqr.js", "/assets/mdx-BVZ4sNxQ.js", "/assets/progress-HmjERaPh.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/_exercises+/$exerciseNumber_.$stepNumber": { "id": "routes/_app+/_exercises+/$exerciseNumber_.$stepNumber", "parentId": "routes/_app+/_exercises+/_layout", "path": ":exerciseNumber/:stepNumber", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_exerciseNumber_._stepNumber-D00x64Vg.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/misc-DBBsMyAP.js"], "css": [] }, "routes/_app+/_exercises+/$exerciseNumber_.$stepNumber.$type+/_layout": { "id": "routes/_app+/_exercises+/$exerciseNumber_.$stepNumber.$type+/_layout", "parentId": "routes/_app+/_exercises+/$exerciseNumber_.$stepNumber", "path": ":type", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_layout-DXegGcTM.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/misc-DBBsMyAP.js", "/assets/request-info-Dyls4H67.js", "/assets/client-hints-BKxdo5Js.js", "/assets/tooltip-BdTNdCYE.js", "/assets/loading-C9f_vBoM.js", "/assets/index-Drecz7hr.js", "/assets/epic-video-BKzHxm70.js", "/assets/progress-bar-TRgQ8YZ8.js", "/assets/mdx-BVZ4sNxQ.js", "/assets/user-73ocDYRe.js", "/assets/index-9nNr0Zqr.js", "/assets/diff-ZJmYghvh.js", "/assets/discord-DZWTKMPn.js", "/assets/index-r90CY6Wk.js", "/assets/button-BfWwrI9B.js", "/assets/use-event-source-aW6X9lN1.js", "/assets/error-boundary-BUV7xD2e.js", "/assets/nav-chevrons-DnG58Hov.js", "/assets/progress-HmjERaPh.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/_exercises+/$exerciseNumber_.$stepNumber.index": { "id": "routes/_app+/_exercises+/$exerciseNumber_.$stepNumber.index", "parentId": "routes/_app+/_exercises+/$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+/_exercises+/$exerciseNumber_.finished": { "id": "routes/_app+/_exercises+/$exerciseNumber_.finished", "parentId": "routes/_app+/_exercises+/_layout", "path": ":exerciseNumber/finished", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_exerciseNumber_.finished-DR3gQ1pK.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/request-info-Dyls4H67.js", "/assets/client-hints-BKxdo5Js.js", "/assets/misc-DBBsMyAP.js", "/assets/tooltip-BdTNdCYE.js", "/assets/loading-C9f_vBoM.js", "/assets/index-Drecz7hr.js", "/assets/epic-video-BKzHxm70.js", "/assets/progress-bar-TRgQ8YZ8.js", "/assets/index-9nNr0Zqr.js", "/assets/nav-chevrons-DnG58Hov.js", "/assets/mdx-BVZ4sNxQ.js", "/assets/progress-HmjERaPh.js"], "css": ["/assets/epic-video-DUnRvy1A.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-Cp6A7SfU.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/request-info-Dyls4H67.js", "/assets/button-BfWwrI9B.js", "/assets/misc-DBBsMyAP.js", "/assets/user-73ocDYRe.js", "/assets/presence-BJPzwbUy.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+/discord": { "id": "routes/_app+/discord", "parentId": "routes/_app+/_layout", "path": "discord", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/discord-fsySDDKv.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/misc-DBBsMyAP.js", "/assets/user-73ocDYRe.js", "/assets/discord-DZWTKMPn.js"], "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-gQ-B3k8j.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/request-info-Dyls4H67.js", "/assets/client-hints-BKxdo5Js.js", "/assets/misc-DBBsMyAP.js", "/assets/tooltip-BdTNdCYE.js", "/assets/loading-C9f_vBoM.js", "/assets/index-Drecz7hr.js", "/assets/epic-video-BKzHxm70.js", "/assets/progress-bar-TRgQ8YZ8.js", "/assets/index-9nNr0Zqr.js", "/assets/mdx-BVZ4sNxQ.js", "/assets/progress-HmjERaPh.js", "/assets/nav-chevrons-DnG58Hov.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-CVJowtf6.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/request-info-Dyls4H67.js", "/assets/client-hints-BKxdo5Js.js", "/assets/misc-DBBsMyAP.js", "/assets/tooltip-BdTNdCYE.js", "/assets/loading-C9f_vBoM.js", "/assets/index-Drecz7hr.js", "/assets/epic-video-BKzHxm70.js", "/assets/progress-bar-TRgQ8YZ8.js", "/assets/index-9nNr0Zqr.js", "/assets/progress-HmjERaPh.js", "/assets/error-boundary-BUV7xD2e.js", "/assets/mdx-BVZ4sNxQ.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-BCM4kJTm.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/components-C5xBZAiL.js", "/assets/clsx-B-dksMZM.js", "/assets/request-info-Dyls4H67.js", "/assets/client-hints-BKxdo5Js.js", "/assets/use-event-source-aW6X9lN1.js", "/assets/button-BfWwrI9B.js", "/assets/loading-C9f_vBoM.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-DUAHYT3r.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/components-C5xBZAiL.js"], "css": [] }, "routes/admin+/_layout": { "id": "routes/admin+/_layout", "parentId": "root", "path": "admin", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-MFX35ekR.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/misc-DBBsMyAP.js", "/assets/tooltip-BdTNdCYE.js", "/assets/progress-HmjERaPh.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/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-Ddyuc0-s.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/misc-DBBsMyAP.js", "/assets/request-info-Dyls4H67.js", "/assets/client-hints-BKxdo5Js.js", "/assets/tooltip-BdTNdCYE.js", "/assets/loading-C9f_vBoM.js", "/assets/index-Drecz7hr.js", "/assets/epic-video-BKzHxm70.js", "/assets/progress-bar-TRgQ8YZ8.js", "/assets/mdx-BVZ4sNxQ.js", "/assets/diff-ZJmYghvh.js", "/assets/nav-chevrons-DnG58Hov.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/discord.callback": { "id": "routes/discord.callback", "parentId": "root", "path": "discord/callback", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/discord.callback-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/exercises": { "id": "routes/exercises", "parentId": "root", "path": "exercises", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/exercises-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/launch-editor": { "id": "routes/launch-editor", "parentId": "root", "path": "launch-editor", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/launch-editor-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/login-sse": { "id": "routes/login-sse", "parentId": "root", "path": "login-sse", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/login-sse-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/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-oSo74A5L.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/request-info-Dyls4H67.js", "/assets/client-hints-BKxdo5Js.js", "/assets/misc-DBBsMyAP.js", "/assets/tooltip-BdTNdCYE.js", "/assets/loading-C9f_vBoM.js", "/assets/index-Drecz7hr.js", "/assets/button-BfWwrI9B.js", "/assets/epic-video-BKzHxm70.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/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/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/update-mdx-cache": { "id": "routes/update-mdx-cache", "parentId": "root", "path": "update-mdx-cache", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/update-mdx-cache-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/video-player/index": { "id": "routes/video-player/index", "parentId": "root", "path": "video-player", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-K6Dvbx-E.js", "imports": [], "css": [] } }, "url": "/assets/manifest-0b01450d.js", "version": "0b01450d" };
12472
+ const serverManifest = { "entry": { "module": "/assets/entry.client-0j1eoieD.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/components-C5xBZAiL.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-BXq0yevS.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/components-C5xBZAiL.js", "/assets/clsx-B-dksMZM.js", "/assets/misc-DNgC2Frq.js", "/assets/request-info-Dyls4H67.js", "/assets/tooltip-Kw0lYWBI.js", "/assets/client-hints-BKxdo5Js.js", "/assets/error-boundary-Bcric_4t.js", "/assets/progress-bar-7LK87ZMh.js", "/assets/index-r90CY6Wk.js", "/assets/index-Bg9MMnnf.js", "/assets/presence-BJPzwbUy.js", "/assets/seo-CHrqghsC.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/_-COWH0sBh.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/misc-DNgC2Frq.js", "/assets/error-boundary-Bcric_4t.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-CNgYirUN.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/misc-DNgC2Frq.js", "/assets/request-info-Dyls4H67.js", "/assets/tooltip-Kw0lYWBI.js", "/assets/client-hints-BKxdo5Js.js", "/assets/user-73ocDYRe.js", "/assets/presence-BJPzwbUy.js", "/assets/progress-CF9Xwfxf.js", "/assets/index-Bg9MMnnf.js"], "css": [] }, "routes/_app+/_exercises+/_layout": { "id": "routes/_app+/_exercises+/_layout", "parentId": "routes/_app+/_layout", "path": void 0, "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-BR-Qyofe.js", "imports": ["/assets/index-D6ygCrVn.js"], "css": [] }, "routes/_app+/_exercises+/$exerciseNumber": { "id": "routes/_app+/_exercises+/$exerciseNumber", "parentId": "routes/_app+/_exercises+/_layout", "path": ":exerciseNumber", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_exerciseNumber-rfzZiDNa.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/components-C5xBZAiL.js", "/assets/clsx-B-dksMZM.js", "/assets/misc-DNgC2Frq.js", "/assets/request-info-Dyls4H67.js", "/assets/tooltip-Kw0lYWBI.js", "/assets/client-hints-BKxdo5Js.js", "/assets/index-Bg9MMnnf.js", "/assets/loading-C9f_vBoM.js", "/assets/epic-video-BwtXsHGU.js", "/assets/progress-bar-7LK87ZMh.js", "/assets/index-9nNr0Zqr.js", "/assets/mdx-BYvGbvEr.js", "/assets/progress-CF9Xwfxf.js", "/assets/seo-CHrqghsC.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/_exercises+/$exerciseNumber_.$stepNumber": { "id": "routes/_app+/_exercises+/$exerciseNumber_.$stepNumber", "parentId": "routes/_app+/_exercises+/_layout", "path": ":exerciseNumber/:stepNumber", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_exerciseNumber_._stepNumber-C37pli7_.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/misc-DNgC2Frq.js"], "css": [] }, "routes/_app+/_exercises+/$exerciseNumber_.$stepNumber.$type+/_layout": { "id": "routes/_app+/_exercises+/$exerciseNumber_.$stepNumber.$type+/_layout", "parentId": "routes/_app+/_exercises+/$exerciseNumber_.$stepNumber", "path": ":type", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": true, "module": "/assets/_layout-BG1Jwh7V.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/misc-DNgC2Frq.js", "/assets/request-info-Dyls4H67.js", "/assets/tooltip-Kw0lYWBI.js", "/assets/client-hints-BKxdo5Js.js", "/assets/index-Bg9MMnnf.js", "/assets/loading-C9f_vBoM.js", "/assets/epic-video-BwtXsHGU.js", "/assets/progress-bar-7LK87ZMh.js", "/assets/mdx-BYvGbvEr.js", "/assets/user-73ocDYRe.js", "/assets/index-9nNr0Zqr.js", "/assets/diff-BKsbFB6w.js", "/assets/error-boundary-Bcric_4t.js", "/assets/nav-chevrons-DOYtx9XE.js", "/assets/progress-CF9Xwfxf.js", "/assets/seo-CHrqghsC.js", "/assets/discord-0kv66Q6F.js", "/assets/index-r90CY6Wk.js", "/assets/button-BfWwrI9B.js", "/assets/use-event-source-aW6X9lN1.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/_app+/_exercises+/$exerciseNumber_.$stepNumber.index": { "id": "routes/_app+/_exercises+/$exerciseNumber_.$stepNumber.index", "parentId": "routes/_app+/_exercises+/$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+/_exercises+/$exerciseNumber_.finished": { "id": "routes/_app+/_exercises+/$exerciseNumber_.finished", "parentId": "routes/_app+/_exercises+/_layout", "path": ":exerciseNumber/finished", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_exerciseNumber_.finished-B7SgnqdS.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/components-C5xBZAiL.js", "/assets/clsx-B-dksMZM.js", "/assets/misc-DNgC2Frq.js", "/assets/request-info-Dyls4H67.js", "/assets/tooltip-Kw0lYWBI.js", "/assets/client-hints-BKxdo5Js.js", "/assets/index-Bg9MMnnf.js", "/assets/loading-C9f_vBoM.js", "/assets/epic-video-BwtXsHGU.js", "/assets/progress-bar-7LK87ZMh.js", "/assets/index-9nNr0Zqr.js", "/assets/nav-chevrons-DOYtx9XE.js", "/assets/mdx-BYvGbvEr.js", "/assets/progress-CF9Xwfxf.js", "/assets/seo-CHrqghsC.js"], "css": ["/assets/epic-video-DUnRvy1A.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-DesvwOeg.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/request-info-Dyls4H67.js", "/assets/button-BfWwrI9B.js", "/assets/misc-DNgC2Frq.js", "/assets/user-73ocDYRe.js", "/assets/presence-BJPzwbUy.js"], "css": [] }, "routes/_app+/app.$appName+/$": { "id": "routes/_app+/app.$appName+/$", "parentId": "routes/_app+/_layout", "path": "app/:appName/*", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/api.$": { "id": "routes/_app+/app.$appName+/api.$", "parentId": "routes/_app+/_layout", "path": "app/:appName/api/*", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/api._-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/epic_ws[.js]": { "id": "routes/_app+/app.$appName+/epic_ws[.js]", "parentId": "routes/_app+/_layout", "path": "app/:appName/epic_ws.js", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/epic_ws_.js_-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/index": { "id": "routes/_app+/app.$appName+/index", "parentId": "routes/_app+/_layout", "path": "app/:appName/", "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-K6Dvbx-E.js", "imports": [], "css": [] }, "routes/_app+/app.$appName+/test.$testName": { "id": "routes/_app+/app.$appName+/test.$testName", "parentId": "routes/_app+/_layout", "path": "app/:appName/test/:testName", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test._testName-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/_app+/discord": { "id": "routes/_app+/discord", "parentId": "routes/_app+/_layout", "path": "discord", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/discord-Xp0X4-Fl.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/misc-DNgC2Frq.js", "/assets/user-73ocDYRe.js", "/assets/discord-0kv66Q6F.js"], "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-BI2-0Ykt.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/components-C5xBZAiL.js", "/assets/clsx-B-dksMZM.js", "/assets/misc-DNgC2Frq.js", "/assets/request-info-Dyls4H67.js", "/assets/tooltip-Kw0lYWBI.js", "/assets/client-hints-BKxdo5Js.js", "/assets/index-Bg9MMnnf.js", "/assets/loading-C9f_vBoM.js", "/assets/epic-video-BwtXsHGU.js", "/assets/progress-bar-7LK87ZMh.js", "/assets/index-9nNr0Zqr.js", "/assets/nav-chevrons-DOYtx9XE.js", "/assets/mdx-BYvGbvEr.js", "/assets/seo-CHrqghsC.js", "/assets/progress-CF9Xwfxf.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-BQRtqn3g.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/components-C5xBZAiL.js", "/assets/clsx-B-dksMZM.js", "/assets/misc-DNgC2Frq.js", "/assets/request-info-Dyls4H67.js", "/assets/tooltip-Kw0lYWBI.js", "/assets/client-hints-BKxdo5Js.js", "/assets/index-Bg9MMnnf.js", "/assets/loading-C9f_vBoM.js", "/assets/epic-video-BwtXsHGU.js", "/assets/progress-bar-7LK87ZMh.js", "/assets/index-9nNr0Zqr.js", "/assets/error-boundary-Bcric_4t.js", "/assets/mdx-BYvGbvEr.js", "/assets/progress-CF9Xwfxf.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-D8zyjBAb.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/request-info-Dyls4H67.js", "/assets/client-hints-BKxdo5Js.js", "/assets/use-event-source-aW6X9lN1.js", "/assets/button-BfWwrI9B.js", "/assets/loading-C9f_vBoM.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-DUAHYT3r.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/components-C5xBZAiL.js"], "css": [] }, "routes/admin+/_layout": { "id": "routes/admin+/_layout", "parentId": "root", "path": "admin", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/_layout-D0zbQZjf.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/misc-DNgC2Frq.js", "/assets/tooltip-Kw0lYWBI.js", "/assets/progress-CF9Xwfxf.js"], "css": [] }, "routes/admin+/apps": { "id": "routes/admin+/apps", "parentId": "routes/admin+/_layout", "path": "apps", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/apps-DP2rzg_V.js", "imports": [], "css": [] }, "routes/apps": { "id": "routes/apps", "parentId": "root", "path": "apps", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/apps-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/diff": { "id": "routes/diff", "parentId": "root", "path": "diff", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/diff-KDzcgGYL.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/misc-DNgC2Frq.js", "/assets/request-info-Dyls4H67.js", "/assets/tooltip-Kw0lYWBI.js", "/assets/client-hints-BKxdo5Js.js", "/assets/index-Bg9MMnnf.js", "/assets/loading-C9f_vBoM.js", "/assets/epic-video-BwtXsHGU.js", "/assets/progress-bar-7LK87ZMh.js", "/assets/mdx-BYvGbvEr.js", "/assets/diff-BKsbFB6w.js", "/assets/nav-chevrons-DOYtx9XE.js"], "css": ["/assets/epic-video-DUnRvy1A.css"] }, "routes/discord.callback": { "id": "routes/discord.callback", "parentId": "root", "path": "discord/callback", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/discord.callback-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/exercises": { "id": "routes/exercises", "parentId": "root", "path": "exercises", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/exercises-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/launch-editor": { "id": "routes/launch-editor", "parentId": "root", "path": "launch-editor", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/launch-editor-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/login-sse": { "id": "routes/login-sse", "parentId": "root", "path": "login-sse", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/login-sse-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/og": { "id": "routes/og", "parentId": "root", "path": "og", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/og-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/onboarding": { "id": "routes/onboarding", "parentId": "root", "path": "onboarding", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/onboarding-euWyXpCL.js", "imports": ["/assets/index-D6ygCrVn.js", "/assets/clsx-B-dksMZM.js", "/assets/components-C5xBZAiL.js", "/assets/misc-DNgC2Frq.js", "/assets/request-info-Dyls4H67.js", "/assets/tooltip-Kw0lYWBI.js", "/assets/client-hints-BKxdo5Js.js", "/assets/index-Bg9MMnnf.js", "/assets/loading-C9f_vBoM.js", "/assets/button-BfWwrI9B.js", "/assets/epic-video-BwtXsHGU.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/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/start": { "id": "routes/start", "parentId": "root", "path": "start", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/start-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/test": { "id": "routes/test", "parentId": "root", "path": "test", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/test-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/theme/index": { "id": "routes/theme/index", "parentId": "root", "path": "theme", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/update-mdx-cache": { "id": "routes/update-mdx-cache", "parentId": "root", "path": "update-mdx-cache", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/update-mdx-cache-l0sNRNKZ.js", "imports": [], "css": [] }, "routes/video-player/index": { "id": "routes/video-player/index", "parentId": "root", "path": "video-player", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasErrorBoundary": false, "module": "/assets/index-DP2rzg_V.js", "imports": [], "css": [] } }, "url": "/assets/manifest-c65c0481.js", "version": "c65c0481" };
12137
12473
  const mode = "production";
12138
12474
  const assetsBuildDirectory = "build/client";
12139
12475
  const basename = "/";
@@ -12366,13 +12702,21 @@ const routes = {
12366
12702
  caseSensitive: void 0,
12367
12703
  module: route27
12368
12704
  },
12705
+ "routes/og": {
12706
+ id: "routes/og",
12707
+ parentId: "root",
12708
+ path: "og",
12709
+ index: void 0,
12710
+ caseSensitive: void 0,
12711
+ module: route28
12712
+ },
12369
12713
  "routes/onboarding": {
12370
12714
  id: "routes/onboarding",
12371
12715
  parentId: "root",
12372
12716
  path: "onboarding",
12373
12717
  index: void 0,
12374
12718
  caseSensitive: void 0,
12375
- module: route28
12719
+ module: route29
12376
12720
  },
12377
12721
  "routes/processes": {
12378
12722
  id: "routes/processes",
@@ -12380,7 +12724,7 @@ const routes = {
12380
12724
  path: "processes",
12381
12725
  index: void 0,
12382
12726
  caseSensitive: void 0,
12383
- module: route29
12727
+ module: route30
12384
12728
  },
12385
12729
  "routes/progress": {
12386
12730
  id: "routes/progress",
@@ -12388,7 +12732,7 @@ const routes = {
12388
12732
  path: "progress",
12389
12733
  index: void 0,
12390
12734
  caseSensitive: void 0,
12391
- module: route30
12735
+ module: route31
12392
12736
  },
12393
12737
  "routes/set-playground": {
12394
12738
  id: "routes/set-playground",
@@ -12396,7 +12740,7 @@ const routes = {
12396
12740
  path: "set-playground",
12397
12741
  index: void 0,
12398
12742
  caseSensitive: void 0,
12399
- module: route31
12743
+ module: route32
12400
12744
  },
12401
12745
  "routes/start": {
12402
12746
  id: "routes/start",
@@ -12404,7 +12748,7 @@ const routes = {
12404
12748
  path: "start",
12405
12749
  index: void 0,
12406
12750
  caseSensitive: void 0,
12407
- module: route32
12751
+ module: route33
12408
12752
  },
12409
12753
  "routes/test": {
12410
12754
  id: "routes/test",
@@ -12412,7 +12756,7 @@ const routes = {
12412
12756
  path: "test",
12413
12757
  index: void 0,
12414
12758
  caseSensitive: void 0,
12415
- module: route33
12759
+ module: route34
12416
12760
  },
12417
12761
  "routes/theme/index": {
12418
12762
  id: "routes/theme/index",
@@ -12420,7 +12764,7 @@ const routes = {
12420
12764
  path: "theme",
12421
12765
  index: void 0,
12422
12766
  caseSensitive: void 0,
12423
- module: route34
12767
+ module: route35
12424
12768
  },
12425
12769
  "routes/update-mdx-cache": {
12426
12770
  id: "routes/update-mdx-cache",
@@ -12428,7 +12772,7 @@ const routes = {
12428
12772
  path: "update-mdx-cache",
12429
12773
  index: void 0,
12430
12774
  caseSensitive: void 0,
12431
- module: route35
12775
+ module: route36
12432
12776
  },
12433
12777
  "routes/video-player/index": {
12434
12778
  id: "routes/video-player/index",
@@ -12436,7 +12780,7 @@ const routes = {
12436
12780
  path: "video-player",
12437
12781
  index: void 0,
12438
12782
  caseSensitive: void 0,
12439
- module: route36
12783
+ module: route37
12440
12784
  }
12441
12785
  };
12442
12786
  export {