@learnpack/learnpack 2.1.52 → 2.1.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/lib/commands/start.js +22 -0
- package/lib/managers/socket.js +7 -0
- package/lib/managers/telemetry.d.ts +1 -1
- package/lib/managers/telemetry.js +10 -2
- package/lib/models/action.d.ts +1 -1
- package/lib/models/socket.d.ts +1 -0
- package/lib/utils/checkNotInstalled.js +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
- package/src/commands/start.ts +355 -320
- package/src/managers/socket.ts +9 -0
- package/src/managers/telemetry.ts +353 -346
- package/src/models/action.ts +11 -10
- package/src/models/socket.ts +60 -59
- package/src/models/status.ts +16 -16
- package/src/utils/checkNotInstalled.ts +3 -4
    
        package/src/commands/start.ts
    CHANGED
    
    | @@ -1,320 +1,355 @@ | |
| 1 | 
            -
            // import path from "path";
         | 
| 2 | 
            -
            import { flags } from "@oclif/command"
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            import  | 
| 5 | 
            -
             | 
| 6 | 
            -
            import  | 
| 7 | 
            -
            import  | 
| 8 | 
            -
            import  | 
| 9 | 
            -
            import  | 
| 10 | 
            -
            import  | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
               | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
            import {  | 
| 18 | 
            -
             | 
| 19 | 
            -
            import {  | 
| 20 | 
            -
            import {  | 
| 21 | 
            -
            import {  | 
| 22 | 
            -
            import {
         | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
              static  | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
                 | 
| 34 | 
            -
                 | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
                   | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
                 | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
                   | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
                   | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
                   | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
                   | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
                   | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
               | 
| 68 | 
            -
             | 
| 69 | 
            -
               | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
               | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
                 | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 81 | 
            -
                const  | 
| 82 | 
            -
             | 
| 83 | 
            -
                 | 
| 84 | 
            -
             | 
| 85 | 
            -
                 | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
                   | 
| 89 | 
            -
             | 
| 90 | 
            -
                   | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
                     | 
| 94 | 
            -
                       | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 99 | 
            -
             | 
| 100 | 
            -
                   | 
| 101 | 
            -
             | 
| 102 | 
            -
             | 
| 103 | 
            -
                     | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
                   | 
| 107 | 
            -
             | 
| 108 | 
            -
                   | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 | 
            -
                   | 
| 112 | 
            -
             | 
| 113 | 
            -
                   | 
| 114 | 
            -
             | 
| 115 | 
            -
                   | 
| 116 | 
            -
             | 
| 117 | 
            -
                   | 
| 118 | 
            -
             | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 121 | 
            -
             | 
| 122 | 
            -
             | 
| 123 | 
            -
             | 
| 124 | 
            -
                     | 
| 125 | 
            -
             | 
| 126 | 
            -
             | 
| 127 | 
            -
             | 
| 128 | 
            -
             | 
| 129 | 
            -
             | 
| 130 | 
            -
             | 
| 131 | 
            -
                   | 
| 132 | 
            -
             | 
| 133 | 
            -
             | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 136 | 
            -
                       | 
| 137 | 
            -
             | 
| 138 | 
            -
             | 
| 139 | 
            -
             | 
| 140 | 
            -
                     | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 146 | 
            -
                     | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 149 | 
            -
                      const  | 
| 150 | 
            -
             | 
| 151 | 
            -
                      const  | 
| 152 | 
            -
             | 
| 153 | 
            -
             | 
| 154 | 
            -
             | 
| 155 | 
            -
                           | 
| 156 | 
            -
                           | 
| 157 | 
            -
                           | 
| 158 | 
            -
                           | 
| 159 | 
            -
                           | 
| 160 | 
            -
             | 
| 161 | 
            -
             | 
| 162 | 
            -
             | 
| 163 | 
            -
             | 
| 164 | 
            -
                       | 
| 165 | 
            -
             | 
| 166 | 
            -
                       | 
| 167 | 
            -
             | 
| 168 | 
            -
                       | 
| 169 | 
            -
             | 
| 170 | 
            -
             | 
| 171 | 
            -
                     | 
| 172 | 
            -
             | 
| 173 | 
            -
                    socket. | 
| 174 | 
            -
             | 
| 175 | 
            -
             | 
| 176 | 
            -
                       | 
| 177 | 
            -
             | 
| 178 | 
            -
                       | 
| 179 | 
            -
             | 
| 180 | 
            -
                       | 
| 181 | 
            -
                         | 
| 182 | 
            -
                      }
         | 
| 183 | 
            -
             | 
| 184 | 
            -
                       | 
| 185 | 
            -
             | 
| 186 | 
            -
             | 
| 187 | 
            -
                     | 
| 188 | 
            -
             | 
| 189 | 
            -
             | 
| 190 | 
            -
                       | 
| 191 | 
            -
             | 
| 192 | 
            -
                       | 
| 193 | 
            -
                         | 
| 194 | 
            -
                      }
         | 
| 195 | 
            -
             | 
| 196 | 
            -
                       | 
| 197 | 
            -
             | 
| 198 | 
            -
             | 
| 199 | 
            -
                     | 
| 200 | 
            -
             | 
| 201 | 
            -
             | 
| 202 | 
            -
                       | 
| 203 | 
            -
             | 
| 204 | 
            -
                       | 
| 205 | 
            -
             | 
| 206 | 
            -
             | 
| 207 | 
            -
                     | 
| 208 | 
            -
             | 
| 209 | 
            -
             | 
| 210 | 
            -
             | 
| 211 | 
            -
             | 
| 212 | 
            -
                        socket. | 
| 213 | 
            -
             | 
| 214 | 
            -
             | 
| 215 | 
            -
             | 
| 216 | 
            -
             | 
| 217 | 
            -
             | 
| 218 | 
            -
             | 
| 219 | 
            -
             | 
| 220 | 
            -
             | 
| 221 | 
            -
                     | 
| 222 | 
            -
             | 
| 223 | 
            -
             | 
| 224 | 
            -
                       | 
| 225 | 
            -
             | 
| 226 | 
            -
             | 
| 227 | 
            -
             | 
| 228 | 
            -
             | 
| 229 | 
            -
             | 
| 230 | 
            -
             | 
| 231 | 
            -
             | 
| 232 | 
            -
             | 
| 233 | 
            -
             | 
| 234 | 
            -
                       | 
| 235 | 
            -
             | 
| 236 | 
            -
             | 
| 237 | 
            -
             | 
| 238 | 
            -
             | 
| 239 | 
            -
                           | 
| 240 | 
            -
                          " | 
| 241 | 
            -
             | 
| 242 | 
            -
             | 
| 243 | 
            -
             | 
| 244 | 
            -
             | 
| 245 | 
            -
                         | 
| 246 | 
            -
                         | 
| 247 | 
            -
                         | 
| 248 | 
            -
             | 
| 249 | 
            -
             | 
| 250 | 
            -
             | 
| 251 | 
            -
                     | 
| 252 | 
            -
             | 
| 253 | 
            -
             | 
| 254 | 
            -
             | 
| 255 | 
            -
             | 
| 256 | 
            -
                     | 
| 257 | 
            -
             | 
| 258 | 
            -
             | 
| 259 | 
            -
                       | 
| 260 | 
            -
             | 
| 261 | 
            -
             | 
| 262 | 
            -
             | 
| 263 | 
            -
             | 
| 264 | 
            -
             | 
| 265 | 
            -
             | 
| 266 | 
            -
             | 
| 267 | 
            -
             | 
| 268 | 
            -
             | 
| 269 | 
            -
                       | 
| 270 | 
            -
             | 
| 271 | 
            -
             | 
| 272 | 
            -
             | 
| 273 | 
            -
                         | 
| 274 | 
            -
             | 
| 275 | 
            -
             | 
| 276 | 
            -
             | 
| 277 | 
            -
                       | 
| 278 | 
            -
             | 
| 279 | 
            -
             | 
| 280 | 
            -
             | 
| 281 | 
            -
             | 
| 282 | 
            -
                       | 
| 283 | 
            -
             | 
| 284 | 
            -
             | 
| 285 | 
            -
                         | 
| 286 | 
            -
                         | 
| 287 | 
            -
                         | 
| 288 | 
            -
             | 
| 289 | 
            -
             | 
| 290 | 
            -
                       | 
| 291 | 
            -
             | 
| 292 | 
            -
                       | 
| 293 | 
            -
             | 
| 294 | 
            -
             | 
| 295 | 
            -
             | 
| 296 | 
            -
                       | 
| 297 | 
            -
             | 
| 298 | 
            -
                       | 
| 299 | 
            -
             | 
| 300 | 
            -
                       | 
| 301 | 
            -
             | 
| 302 | 
            -
             | 
| 303 | 
            -
             | 
| 304 | 
            -
             | 
| 305 | 
            -
             | 
| 306 | 
            -
             | 
| 307 | 
            -
             | 
| 308 | 
            -
             | 
| 309 | 
            -
             | 
| 310 | 
            -
             | 
| 311 | 
            -
             | 
| 312 | 
            -
             | 
| 313 | 
            -
             | 
| 314 | 
            -
             | 
| 315 | 
            -
                         | 
| 316 | 
            -
             | 
| 317 | 
            -
             | 
| 318 | 
            -
             | 
| 319 | 
            -
             | 
| 320 | 
            -
            }
         | 
| 1 | 
            +
            // import path from "path";
         | 
| 2 | 
            +
            import { flags } from "@oclif/command"
         | 
| 3 | 
            +
            import * as fs from "fs"
         | 
| 4 | 
            +
            import * as path from "path"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            import SessionCommand from "../utils/SessionCommand"
         | 
| 7 | 
            +
            import Console from "../utils/console"
         | 
| 8 | 
            +
            import socket from "../managers/socket"
         | 
| 9 | 
            +
            import TelemetryManager, { TStep } from "../managers/telemetry"
         | 
| 10 | 
            +
            import createServer from "../managers/server"
         | 
| 11 | 
            +
            import queue from "../utils/fileQueue"
         | 
| 12 | 
            +
            import {
         | 
| 13 | 
            +
              decompress,
         | 
| 14 | 
            +
              downloadEditor,
         | 
| 15 | 
            +
              checkIfDirectoryExists,
         | 
| 16 | 
            +
            } from "../managers/file"
         | 
| 17 | 
            +
            import { prioritizeHTMLFile } from "../utils/misc"
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            import { IGitpodData } from "../models/gitpod-data"
         | 
| 20 | 
            +
            import { IExercise, IExerciseData } from "../models/exercise-obj"
         | 
| 21 | 
            +
            import { eventManager } from "../utils/osOperations"
         | 
| 22 | 
            +
            import { cli } from "cli-ux"
         | 
| 23 | 
            +
            import { TOpenWindowData } from "../models/socket"
         | 
| 24 | 
            +
            import {
         | 
| 25 | 
            +
              checkNotInstalledPlugins,
         | 
| 26 | 
            +
              checkNotInstalledDependencies,
         | 
| 27 | 
            +
            } from "../utils/checkNotInstalled"
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            export default class StartCommand extends SessionCommand {
         | 
| 30 | 
            +
              static description = "Runs a small server with all the exercise instructions"
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              static flags = {
         | 
| 33 | 
            +
                ...SessionCommand.flags,
         | 
| 34 | 
            +
                port: flags.string({ char: "p", description: "server port" }),
         | 
| 35 | 
            +
                host: flags.string({ char: "h", description: "server host" }),
         | 
| 36 | 
            +
                disableGrading: flags.boolean({
         | 
| 37 | 
            +
                  char: "D",
         | 
| 38 | 
            +
                  description: "disble grading functionality",
         | 
| 39 | 
            +
                  default: false,
         | 
| 40 | 
            +
                }),
         | 
| 41 | 
            +
                // disableGrading: flags.boolean({char: 'dg', description: 'disble grading functionality', default: false }),
         | 
| 42 | 
            +
                watch: flags.boolean({
         | 
| 43 | 
            +
                  char: "w",
         | 
| 44 | 
            +
                  description: "Watch for file changes",
         | 
| 45 | 
            +
                  default: false,
         | 
| 46 | 
            +
                }),
         | 
| 47 | 
            +
                editor: flags.string({
         | 
| 48 | 
            +
                  char: "e",
         | 
| 49 | 
            +
                  description: "[preview, extension]",
         | 
| 50 | 
            +
                  options: ["extension", "preview"],
         | 
| 51 | 
            +
                }),
         | 
| 52 | 
            +
                version: flags.string({
         | 
| 53 | 
            +
                  char: "v",
         | 
| 54 | 
            +
                  description: "E.g: 1.0.1",
         | 
| 55 | 
            +
                  default: undefined,
         | 
| 56 | 
            +
                }),
         | 
| 57 | 
            +
                grading: flags.string({
         | 
| 58 | 
            +
                  char: "g",
         | 
| 59 | 
            +
                  description: "[isolated, incremental]",
         | 
| 60 | 
            +
                  options: ["isolated", "incremental"],
         | 
| 61 | 
            +
                }),
         | 
| 62 | 
            +
                debug: flags.boolean({
         | 
| 63 | 
            +
                  char: "d",
         | 
| 64 | 
            +
                  description: "debugger mode for more verbage",
         | 
| 65 | 
            +
                  default: false,
         | 
| 66 | 
            +
                }),
         | 
| 67 | 
            +
              }
         | 
| 68 | 
            +
             | 
| 69 | 
            +
              // 🛑 IMPORTANT
         | 
| 70 | 
            +
              // Every command that will use the configManager needs this init method
         | 
| 71 | 
            +
              async init() {
         | 
| 72 | 
            +
                const { flags } = this.parse(StartCommand)
         | 
| 73 | 
            +
                await this.initSession(flags)
         | 
| 74 | 
            +
              }
         | 
| 75 | 
            +
             | 
| 76 | 
            +
              async run() {
         | 
| 77 | 
            +
                // get configuration object
         | 
| 78 | 
            +
                const configObject = this.configManager?.get()
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                // TODO: console.log(this.config.platform); get the platfrom from Oclif
         | 
| 81 | 
            +
                const hasXDG = await eventManager.checkXDGInstalled()
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                const installedPlugins = this.config.plugins.map(plugin => {
         | 
| 84 | 
            +
                  return `${plugin.pjson.name}`
         | 
| 85 | 
            +
                })
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                if (configObject) {
         | 
| 88 | 
            +
                  const { config } = configObject
         | 
| 89 | 
            +
                  // build exerises
         | 
| 90 | 
            +
                  this.configManager?.buildIndex()
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                  Console.debug(
         | 
| 93 | 
            +
                    `Grading: ${config?.grading} ${
         | 
| 94 | 
            +
                      config?.disabledActions?.includes("test") ? "(disabled)" : ""
         | 
| 95 | 
            +
                    }, editor: ${config?.editor.mode} ${config?.editor.version}, for ${
         | 
| 96 | 
            +
                      Array.isArray(configObject?.exercises) ?
         | 
| 97 | 
            +
                        configObject?.exercises.length :
         | 
| 98 | 
            +
                        0
         | 
| 99 | 
            +
                    } exercises found`
         | 
| 100 | 
            +
                  )
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                  const neededPlugins = await checkNotInstalledPlugins(
         | 
| 103 | 
            +
                    configObject?.exercises || [],
         | 
| 104 | 
            +
                    installedPlugins,
         | 
| 105 | 
            +
                    this
         | 
| 106 | 
            +
                  )
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                  const allDepsInstalled = await checkNotInstalledDependencies(
         | 
| 109 | 
            +
                    neededPlugins.needed
         | 
| 110 | 
            +
                  )
         | 
| 111 | 
            +
                  if (!allDepsInstalled) {
         | 
| 112 | 
            +
                    this.exit(1)
         | 
| 113 | 
            +
                  }
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                  const appAlreadyExists = checkIfDirectoryExists(
         | 
| 116 | 
            +
                    `${config?.dirPath}/_app`
         | 
| 117 | 
            +
                  )
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                  if (!appAlreadyExists) {
         | 
| 120 | 
            +
                    // download app and decompress
         | 
| 121 | 
            +
                    await downloadEditor(
         | 
| 122 | 
            +
                      config?.editor.version,
         | 
| 123 | 
            +
                      `${config?.dirPath}/app.tar.gz`
         | 
| 124 | 
            +
                    )
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                    Console.info("Decompressing LearnPack UI, this may take a minute...")
         | 
| 127 | 
            +
                    await decompress(
         | 
| 128 | 
            +
                      `${config?.dirPath}/app.tar.gz`,
         | 
| 129 | 
            +
                      `${config?.dirPath}/_app/`
         | 
| 130 | 
            +
                    )
         | 
| 131 | 
            +
                  }
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                  // listen to socket commands
         | 
| 134 | 
            +
                  if (config && this.configManager) {
         | 
| 135 | 
            +
                    const server = await createServer(
         | 
| 136 | 
            +
                      configObject,
         | 
| 137 | 
            +
                      this.configManager,
         | 
| 138 | 
            +
                      process.env.NODE_ENV === "test"
         | 
| 139 | 
            +
                    )
         | 
| 140 | 
            +
                    server.setMaxListeners(25)
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                    // I should call a method to get the EventListener
         | 
| 143 | 
            +
                    const dispatcher = queue.dispatcher({
         | 
| 144 | 
            +
                      create: true,
         | 
| 145 | 
            +
                      path: `${config.dirPath}/vscode_queue.json`,
         | 
| 146 | 
            +
                    })
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                    if (configObject.exercises) {
         | 
| 149 | 
            +
                      const agent = configObject.config?.editor.agent || ""
         | 
| 150 | 
            +
                      const path = configObject.config?.dirPath || ""
         | 
| 151 | 
            +
                      const tutorialSlug = configObject.config?.slug || ""
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                      const steps = configObject.exercises.map(
         | 
| 154 | 
            +
                        (e: IExercise, index): TStep => ({
         | 
| 155 | 
            +
                          slug: e.slug,
         | 
| 156 | 
            +
                          position: e.position || index,
         | 
| 157 | 
            +
                          files: e.files,
         | 
| 158 | 
            +
                          ai_interactions: [],
         | 
| 159 | 
            +
                          compilations: [],
         | 
| 160 | 
            +
                          tests: [],
         | 
| 161 | 
            +
                          is_testeable: e.graded || false,
         | 
| 162 | 
            +
                        })
         | 
| 163 | 
            +
                      )
         | 
| 164 | 
            +
                      if (path && steps.length > 0) {
         | 
| 165 | 
            +
                        TelemetryManager.start(agent, steps, path, tutorialSlug)
         | 
| 166 | 
            +
                      }
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                      if (config.telemetry) {
         | 
| 169 | 
            +
                        TelemetryManager.urls = config.telemetry
         | 
| 170 | 
            +
                      }
         | 
| 171 | 
            +
                    }
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                    socket.start(config, server, false)
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                    socket.on("open", (data: IGitpodData) => {
         | 
| 176 | 
            +
                      Console.debug("Opening these files: ", data)
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                      const files = prioritizeHTMLFile(data.files)
         | 
| 179 | 
            +
             | 
| 180 | 
            +
                      if (config.editor.agent === "os") {
         | 
| 181 | 
            +
                        eventManager.enqueue(dispatcher.events.OPEN_FILES, files)
         | 
| 182 | 
            +
                      } else {
         | 
| 183 | 
            +
                        dispatcher.enqueue(dispatcher.events.OPEN_FILES, files)
         | 
| 184 | 
            +
                      }
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                      socket.ready("Ready to compile...")
         | 
| 187 | 
            +
                    })
         | 
| 188 | 
            +
             | 
| 189 | 
            +
                    socket.on("open_window", (data: TOpenWindowData) => {
         | 
| 190 | 
            +
                      Console.debug("Opening window: ", data)
         | 
| 191 | 
            +
                      // cli.open(data.url); This uses XDG under the ground
         | 
| 192 | 
            +
                      if (config.os !== "linux" || (config.os === "linux" && hasXDG)) {
         | 
| 193 | 
            +
                        eventManager.enqueue(dispatcher.events.OPEN_WINDOW, data)
         | 
| 194 | 
            +
                      } else {
         | 
| 195 | 
            +
                        dispatcher.enqueue(dispatcher.events.OPEN_WINDOW, data)
         | 
| 196 | 
            +
                      }
         | 
| 197 | 
            +
             | 
| 198 | 
            +
                      socket.log("open_window", "", undefined, data.url)
         | 
| 199 | 
            +
                    })
         | 
| 200 | 
            +
             | 
| 201 | 
            +
                    socket.on("open_terminal", (exercise: IExerciseData) => {
         | 
| 202 | 
            +
                      Console.debug("Opening terminal: ", exercise)
         | 
| 203 | 
            +
                      // eventManager.enqueue(dispatcher.events.OPEN_TERMINAL, exercise);
         | 
| 204 | 
            +
                      if (config.editor.agent === "vscode") {
         | 
| 205 | 
            +
                        dispatcher.enqueue(dispatcher.events.OPEN_TERMINAL, exercise)
         | 
| 206 | 
            +
                      }
         | 
| 207 | 
            +
                    })
         | 
| 208 | 
            +
             | 
| 209 | 
            +
                    socket.on("reset", (exercise: IExerciseData) => {
         | 
| 210 | 
            +
                      try {
         | 
| 211 | 
            +
                        this.configManager?.reset(exercise.exerciseSlug)
         | 
| 212 | 
            +
                        socket.ready("Ready to compile...")
         | 
| 213 | 
            +
                      } catch (error) {
         | 
| 214 | 
            +
                        socket.error(
         | 
| 215 | 
            +
                          "compiler-error",
         | 
| 216 | 
            +
                          (error as TypeError).message ||
         | 
| 217 | 
            +
                            "There was an error reseting the exercise"
         | 
| 218 | 
            +
                        )
         | 
| 219 | 
            +
                        setTimeout(() => socket.ready("Ready to compile..."), 2000)
         | 
| 220 | 
            +
                      }
         | 
| 221 | 
            +
                    })
         | 
| 222 | 
            +
             | 
| 223 | 
            +
                    socket.on("build", async (data: IExerciseData) => {
         | 
| 224 | 
            +
                      const exercise = this.configManager?.getExercise(data.exerciseSlug)
         | 
| 225 | 
            +
             | 
| 226 | 
            +
                      if (!exercise?.language) {
         | 
| 227 | 
            +
                        socket.error(
         | 
| 228 | 
            +
                          "compiler-error",
         | 
| 229 | 
            +
                          "Impossible to detect language to build for " +
         | 
| 230 | 
            +
                            data.exerciseSlug +
         | 
| 231 | 
            +
                            "..."
         | 
| 232 | 
            +
                        )
         | 
| 233 | 
            +
                        return
         | 
| 234 | 
            +
                      }
         | 
| 235 | 
            +
             | 
| 236 | 
            +
                      socket.log(
         | 
| 237 | 
            +
                        "compiling",
         | 
| 238 | 
            +
                        "Building exercise " +
         | 
| 239 | 
            +
                          data.exerciseSlug +
         | 
| 240 | 
            +
                          " with " +
         | 
| 241 | 
            +
                          exercise.language +
         | 
| 242 | 
            +
                          "..."
         | 
| 243 | 
            +
                      )
         | 
| 244 | 
            +
                      await this.config.runHook("action", {
         | 
| 245 | 
            +
                        action: "compile",
         | 
| 246 | 
            +
                        socket,
         | 
| 247 | 
            +
                        configuration: config,
         | 
| 248 | 
            +
                        exercise,
         | 
| 249 | 
            +
                        telemetry: TelemetryManager,
         | 
| 250 | 
            +
                      })
         | 
| 251 | 
            +
                    })
         | 
| 252 | 
            +
             | 
| 253 | 
            +
                    socket.on("ai_interaction", (data: any) => {
         | 
| 254 | 
            +
                      const { stepPosition, event, eventData } = data
         | 
| 255 | 
            +
                      TelemetryManager.registerStepEvent(stepPosition, event, eventData)
         | 
| 256 | 
            +
                    })
         | 
| 257 | 
            +
             | 
| 258 | 
            +
                    socket.on("test", async (data: IExerciseData) => {
         | 
| 259 | 
            +
                      const exercise = this.configManager?.getExercise(data.exerciseSlug)
         | 
| 260 | 
            +
             | 
| 261 | 
            +
                      if (!exercise?.language) {
         | 
| 262 | 
            +
                        socket.error(
         | 
| 263 | 
            +
                          "compiler-error",
         | 
| 264 | 
            +
                          "Impossible to detect engine language for testing for " +
         | 
| 265 | 
            +
                            data.exerciseSlug +
         | 
| 266 | 
            +
                            "..."
         | 
| 267 | 
            +
                        )
         | 
| 268 | 
            +
                        return
         | 
| 269 | 
            +
                      }
         | 
| 270 | 
            +
             | 
| 271 | 
            +
                      if (
         | 
| 272 | 
            +
                        config?.disabledActions!.includes("test") ||
         | 
| 273 | 
            +
                        config?.disableGrading
         | 
| 274 | 
            +
                      ) {
         | 
| 275 | 
            +
                        socket.ready("Grading is disabled on configuration")
         | 
| 276 | 
            +
                        return true
         | 
| 277 | 
            +
                      }
         | 
| 278 | 
            +
             | 
| 279 | 
            +
                      socket.log(
         | 
| 280 | 
            +
                        "testing",
         | 
| 281 | 
            +
                        "Testing your exercise using the " + exercise.language + " engine."
         | 
| 282 | 
            +
                      )
         | 
| 283 | 
            +
             | 
| 284 | 
            +
                      await this.config.runHook("action", {
         | 
| 285 | 
            +
                        action: "test",
         | 
| 286 | 
            +
                        socket,
         | 
| 287 | 
            +
                        configuration: config,
         | 
| 288 | 
            +
                        exercise,
         | 
| 289 | 
            +
                        telemetry: TelemetryManager,
         | 
| 290 | 
            +
                      })
         | 
| 291 | 
            +
             | 
| 292 | 
            +
                      // Check if ${configObject.dirPath}/reports/${exercise.slug}/report.md or /reports/${exercise.slug}/report.txt exists
         | 
| 293 | 
            +
                      // If it does, then send the content of the file to the frontend
         | 
| 294 | 
            +
                      // If it doesn't, then send an empty object
         | 
| 295 | 
            +
             | 
| 296 | 
            +
                      if (!configObject.config) {
         | 
| 297 | 
            +
                        return
         | 
| 298 | 
            +
                      }
         | 
| 299 | 
            +
             | 
| 300 | 
            +
                      const markdownReportPath = path.join(
         | 
| 301 | 
            +
                        configObject.config.dirPath,
         | 
| 302 | 
            +
                        "reports",
         | 
| 303 | 
            +
                        `${exercise.slug}`,
         | 
| 304 | 
            +
                        "report.md"
         | 
| 305 | 
            +
                      )
         | 
| 306 | 
            +
                      const textReportPath = path.join(
         | 
| 307 | 
            +
                        configObject.config.dirPath,
         | 
| 308 | 
            +
                        "reports",
         | 
| 309 | 
            +
                        `${exercise.slug}`,
         | 
| 310 | 
            +
                        "report.txt"
         | 
| 311 | 
            +
                      )
         | 
| 312 | 
            +
                      const reportExists =
         | 
| 313 | 
            +
                        fs.existsSync(markdownReportPath) || fs.existsSync(textReportPath)
         | 
| 314 | 
            +
                      if (reportExists) {
         | 
| 315 | 
            +
                        try {
         | 
| 316 | 
            +
                          const reportContent =
         | 
| 317 | 
            +
                            // fs.readFileSync(markdownReportPath, "utf8") ||
         | 
| 318 | 
            +
                            fs.readFileSync(textReportPath, "utf8")
         | 
| 319 | 
            +
                          socket.dialog(reportContent)
         | 
| 320 | 
            +
                        } catch (error) {
         | 
| 321 | 
            +
                          console.log(error)
         | 
| 322 | 
            +
                        }
         | 
| 323 | 
            +
                      }
         | 
| 324 | 
            +
             | 
| 325 | 
            +
                      this.configManager?.save()
         | 
| 326 | 
            +
             | 
| 327 | 
            +
                      return true
         | 
| 328 | 
            +
                    })
         | 
| 329 | 
            +
             | 
| 330 | 
            +
                    const terminate = async () => {
         | 
| 331 | 
            +
                      Console.error("Terminating Learnpack...")
         | 
| 332 | 
            +
                      await TelemetryManager.submit()
         | 
| 333 | 
            +
                      this.configManager?.noCurrentExercise()
         | 
| 334 | 
            +
                      dispatcher.enqueue(dispatcher.events.END)
         | 
| 335 | 
            +
                      process.exit()
         | 
| 336 | 
            +
                    }
         | 
| 337 | 
            +
             | 
| 338 | 
            +
                    server.on("close", terminate)
         | 
| 339 | 
            +
                    process.on("SIGINT", terminate)
         | 
| 340 | 
            +
                    process.on("SIGTERM", terminate)
         | 
| 341 | 
            +
                    process.on("SIGHUP", terminate)
         | 
| 342 | 
            +
             | 
| 343 | 
            +
                    // finish the server startup
         | 
| 344 | 
            +
                    setTimeout(() => dispatcher.enqueue(dispatcher.events.RUNNING), 1000)
         | 
| 345 | 
            +
             | 
| 346 | 
            +
                    // start watching for file changes
         | 
| 347 | 
            +
                    if (StartCommand.flags.watch)
         | 
| 348 | 
            +
                      this.configManager.watchIndex(_filename => {
         | 
| 349 | 
            +
                        // Instead of reloading with socket.reload(), I just notify the frontend for the file change
         | 
| 350 | 
            +
                        socket.emit("file_change", "ready", _filename)
         | 
| 351 | 
            +
                      })
         | 
| 352 | 
            +
                  }
         | 
| 353 | 
            +
                }
         | 
| 354 | 
            +
              }
         | 
| 355 | 
            +
            }
         |