@learnpack/learnpack 5.0.178 → 5.0.180

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 (32) hide show
  1. package/README.md +13 -13
  2. package/lib/commands/serve.js +32 -18
  3. package/lib/creatorDist/assets/{index-CrWESWmj.css → index-Bnq3eZ3T.css} +13 -3
  4. package/lib/creatorDist/assets/index-hhajeHFt.js +35366 -0
  5. package/lib/creatorDist/index.html +2 -2
  6. package/lib/utils/creatorSocket.d.ts +1 -0
  7. package/lib/utils/creatorSocket.js +24 -0
  8. package/oclif.manifest.json +1 -1
  9. package/package.json +1 -1
  10. package/src/commands/serve.ts +48 -26
  11. package/src/creator/package-lock.json +137 -0
  12. package/src/creator/package.json +1 -0
  13. package/src/creator/src/App.tsx +77 -50
  14. package/src/creator/src/components/ConsumablesManager.tsx +1 -3
  15. package/src/creator/src/components/FileUploader.tsx +136 -44
  16. package/src/creator/src/components/PurposeSelector.tsx +70 -0
  17. package/src/creator/src/components/SelectableCard.tsx +5 -3
  18. package/src/creator/src/components/Uploader.tsx +12 -1
  19. package/src/creator/src/components/syllabus/SyllabusEditor.tsx +6 -12
  20. package/src/creator/src/utils/constants.ts +10 -4
  21. package/src/creator/src/utils/lib.ts +0 -2
  22. package/src/creator/src/utils/rigo.ts +9 -5
  23. package/src/creator/src/utils/socket.ts +61 -0
  24. package/src/creator/src/utils/store.ts +7 -1
  25. package/src/creatorDist/assets/{index-CrWESWmj.css → index-Bnq3eZ3T.css} +13 -3
  26. package/src/creatorDist/assets/index-hhajeHFt.js +35366 -0
  27. package/src/creatorDist/index.html +2 -2
  28. package/src/ui/_app/app.js +19 -8
  29. package/src/ui/app.tar.gz +0 -0
  30. package/src/utils/creatorSocket.ts +30 -0
  31. package/lib/creatorDist/assets/index-BvrB0WCf.js +0 -32991
  32. package/src/creatorDist/assets/index-BvrB0WCf.js +0 -32991
@@ -10,8 +10,8 @@
10
10
  />
11
11
 
12
12
  <title>Learnpack Creator: Craft tutorials in seconds!</title>
13
- <script type="module" crossorigin src="/creator/assets/index-BvrB0WCf.js"></script>
14
- <link rel="stylesheet" crossorigin href="/creator/assets/index-CrWESWmj.css">
13
+ <script type="module" crossorigin src="/creator/assets/index-hhajeHFt.js"></script>
14
+ <link rel="stylesheet" crossorigin href="/creator/assets/index-Bnq3eZ3T.css">
15
15
  </head>
16
16
  <body>
17
17
  <div id="root"></div>
@@ -1,4 +1,5 @@
1
1
  import { Server as SocketIOServer } from "socket.io";
2
2
  export declare function initSocketIO(server: any): SocketIOServer<import("socket.io/dist/typed-events").DefaultEventsMap, import("socket.io/dist/typed-events").DefaultEventsMap, import("socket.io/dist/typed-events").DefaultEventsMap, any>;
3
3
  export declare function emitToCourse(courseSlug: string, event: string, payload: any): void;
4
+ export declare function emitToNotification(notificationId: string, payload: any): void;
4
5
  export declare function getSocketIO(): SocketIOServer<import("socket.io/dist/typed-events").DefaultEventsMap, import("socket.io/dist/typed-events").DefaultEventsMap, import("socket.io/dist/typed-events").DefaultEventsMap, any>;
@@ -2,9 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.initSocketIO = initSocketIO;
4
4
  exports.emitToCourse = emitToCourse;
5
+ exports.emitToNotification = emitToNotification;
5
6
  exports.getSocketIO = getSocketIO;
6
7
  const socket_io_1 = require("socket.io");
7
8
  const courseSocketMap = new Map(); // slug -> Set<socket.id>
9
+ const notificationSocketMap = new Map(); // notificationId -> Set<socket.id>
8
10
  const socketStore = new Map(); // socket.id -> socket
9
11
  let io = null;
10
12
  function initSocketIO(server) {
@@ -29,6 +31,17 @@ function initSocketIO(server) {
29
31
  (_a = courseSocketMap.get(courseSlug)) === null || _a === void 0 ? void 0 : _a.add(socket.id);
30
32
  console.log(`📦 Socket ${socket.id} registered to course: ${courseSlug}`);
31
33
  });
34
+ socket.on("registerNotification", (data) => {
35
+ var _a;
36
+ const { notificationId } = data;
37
+ if (!notificationId)
38
+ return;
39
+ if (!notificationSocketMap.has(notificationId)) {
40
+ notificationSocketMap.set(notificationId, new Set());
41
+ }
42
+ (_a = notificationSocketMap.get(notificationId)) === null || _a === void 0 ? void 0 : _a.add(socket.id);
43
+ console.log(`📧 Socket ${socket.id} registered to notification: ${notificationId}`);
44
+ });
32
45
  socket.on("disconnect", () => {
33
46
  console.log("🔥 Socket disconnected:", socket.id);
34
47
  socketStore.delete(socket.id);
@@ -49,6 +62,17 @@ function emitToCourse(courseSlug, event, payload) {
49
62
  socket.emit(event, payload);
50
63
  }
51
64
  }
65
+ function emitToNotification(notificationId, payload) {
66
+ console.log("Emitting to notification", notificationId, payload);
67
+ const socketIds = notificationSocketMap.get(notificationId);
68
+ if (!socketIds || socketIds.size === 0)
69
+ return;
70
+ for (const id of socketIds) {
71
+ const socket = socketStore.get(id);
72
+ if (socket)
73
+ socket.emit(notificationId, payload);
74
+ }
75
+ }
52
76
  function getSocketIO() {
53
77
  if (!io)
54
78
  throw new Error("Socket.IO not initialized");
@@ -1 +1 @@
1
- {"version":"5.0.178","commands":{"audit":{"id":"audit","description":"learnpack audit is the command in charge of creating an auditory of the repository\n...\nlearnpack audit checks for the following information in a repository:\n 1. The configuration object has slug, repository and description. (Error)\n 2. The command learnpack clean has been run. (Error)\n 3. If a markdown or test file doesn't have any content. (Error)\n 4. The links are accessing to valid servers. (Error)\n 5. The relative images are working (If they have the shortest path to the image or if the images exists in the assets). (Error)\n 6. The external images are working (If they are pointing to a valid server). (Error)\n 7. The exercises directory names are valid. (Error)\n 8. If an exercise doesn't have a README file. (Error)\n 9. The exercises array (Of the config file) has content. (Error)\n 10. The exercses have the same translations. (Warning)\n 11. The .gitignore file exists. (Warning)\n 12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"strict":{"name":"strict","type":"boolean","char":"s","description":"strict mode","allowNo":false}},"args":[]},"breakToken":{"id":"breakToken","description":"Break the token","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"grading":{"name":"grading","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"clean":{"id":"clean","description":"Clean the configuration object\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[]},"download":{"id":"download","description":"Describe the command here\n...\nExtra documentation goes here\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"init":{"id":"init","description":"Create a new learning package: Book, Tutorial or Exercise","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"grading":{"name":"grading","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"login":{"id":"login","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"logout":{"id":"logout","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"publish":{"id":"publish","description":"Builds the project by copying necessary files and directories into a zip file","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"strict":{"name":"strict","type":"boolean","char":"s","description":"strict mode","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"serve":{"id":"serve","description":"Runs a small server to build tutorials","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"port":{"name":"port","type":"option","char":"p","description":"server port"},"host":{"name":"host","type":"option","char":"h","description":"server host"},"debug":{"name":"debug","type":"boolean","char":"d","description":"debugger mode for more verbage","allowNo":false}},"args":[]},"start":{"id":"start","description":"Runs a small server with all the exercise instructions","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"port":{"name":"port","type":"option","char":"p","description":"server port"},"host":{"name":"host","type":"option","char":"h","description":"server host"},"disableGrading":{"name":"disableGrading","type":"boolean","char":"D","description":"disble grading functionality","allowNo":false},"watch":{"name":"watch","type":"boolean","char":"w","description":"Watch for file changes","allowNo":false},"editor":{"name":"editor","type":"option","char":"e","description":"[preview, extension]","options":["extension","preview"]},"version":{"name":"version","type":"option","char":"v","description":"E.g: 1.0.1"},"grading":{"name":"grading","type":"option","char":"g","description":"[isolated, incremental]","options":["isolated","incremental"]},"debug":{"name":"debug","type":"boolean","char":"d","description":"debugger mode for more verbage","allowNo":false}},"args":[]},"test":{"id":"test","description":"Test exercises","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false}},"args":[{"name":"exerciseSlug","description":"The name of the exercise to test","required":false,"hidden":false}]},"translate":{"id":"translate","description":"List all the lessons, the user is able of select many of them to translate to the given languages","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false}},"args":[]}}}
1
+ {"version":"5.0.180","commands":{"audit":{"id":"audit","description":"learnpack audit is the command in charge of creating an auditory of the repository\n...\nlearnpack audit checks for the following information in a repository:\n 1. The configuration object has slug, repository and description. (Error)\n 2. The command learnpack clean has been run. (Error)\n 3. If a markdown or test file doesn't have any content. (Error)\n 4. The links are accessing to valid servers. (Error)\n 5. The relative images are working (If they have the shortest path to the image or if the images exists in the assets). (Error)\n 6. The external images are working (If they are pointing to a valid server). (Error)\n 7. The exercises directory names are valid. (Error)\n 8. If an exercise doesn't have a README file. (Error)\n 9. The exercises array (Of the config file) has content. (Error)\n 10. The exercses have the same translations. (Warning)\n 11. The .gitignore file exists. (Warning)\n 12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"strict":{"name":"strict","type":"boolean","char":"s","description":"strict mode","allowNo":false}},"args":[]},"breakToken":{"id":"breakToken","description":"Break the token","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"grading":{"name":"grading","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"clean":{"id":"clean","description":"Clean the configuration object\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[]},"download":{"id":"download","description":"Describe the command here\n...\nExtra documentation goes here\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"init":{"id":"init","description":"Create a new learning package: Book, Tutorial or Exercise","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"grading":{"name":"grading","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"login":{"id":"login","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"logout":{"id":"logout","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"publish":{"id":"publish","description":"Builds the project by copying necessary files and directories into a zip file","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"strict":{"name":"strict","type":"boolean","char":"s","description":"strict mode","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"serve":{"id":"serve","description":"Runs a small server to build tutorials","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"port":{"name":"port","type":"option","char":"p","description":"server port"},"host":{"name":"host","type":"option","char":"h","description":"server host"},"debug":{"name":"debug","type":"boolean","char":"d","description":"debugger mode for more verbage","allowNo":false}},"args":[]},"start":{"id":"start","description":"Runs a small server with all the exercise instructions","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"port":{"name":"port","type":"option","char":"p","description":"server port"},"host":{"name":"host","type":"option","char":"h","description":"server host"},"disableGrading":{"name":"disableGrading","type":"boolean","char":"D","description":"disble grading functionality","allowNo":false},"watch":{"name":"watch","type":"boolean","char":"w","description":"Watch for file changes","allowNo":false},"editor":{"name":"editor","type":"option","char":"e","description":"[preview, extension]","options":["extension","preview"]},"version":{"name":"version","type":"option","char":"v","description":"E.g: 1.0.1"},"grading":{"name":"grading","type":"option","char":"g","description":"[isolated, incremental]","options":["isolated","incremental"]},"debug":{"name":"debug","type":"boolean","char":"d","description":"debugger mode for more verbage","allowNo":false}},"args":[]},"test":{"id":"test","description":"Test exercises","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false}},"args":[{"name":"exerciseSlug","description":"The name of the exercise to test","required":false,"hidden":false}]},"translate":{"id":"translate","description":"List all the lessons, the user is able of select many of them to translate to the given languages","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false}},"args":[]}}}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@learnpack/learnpack",
3
3
  "description": "Seamlessly build, sell and/or take interactive & auto-graded tutorials, start learning now or build a new tutorial to your audience.",
4
- "version": "5.0.178",
4
+ "version": "5.0.180",
5
5
  "author": "Alejandro Sanchez @alesanchezr",
6
6
  "contributors": [
7
7
  {
@@ -7,7 +7,11 @@ import * as cors from "cors"
7
7
  import * as path from "path"
8
8
  import * as http from "http"
9
9
 
10
- import { initSocketIO, emitToCourse } from "../utils/creatorSocket"
10
+ import {
11
+ initSocketIO,
12
+ emitToCourse,
13
+ emitToNotification,
14
+ } from "../utils/creatorSocket"
11
15
 
12
16
  import * as os from "os"
13
17
  import * as archiver from "archiver"
@@ -331,6 +335,14 @@ export default class ServeCommand extends SessionCommand {
331
335
  process.exit(1)
332
336
  }
333
337
 
338
+ let deploymentURL = process.env.DEPLOYMENT_URL
339
+ if (!deploymentURL) {
340
+ console.log("DEPLOYMENT_URL is not set, using default value")
341
+ deploymentURL = "https://app.learnpack.co"
342
+ }
343
+
344
+ console.log("DEPLOYMENT_URL", deploymentURL)
345
+
334
346
  const credentials = JSON.parse(crendsEnv)
335
347
  const bucketStorage = new Storage({
336
348
  credentials,
@@ -537,10 +549,10 @@ export default class ServeCommand extends SessionCommand {
537
549
 
538
550
  app.post("/read-document", upload.single("file"), async (req, res) => {
539
551
  console.log("READING A DOCUMENT")
540
- // const rigoToken = req.header("x-rigo-token")
541
- // if (!rigoToken) {
542
- // return res.status(400).json({ error: "Rigo token is required" })
543
- // }
552
+ const publicToken = req.header("x-public-token")
553
+ if (!publicToken) {
554
+ return res.status(400).json({ error: "Public token is required" })
555
+ }
544
556
 
545
557
  try {
546
558
  // eslint-disable-next-line
@@ -549,10 +561,14 @@ export default class ServeCommand extends SessionCommand {
549
561
  return res.status(400).json({ error: "Missing file" })
550
562
  }
551
563
 
552
- const resultId = `${Date.now()}-${Math.floor(Math.random() * 1e6)}`
564
+ console.log("PUBLIC TOKEN", publicToken)
553
565
 
554
- const webhookUrl = `https://9cw5zmww-3000.use2.devtunnels.ms/document/results/result_id/${resultId}/`
566
+ const resultId = `document-read-${Date.now()}-${Math.floor(
567
+ Math.random() * 1e6
568
+ )}`
555
569
 
570
+ const webhookUrl = `${deploymentURL}/notifications/${resultId}`
571
+ console.log("WEBHOOK URL", webhookUrl)
556
572
  // Construir form-data para enviar al servidor proxy
557
573
  const formData = new FormData()
558
574
  // eslint-disable-next-line
@@ -567,28 +583,37 @@ export default class ServeCommand extends SessionCommand {
567
583
  })
568
584
  formData.append("webhook_callback_url", webhookUrl)
569
585
 
570
- // Hacer POST al servidor externo
571
- const response = await axios.post(
572
- `${RIGOBOT_HOST}/v1/learnpack/documents/pdf/read`,
573
- formData,
574
- {
575
- headers: {
576
- ...formData.getHeaders(),
577
- Authorization: `Token `,
578
- },
579
- maxBodyLength: Infinity,
580
- }
581
- )
582
- console.log("RESPONSE FROM RIGOBOT", response)
586
+ try {
587
+ const response = await axios.post(
588
+ `${RIGOBOT_HOST}/v1/learnpack/public/tools/read-document`,
589
+ formData,
590
+ {
591
+ headers: {
592
+ ...formData.getHeaders(),
593
+ Authorization: `Token ${publicToken.trim()}`,
594
+ },
595
+ }
596
+ )
597
+ } catch (error) {
598
+ console.error(" Error in /read-document:", error)
599
+ return res.status(500).json({ error: (error as Error).message })
600
+ }
583
601
 
584
- // Responder con el UUID generado
585
- return res.json({ resultId })
602
+ return res.json({ notificationId: resultId, status: "PROCESSING" })
586
603
  } catch (error) {
587
604
  console.error("❌ Error in /read-document:", error)
588
605
  return res.status(500).json({ error: (error as Error).message })
589
606
  }
590
607
  })
591
608
 
609
+ app.post("/notifications/:id", async (req, res) => {
610
+ console.log("Receiving a webhook to notification id", req.params.id)
611
+ const { id } = req.params
612
+ const body = req.body
613
+ emitToNotification(id, body)
614
+ res.json({ id, status: "SUCCESS" })
615
+ })
616
+
592
617
  app.get("/check-preview-image/:slug", async (req, res) => {
593
618
  const { slug } = req.params
594
619
  const file = bucket.file(`courses/${slug}/preview.png`)
@@ -989,10 +1014,7 @@ export default class ServeCommand extends SessionCommand {
989
1014
  bucket,
990
1015
  rigoToken,
991
1016
  syllabus.lessons,
992
- `{
993
- "courseInfo": ${JSON.stringify(syllabus.courseInfo)},
994
- "sources": ${JSON.stringify(syllabus.sources)}
995
- }`,
1017
+ JSON.stringify(syllabus.courseInfo),
996
1018
  lesson,
997
1019
  tutorialDir + "/exercises",
998
1020
  slugify(syllabus.courseInfo.title)
@@ -23,6 +23,7 @@
23
23
  "react-hot-toast": "^2.5.2",
24
24
  "react-markdown": "^10.1.0",
25
25
  "react-router": "^7.5.0",
26
+ "socket.io-client": "^4.8.1",
26
27
  "syllable": "^5.0.1",
27
28
  "youtube-transcript": "^1.2.1",
28
29
  "zustand": "^5.0.3"
@@ -1211,6 +1212,12 @@
1211
1212
  "win32"
1212
1213
  ]
1213
1214
  },
1215
+ "node_modules/@socket.io/component-emitter": {
1216
+ "version": "3.1.2",
1217
+ "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
1218
+ "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
1219
+ "license": "MIT"
1220
+ },
1214
1221
  "node_modules/@swc/core": {
1215
1222
  "version": "1.11.18",
1216
1223
  "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.11.18.tgz",
@@ -2673,6 +2680,45 @@
2673
2680
  "once": "^1.4.0"
2674
2681
  }
2675
2682
  },
2683
+ "node_modules/engine.io-client": {
2684
+ "version": "6.6.3",
2685
+ "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz",
2686
+ "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==",
2687
+ "license": "MIT",
2688
+ "dependencies": {
2689
+ "@socket.io/component-emitter": "~3.1.0",
2690
+ "debug": "~4.3.1",
2691
+ "engine.io-parser": "~5.2.1",
2692
+ "ws": "~8.17.1",
2693
+ "xmlhttprequest-ssl": "~2.1.1"
2694
+ }
2695
+ },
2696
+ "node_modules/engine.io-client/node_modules/debug": {
2697
+ "version": "4.3.7",
2698
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
2699
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
2700
+ "license": "MIT",
2701
+ "dependencies": {
2702
+ "ms": "^2.1.3"
2703
+ },
2704
+ "engines": {
2705
+ "node": ">=6.0"
2706
+ },
2707
+ "peerDependenciesMeta": {
2708
+ "supports-color": {
2709
+ "optional": true
2710
+ }
2711
+ }
2712
+ },
2713
+ "node_modules/engine.io-parser": {
2714
+ "version": "5.2.3",
2715
+ "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
2716
+ "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
2717
+ "license": "MIT",
2718
+ "engines": {
2719
+ "node": ">=10.0.0"
2720
+ }
2721
+ },
2676
2722
  "node_modules/enhanced-resolve": {
2677
2723
  "version": "5.18.1",
2678
2724
  "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz",
@@ -5611,6 +5657,68 @@
5611
5657
  "node": ">=8"
5612
5658
  }
5613
5659
  },
5660
+ "node_modules/socket.io-client": {
5661
+ "version": "4.8.1",
5662
+ "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz",
5663
+ "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==",
5664
+ "license": "MIT",
5665
+ "dependencies": {
5666
+ "@socket.io/component-emitter": "~3.1.0",
5667
+ "debug": "~4.3.2",
5668
+ "engine.io-client": "~6.6.1",
5669
+ "socket.io-parser": "~4.2.4"
5670
+ },
5671
+ "engines": {
5672
+ "node": ">=10.0.0"
5673
+ }
5674
+ },
5675
+ "node_modules/socket.io-client/node_modules/debug": {
5676
+ "version": "4.3.7",
5677
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
5678
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
5679
+ "license": "MIT",
5680
+ "dependencies": {
5681
+ "ms": "^2.1.3"
5682
+ },
5683
+ "engines": {
5684
+ "node": ">=6.0"
5685
+ },
5686
+ "peerDependenciesMeta": {
5687
+ "supports-color": {
5688
+ "optional": true
5689
+ }
5690
+ }
5691
+ },
5692
+ "node_modules/socket.io-parser": {
5693
+ "version": "4.2.4",
5694
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
5695
+ "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
5696
+ "license": "MIT",
5697
+ "dependencies": {
5698
+ "@socket.io/component-emitter": "~3.1.0",
5699
+ "debug": "~4.3.1"
5700
+ },
5701
+ "engines": {
5702
+ "node": ">=10.0.0"
5703
+ }
5704
+ },
5705
+ "node_modules/socket.io-parser/node_modules/debug": {
5706
+ "version": "4.3.7",
5707
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
5708
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
5709
+ "license": "MIT",
5710
+ "dependencies": {
5711
+ "ms": "^2.1.3"
5712
+ },
5713
+ "engines": {
5714
+ "node": ">=6.0"
5715
+ },
5716
+ "peerDependenciesMeta": {
5717
+ "supports-color": {
5718
+ "optional": true
5719
+ }
5720
+ }
5721
+ },
5614
5722
  "node_modules/source-map-js": {
5615
5723
  "version": "1.2.1",
5616
5724
  "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -6257,6 +6365,27 @@
6257
6365
  "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
6258
6366
  "license": "ISC"
6259
6367
  },
6368
+ "node_modules/ws": {
6369
+ "version": "8.17.1",
6370
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
6371
+ "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
6372
+ "license": "MIT",
6373
+ "engines": {
6374
+ "node": ">=10.0.0"
6375
+ },
6376
+ "peerDependencies": {
6377
+ "bufferutil": "^4.0.1",
6378
+ "utf-8-validate": ">=5.0.2"
6379
+ },
6380
+ "peerDependenciesMeta": {
6381
+ "bufferutil": {
6382
+ "optional": true
6383
+ },
6384
+ "utf-8-validate": {
6385
+ "optional": true
6386
+ }
6387
+ }
6388
+ },
6260
6389
  "node_modules/xmlbuilder": {
6261
6390
  "version": "10.1.1",
6262
6391
  "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-10.1.1.tgz",
@@ -6266,6 +6395,14 @@
6266
6395
  "node": ">=4.0"
6267
6396
  }
6268
6397
  },
6398
+ "node_modules/xmlhttprequest-ssl": {
6399
+ "version": "2.1.2",
6400
+ "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz",
6401
+ "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==",
6402
+ "engines": {
6403
+ "node": ">=0.4.0"
6404
+ }
6405
+ },
6269
6406
  "node_modules/yocto-queue": {
6270
6407
  "version": "0.1.0",
6271
6408
  "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
@@ -26,6 +26,7 @@
26
26
  "react-hot-toast": "^2.5.2",
27
27
  "react-markdown": "^10.1.0",
28
28
  "react-router": "^7.5.0",
29
+ "socket.io-client": "^4.8.1",
29
30
  "syllable": "^5.0.1",
30
31
  "youtube-transcript": "^1.2.1",
31
32
  "zustand": "^5.0.3"