@learnpack/learnpack 2.1.26 → 2.1.28

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. package/README.md +10 -10
  2. package/lib/commands/start.js +15 -4
  3. package/lib/managers/file.d.ts +1 -0
  4. package/lib/managers/file.js +8 -1
  5. package/lib/managers/server/routes.js +48 -14
  6. package/lib/managers/session.d.ts +1 -1
  7. package/lib/managers/session.js +39 -12
  8. package/lib/managers/socket.d.ts +1 -1
  9. package/lib/managers/socket.js +57 -43
  10. package/lib/models/action.d.ts +1 -1
  11. package/lib/models/config.d.ts +1 -1
  12. package/lib/models/exercise-obj.d.ts +3 -0
  13. package/lib/models/session.d.ts +4 -1
  14. package/lib/models/socket.d.ts +7 -6
  15. package/lib/models/status.d.ts +1 -1
  16. package/lib/utils/api.d.ts +2 -0
  17. package/lib/utils/api.js +51 -6
  18. package/oclif.manifest.json +1 -1
  19. package/package.json +3 -1
  20. package/src/commands/audit.ts +113 -113
  21. package/src/commands/clean.ts +10 -10
  22. package/src/commands/download.ts +18 -18
  23. package/src/commands/init.ts +39 -39
  24. package/src/commands/login.ts +13 -13
  25. package/src/commands/logout.ts +9 -9
  26. package/src/commands/publish.ts +25 -25
  27. package/src/commands/start.ts +101 -75
  28. package/src/commands/test.ts +34 -34
  29. package/src/managers/config/allowed_files.ts +2 -2
  30. package/src/managers/config/defaults.ts +2 -2
  31. package/src/managers/config/exercise.ts +79 -79
  32. package/src/managers/config/index.ts +145 -145
  33. package/src/managers/file.ts +74 -65
  34. package/src/managers/server/index.ts +32 -31
  35. package/src/managers/server/routes.ts +139 -90
  36. package/src/managers/session.ts +53 -24
  37. package/src/managers/socket.ts +92 -79
  38. package/src/models/action.ts +8 -1
  39. package/src/models/config-manager.ts +2 -2
  40. package/src/models/config.ts +7 -2
  41. package/src/models/exercise-obj.ts +6 -3
  42. package/src/models/plugin-config.ts +2 -2
  43. package/src/models/session.ts +5 -2
  44. package/src/models/socket.ts +12 -6
  45. package/src/models/status.ts +15 -14
  46. package/src/plugin/command/compile.ts +10 -10
  47. package/src/plugin/command/test.ts +14 -14
  48. package/src/plugin/index.ts +5 -5
  49. package/src/plugin/plugin.ts +26 -26
  50. package/src/plugin/utils.ts +23 -23
  51. package/src/utils/BaseCommand.ts +16 -16
  52. package/src/utils/api.ts +143 -91
  53. package/src/utils/audit.ts +93 -96
  54. package/src/utils/exercisesQueue.ts +15 -15
  55. package/src/utils/fileQueue.ts +85 -85
  56. package/src/utils/watcher.ts +14 -14
@@ -1,34 +1,34 @@
1
- import * as fs from "fs";
2
- import { validateExerciseDirectoryName } from "../managers/config/exercise";
3
- import Console from "../utils/console";
4
- import Audit from "../utils/audit";
5
- import SessionCommand from "../utils/SessionCommand";
6
- import * as path from "path";
7
- import { IFile } from "../models/file";
8
- import { IExercise } from "../models/exercise-obj";
9
- import { IFrontmatter } from "../models/front-matter";
10
- import { IAuditErrors } from "../models/audit";
11
- import { ICounter } from "../models/counter";
12
- import { IFindings } from "../models/findings";
1
+ import * as fs from "fs"
2
+ import { validateExerciseDirectoryName } from "../managers/config/exercise"
3
+ import Console from "../utils/console"
4
+ import Audit from "../utils/audit"
5
+ import SessionCommand from "../utils/SessionCommand"
6
+ import * as path from "path"
7
+ import { IFile } from "../models/file"
8
+ import { IExercise } from "../models/exercise-obj"
9
+ import { IFrontmatter } from "../models/front-matter"
10
+ import { IAuditErrors } from "../models/audit"
11
+ import { ICounter } from "../models/counter"
12
+ import { IFindings } from "../models/findings"
13
13
 
14
14
  // eslint-disable-next-line
15
15
  const fetch = require("node-fetch");
16
16
 
17
17
  class AuditCommand extends SessionCommand {
18
18
  async init() {
19
- const { flags } = this.parse(AuditCommand);
20
- await this.initSession(flags);
19
+ const { flags } = this.parse(AuditCommand)
20
+ await this.initSession(flags)
21
21
  }
22
22
 
23
23
  async run() {
24
- Console.log("Running command audit...");
24
+ Console.log("Running command audit...")
25
25
 
26
26
  // Get configuration object.
27
- let config = this.configManager?.get();
27
+ let config = this.configManager?.get()
28
28
 
29
29
  if (config) {
30
- const errors: IAuditErrors[] = [];
31
- const warnings: IAuditErrors[] = [];
30
+ const errors: IAuditErrors[] = []
31
+ const warnings: IAuditErrors[] = []
32
32
  if (config?.config?.projectType === "tutorial") {
33
33
  const counter: ICounter = {
34
34
  images: {
@@ -41,34 +41,34 @@ class AuditCommand extends SessionCommand {
41
41
  },
42
42
  exercises: 0,
43
43
  readmeFiles: 0,
44
- };
44
+ }
45
45
 
46
46
  // Checks if learnpack clean has been run
47
- Audit.checkLearnpackClean(config, errors);
47
+ Audit.checkLearnpackClean(config, errors)
48
48
 
49
49
  // Build exercises if they are not built yet.
50
- this.configManager?.buildIndex();
51
- config = this.configManager?.get();
50
+ this.configManager?.buildIndex()
51
+ config = this.configManager?.get()
52
52
 
53
53
  // Check if the exercises folder has some files within any ./exercise
54
- const exercisesPath: string = config!.config!.exercisesPath;
54
+ const exercisesPath: string = config!.config!.exercisesPath
55
55
 
56
56
  fs.readdir(exercisesPath, (err, files) => {
57
57
  if (err) {
58
- return console.log("Unable to scan directory: " + err);
58
+ return console.log("Unable to scan directory: " + err)
59
59
  }
60
60
 
61
61
  // listing all files using forEach
62
62
  for (const file of files) {
63
63
  // Do whatever you want to do with the file
64
- const filePath: string = path.join(exercisesPath, file);
64
+ const filePath: string = path.join(exercisesPath, file)
65
65
  if (fs.statSync(filePath).isFile())
66
66
  warnings.push({
67
67
  exercise: file!,
68
68
  msg: "This file is not inside any exercise folder.",
69
- });
69
+ })
70
70
  }
71
- });
71
+ })
72
72
 
73
73
  // This function is being created because the find method doesn't work with promises.
74
74
  const find = async (file: IFile, lang: string, exercise: IExercise) => {
@@ -81,96 +81,96 @@ class AuditCommand extends SessionCommand {
81
81
  errors,
82
82
  warnings,
83
83
  counter
84
- );
85
- return true;
84
+ )
85
+ return true
86
86
  }
87
87
 
88
- return false;
89
- };
88
+ return false
89
+ }
90
90
 
91
- Console.debug("config", config);
91
+ Console.debug("config", config)
92
92
 
93
- Console.info(" Checking if the config file is fine...");
93
+ Console.info(" Checking if the config file is fine...")
94
94
  // These two lines check if the 'slug' property is inside the configuration object.
95
95
  Console.debug(
96
96
  "Checking if the slug property is inside the configuration object..."
97
- );
97
+ )
98
98
  // check if the slug property is in the configuration object
99
99
  if (!config!.config?.slug)
100
100
  errors.push({
101
101
  exercise: undefined,
102
102
  msg: "The slug property is not in the configuration object",
103
- });
103
+ })
104
104
  // check if the duration property is in the configuration object
105
105
  if (!config!.config?.duration)
106
106
  warnings.push({
107
107
  exercise: undefined,
108
108
  msg: "The duration property is not in the configuration object",
109
- });
109
+ })
110
110
  // check if the difficulty property is in the configuration object
111
111
  if (!config!.config?.difficulty)
112
112
  warnings.push({
113
113
  exercise: undefined,
114
114
  msg: "The difficulty property is not in the configuration object",
115
- });
115
+ })
116
116
  // check if the bugs_link property is in the configuration object
117
117
  if (!config!.config?.bugsLink)
118
118
  errors.push({
119
119
  exercise: undefined,
120
120
  msg: "The bugsLink property is not in the configuration object",
121
- });
121
+ })
122
122
  // check if the video_solutions property is in the configuration object
123
123
  if (config!.config?.videoSolutions === undefined)
124
124
  warnings.push({
125
125
  exercise: undefined,
126
126
  msg: "The videoSolutions property is not in the configuration object",
127
- });
127
+ })
128
128
 
129
129
  // These two lines check if the 'repository' property is inside the configuration object.
130
130
  Console.debug(
131
131
  "Checking if the repository property is inside the configuration object..."
132
- );
132
+ )
133
133
  if (!config!.config?.repository)
134
134
  errors.push({
135
135
  exercise: undefined,
136
136
  msg: "The repository property is not in the configuration object",
137
- });
137
+ })
138
138
  else
139
- Audit.isUrl(config!.config?.repository, errors, counter);
139
+ Audit.isUrl(config!.config?.repository, errors, counter)
140
140
 
141
141
  // These two lines check if the 'description' property is inside the configuration object.
142
142
  Console.debug(
143
143
  "Checking if the description property is inside the configuration object..."
144
- );
144
+ )
145
145
  if (!config!.config?.description)
146
146
  errors.push({
147
147
  exercise: undefined,
148
148
  msg: "The description property is not in the configuration object",
149
- });
149
+ })
150
150
 
151
151
  if (errors.length === 0)
152
- Console.log("The config file is ok");
152
+ Console.log("The config file is ok")
153
153
 
154
154
  // Validates if images and links are working at every README file.
155
- const exercises = config!.exercises;
156
- const readmeFiles = [];
155
+ const exercises = config!.exercises
156
+ const readmeFiles = []
157
157
 
158
158
  if (exercises && exercises.length > 0) {
159
- Console.info(" Checking if the images are working...");
159
+ Console.info(" Checking if the images are working...")
160
160
  for (const index in exercises) {
161
161
  if (Object.prototype.hasOwnProperty.call(exercises, index)) {
162
- const exercise = exercises[index];
162
+ const exercise = exercises[index]
163
163
  if (!validateExerciseDirectoryName(exercise.title))
164
164
  errors.push({
165
165
  exercise: exercise.title,
166
166
  msg: `The exercise ${exercise.title} has an invalid name.`,
167
- });
168
- let readmeFilesCount = { exercise: exercise.title, count: 0 };
167
+ })
168
+ let readmeFilesCount = { exercise: exercise.title, count: 0 }
169
169
  if (Object.keys(exercise.translations!).length === 0)
170
170
  errors.push({
171
171
  exercise: exercise.title,
172
172
  msg: `The exercise ${exercise.title} doesn't have a README.md file.`,
173
- });
173
+ })
174
174
 
175
175
  if (
176
176
  exercise.language === "python3" ||
@@ -181,13 +181,13 @@ Console.log("The config file is ok");
181
181
  f.path.includes("test.py") ||
182
182
  f.path.includes("tests.py")
183
183
  ) {
184
- const content = fs.readFileSync(f.path).toString();
185
- const isEmpty = Audit.checkForEmptySpaces(content);
184
+ const content = fs.readFileSync(f.path).toString()
185
+ const isEmpty = Audit.checkForEmptySpaces(content)
186
186
  if (isEmpty || !content)
187
187
  errors.push({
188
188
  exercise: exercise.title,
189
189
  msg: `This file (${f.name}) doesn't have any content inside.`,
190
- });
190
+ })
191
191
  }
192
192
  }
193
193
  } else {
@@ -196,13 +196,13 @@ Console.log("The config file is ok");
196
196
  f.path.includes("test.js") ||
197
197
  f.path.includes("tests.js")
198
198
  ) {
199
- const content = fs.readFileSync(f.path).toString();
200
- const isEmpty: boolean = Audit.checkForEmptySpaces(content);
199
+ const content = fs.readFileSync(f.path).toString()
200
+ const isEmpty: boolean = Audit.checkForEmptySpaces(content)
201
201
  if (isEmpty || !content)
202
202
  errors.push({
203
203
  exercise: exercise.title,
204
204
  msg: `This file (${f.name}) doesn't have any content inside.`,
205
- });
205
+ })
206
206
  }
207
207
  }
208
208
  }
@@ -214,15 +214,15 @@ Console.log("The config file is ok");
214
214
  lang
215
215
  )
216
216
  ) {
217
- const files: any[] = [];
218
- const findResultPromises = [];
217
+ const files: any[] = []
218
+ const findResultPromises = []
219
219
  for (const file of exercise.files) {
220
220
  const found = find(
221
221
  file,
222
222
  exercise.translations[lang],
223
223
  exercise
224
- );
225
- findResultPromises.push(found);
224
+ )
225
+ findResultPromises.push(found)
226
226
  }
227
227
  // eslint-disable-next-line
228
228
  let findResults = await Promise.all(findResultPromises);
@@ -231,8 +231,8 @@ Console.log("The config file is ok");
231
231
  readmeFilesCount = {
232
232
  ...readmeFilesCount,
233
233
  count: readmeFilesCount.count + 1,
234
- };
235
- files.push(found);
234
+ }
235
+ files.push(found)
236
236
  }
237
237
  }
238
238
 
@@ -240,50 +240,50 @@ Console.log("The config file is ok");
240
240
  errors.push({
241
241
  exercise: exercise.title,
242
242
  msg: "This exercise doesn't have a README.md file.",
243
- });
243
+ })
244
244
  }
245
245
  }
246
246
 
247
- readmeFiles.push(readmeFilesCount);
247
+ readmeFiles.push(readmeFilesCount)
248
248
  }
249
249
  }
250
250
  } else
251
251
  errors.push({
252
252
  exercise: undefined,
253
253
  msg: "The exercises array is empty.",
254
- });
254
+ })
255
255
 
256
256
  Console.log(
257
257
  `${counter.images.total - counter.images.error} images ok from ${
258
258
  counter.images.total
259
259
  }`
260
- );
260
+ )
261
261
 
262
262
  Console.info(
263
263
  " Checking if important files are missing... (README's, translations, gitignore...)"
264
- );
264
+ )
265
265
  // Check if all the exercises has the same ammount of README's, this way we can check if they have the same ammount of translations.
266
- const files: string[] = [];
267
- let count = 0;
266
+ const files: string[] = []
267
+ let count = 0
268
268
  for (const item of readmeFiles) {
269
269
  if (count < item.count)
270
- count = item.count;
270
+ count = item.count
271
271
  }
272
272
 
273
273
  for (const item of readmeFiles) {
274
274
  if (item.count !== count)
275
- files.push(` ${item.exercise}`);
275
+ files.push(` ${item.exercise}`)
276
276
  }
277
277
 
278
278
  if (files.length > 0) {
279
- const filesString: string = files.join(",");
279
+ const filesString: string = files.join(",")
280
280
  warnings.push({
281
281
  exercise: undefined,
282
282
  msg:
283
283
  files.length === 1 ?
284
284
  `This exercise is missing translations:${filesString}` :
285
285
  `These exercises are missing translations:${filesString}`,
286
- });
286
+ })
287
287
  }
288
288
 
289
289
  // Checks if the .gitignore file exists.
@@ -291,11 +291,11 @@ files.push(` ${item.exercise}`);
291
291
  warnings.push({
292
292
  exercise: undefined,
293
293
  msg: ".gitignore file doesn't exist",
294
- });
294
+ })
295
295
 
296
- counter.exercises = exercises!.length;
296
+ counter.exercises = exercises!.length
297
297
  for (const readme of readmeFiles) {
298
- counter.readmeFiles += readme.count;
298
+ counter.readmeFiles += readme.count
299
299
  }
300
300
  } else {
301
301
  // This is the audit code for Projects
@@ -303,68 +303,68 @@ files.push(` ${item.exercise}`);
303
303
  // Getting the learn.json schema
304
304
  const schemaResponse = await fetch(
305
305
  "https://raw.githubusercontent.com/tommygonzaleza/project-template/main/.github/learn-schema.json"
306
- );
307
- const schema = await schemaResponse.json();
306
+ )
307
+ const schema = await schemaResponse.json()
308
308
 
309
309
  // Checking the "learn.json" file:
310
310
  const learnjson = JSON.parse(
311
311
  fs.readFileSync("./learn.json").toString()
312
- );
312
+ )
313
313
 
314
314
  if (!learnjson) {
315
315
  Console.error(
316
316
  "There is no learn.json file located in the root of the project."
317
- );
318
- process.exit(1);
317
+ )
318
+ process.exit(1)
319
319
  }
320
320
 
321
321
  // Checking the README.md files and possible translations.
322
- let readmeFiles: any[] = [];
323
- const translations: string[] = [];
324
- const translationRegex = /README\.([a-z]{2,3})\.md/;
322
+ let readmeFiles: any[] = []
323
+ const translations: string[] = []
324
+ const translationRegex = /README\.([a-z]{2,3})\.md/
325
325
 
326
326
  try {
327
- const data = await fs.promises.readdir("./");
328
- readmeFiles = data.filter(file => file.includes("README"));
327
+ const data = await fs.promises.readdir("./")
328
+ readmeFiles = data.filter(file => file.includes("README"))
329
329
  if (readmeFiles.length === 0)
330
330
  errors.push({
331
331
  exercise: undefined!,
332
332
  msg: `There is no README file in the repository.`,
333
- });
333
+ })
334
334
  } catch (error) {
335
335
  if (error)
336
336
  Console.error(
337
337
  "There was an error getting the directory files",
338
338
  error
339
- );
339
+ )
340
340
  }
341
341
 
342
342
  for (const readmeFile of readmeFiles) {
343
343
  // Checking the language of each README file.
344
344
  if (readmeFile === "README.md")
345
- translations.push("us");
345
+ translations.push("us")
346
346
  else {
347
- const regexGroups = translationRegex.exec(readmeFile);
347
+ const regexGroups = translationRegex.exec(readmeFile)
348
348
  if (regexGroups)
349
- translations.push(regexGroups[1]);
349
+ translations.push(regexGroups[1])
350
350
  }
351
351
 
352
- const readme = fs.readFileSync(path.resolve(readmeFile)).toString();
352
+ const readme = fs.readFileSync(path.resolve(readmeFile)).toString()
353
353
 
354
- const isEmpty = Audit.checkForEmptySpaces(readme);
354
+ const isEmpty = Audit.checkForEmptySpaces(readme)
355
355
  if (isEmpty || !readme) {
356
356
  errors.push({
357
357
  exercise: undefined!,
358
358
  msg: `This file "${readmeFile}" doesn't have any content inside.`,
359
- });
360
- continue;
359
+ })
360
+ continue
361
361
  }
362
362
 
363
363
  if (readme.length < 800)
364
364
  errors.push({
365
365
  exercise: undefined,
366
366
  msg: `The "${readmeFile}" file should have at least 800 characters (It currently have: ${readme.length}).`,
367
- });
367
+ })
368
368
 
369
369
  // eslint-disable-next-line
370
370
  await Audit.checkUrl(
@@ -376,43 +376,43 @@ translations.push(regexGroups[1]);
376
376
  warnings,
377
377
  // eslint-disable-next-line
378
378
  undefined
379
- );
379
+ )
380
380
  }
381
381
 
382
382
  // Adding the translations to the learn.json
383
- learnjson.translations = translations;
383
+ learnjson.translations = translations
384
384
 
385
385
  // Checking if the preview image (from the learn.json) is OK.
386
386
  try {
387
- const res = await fetch(learnjson.preview, { method: "HEAD" });
387
+ const res = await fetch(learnjson.preview, { method: "HEAD" })
388
388
  if (res.status > 399 && res.status < 500) {
389
389
  errors.push({
390
390
  exercise: undefined,
391
391
  msg: `The link of the "preview" is broken: ${learnjson.preview}`,
392
- });
392
+ })
393
393
  }
394
394
  } catch {
395
395
  errors.push({
396
396
  exercise: undefined,
397
397
  msg: `The link of the "preview" is broken: ${learnjson.preview}`,
398
- });
398
+ })
399
399
  }
400
400
 
401
- const date = new Date();
402
- learnjson.validationAt = date.getTime();
401
+ const date = new Date()
402
+ learnjson.validationAt = date.getTime()
403
403
 
404
404
  if (errors.length > 0)
405
- learnjson.validationStatus = "error";
405
+ learnjson.validationStatus = "error"
406
406
  else if (warnings.length > 0)
407
- learnjson.validationStatus = "warning";
407
+ learnjson.validationStatus = "warning"
408
408
  else
409
- learnjson.validationStatus = "success";
409
+ learnjson.validationStatus = "success"
410
410
 
411
411
  // Writes the "learn.json" file with all the new properties
412
- await fs.promises.writeFile("./learn.json", JSON.stringify(learnjson));
412
+ await fs.promises.writeFile("./learn.json", JSON.stringify(learnjson))
413
413
  }
414
414
 
415
- await Audit.showWarnings(warnings);
415
+ await Audit.showWarnings(warnings)
416
416
  // eslint-disable-next-line
417
417
  await Audit.showErrors(errors, undefined);
418
418
  }
@@ -434,10 +434,10 @@ learnpack audit checks for the following information in a repository:
434
434
  10. The exercses have the same translations. (Warning)
435
435
  11. The .gitignore file exists. (Warning)
436
436
  12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)
437
- `;
437
+ `
438
438
 
439
439
  AuditCommand.flags = {
440
440
  // name: flags.string({char: 'n', description: 'name to print'}),
441
- };
441
+ }
442
442
 
443
- export default AuditCommand;
443
+ export default AuditCommand
@@ -1,29 +1,29 @@
1
1
  // import {flags} from '@oclif/command'
2
- import Console from "../utils/console";
3
- import SessionCommand from "../utils/SessionCommand";
2
+ import Console from "../utils/console"
3
+ import SessionCommand from "../utils/SessionCommand"
4
4
 
5
5
  class CleanCommand extends SessionCommand {
6
6
  static description = `Clean the configuration object
7
7
  ...
8
8
  Extra documentation goes here
9
- `;
9
+ `
10
10
 
11
11
  static flags: any = {
12
12
  // name: flags.string({char: 'n', description: 'name to print'}),
13
- };
13
+ }
14
14
 
15
15
  async init() {
16
- const { flags } = this.parse(CleanCommand);
17
- await this.initSession(flags);
16
+ const { flags } = this.parse(CleanCommand)
17
+ await this.initSession(flags)
18
18
  }
19
19
 
20
20
  async run() {
21
- const { flags } = this.parse(CleanCommand);
21
+ const { flags } = this.parse(CleanCommand)
22
22
 
23
- this.configManager?.clean();
23
+ this.configManager?.clean()
24
24
 
25
- Console.success("Package cleaned successfully, ready to publish");
25
+ Console.success("Package cleaned successfully, ready to publish")
26
26
  }
27
27
  }
28
28
 
29
- export default CleanCommand;
29
+ export default CleanCommand
@@ -1,20 +1,20 @@
1
- import { Command /* , flags */ } from "@oclif/command";
1
+ import { Command /* , flags */ } from "@oclif/command"
2
2
  // import fetch from 'node-fetch'
3
- import { clone } from "../managers/file";
4
- import Console from "../utils/console";
5
- import api from "../utils/api";
6
- import { askPackage } from "../ui/download";
3
+ import { clone } from "../managers/file"
4
+ import Console from "../utils/console"
5
+ import api from "../utils/api"
6
+ import { askPackage } from "../ui/download"
7
7
  // const BaseCommand = require('../utils/BaseCommand');
8
8
 
9
9
  class DownloadCommand extends Command {
10
10
  static description = `Describe the command here
11
11
  ...
12
12
  Extra documentation goes here
13
- `;
13
+ `
14
14
 
15
15
  static flags: any = {
16
16
  // name: flags.string({char: 'n', description: 'name to print'}),
17
- };
17
+ }
18
18
 
19
19
  static args = [
20
20
  {
@@ -24,39 +24,39 @@ Extra documentation goes here
24
24
  "The unique string that identifies this package on learnpack", // help description
25
25
  hidden: false, // hide this arg from help
26
26
  },
27
- ];
27
+ ]
28
28
  // async init() {
29
29
  // const {flags} = this.parse(DownloadCommand)
30
30
  // await this.initSession(flags)
31
31
  // }
32
32
 
33
33
  async run() {
34
- const { /* flags, */ args } = this.parse(DownloadCommand);
34
+ const { /* flags, */ args } = this.parse(DownloadCommand)
35
35
  // start watching for file changes
36
- let _package: string = args.package;
36
+ let _package: string = args.package
37
37
  if (!_package) {
38
- _package = (await askPackage()) as string;
38
+ _package = (await askPackage()) as string
39
39
  }
40
40
 
41
41
  if (!_package) {
42
- return null;
42
+ return null
43
43
  }
44
44
 
45
45
  try {
46
- const packageInfo = await api.getAllPackages({ slug: _package });
46
+ const packageInfo = await api.getAllPackages({ slug: _package })
47
47
  if (packageInfo.results.length === 0)
48
- Console.error(`Package ${_package} not found`);
48
+ Console.error(`Package ${_package} not found`)
49
49
  else
50
50
  clone(packageInfo.results[0].repository)
51
51
  .then(_result => {
52
- Console.success("Successfully downloaded");
52
+ Console.success("Successfully downloaded")
53
53
  Console.info(
54
54
  `You can now CD into the folder like this: $ cd ${_package}`
55
- );
55
+ )
56
56
  })
57
- .catch(error => Console.error(error.message || error));
57
+ .catch(error => Console.error(error.message || error))
58
58
  } catch {}
59
59
  }
60
60
  }
61
61
 
62
- export default DownloadCommand;
62
+ export default DownloadCommand