@learnpack/learnpack 4.0.7 → 4.0.8

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -21,7 +21,7 @@ $ npm install -g @learnpack/learnpack
21
21
  $ learnpack COMMAND
22
22
  running command...
23
23
  $ learnpack (-v|--version|version)
24
- @learnpack/learnpack/4.0.7 win32-x64 node-v20.16.0
24
+ @learnpack/learnpack/4.0.8 win32-x64 node-v20.16.0
25
25
  $ learnpack --help [COMMAND]
26
26
  USAGE
27
27
  $ learnpack COMMAND
@@ -74,7 +74,7 @@ DESCRIPTION
74
74
  12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)
75
75
  ```
76
76
 
77
- _See code: [src\commands\audit.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\audit.ts)_
77
+ _See code: [src\commands\audit.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.8/src\commands\audit.ts)_
78
78
 
79
79
  ## `learnpack clean`
80
80
 
@@ -89,7 +89,7 @@ DESCRIPTION
89
89
  Extra documentation goes here
90
90
  ```
91
91
 
92
- _See code: [src\commands\clean.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\clean.ts)_
92
+ _See code: [src\commands\clean.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.8/src\commands\clean.ts)_
93
93
 
94
94
  ## `learnpack download [PACKAGE]`
95
95
 
@@ -107,7 +107,7 @@ DESCRIPTION
107
107
  Extra documentation goes here
108
108
  ```
109
109
 
110
- _See code: [src\commands\download.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\download.ts)_
110
+ _See code: [src\commands\download.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.8/src\commands\download.ts)_
111
111
 
112
112
  ## `learnpack help [COMMAND]`
113
113
 
@@ -138,7 +138,7 @@ OPTIONS
138
138
  -h, --grading show CLI help
139
139
  ```
140
140
 
141
- _See code: [src\commands\init.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\init.ts)_
141
+ _See code: [src\commands\init.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.8/src\commands\init.ts)_
142
142
 
143
143
  ## `learnpack login [PACKAGE]`
144
144
 
@@ -156,7 +156,7 @@ DESCRIPTION
156
156
  Extra documentation goes here
157
157
  ```
158
158
 
159
- _See code: [src\commands\login.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\login.ts)_
159
+ _See code: [src\commands\login.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.8/src\commands\login.ts)_
160
160
 
161
161
  ## `learnpack logout [PACKAGE]`
162
162
 
@@ -174,7 +174,7 @@ DESCRIPTION
174
174
  Extra documentation goes here
175
175
  ```
176
176
 
177
- _See code: [src\commands\logout.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\logout.ts)_
177
+ _See code: [src\commands\logout.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.8/src\commands\logout.ts)_
178
178
 
179
179
  ## `learnpack plugins`
180
180
 
@@ -309,7 +309,7 @@ DESCRIPTION
309
309
  Extra documentation goes here
310
310
  ```
311
311
 
312
- _See code: [src\commands\publish.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\publish.ts)_
312
+ _See code: [src\commands\publish.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.8/src\commands\publish.ts)_
313
313
 
314
314
  ## `learnpack start`
315
315
 
@@ -330,7 +330,7 @@ OPTIONS
330
330
  -w, --watch Watch for file changes
331
331
  ```
332
332
 
333
- _See code: [src\commands\start.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\start.ts)_
333
+ _See code: [src\commands\start.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.8/src\commands\start.ts)_
334
334
 
335
335
  ## `learnpack test [EXERCISESLUG]`
336
336
 
@@ -344,7 +344,7 @@ ARGUMENTS
344
344
  EXERCISESLUG The name of the exercise to test
345
345
  ```
346
346
 
347
- _See code: [src\commands\test.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.7/src\commands\test.ts)_
347
+ _See code: [src\commands\test.ts](https://github.com/learnpack/learnpack-cli/blob/v4.0.8/src\commands\test.ts)_
348
348
  <!-- commandsstop -->
349
349
 
350
350
  > > > > > > > 0cb3e56d84c197f9d008836bb573eade212b7e57
@@ -22,7 +22,7 @@ class StartCommand extends SessionCommand_1.default {
22
22
  await this.initSession(flags);
23
23
  }
24
24
  async run() {
25
- var _a, _b, _c, _d, _e, _f, _g, _h;
25
+ var _a, _b, _c, _d, _e, _f;
26
26
  // get configuration object
27
27
  const configObject = (_a = this.configManager) === null || _a === void 0 ? void 0 : _a.get();
28
28
  const hasXDG = await osOperations_1.eventManager.checkXDGInstalled();
@@ -77,18 +77,6 @@ class StartCommand extends SessionCommand_1.default {
77
77
  }
78
78
  }
79
79
  socket_1.default.start(config, server, false);
80
- if ((_g = config === null || config === void 0 ? void 0 : config.warnings) === null || _g === void 0 ? void 0 : _g.agent) {
81
- const message = config.warnings.agent;
82
- setTimeout(() => {
83
- socket_1.default.dialog(message);
84
- }, 2000);
85
- }
86
- if ((_h = config === null || config === void 0 ? void 0 : config.warnings) === null || _h === void 0 ? void 0 : _h.extension) {
87
- const message = config.warnings.extension;
88
- setTimeout(() => {
89
- socket_1.default.dialog(message);
90
- }, 3000);
91
- }
92
80
  socket_1.default.on("open", (data) => {
93
81
  console_1.default.debug("Opening these files: ", data);
94
82
  const files = misc_1.prioritizeHTMLFile(data.files);
@@ -31,18 +31,18 @@ declare const _default: {
31
31
  python3: string;
32
32
  java: string;
33
33
  };
34
+ suggestions: {
35
+ agent: null;
36
+ };
37
+ warnings: {
38
+ agent: null;
39
+ };
34
40
  };
35
41
  address: string;
36
42
  currentExercise: null;
37
43
  exercises: never[];
38
44
  bugsLink: null;
39
45
  videoSolutions: boolean;
40
- suggestions: {
41
- agent: null;
42
- };
43
- warnings: {
44
- agent: null;
45
- };
46
46
  localhostOnly: boolean;
47
47
  };
48
48
  export default _default;
@@ -35,17 +35,17 @@ exports.default = {
35
35
  python3: "app.py",
36
36
  java: "app.java",
37
37
  },
38
+ suggestions: {
39
+ agent: null,
40
+ },
41
+ warnings: {
42
+ agent: null,
43
+ },
38
44
  },
39
45
  address: "http://localhost",
40
46
  currentExercise: null,
41
47
  exercises: [],
42
48
  bugsLink: null,
43
49
  videoSolutions: false,
44
- suggestions: {
45
- agent: null,
46
- },
47
- warnings: {
48
- agent: null,
49
- },
50
50
  localhostOnly: false,
51
51
  };
@@ -153,6 +153,7 @@ exports.default = async ({ grading, mode, disableGrading, version, }) => {
153
153
  }
154
154
  if (configObj.config.suggestions &&
155
155
  configObj.config.editor &&
156
+ configObj.config.suggestions.agent !== null &&
156
157
  configObj.config.suggestions.agent !== configObj.config.editor.agent) {
157
158
  console_1.default.warning(`The suggested agent "${configObj.config.suggestions.agent}" is different from the detected agent "${configObj.config.editor.agent}"`);
158
159
  try {
@@ -169,7 +170,7 @@ exports.default = async ({ grading, mode, disableGrading, version, }) => {
169
170
  }
170
171
  if (!configObj.config.editor.mode) {
171
172
  configObj.config.editor.mode =
172
- configObj.config.editor.agent === "vscode" ? "extension" : "preview";
173
+ process.env.TERM_PROGRAM === "vscode" ? "extension" : "preview";
173
174
  }
174
175
  if (version)
175
176
  configObj.config.editor.version = version;
@@ -240,13 +241,13 @@ exports.default = async ({ grading, mode, disableGrading, version, }) => {
240
241
  console_1.default.debug(`Validating engine for ${language} compilation`);
241
242
  let result = shell.exec("learnpack plugins", { silent: true });
242
243
  if (result.code === 0 &&
243
- result.stdout.includes(`learnpack-${language}`)) {
244
+ result.stdout.includes(`@learnpack/${language}`)) {
244
245
  this.validLanguages[language] = true;
245
246
  return true;
246
247
  }
247
248
  console_1.default.info(`Language engine for ${language} not found, installing...`);
248
249
  // Install the compiler in their new versions
249
- result = shell.exec(`learnpack plugins:install learnpack-${language}`, {
250
+ result = shell.exec(`learnpack plugins:install @learnpack/${language}`, {
250
251
  silent: true,
251
252
  });
252
253
  if (result.code === 0) {
@@ -374,7 +375,7 @@ exports.default = async ({ grading, mode, disableGrading, version, }) => {
374
375
  });
375
376
  },
376
377
  save: () => {
377
- // Console.debug("Saving configuration with: ", configObj)
378
+ console_1.default.debug("Saving configuration with: ", configObj);
378
379
  // remove the duplicates form the actions array
379
380
  // configObj.config.actions = [...new Set(configObj.config.actions)];
380
381
  if (configObj.config) {
@@ -36,7 +36,8 @@ async function default_1(app, configObject, configManager) {
36
36
  path: `${config === null || config === void 0 ? void 0 : config.dirPath}/vscode_queue.json`,
37
37
  });
38
38
  app.get("/config", withHandler((_, res) => {
39
- res.json(configObject);
39
+ const confObject = configManager.get();
40
+ res.json(confObject);
40
41
  }));
41
42
  // Added this line to parse the json body
42
43
  const jsonBodyParser = bodyParser.json();
@@ -1 +1 @@
1
- {"version":"4.0.7","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":{},"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":{"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":"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}]},"start":{"id":"start","description":"Runs a small server with all the exercise instructions","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"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":{},"args":[{"name":"exerciseSlug","description":"The name of the exercise to test","required":false,"hidden":false}]}}}
1
+ {"version":"4.0.8","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":{},"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":{"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":"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}]},"start":{"id":"start","description":"Runs a small server with all the exercise instructions","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"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":{},"args":[{"name":"exerciseSlug","description":"The name of the exercise to test","required":false,"hidden":false}]}}}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@learnpack/learnpack",
3
3
  "description": "Create, sell or download and take learning amazing learning packages",
4
- "version": "4.0.7",
4
+ "version": "4.0.8",
5
5
  "author": "Alejandro Sanchez @alesanchezr",
6
6
  "contributors": [
7
7
  {
@@ -170,20 +170,6 @@ export default class StartCommand extends SessionCommand {
170
170
 
171
171
  socket.start(config, server, false)
172
172
 
173
- if (config?.warnings?.agent) {
174
- const message = config.warnings.agent
175
- setTimeout(() => {
176
- socket.dialog(message)
177
- }, 2000)
178
- }
179
-
180
- if (config?.warnings?.extension) {
181
- const message = config.warnings.extension
182
- setTimeout(() => {
183
- socket.dialog(message)
184
- }, 3000)
185
- }
186
-
187
173
  socket.on("open", (data: IGitpodData) => {
188
174
  Console.debug("Opening these files: ", data)
189
175
 
@@ -33,17 +33,17 @@ export default {
33
33
  python3: "app.py",
34
34
  java: "app.java",
35
35
  },
36
+ suggestions: {
37
+ agent: null,
38
+ },
39
+ warnings: {
40
+ agent: null,
41
+ },
36
42
  },
37
43
  address: "http://localhost",
38
44
  currentExercise: null,
39
45
  exercises: [],
40
46
  bugsLink: null,
41
47
  videoSolutions: false,
42
- suggestions: {
43
- agent: null,
44
- },
45
- warnings: {
46
- agent: null,
47
- },
48
48
  localhostOnly: false, // if true, the exercise should not run on gitpod or codespaces but show an error message encouraging the user to run locally
49
49
  }
@@ -221,6 +221,7 @@ throw InternalError("Config object not found")
221
221
  if (
222
222
  configObj.config.suggestions &&
223
223
  configObj.config.editor &&
224
+ configObj.config.suggestions.agent !== null &&
224
225
  configObj.config.suggestions.agent !== configObj.config.editor.agent
225
226
  ) {
226
227
  Console.warning(
@@ -249,7 +250,7 @@ throw InternalError("Config object not found")
249
250
 
250
251
  if (!configObj.config.editor.mode) {
251
252
  configObj.config.editor.mode =
252
- configObj.config.editor.agent === "vscode" ? "extension" : "preview"
253
+ process.env.TERM_PROGRAM === "vscode" ? "extension" : "preview"
253
254
  }
254
255
 
255
256
  if (version)
@@ -337,7 +338,7 @@ return true
337
338
 
338
339
  if (
339
340
  result.code === 0 &&
340
- result.stdout.includes(`learnpack-${language}`)
341
+ result.stdout.includes(`@learnpack/${language}`)
341
342
  ) {
342
343
  this.validLanguages[language] = true
343
344
  return true
@@ -345,7 +346,7 @@ return true
345
346
 
346
347
  Console.info(`Language engine for ${language} not found, installing...`)
347
348
  // Install the compiler in their new versions
348
- result = shell.exec(`learnpack plugins:install learnpack-${language}`, {
349
+ result = shell.exec(`learnpack plugins:install @learnpack/${language}`, {
349
350
  silent: true,
350
351
  })
351
352
  if (result.code === 0) {
@@ -515,8 +516,7 @@ fs.mkdirSync(confPath.base)
515
516
  },
516
517
 
517
518
  save: () => {
518
- // Console.debug("Saving configuration with: ", configObj)
519
-
519
+ Console.debug("Saving configuration with: ", configObj)
520
520
  // remove the duplicates form the actions array
521
521
  // configObj.config.actions = [...new Set(configObj.config.actions)];
522
522
  if (configObj.config) {
@@ -599,7 +599,7 @@ We strongly recommend using VSCode for a better learning experience.
599
599
  `
600
600
  }
601
601
 
602
- if (agent === "os") {
602
+ if (agent === "os") {
603
603
  return `
604
604
  # Steps to Change Agent to OS
605
605
 
@@ -1,330 +1,327 @@
1
- import Console from "../../utils/console"
2
- import * as express from "express"
3
- import * as fs from "fs"
4
- import * as bodyParser from "body-parser"
5
- import socket from "../socket"
6
- import queue from "../../utils/fileQueue"
7
- // import gitpod from '../gitpod'
8
- import { detect, filterFiles } from "../config/exercise"
9
- import { IFile } from "../../models/file"
10
- import { IConfigObj, TEntries } from "../../models/config"
11
- import { IConfigManager } from "../../models/config-manager"
12
- import { IExercise } from "../../models/exercise-obj"
13
- import SessionManager from "../../managers/session"
14
- import TelemetryManager from "../telemetry"
15
- import { eventManager } from "../../utils/osOperations"
16
-
17
- const withHandler =
18
- (func: (req: express.Request, res: express.Response) => void) =>
19
- (req: express.Request, res: express.Response) => {
20
- try {
21
- func(req, res)
22
- } catch (error) {
23
- Console.debug(error)
24
- const _err = {
25
- message: (error as TypeError).message || "There has been an error",
26
- status: (error as any).status || 500,
27
- type: (error as any).type || null,
28
- }
29
- Console.error(_err.message)
30
-
31
- // send rep to the server
32
- res.status(_err.status)
33
- res.json(_err)
34
- }
35
- }
36
-
37
- export default async function (
38
- app: express.Application,
39
- configObject: IConfigObj,
40
- configManager: IConfigManager
41
- ) {
42
- const { config, exercises } = configObject
43
- const session = await SessionManager.get(configManager?.get())
44
-
45
- const dispatcher = queue.dispatcher({
46
- create: true,
47
- path: `${config?.dirPath}/vscode_queue.json`,
48
- })
49
- app.get(
50
- "/config",
51
- withHandler((_: express.Request, res: express.Response) => {
52
- res.json(configObject)
53
- })
54
- )
55
-
56
- // Added this line to parse the json body
57
-
58
- const jsonBodyParser = bodyParser.json()
59
- // Trying to log in from frontend
60
- app.post(
61
- "/login",
62
- jsonBodyParser,
63
- withHandler(async (req: express.Request, res: express.Response) => {
64
- const email = req.body.email
65
- const password = req.body.password
66
-
67
- SessionManager.destroy()
68
- const payload = await SessionManager.loginWeb(email, password)
69
-
70
- res.json(payload)
71
- })
72
- )
73
- app.post(
74
- "/set-rigobot-token",
75
- jsonBodyParser,
76
- withHandler(async (req: express.Request, res: express.Response) => {
77
- const token = req.body.token
78
- // Ensure token is provided in the request body
79
- if (!token) {
80
- return res.status(400).json({ error: "Token is required" })
81
- }
82
-
83
- try {
84
- const tokenSaved = await SessionManager.setRigoToken(token)
85
- // Check if the token was saved successfully
86
- if (tokenSaved) {
87
- res.json({ status: "ok" })
88
- } else {
89
- res.status(500).json({ error: "Failed to save the token" })
90
- }
91
- } catch {
92
- // Handle any unexpected errors during the process
93
- res.status(500).json({ error: "Internal server error" })
94
- }
95
- })
96
- )
97
- app.get(
98
- "/check/rigo/status",
99
- withHandler(async (_: express.Request, res: express.Response) => {
100
- const payload = await SessionManager.getPayload()
101
-
102
- if (payload && payload.rigobot && payload.rigobot.key) {
103
- res.json({ rigoToken: payload.rigobot.key })
104
- } else {
105
- res
106
- .status(400)
107
- .json({ details: `Rigobot token not found, please log in first!` })
108
- }
109
- })
110
- )
111
-
112
- // symbolic link to maintain path compatiblity
113
- const fetchStaticAsset = withHandler((req, res) => {
114
- const filePath = `${config?.dirPath}/assets/${req.params.filePath}`
115
- if (!fs.existsSync(filePath))
116
- throw new Error("File not found: " + filePath)
117
- const content = fs.readFileSync(filePath)
118
- res.write(content)
119
- res.end()
120
- })
121
-
122
- app.get(
123
- `${
124
- config?.dirPath.indexOf("./") === 0 ?
125
- config.dirPath.slice(1) :
126
- config?.dirPath
127
- }/assets/:filePath`,
128
- fetchStaticAsset
129
- )
130
-
131
- app.get("/assets/:filePath", fetchStaticAsset)
132
-
133
- app.get(
134
- "/exercise",
135
- withHandler((_: express.Request, res: express.Response) => {
136
- res.json(exercises)
137
- })
138
- )
139
-
140
- app.get(
141
- "/exercise/:slug/readme",
142
- withHandler(
143
- (
144
- { params: { slug }, query: { lang } }: express.Request,
145
- res: express.Response
146
- ) => {
147
- const exercise: IExercise = configManager.getExercise(slug)
148
-
149
- if (exercise && exercise.getReadme) {
150
- const readme = exercise.getReadme((lang as string) || null)
151
- res.json(readme)
152
- } else {
153
- res.status(400)
154
- }
155
- }
156
- )
157
- )
158
-
159
- app.get(
160
- "/exercise/:slug/report",
161
- withHandler(
162
- ({ params: { slug } }: express.Request, res: express.Response) => {
163
- const exercise = configManager.getExercise(slug)
164
- if (exercise && exercise.getTestReport) {
165
- const report = exercise.getTestReport()
166
- res.json(JSON.stringify(report))
167
- }
168
- }
169
- )
170
- )
171
-
172
- app.get(
173
- "/exercise/:slug",
174
- withHandler((req: express.Request, res: express.Response) => {
175
- // no need to re-start exercise if it's already started
176
- if (
177
- configObject.currentExercise &&
178
- req.params.slug === configObject.currentExercise
179
- ) {
180
- const exercise = configManager.getExercise(req.params.slug)
181
- res.json(exercise)
182
- if (exercise.position) {
183
- TelemetryManager.registerStepEvent(
184
- exercise.position,
185
- "open_step",
186
- {}
187
- )
188
- }
189
-
190
- return
191
- }
192
-
193
- const exercise = configManager.startExercise(req.params.slug)
194
- if (exercise.position) {
195
- TelemetryManager.registerStepEvent(exercise.position, "open_step", {})
196
- }
197
-
198
- if (configObject.config?.editor.agent === "os") {
199
- eventManager.enqueue(dispatcher.events.START_EXERCISE, exercise)
200
- } else {
201
- dispatcher.enqueue(dispatcher.events.START_EXERCISE, req.params.slug)
202
- }
203
-
204
- type TEntry = "python3" | "html" | "node" | "react" | "java";
205
-
206
- const entries = new Set(
207
- Object.keys(config?.entries!).map(
208
- lang => config?.entries[lang as TEntry]
209
- )
210
- )
211
-
212
- // if we are in incremental grading, the entry file can by dinamically detected
213
- // based on the changes the student is making during the exercise
214
- if (config?.grading === "incremental") {
215
- const scanedFiles = fs.readdirSync("./")
216
-
217
- // update the file hierarchy with updates
218
- exercise.files = [
219
- ...exercise.files.filter(f => f.name.includes("test.")),
220
- ...filterFiles(scanedFiles),
221
- ]
222
- Console.debug(`Exercise updated files: `, exercise.files)
223
- }
224
-
225
- const detected = detect(
226
- configObject,
227
- exercise.files
228
- .filter(fileName => entries.has(fileName.name))
229
- .map(f => f.name || f) as string[]
230
- )
231
-
232
- // if a new language for the testing engine is detected, we replace it
233
- // if not we leave it as it was before
234
- if (config?.language && !["", "auto"].includes(config?.language)) {
235
- Console.debug(
236
- `Exercise language ignored, instead imported from configuration ${config?.language}`
237
- )
238
- exercise.language = detected?.language
239
- } else if (
240
- detected?.language &&
241
- (!config?.language || config?.language === "auto")
242
- ) {
243
- Console.debug(
244
- `Switching to ${detected.language} engine in this exercise`
245
- )
246
- exercise.language = detected.language
247
- }
248
-
249
- // WARNING: has to be the FULL PATH to the entry path
250
- // We need to detect entry in both gradings: Incremental and Isolate
251
- exercise.entry = detected?.entry
252
- Console.debug(
253
- `Exercise detected entry: ${detected?.entry} and language ${exercise.language}`
254
- )
255
-
256
- // exercises.graded and exercises.disableGrading deprecated.
257
- if (
258
- !exercise.graded ||
259
- config?.disableGrading ||
260
- config?.disabledActions?.includes("test")
261
- ) {
262
- socket.removeAllowed("test")
263
- } else {
264
- socket.addAllowed("test")
265
- }
266
-
267
- if (!exercise.entry || config?.disabledActions?.includes("build")) {
268
- socket.removeAllowed("build")
269
- } else {
270
- socket.addAllowed("build")
271
- }
272
-
273
- if (
274
- exercise.files.filter(
275
- (f: IFile) =>
276
- !f.name.toLowerCase().includes("readme.") &&
277
- !f.name.toLowerCase().includes("test.")
278
- ).length === 0 ||
279
- config?.disabledActions?.includes("reset")
280
- ) {
281
- socket.removeAllowed("reset")
282
- } else if (!config?.disabledActions?.includes("reset")) {
283
- socket.addAllowed("reset")
284
- }
285
-
286
- socket.log("ready")
287
- res.json(exercise)
288
- })
289
- )
290
-
291
- app.get(
292
- "/exercise/:slug/file/:fileName",
293
- withHandler((req: express.Request, res: express.Response) => {
294
- const exercise = configManager.getExercise(req.params.slug)
295
- if (exercise && exercise.getFile) {
296
- res.write(exercise.getFile(req.params.fileName))
297
- res.end()
298
- }
299
- })
300
- )
301
-
302
- /*
303
- app.post(
304
- "/exercise/:slug/file/:fileName",
305
- withHandler((req: express.Request, res: express.Response) => {
306
- get tokens but also, add allowed action for 'generate'
307
- use the sessionManager to keep compatibility with the cli login command.
308
- })
309
- );
310
- */
311
-
312
- const textBodyParser = bodyParser.text()
313
- app.put(
314
- "/exercise/:slug/file/:fileName",
315
- textBodyParser,
316
- withHandler((req: express.Request, res: express.Response) => {
317
- const exercise = configManager.getExercise(req.params.slug)
318
- if (exercise && exercise.saveFile) {
319
- exercise.saveFile(req.params.fileName, req.body)
320
- res.end()
321
- }
322
- })
323
- )
324
-
325
- if (config?.outputPath) {
326
- app.use("/preview", express.static(config.outputPath))
327
- }
328
-
329
- app.use("/", express.static(`${config?.dirPath}/_app`))
330
- }
1
+ import Console from "../../utils/console"
2
+ import * as express from "express"
3
+ import * as fs from "fs"
4
+ import * as bodyParser from "body-parser"
5
+ import socket from "../socket"
6
+ import queue from "../../utils/fileQueue"
7
+ // import gitpod from '../gitpod'
8
+ import { detect, filterFiles } from "../config/exercise"
9
+ import { IFile } from "../../models/file"
10
+ import { IConfigObj, TEntries } from "../../models/config"
11
+ import { IConfigManager } from "../../models/config-manager"
12
+ import { IExercise } from "../../models/exercise-obj"
13
+ import SessionManager from "../../managers/session"
14
+ import TelemetryManager from "../telemetry"
15
+ import { eventManager } from "../../utils/osOperations"
16
+
17
+ const withHandler =
18
+ (func: (req: express.Request, res: express.Response) => void) =>
19
+ (req: express.Request, res: express.Response) => {
20
+ try {
21
+ func(req, res)
22
+ } catch (error) {
23
+ Console.debug(error)
24
+ const _err = {
25
+ message: (error as TypeError).message || "There has been an error",
26
+ status: (error as any).status || 500,
27
+ type: (error as any).type || null,
28
+ }
29
+ Console.error(_err.message)
30
+
31
+ // send rep to the server
32
+ res.status(_err.status)
33
+ res.json(_err)
34
+ }
35
+ }
36
+
37
+ export default async function (
38
+ app: express.Application,
39
+ configObject: IConfigObj,
40
+ configManager: IConfigManager
41
+ ) {
42
+ const { config, exercises } = configObject
43
+ const session = await SessionManager.get(configManager?.get())
44
+
45
+ const dispatcher = queue.dispatcher({
46
+ create: true,
47
+ path: `${config?.dirPath}/vscode_queue.json`,
48
+ })
49
+ app.get(
50
+ "/config",
51
+ withHandler((_: express.Request, res: express.Response) => {
52
+ const confObject = configManager.get()
53
+ res.json(confObject)
54
+ })
55
+ )
56
+
57
+ // Added this line to parse the json body
58
+
59
+ const jsonBodyParser = bodyParser.json()
60
+ // Trying to log in from frontend
61
+ app.post(
62
+ "/login",
63
+ jsonBodyParser,
64
+ withHandler(async (req: express.Request, res: express.Response) => {
65
+ const email = req.body.email
66
+ const password = req.body.password
67
+
68
+ SessionManager.destroy()
69
+ const payload = await SessionManager.loginWeb(email, password)
70
+
71
+ res.json(payload)
72
+ })
73
+ )
74
+ app.post(
75
+ "/set-rigobot-token",
76
+ jsonBodyParser,
77
+ withHandler(async (req: express.Request, res: express.Response) => {
78
+ const token = req.body.token
79
+ // Ensure token is provided in the request body
80
+ if (!token) {
81
+ return res.status(400).json({ error: "Token is required" })
82
+ }
83
+
84
+ try {
85
+ const tokenSaved = await SessionManager.setRigoToken(token)
86
+ // Check if the token was saved successfully
87
+ if (tokenSaved) {
88
+ res.json({ status: "ok" })
89
+ } else {
90
+ res.status(500).json({ error: "Failed to save the token" })
91
+ }
92
+ } catch {
93
+ // Handle any unexpected errors during the process
94
+ res.status(500).json({ error: "Internal server error" })
95
+ }
96
+ })
97
+ )
98
+ app.get(
99
+ "/check/rigo/status",
100
+ withHandler(async (_: express.Request, res: express.Response) => {
101
+ const payload = await SessionManager.getPayload()
102
+
103
+ if (payload && payload.rigobot && payload.rigobot.key) {
104
+ res.json({ rigoToken: payload.rigobot.key })
105
+ } else {
106
+ res
107
+ .status(400)
108
+ .json({ details: `Rigobot token not found, please log in first!` })
109
+ }
110
+ })
111
+ )
112
+
113
+ // symbolic link to maintain path compatiblity
114
+ const fetchStaticAsset = withHandler((req, res) => {
115
+ const filePath = `${config?.dirPath}/assets/${req.params.filePath}`
116
+ if (!fs.existsSync(filePath))
117
+ throw new Error("File not found: " + filePath)
118
+ const content = fs.readFileSync(filePath)
119
+ res.write(content)
120
+ res.end()
121
+ })
122
+
123
+ app.get(
124
+ `${
125
+ config?.dirPath.indexOf("./") === 0 ?
126
+ config.dirPath.slice(1) :
127
+ config?.dirPath
128
+ }/assets/:filePath`,
129
+ fetchStaticAsset
130
+ )
131
+
132
+ app.get("/assets/:filePath", fetchStaticAsset)
133
+
134
+ app.get(
135
+ "/exercise",
136
+ withHandler((_: express.Request, res: express.Response) => {
137
+ res.json(exercises)
138
+ })
139
+ )
140
+
141
+ app.get(
142
+ "/exercise/:slug/readme",
143
+ withHandler(
144
+ (
145
+ { params: { slug }, query: { lang } }: express.Request,
146
+ res: express.Response
147
+ ) => {
148
+ const exercise: IExercise = configManager.getExercise(slug)
149
+
150
+ if (exercise && exercise.getReadme) {
151
+ const readme = exercise.getReadme((lang as string) || null)
152
+ res.json(readme)
153
+ } else {
154
+ res.status(400)
155
+ }
156
+ }
157
+ )
158
+ )
159
+
160
+ app.get(
161
+ "/exercise/:slug/report",
162
+ withHandler(
163
+ ({ params: { slug } }: express.Request, res: express.Response) => {
164
+ const exercise = configManager.getExercise(slug)
165
+ if (exercise && exercise.getTestReport) {
166
+ const report = exercise.getTestReport()
167
+ res.json(JSON.stringify(report))
168
+ }
169
+ }
170
+ )
171
+ )
172
+
173
+ app.get(
174
+ "/exercise/:slug",
175
+ withHandler((req: express.Request, res: express.Response) => {
176
+ // no need to re-start exercise if it's already started
177
+ if (
178
+ configObject.currentExercise &&
179
+ req.params.slug === configObject.currentExercise
180
+ ) {
181
+ const exercise = configManager.getExercise(req.params.slug)
182
+ res.json(exercise)
183
+ if (exercise.position) {
184
+ TelemetryManager.registerStepEvent(exercise.position, "open_step", {})
185
+ }
186
+
187
+ return
188
+ }
189
+
190
+ const exercise = configManager.startExercise(req.params.slug)
191
+ if (exercise.position) {
192
+ TelemetryManager.registerStepEvent(exercise.position, "open_step", {})
193
+ }
194
+
195
+ if (configObject.config?.editor.agent === "os") {
196
+ eventManager.enqueue(dispatcher.events.START_EXERCISE, exercise)
197
+ } else {
198
+ dispatcher.enqueue(dispatcher.events.START_EXERCISE, req.params.slug)
199
+ }
200
+
201
+ type TEntry = "python3" | "html" | "node" | "react" | "java"
202
+
203
+ const entries = new Set(
204
+ Object.keys(config?.entries!).map(
205
+ lang => config?.entries[lang as TEntry]
206
+ )
207
+ )
208
+
209
+ // if we are in incremental grading, the entry file can by dinamically detected
210
+ // based on the changes the student is making during the exercise
211
+ if (config?.grading === "incremental") {
212
+ const scanedFiles = fs.readdirSync("./")
213
+
214
+ // update the file hierarchy with updates
215
+ exercise.files = [
216
+ ...exercise.files.filter(f => f.name.includes("test.")),
217
+ ...filterFiles(scanedFiles),
218
+ ]
219
+ Console.debug(`Exercise updated files: `, exercise.files)
220
+ }
221
+
222
+ const detected = detect(
223
+ configObject,
224
+ exercise.files
225
+ .filter(fileName => entries.has(fileName.name))
226
+ .map(f => f.name || f) as string[]
227
+ )
228
+
229
+ // if a new language for the testing engine is detected, we replace it
230
+ // if not we leave it as it was before
231
+ if (config?.language && !["", "auto"].includes(config?.language)) {
232
+ Console.debug(
233
+ `Exercise language ignored, instead imported from configuration ${config?.language}`
234
+ )
235
+ exercise.language = detected?.language
236
+ } else if (
237
+ detected?.language &&
238
+ (!config?.language || config?.language === "auto")
239
+ ) {
240
+ Console.debug(
241
+ `Switching to ${detected.language} engine in this exercise`
242
+ )
243
+ exercise.language = detected.language
244
+ }
245
+
246
+ // WARNING: has to be the FULL PATH to the entry path
247
+ // We need to detect entry in both gradings: Incremental and Isolate
248
+ exercise.entry = detected?.entry
249
+ Console.debug(
250
+ `Exercise detected entry: ${detected?.entry} and language ${exercise.language}`
251
+ )
252
+
253
+ // exercises.graded and exercises.disableGrading deprecated.
254
+ if (
255
+ !exercise.graded ||
256
+ config?.disableGrading ||
257
+ config?.disabledActions?.includes("test")
258
+ ) {
259
+ socket.removeAllowed("test")
260
+ } else {
261
+ socket.addAllowed("test")
262
+ }
263
+
264
+ if (!exercise.entry || config?.disabledActions?.includes("build")) {
265
+ socket.removeAllowed("build")
266
+ } else {
267
+ socket.addAllowed("build")
268
+ }
269
+
270
+ if (
271
+ exercise.files.filter(
272
+ (f: IFile) =>
273
+ !f.name.toLowerCase().includes("readme.") &&
274
+ !f.name.toLowerCase().includes("test.")
275
+ ).length === 0 ||
276
+ config?.disabledActions?.includes("reset")
277
+ ) {
278
+ socket.removeAllowed("reset")
279
+ } else if (!config?.disabledActions?.includes("reset")) {
280
+ socket.addAllowed("reset")
281
+ }
282
+
283
+ socket.log("ready")
284
+ res.json(exercise)
285
+ })
286
+ )
287
+
288
+ app.get(
289
+ "/exercise/:slug/file/:fileName",
290
+ withHandler((req: express.Request, res: express.Response) => {
291
+ const exercise = configManager.getExercise(req.params.slug)
292
+ if (exercise && exercise.getFile) {
293
+ res.write(exercise.getFile(req.params.fileName))
294
+ res.end()
295
+ }
296
+ })
297
+ )
298
+
299
+ /*
300
+ app.post(
301
+ "/exercise/:slug/file/:fileName",
302
+ withHandler((req: express.Request, res: express.Response) => {
303
+ get tokens but also, add allowed action for 'generate'
304
+ use the sessionManager to keep compatibility with the cli login command.
305
+ })
306
+ );
307
+ */
308
+
309
+ const textBodyParser = bodyParser.text()
310
+ app.put(
311
+ "/exercise/:slug/file/:fileName",
312
+ textBodyParser,
313
+ withHandler((req: express.Request, res: express.Response) => {
314
+ const exercise = configManager.getExercise(req.params.slug)
315
+ if (exercise && exercise.saveFile) {
316
+ exercise.saveFile(req.params.fileName, req.body)
317
+ res.end()
318
+ }
319
+ })
320
+ )
321
+
322
+ if (config?.outputPath) {
323
+ app.use("/preview", express.static(config.outputPath))
324
+ }
325
+
326
+ app.use("/", express.static(`${config?.dirPath}/_app`))
327
+ }