@learnpack/learnpack 2.1.26 → 2.1.27

Sign up to get free protection for your applications and to get access to all the features.
Files changed (154) hide show
  1. package/README.md +10 -10
  2. package/oclif.manifest.json +1 -1
  3. package/package.json +2 -1
  4. package/src/commands/audit.ts +113 -113
  5. package/src/commands/clean.ts +10 -10
  6. package/src/commands/download.ts +18 -18
  7. package/src/commands/init.ts +39 -39
  8. package/src/commands/login.ts +13 -13
  9. package/src/commands/logout.ts +9 -9
  10. package/src/commands/publish.ts +25 -25
  11. package/src/commands/start.ts +101 -75
  12. package/src/commands/test.ts +34 -34
  13. package/src/managers/config/allowed_files.ts +2 -2
  14. package/src/managers/config/defaults.ts +2 -2
  15. package/src/managers/config/exercise.ts +79 -79
  16. package/src/managers/config/index.ts +145 -145
  17. package/src/managers/file.ts +74 -65
  18. package/src/managers/server/index.ts +32 -31
  19. package/src/managers/server/routes.ts +139 -90
  20. package/src/managers/session.ts +53 -24
  21. package/src/managers/socket.ts +92 -79
  22. package/src/models/action.ts +8 -1
  23. package/src/models/config-manager.ts +2 -2
  24. package/src/models/config.ts +7 -2
  25. package/src/models/exercise-obj.ts +6 -3
  26. package/src/models/plugin-config.ts +2 -2
  27. package/src/models/session.ts +5 -2
  28. package/src/models/socket.ts +12 -6
  29. package/src/models/status.ts +15 -14
  30. package/src/plugin/command/compile.ts +10 -10
  31. package/src/plugin/command/test.ts +14 -14
  32. package/src/plugin/index.ts +5 -5
  33. package/src/plugin/plugin.ts +26 -26
  34. package/src/plugin/utils.ts +23 -23
  35. package/src/utils/BaseCommand.ts +16 -16
  36. package/src/utils/api.ts +143 -91
  37. package/src/utils/audit.ts +93 -96
  38. package/src/utils/exercisesQueue.ts +15 -15
  39. package/src/utils/fileQueue.ts +85 -85
  40. package/src/utils/watcher.ts +14 -14
  41. package/lib/commands/audit.d.ts +0 -6
  42. package/lib/commands/audit.js +0 -342
  43. package/lib/commands/clean.d.ts +0 -8
  44. package/lib/commands/clean.js +0 -25
  45. package/lib/commands/download.d.ts +0 -13
  46. package/lib/commands/download.js +0 -55
  47. package/lib/commands/init.d.ts +0 -9
  48. package/lib/commands/init.js +0 -123
  49. package/lib/commands/login.d.ts +0 -14
  50. package/lib/commands/login.js +0 -37
  51. package/lib/commands/logout.d.ts +0 -14
  52. package/lib/commands/logout.js +0 -37
  53. package/lib/commands/publish.d.ts +0 -14
  54. package/lib/commands/publish.js +0 -82
  55. package/lib/commands/start.d.ts +0 -7
  56. package/lib/commands/start.js +0 -165
  57. package/lib/commands/test.d.ts +0 -6
  58. package/lib/commands/test.js +0 -62
  59. package/lib/index.d.ts +0 -1
  60. package/lib/index.js +0 -4
  61. package/lib/managers/config/allowed_files.d.ts +0 -5
  62. package/lib/managers/config/allowed_files.js +0 -30
  63. package/lib/managers/config/defaults.d.ts +0 -39
  64. package/lib/managers/config/defaults.js +0 -40
  65. package/lib/managers/config/exercise.d.ts +0 -36
  66. package/lib/managers/config/exercise.js +0 -233
  67. package/lib/managers/config/index.d.ts +0 -3
  68. package/lib/managers/config/index.js +0 -320
  69. package/lib/managers/file.d.ts +0 -13
  70. package/lib/managers/file.js +0 -134
  71. package/lib/managers/gitpod.d.ts +0 -3
  72. package/lib/managers/gitpod.js +0 -67
  73. package/lib/managers/server/index.d.ts +0 -6
  74. package/lib/managers/server/index.js +0 -58
  75. package/lib/managers/server/routes.d.ts +0 -4
  76. package/lib/managers/server/routes.js +0 -167
  77. package/lib/managers/session.d.ts +0 -3
  78. package/lib/managers/session.js +0 -104
  79. package/lib/managers/socket.d.ts +0 -3
  80. package/lib/managers/socket.js +0 -164
  81. package/lib/managers/test.d.ts +0 -0
  82. package/lib/managers/test.js +0 -84
  83. package/lib/models/action.d.ts +0 -2
  84. package/lib/models/action.js +0 -2
  85. package/lib/models/audit.d.ts +0 -15
  86. package/lib/models/audit.js +0 -2
  87. package/lib/models/config-manager.d.ts +0 -21
  88. package/lib/models/config-manager.js +0 -2
  89. package/lib/models/config.d.ts +0 -62
  90. package/lib/models/config.js +0 -2
  91. package/lib/models/counter.d.ts +0 -11
  92. package/lib/models/counter.js +0 -2
  93. package/lib/models/errors.d.ts +0 -15
  94. package/lib/models/errors.js +0 -2
  95. package/lib/models/exercise-obj.d.ts +0 -27
  96. package/lib/models/exercise-obj.js +0 -2
  97. package/lib/models/file.d.ts +0 -5
  98. package/lib/models/file.js +0 -2
  99. package/lib/models/findings.d.ts +0 -17
  100. package/lib/models/findings.js +0 -2
  101. package/lib/models/flags.d.ts +0 -10
  102. package/lib/models/flags.js +0 -2
  103. package/lib/models/front-matter.d.ts +0 -11
  104. package/lib/models/front-matter.js +0 -2
  105. package/lib/models/gitpod-data.d.ts +0 -16
  106. package/lib/models/gitpod-data.js +0 -2
  107. package/lib/models/language.d.ts +0 -4
  108. package/lib/models/language.js +0 -2
  109. package/lib/models/package.d.ts +0 -7
  110. package/lib/models/package.js +0 -2
  111. package/lib/models/plugin-config.d.ts +0 -16
  112. package/lib/models/plugin-config.js +0 -2
  113. package/lib/models/session.d.ts +0 -23
  114. package/lib/models/session.js +0 -2
  115. package/lib/models/socket.d.ts +0 -31
  116. package/lib/models/socket.js +0 -2
  117. package/lib/models/status.d.ts +0 -1
  118. package/lib/models/status.js +0 -2
  119. package/lib/models/success-types.d.ts +0 -1
  120. package/lib/models/success-types.js +0 -2
  121. package/lib/plugin/command/compile.d.ts +0 -6
  122. package/lib/plugin/command/compile.js +0 -18
  123. package/lib/plugin/command/test.d.ts +0 -6
  124. package/lib/plugin/command/test.js +0 -25
  125. package/lib/plugin/index.d.ts +0 -27
  126. package/lib/plugin/index.js +0 -7
  127. package/lib/plugin/plugin.d.ts +0 -8
  128. package/lib/plugin/plugin.js +0 -68
  129. package/lib/plugin/utils.d.ts +0 -16
  130. package/lib/plugin/utils.js +0 -58
  131. package/lib/ui/download.d.ts +0 -5
  132. package/lib/ui/download.js +0 -61
  133. package/lib/utils/BaseCommand.d.ts +0 -8
  134. package/lib/utils/BaseCommand.js +0 -41
  135. package/lib/utils/SessionCommand.d.ts +0 -10
  136. package/lib/utils/SessionCommand.js +0 -47
  137. package/lib/utils/api.d.ts +0 -12
  138. package/lib/utils/api.js +0 -173
  139. package/lib/utils/audit.d.ts +0 -16
  140. package/lib/utils/audit.js +0 -302
  141. package/lib/utils/console.d.ts +0 -12
  142. package/lib/utils/console.js +0 -19
  143. package/lib/utils/errors.d.ts +0 -17
  144. package/lib/utils/errors.js +0 -100
  145. package/lib/utils/exercisesQueue.d.ts +0 -9
  146. package/lib/utils/exercisesQueue.js +0 -38
  147. package/lib/utils/fileQueue.d.ts +0 -40
  148. package/lib/utils/fileQueue.js +0 -168
  149. package/lib/utils/misc.d.ts +0 -1
  150. package/lib/utils/misc.js +0 -23
  151. package/lib/utils/validators.d.ts +0 -5
  152. package/lib/utils/validators.js +0 -17
  153. package/lib/utils/watcher.d.ts +0 -2
  154. package/lib/utils/watcher.js +0 -23
@@ -1,24 +1,24 @@
1
- import * as path from "path";
2
- import * as fs from "fs";
3
- import * as shell from "shelljs";
4
- import Console from "../../utils/console";
5
- import watch from "../../utils/watcher";
1
+ import * as path from "path"
2
+ import * as fs from "fs"
3
+ import * as shell from "shelljs"
4
+ import Console from "../../utils/console"
5
+ import watch from "../../utils/watcher"
6
6
  import {
7
7
  ValidationError,
8
8
  NotFoundError,
9
9
  InternalError,
10
- } from "../../utils/errors";
10
+ } from "../../utils/errors"
11
11
 
12
- import defaults from "./defaults";
13
- import { exercise } from "./exercise";
12
+ import defaults from "./defaults"
13
+ import { exercise } from "./exercise"
14
14
 
15
- import { rmSync } from "../file";
16
- import { IConfigObj, TConfigObjAttributes, TMode } from "../../models/config";
15
+ import { rmSync } from "../file"
16
+ import { IConfigObj, TConfigObjAttributes, TMode } from "../../models/config"
17
17
  import {
18
18
  IConfigManagerAttributes,
19
19
  IConfigManager,
20
- } from "../../models/config-manager";
21
- import { IFile } from "../../models/file";
20
+ } from "../../models/config-manager"
21
+ import { IFile } from "../../models/file"
22
22
 
23
23
  /* exercise folder name standard */
24
24
 
@@ -30,49 +30,49 @@ const chalk = require("chalk");
30
30
  /* exercise folder name standard */
31
31
 
32
32
  const getConfigPath = () => {
33
- const possibleFileNames = ["learn.json", ".learn/learn.json"];
34
- const config = possibleFileNames.find(file => fs.existsSync(file)) || null;
33
+ const possibleFileNames = ["learn.json", ".learn/learn.json"]
34
+ const config = possibleFileNames.find(file => fs.existsSync(file)) || null
35
35
  if (config && fs.existsSync(".breathecode"))
36
- return { config, base: ".breathecode" };
36
+ return { config, base: ".breathecode" }
37
37
  if (config === null)
38
38
  throw NotFoundError(
39
39
  "learn.json file not found on current folder, is this a learnpack package?"
40
- );
41
- return { config, base: ".learn" };
42
- };
40
+ )
41
+ return { config, base: ".learn" }
42
+ }
43
43
 
44
44
  const getExercisesPath = (base: string) => {
45
- const possibleFileNames = ["./exercises", base + "/exercises", "./"];
46
- return possibleFileNames.find(file => fs.existsSync(file)) || null;
47
- };
45
+ const possibleFileNames = ["./exercises", base + "/exercises", "./"]
46
+ return possibleFileNames.find(file => fs.existsSync(file)) || null
47
+ }
48
48
 
49
49
  const getGitpodAddress = () => {
50
50
  if (shell.exec("gp -h", { silent: true }).code === 0) {
51
51
  return shell
52
52
  .exec("gp url", { silent: true })
53
- .stdout.replace(/(\r\n|\n|\r)/gm, "");
53
+ .stdout.replace(/(\r\n|\n|\r)/gm, "")
54
54
  }
55
55
 
56
- Console.debug("Gitpod command line tool not found");
57
- return "http://localhost";
58
- };
56
+ Console.debug("Gitpod command line tool not found")
57
+ return "http://localhost"
58
+ }
59
59
 
60
60
  const getCodespacesNamespace = () => {
61
61
  // https://orange-rotary-phone-wxpg49q5gcg4rp-3000.app.github.dev
62
62
  const codespace_name = shell
63
63
  .exec("echo $CODESPACE_NAME", { silent: true })
64
- .stdout.replace(/(\r\n|\n|\r)/gm, "");
64
+ .stdout.replace(/(\r\n|\n|\r)/gm, "")
65
65
 
66
66
  if (
67
67
  !codespace_name ||
68
68
  codespace_name === "" ||
69
69
  codespace_name === undefined
70
70
  ) {
71
- return null;
71
+ return null
72
72
  }
73
73
 
74
- return codespace_name;
75
- };
74
+ return codespace_name
75
+ }
76
76
 
77
77
  export default async ({
78
78
  grading,
@@ -80,46 +80,46 @@ export default async ({
80
80
  disableGrading,
81
81
  version,
82
82
  }: IConfigManagerAttributes): Promise<IConfigManager> => {
83
- const confPath = getConfigPath();
84
- Console.debug("This is the config path: ", confPath);
83
+ const confPath = getConfigPath()
84
+ Console.debug("This is the config path: ", confPath)
85
85
 
86
- let configObj: IConfigObj = {};
86
+ let configObj: IConfigObj = {}
87
87
 
88
88
  if (confPath) {
89
- const bcContent = fs.readFileSync(confPath.config);
90
- let hiddenBcContent = {};
89
+ const bcContent = fs.readFileSync(confPath.config)
90
+ let hiddenBcContent = {}
91
91
  if (fs.existsSync(confPath.base + "/config.json")) {
92
- hiddenBcContent = fs.readFileSync(confPath.base + "/config.json");
93
- hiddenBcContent = JSON.parse(hiddenBcContent as string);
92
+ hiddenBcContent = fs.readFileSync(confPath.base + "/config.json")
93
+ hiddenBcContent = JSON.parse(hiddenBcContent as string)
94
94
  if (!hiddenBcContent)
95
95
  throw new Error(
96
96
  `Invalid ${confPath.base}/config.json syntax: Unable to parse.`
97
- );
97
+ )
98
98
  }
99
99
 
100
- const jsonConfig = JSON.parse(`${bcContent}`);
100
+ const jsonConfig = JSON.parse(`${bcContent}`)
101
101
  if (!jsonConfig)
102
- throw new Error(`Invalid ${confPath.config} syntax: Unable to parse.`);
102
+ throw new Error(`Invalid ${confPath.config} syntax: Unable to parse.`)
103
103
 
104
- let session: number;
104
+ let session: number
105
105
 
106
106
  // add using id to the installation
107
107
  if (!jsonConfig.session) {
108
- session = Math.floor(Math.random() * 10_000_000_000_000_000_000);
108
+ session = Math.floor(Math.random() * 10_000_000_000_000_000_000)
109
109
  } else {
110
- session = jsonConfig.session;
111
- delete jsonConfig.session;
110
+ session = jsonConfig.session
111
+ delete jsonConfig.session
112
112
  }
113
113
 
114
114
  configObj = deepMerge(hiddenBcContent, {
115
115
  config: jsonConfig,
116
116
  session: session,
117
- });
118
- Console.debug("Content from the configuration .json ", configObj);
117
+ })
118
+ Console.debug("Content from the configuration .json ", configObj)
119
119
  } else {
120
120
  throw ValidationError(
121
121
  "No learn.json file has been found, make sure you are in the folder"
122
- );
122
+ )
123
123
  }
124
124
 
125
125
  configObj = deepMerge(defaults || {}, configObj, {
@@ -127,10 +127,10 @@ export default async ({
127
127
  grading: grading || configObj.config?.grading,
128
128
  configPath: confPath.config,
129
129
  },
130
- });
130
+ })
131
131
 
132
132
  if (configObj.config) {
133
- configObj.config.outputPath = confPath.base + "/dist";
133
+ configObj.config.outputPath = confPath.base + "/dist"
134
134
  }
135
135
 
136
136
  Console.debug("This is your configuration object: ", {
@@ -138,50 +138,50 @@ export default async ({
138
138
  exercises: configObj.exercises ?
139
139
  configObj.exercises.map(e => e.slug) :
140
140
  [],
141
- });
141
+ })
142
142
 
143
143
  // auto detect agent (if possible)
144
- const codespaces_workspace = getCodespacesNamespace();
144
+ const codespaces_workspace = getCodespacesNamespace()
145
145
  if (shell.which("gp") && configObj && configObj.config) {
146
- configObj.config.editor.agent = "vscode";
147
- configObj.address = getGitpodAddress();
146
+ configObj.config.editor.agent = "vscode"
147
+ configObj.address = getGitpodAddress()
148
148
  configObj.config.publicUrl = `https://${
149
149
  configObj.config.port
150
- }-${configObj.address?.slice(8)}`;
150
+ }-${configObj.address?.slice(8)}`
151
151
  } else if (configObj.config && codespaces_workspace) {
152
- configObj.config.editor.agent = "vscode";
153
- configObj.address = `https://${codespaces_workspace}.github.dev`;
154
- configObj.config.publicUrl = `https://${codespaces_workspace}-${configObj.config.port}.app.github.dev`;
152
+ configObj.config.editor.agent = "vscode"
153
+ configObj.address = `https://${codespaces_workspace}.github.dev`
154
+ configObj.config.publicUrl = `https://${codespaces_workspace}-${configObj.config.port}.app.github.dev`
155
155
  } else if (configObj.config && !configObj.config.editor.agent) {
156
- configObj.config.editor.agent = "localhost";
156
+ configObj.config.editor.agent = "localhost"
157
157
  }
158
158
 
159
159
  if (configObj.config && !configObj.config.publicUrl)
160
- configObj.config.publicUrl = `${configObj.address}:${configObj.config.port}`;
160
+ configObj.config.publicUrl = `${configObj.address}:${configObj.config.port}`
161
161
 
162
162
  // Assign default editor mode if not set already
163
163
  if (configObj.config && !mode) {
164
- configObj.config.editor.mode = mode as TMode;
164
+ configObj.config.editor.mode = mode as TMode
165
165
  }
166
166
 
167
167
  if (configObj.config && !configObj.config.editor.mode)
168
168
  configObj.config.editor.mode =
169
- configObj.config.editor.agent === "localhost" ? "standalone" : "preview";
169
+ configObj.config.editor.agent === "localhost" ? "standalone" : "preview"
170
170
 
171
171
  if (version && configObj.config)
172
- configObj.config.editor.version = version;
172
+ configObj.config.editor.version = version
173
173
  else if (configObj.config && configObj.config.editor.version === null) {
174
- Console.debug("Config version not found, downloading default.");
174
+ Console.debug("Config version not found, downloading default.")
175
175
  const resp = await fetch(
176
176
  "https://raw.githubusercontent.com/learnpack/coding-ide/learnpack/package.json"
177
- );
178
- const packageJSON = await resp.json();
179
- configObj.config.editor.version = packageJSON.version || "1.0.73";
177
+ )
178
+ const packageJSON = await resp.json()
179
+ configObj.config.editor.version = packageJSON.version || "1.0.73"
180
180
  }
181
181
 
182
182
  if (configObj.config) {
183
- configObj.config.dirPath = "./" + confPath.base;
184
- configObj.config.exercisesPath = getExercisesPath(confPath.base) || "./";
183
+ configObj.config.dirPath = "./" + confPath.base
184
+ configObj.config.exercisesPath = getExercisesPath(confPath.base) || "./"
185
185
  }
186
186
 
187
187
  return {
@@ -192,125 +192,125 @@ configObj.config.editor.version = version;
192
192
  const alias = (_l: string) => {
193
193
  const map: any = {
194
194
  python3: "python",
195
- };
195
+ }
196
196
  if (map[_l])
197
- return map[_l];
198
- return _l;
199
- };
197
+ return map[_l]
198
+ return _l
199
+ }
200
200
 
201
201
  // decode aliases
202
- language = alias(language);
202
+ language = alias(language)
203
203
 
204
204
  if (this.validLanguages[language])
205
- return true;
205
+ return true
206
206
 
207
- Console.debug(`Validating engine for ${language} compilation`);
208
- let result = shell.exec("learnpack plugins", { silent: true });
207
+ Console.debug(`Validating engine for ${language} compilation`)
208
+ let result = shell.exec("learnpack plugins", { silent: true })
209
209
 
210
210
  if (
211
211
  result.code === 0 &&
212
212
  result.stdout.includes(`learnpack-${language}`)
213
213
  ) {
214
- this.validLanguages[language] = true;
215
- return true;
214
+ this.validLanguages[language] = true
215
+ return true
216
216
  }
217
217
 
218
- Console.info(`Language engine for ${language} not found, installing...`);
218
+ Console.info(`Language engine for ${language} not found, installing...`)
219
219
  result = shell.exec(`learnpack plugins:install learnpack-${language}`, {
220
220
  silent: true,
221
- });
221
+ })
222
222
  if (result.code === 0) {
223
223
  socket.log(
224
224
  "compiling",
225
225
  "Installing the python compiler, you will have to reset the exercises after installation by writing on your terminal: $ learnpack run"
226
- );
226
+ )
227
227
  Console.info(
228
228
  `Successfully installed the ${language} exercise engine, \n please start learnpack again by running the following command: \n ${chalk.white(
229
229
  "$ learnpack start"
230
230
  )}\n\n `
231
- );
232
- server.terminate();
233
- return false;
231
+ )
232
+ server.terminate()
233
+ return false
234
234
  }
235
235
 
236
- this.validLanguages[language] = false;
237
- socket.error(`Error installing ${language} exercise engine`);
238
- Console.error(`Error installing ${language} exercise engine`);
239
- Console.log(result.stdout);
240
- throw InternalError(`Error installing ${language} exercise engine`);
236
+ this.validLanguages[language] = false
237
+ socket.error(`Error installing ${language} exercise engine`)
238
+ Console.error(`Error installing ${language} exercise engine`)
239
+ Console.log(result.stdout)
240
+ throw InternalError(`Error installing ${language} exercise engine`)
241
241
  },
242
242
  clean: () => {
243
243
  if (configObj.config) {
244
244
  if (configObj.config.outputPath) {
245
- rmSync(configObj.config.outputPath);
245
+ rmSync(configObj.config.outputPath)
246
246
  }
247
247
 
248
- rmSync(configObj.config.dirPath + "/_app");
249
- rmSync(configObj.config.dirPath + "/reports");
250
- rmSync(configObj.config.dirPath + "/.session");
251
- rmSync(configObj.config.dirPath + "/resets");
248
+ rmSync(configObj.config.dirPath + "/_app")
249
+ rmSync(configObj.config.dirPath + "/reports")
250
+ rmSync(configObj.config.dirPath + "/.session")
251
+ rmSync(configObj.config.dirPath + "/resets")
252
252
 
253
253
  // clean tag gz
254
254
  if (fs.existsSync(configObj.config.dirPath + "/app.tar.gz"))
255
- fs.unlinkSync(configObj.config.dirPath + "/app.tar.gz");
255
+ fs.unlinkSync(configObj.config.dirPath + "/app.tar.gz")
256
256
 
257
257
  if (fs.existsSync(configObj.config.dirPath + "/config.json"))
258
- fs.unlinkSync(configObj.config.dirPath + "/config.json");
258
+ fs.unlinkSync(configObj.config.dirPath + "/config.json")
259
259
 
260
260
  if (fs.existsSync(configObj.config.dirPath + "/vscode_queue.json"))
261
- fs.unlinkSync(configObj.config.dirPath + "/vscode_queue.json");
261
+ fs.unlinkSync(configObj.config.dirPath + "/vscode_queue.json")
262
262
  }
263
263
  },
264
264
  getExercise: slug => {
265
- Console.debug("ExercisePath Slug", slug);
265
+ Console.debug("ExercisePath Slug", slug)
266
266
  const exercise = (configObj.exercises || []).find(
267
267
  ex => ex.slug === slug
268
- );
268
+ )
269
269
  if (!exercise)
270
- throw ValidationError(`Exercise ${slug} not found`);
270
+ throw ValidationError(`Exercise ${slug} not found`)
271
271
 
272
- return exercise;
272
+ return exercise
273
273
  },
274
274
  getAllExercises: () => {
275
- return configObj.exercises;
275
+ return configObj.exercises
276
276
  },
277
277
  startExercise: function (slug: string) {
278
- const exercise = this.getExercise(slug);
278
+ const exercise = this.getExercise(slug)
279
279
 
280
280
  // set config.json with current exercise
281
- configObj.currentExercise = exercise.slug;
281
+ configObj.currentExercise = exercise.slug
282
282
 
283
- this.save();
283
+ this.save()
284
284
 
285
285
  // eslint-disable-next-line
286
286
  exercise.files.forEach((f: IFile) => {
287
287
  if (configObj.config) {
288
- const _path = configObj.config.outputPath + "/" + f.name;
288
+ const _path = configObj.config.outputPath + "/" + f.name
289
289
  if (f.hidden === false && fs.existsSync(_path))
290
- fs.unlinkSync(_path);
290
+ fs.unlinkSync(_path)
291
291
  }
292
- });
292
+ })
293
293
 
294
- return exercise;
294
+ return exercise
295
295
  },
296
296
  noCurrentExercise: function () {
297
- configObj.currentExercise = null;
298
- this.save();
297
+ configObj.currentExercise = null
298
+ this.save()
299
299
  },
300
300
  reset: slug => {
301
301
  if (
302
302
  configObj.config &&
303
303
  !fs.existsSync(`${configObj.config.dirPath}/resets/` + slug)
304
304
  )
305
- throw ValidationError("Could not find the original files for " + slug);
305
+ throw ValidationError("Could not find the original files for " + slug)
306
306
 
307
307
  const exercise = (configObj.exercises || []).find(
308
308
  ex => ex.slug === slug
309
- );
309
+ )
310
310
  if (!exercise)
311
311
  throw ValidationError(
312
312
  `Exercise ${slug} not found on the configuration`
313
- );
313
+ )
314
314
 
315
315
  if (configObj.config) {
316
316
  for (const fileName of fs.readdirSync(
@@ -318,110 +318,110 @@ fs.unlinkSync(_path);
318
318
  )) {
319
319
  const content = fs.readFileSync(
320
320
  `${configObj.config?.dirPath}/resets/${slug}/${fileName}`
321
- );
322
- fs.writeFileSync(`${exercise.path}/${fileName}`, content);
321
+ )
322
+ fs.writeFileSync(`${exercise.path}/${fileName}`, content)
323
323
  }
324
324
  }
325
325
  },
326
326
  buildIndex: function () {
327
- Console.info("Building the exercise index...");
327
+ Console.info("Building the exercise index...")
328
328
 
329
329
  const isDirectory = (source: string) => {
330
- const name = path.basename(source);
330
+ const name = path.basename(source)
331
331
  if (name === path.basename(configObj?.config?.dirPath || ""))
332
- return false;
332
+ return false
333
333
  // ignore folders that start with a dot
334
334
  if (name.charAt(0) === "." || name.charAt(0) === "_")
335
- return false;
335
+ return false
336
336
 
337
- return fs.lstatSync(source).isDirectory();
338
- };
337
+ return fs.lstatSync(source).isDirectory()
338
+ }
339
339
 
340
340
  const getDirectories = (source: string) =>
341
341
  fs
342
342
  .readdirSync(source)
343
343
  .map(name => path.join(source, name))
344
- .filter(isDirectory);
344
+ .filter(isDirectory)
345
345
  // add the .learn folder
346
346
  if (!fs.existsSync(confPath.base))
347
- fs.mkdirSync(confPath.base);
347
+ fs.mkdirSync(confPath.base)
348
348
  // add the outout folder where webpack will publish the the html/css/js files
349
349
  if (
350
350
  configObj.config &&
351
351
  configObj.config.outputPath &&
352
352
  !fs.existsSync(configObj.config.outputPath)
353
353
  )
354
- fs.mkdirSync(configObj.config.outputPath);
354
+ fs.mkdirSync(configObj.config.outputPath)
355
355
 
356
356
  // TODO: we could use npm library front-mater to read the title of the exercises from the README.md
357
357
  const grupedByDirectory = getDirectories(
358
358
  configObj?.config?.exercisesPath || ""
359
- );
359
+ )
360
360
  configObj.exercises =
361
361
  grupedByDirectory.length > 0 ?
362
362
  grupedByDirectory.map((path, position) =>
363
363
  exercise(path, position, configObj)
364
364
  ) :
365
- [exercise(configObj?.config?.exercisesPath || "", 0, configObj)];
366
- this.save();
365
+ [exercise(configObj?.config?.exercisesPath || "", 0, configObj)]
366
+ this.save()
367
367
  },
368
368
  watchIndex: function (onChange: () => void) {
369
369
  if (configObj.config && !configObj.config.exercisesPath)
370
370
  throw ValidationError(
371
371
  "No exercises directory to watch: " + configObj.config.exercisesPath
372
- );
372
+ )
373
373
 
374
- this.buildIndex();
374
+ this.buildIndex()
375
375
  watch(configObj?.config?.exercisesPath || "", onChange)
376
376
  .then((/* eventname, filename */) => {
377
- Console.debug("Changes detected on your exercises");
378
- this.buildIndex();
377
+ Console.debug("Changes detected on your exercises")
378
+ this.buildIndex()
379
379
  if (onChange)
380
- onChange();
380
+ onChange()
381
381
  })
382
382
  .catch(error => {
383
- throw error;
384
- });
383
+ throw error
384
+ })
385
385
  },
386
386
  save: () => {
387
- Console.debug("Saving configuration with: ", configObj);
387
+ Console.debug("Saving configuration with: ", configObj)
388
388
 
389
389
  // remove the duplicates form the actions array
390
390
  // configObj.config.actions = [...new Set(configObj.config.actions)];
391
391
  if (configObj.config) {
392
392
  configObj.config.translations = [
393
393
  ...new Set(configObj.config.translations),
394
- ];
394
+ ]
395
395
  fs.writeFileSync(
396
396
  configObj.config.dirPath + "/config.json",
397
397
  JSON.stringify(configObj, null, 4)
398
- );
398
+ )
399
399
  }
400
400
  },
401
- } as IConfigManager;
402
- };
401
+ } as IConfigManager
402
+ }
403
403
 
404
404
  function deepMerge(...sources: any): any {
405
- let acc: any = {};
405
+ let acc: any = {}
406
406
  for (const source of sources) {
407
407
  if (Array.isArray(source)) {
408
408
  if (!Array.isArray(acc)) {
409
- acc = [];
409
+ acc = []
410
410
  }
411
411
 
412
- acc = [...source];
412
+ acc = [...source]
413
413
  } else if (source instanceof Object) {
414
414
  // eslint-disable-next-line
415
415
  for (let [key, value] of Object.entries(source)) {
416
416
  if (value instanceof Object && key in acc) {
417
- value = deepMerge(acc[key], value);
417
+ value = deepMerge(acc[key], value)
418
418
  }
419
419
 
420
420
  if (value !== undefined)
421
- acc = { ...acc, [key]: value };
421
+ acc = { ...acc, [key]: value }
422
422
  }
423
423
  }
424
424
  }
425
425
 
426
- return acc;
426
+ return acc
427
427
  }