@learnpack/learnpack 2.0.13 → 2.0.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. package/README.md +10 -10
  2. package/lib/commands/audit.d.ts +6 -0
  3. package/lib/commands/audit.js +369 -0
  4. package/lib/commands/clean.d.ts +8 -0
  5. package/lib/commands/clean.js +25 -0
  6. package/lib/commands/download.d.ts +13 -0
  7. package/lib/commands/download.js +55 -0
  8. package/lib/commands/init.d.ts +9 -0
  9. package/lib/commands/init.js +117 -0
  10. package/lib/commands/login.d.ts +14 -0
  11. package/lib/commands/login.js +37 -0
  12. package/lib/commands/logout.d.ts +14 -0
  13. package/lib/commands/logout.js +37 -0
  14. package/lib/commands/publish.d.ts +14 -0
  15. package/lib/commands/publish.js +82 -0
  16. package/lib/commands/start.d.ts +7 -0
  17. package/lib/commands/start.js +165 -0
  18. package/lib/commands/test.d.ts +6 -0
  19. package/lib/commands/test.js +62 -0
  20. package/lib/index.d.ts +1 -0
  21. package/lib/managers/config/allowed_files.d.ts +5 -0
  22. package/lib/managers/config/allowed_files.js +30 -0
  23. package/lib/managers/config/defaults.d.ts +34 -0
  24. package/lib/managers/config/defaults.js +35 -0
  25. package/lib/managers/config/exercise.d.ts +36 -0
  26. package/lib/managers/config/exercise.js +230 -0
  27. package/lib/managers/config/index.d.ts +3 -0
  28. package/lib/managers/config/index.js +307 -0
  29. package/lib/managers/file.d.ts +13 -0
  30. package/lib/managers/file.js +134 -0
  31. package/lib/managers/gitpod.d.ts +3 -0
  32. package/lib/managers/gitpod.js +67 -0
  33. package/lib/managers/server/index.d.ts +6 -0
  34. package/lib/managers/server/index.js +51 -0
  35. package/lib/managers/server/routes.d.ts +4 -0
  36. package/lib/managers/server/routes.js +160 -0
  37. package/lib/managers/session.d.ts +3 -0
  38. package/lib/managers/session.js +104 -0
  39. package/lib/managers/socket.d.ts +3 -0
  40. package/lib/managers/socket.js +164 -0
  41. package/lib/managers/test.d.ts +0 -0
  42. package/lib/managers/test.js +84 -0
  43. package/lib/models/action.d.ts +2 -0
  44. package/lib/models/action.js +2 -0
  45. package/lib/models/audit-errors.d.ts +4 -0
  46. package/lib/models/audit-errors.js +2 -0
  47. package/lib/models/config-manager.d.ts +21 -0
  48. package/lib/models/config-manager.js +2 -0
  49. package/lib/models/config.d.ts +57 -0
  50. package/lib/models/config.js +2 -0
  51. package/lib/models/counter.d.ts +11 -0
  52. package/lib/models/counter.js +2 -0
  53. package/lib/models/errors.d.ts +15 -0
  54. package/lib/models/errors.js +2 -0
  55. package/lib/models/exercise-obj.d.ts +27 -0
  56. package/lib/models/exercise-obj.js +2 -0
  57. package/lib/models/file.d.ts +5 -0
  58. package/lib/models/file.js +2 -0
  59. package/lib/models/findings.d.ts +17 -0
  60. package/lib/models/findings.js +2 -0
  61. package/lib/models/flags.d.ts +10 -0
  62. package/lib/models/flags.js +2 -0
  63. package/lib/models/front-matter.d.ts +11 -0
  64. package/lib/models/front-matter.js +2 -0
  65. package/lib/models/gitpod-data.d.ts +16 -0
  66. package/lib/models/gitpod-data.js +2 -0
  67. package/lib/models/language.d.ts +4 -0
  68. package/lib/models/language.js +2 -0
  69. package/lib/models/package.d.ts +7 -0
  70. package/lib/models/package.js +2 -0
  71. package/lib/models/plugin-config.d.ts +16 -0
  72. package/lib/models/plugin-config.js +2 -0
  73. package/lib/models/session.d.ts +23 -0
  74. package/lib/models/session.js +2 -0
  75. package/lib/models/socket.d.ts +31 -0
  76. package/lib/models/socket.js +2 -0
  77. package/lib/models/status.d.ts +1 -0
  78. package/lib/models/status.js +2 -0
  79. package/lib/models/success-types.d.ts +1 -0
  80. package/lib/models/success-types.js +2 -0
  81. package/lib/plugin/command/compile.d.ts +6 -0
  82. package/lib/plugin/command/compile.js +18 -0
  83. package/lib/plugin/command/test.d.ts +6 -0
  84. package/lib/plugin/command/test.js +25 -0
  85. package/lib/plugin/index.d.ts +27 -0
  86. package/lib/plugin/index.js +7 -0
  87. package/lib/plugin/plugin.d.ts +8 -0
  88. package/lib/plugin/plugin.js +68 -0
  89. package/lib/plugin/utils.d.ts +16 -0
  90. package/lib/plugin/utils.js +58 -0
  91. package/lib/ui/download.d.ts +5 -0
  92. package/lib/ui/download.js +61 -0
  93. package/lib/utils/BaseCommand.d.ts +8 -0
  94. package/lib/utils/BaseCommand.js +41 -0
  95. package/lib/utils/SessionCommand.d.ts +10 -0
  96. package/lib/utils/SessionCommand.js +47 -0
  97. package/lib/utils/api.d.ts +12 -0
  98. package/lib/utils/api.js +173 -0
  99. package/lib/utils/audit.d.ts +13 -0
  100. package/lib/utils/audit.js +129 -0
  101. package/lib/utils/console.d.ts +12 -0
  102. package/lib/utils/console.js +19 -0
  103. package/lib/utils/errors.d.ts +17 -0
  104. package/lib/utils/errors.js +100 -0
  105. package/lib/utils/exercisesQueue.d.ts +9 -0
  106. package/lib/utils/exercisesQueue.js +38 -0
  107. package/lib/utils/fileQueue.d.ts +40 -0
  108. package/lib/utils/fileQueue.js +168 -0
  109. package/lib/utils/misc.d.ts +1 -0
  110. package/lib/utils/misc.js +23 -0
  111. package/lib/utils/validators.d.ts +5 -0
  112. package/lib/utils/validators.js +17 -0
  113. package/lib/utils/watcher.d.ts +2 -0
  114. package/lib/utils/watcher.js +24 -0
  115. package/oclif.manifest.json +1 -1
  116. package/package.json +4 -3
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/2.0.13 win32-x64 node-v16.14.0
24
+ @learnpack/learnpack/2.0.16 win32-x64 node-v16.14.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/v2.0.13/src\commands\audit.ts)_
77
+ _See code: [src\commands\audit.ts](https://github.com/learnpack/learnpack-cli/blob/v2.0.16/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/v2.0.13/src\commands\clean.ts)_
92
+ _See code: [src\commands\clean.ts](https://github.com/learnpack/learnpack-cli/blob/v2.0.16/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/v2.0.13/src\commands\download.ts)_
110
+ _See code: [src\commands\download.ts](https://github.com/learnpack/learnpack-cli/blob/v2.0.16/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/v2.0.13/src\commands\init.ts)_
141
+ _See code: [src\commands\init.ts](https://github.com/learnpack/learnpack-cli/blob/v2.0.16/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/v2.0.13/src\commands\login.ts)_
159
+ _See code: [src\commands\login.ts](https://github.com/learnpack/learnpack-cli/blob/v2.0.16/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/v2.0.13/src\commands\logout.ts)_
177
+ _See code: [src\commands\logout.ts](https://github.com/learnpack/learnpack-cli/blob/v2.0.16/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/v2.0.13/src\commands\publish.ts)_
312
+ _See code: [src\commands\publish.ts](https://github.com/learnpack/learnpack-cli/blob/v2.0.16/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/v2.0.13/src\commands\start.ts)_
333
+ _See code: [src\commands\start.ts](https://github.com/learnpack/learnpack-cli/blob/v2.0.16/src\commands\start.ts)_
334
334
 
335
335
  ## `learnpack test [EXERCISESLUG]`
336
336
 
@@ -344,5 +344,5 @@ 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/v2.0.13/src\commands\test.ts)_
347
+ _See code: [src\commands\test.ts](https://github.com/learnpack/learnpack-cli/blob/v2.0.16/src\commands\test.ts)_
348
348
  <!-- commandsstop -->
@@ -0,0 +1,6 @@
1
+ import SessionCommand from '../utils/SessionCommand';
2
+ declare class AuditCommand extends SessionCommand {
3
+ init(): Promise<void>;
4
+ run(): Promise<void>;
5
+ }
6
+ export default AuditCommand;
@@ -0,0 +1,369 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const fs = require("fs");
4
+ const exercise_1 = require("../managers/config/exercise");
5
+ const console_1 = require("../utils/console");
6
+ const audit_1 = require("../utils/audit");
7
+ const SessionCommand_1 = require("../utils/SessionCommand");
8
+ const path = require("path");
9
+ // eslint-disable-next-line
10
+ const fetch = require("node-fetch");
11
+ // eslint-disable-next-line
12
+ const fm = require("front-matter");
13
+ class AuditCommand extends SessionCommand_1.default {
14
+ async init() {
15
+ const { flags } = this.parse(AuditCommand);
16
+ await this.initSession(flags);
17
+ }
18
+ async run() {
19
+ var _a, _b, _c, _d, _e, _f, _g;
20
+ console_1.default.log('Running command audit...');
21
+ // Get configuration object.
22
+ let config = (_a = this.configManager) === null || _a === void 0 ? void 0 : _a.get();
23
+ if (config) {
24
+ const errors = [];
25
+ const warnings = [];
26
+ const counter = {
27
+ images: {
28
+ error: 0,
29
+ total: 0,
30
+ },
31
+ links: {
32
+ error: 0,
33
+ total: 0,
34
+ },
35
+ exercises: 0,
36
+ readmeFiles: 0,
37
+ };
38
+ // Checks if learnpack clean has been run
39
+ audit_1.default.checkLearnpackClean(config, errors);
40
+ // Build exercises if they are not built yet.
41
+ if (!config.exercises || config.exercises.length === 0) {
42
+ (_b = this.configManager) === null || _b === void 0 ? void 0 : _b.buildIndex();
43
+ config = (_c = this.configManager) === null || _c === void 0 ? void 0 : _c.get();
44
+ }
45
+ // Check if the exercises folder has some files within any ./exercise
46
+ const exercisesPath = config.config.exercisesPath;
47
+ fs.readdir(exercisesPath, (err, files) => {
48
+ if (err) {
49
+ return console.log('Unable to scan directory: ' + err);
50
+ }
51
+ // listing all files using forEach
52
+ for (const file of files) {
53
+ // Do whatever you want to do with the file
54
+ const filePath = path.join(exercisesPath, file);
55
+ if (fs.statSync(filePath).isFile())
56
+ warnings.push({
57
+ exercise: file,
58
+ msg: 'This file is not inside any exercise folder.',
59
+ });
60
+ }
61
+ });
62
+ // This function checks that each of the url's are working.
63
+ const checkUrl = async (file, exercise) => {
64
+ var _a, _b, _c, _d;
65
+ if (!fs.existsSync(file.path))
66
+ return false;
67
+ const content = fs.readFileSync(file.path).toString();
68
+ const isEmpty = audit_1.default.checkForEmptySpaces(content);
69
+ if (isEmpty || !content)
70
+ errors.push({
71
+ exercise: exercise.title,
72
+ msg: `This file (${file.name}) doesn't have any content inside.`,
73
+ });
74
+ const frontmatter = fm(content);
75
+ for (const attribute in frontmatter.attributes) {
76
+ if (Object.prototype.hasOwnProperty.call(frontmatter.attributes, attribute) &&
77
+ (attribute === 'intro' || attribute === 'tutorial')) {
78
+ counter.links.total++;
79
+ try {
80
+ // eslint-disable-next-line
81
+ let res = await fetch(frontmatter.attributes[attribute], {
82
+ method: 'HEAD',
83
+ });
84
+ if (!res.ok) {
85
+ counter.links.error++;
86
+ errors.push({
87
+ exercise: exercise.title,
88
+ msg: `This link is broken (${res.ok}): ${frontmatter.attributes[attribute]}`,
89
+ });
90
+ }
91
+ }
92
+ catch (_e) {
93
+ counter.links.error++;
94
+ errors.push({
95
+ exercise: exercise.title,
96
+ msg: `This link is broken: ${frontmatter.attributes[attribute]}`,
97
+ });
98
+ }
99
+ }
100
+ }
101
+ // Check url's of each README file.
102
+ const findings = audit_1.default.findInFile(['relativeImages', 'externalImages', 'markdownLinks'], content);
103
+ for (const finding in findings) {
104
+ if (Object.prototype.hasOwnProperty.call(findings, finding)) {
105
+ const obj = findings[finding];
106
+ // Valdites all the relative path images.
107
+ if (finding === 'relativeImages' && Object.keys(obj).length > 0) {
108
+ for (const img in obj) {
109
+ if (Object.prototype.hasOwnProperty.call(obj, img)) {
110
+ // Validates if the image is in the assets folder.
111
+ counter.images.total++;
112
+ const relativePath = path
113
+ .relative(exercise.path.replace(/\\/gm, '/'), `${(_a = config.config) === null || _a === void 0 ? void 0 : _a.dirPath}/assets/${obj[img].relUrl}`)
114
+ .replace(/\\/gm, '/');
115
+ if (relativePath !== obj[img].absUrl.split('?').shift()) {
116
+ counter.images.error++;
117
+ errors.push({
118
+ exercise: exercise.title,
119
+ msg: `This relative path (${obj[img].relUrl}) is not pointing to the assets folder.`,
120
+ });
121
+ }
122
+ if (!fs.existsSync(`${(_b = config.config) === null || _b === void 0 ? void 0 : _b.dirPath}/assets/${obj[img].relUrl}`)) {
123
+ counter.images.error++;
124
+ errors.push({
125
+ exercise: exercise.title,
126
+ msg: `The file ${obj[img].relUrl} doesn't exist in the assets folder.`,
127
+ });
128
+ }
129
+ }
130
+ }
131
+ }
132
+ else if (finding === 'externalImages' &&
133
+ Object.keys(obj).length > 0) {
134
+ // Valdites all the aboslute path images.
135
+ for (const img in obj) {
136
+ if (Object.prototype.hasOwnProperty.call(obj, img)) {
137
+ counter.images.total++;
138
+ if (fs.existsSync(`${(_c = config.config) === null || _c === void 0 ? void 0 : _c.dirPath}/assets${obj[img].mdUrl
139
+ .split('?')
140
+ .shift()}`)) {
141
+ const relativePath = path
142
+ .relative(exercise.path.replace(/\\/gm, '/'), `${(_d = config.config) === null || _d === void 0 ? void 0 : _d.dirPath}/assets/${obj[img].mdUrl}`)
143
+ .replace(/\\/gm, '/');
144
+ warnings.push({
145
+ exercise: exercise.title,
146
+ msg: `On this exercise you have an image with an absolute path "${obj[img].absUrl}". We recommend you to replace it by the relative path: "${relativePath}".`,
147
+ });
148
+ }
149
+ try {
150
+ // eslint-disable-next-line
151
+ let res = await fetch(obj[img].absUrl, { method: "HEAD" });
152
+ if (!res.ok) {
153
+ counter.images.error++;
154
+ errors.push({
155
+ exercise: exercise.title,
156
+ msg: `This link is broken: ${obj[img].absUrl}`,
157
+ });
158
+ }
159
+ }
160
+ catch (_f) {
161
+ counter.images.error++;
162
+ errors.push({
163
+ exercise: exercise.title,
164
+ msg: `This link is broken: ${obj[img].absUrl}`,
165
+ });
166
+ }
167
+ }
168
+ }
169
+ }
170
+ else if (finding === 'markdownLinks' &&
171
+ Object.keys(obj).length > 0) {
172
+ for (const link in obj) {
173
+ if (Object.prototype.hasOwnProperty.call(obj, link)) {
174
+ counter.links.total++;
175
+ try {
176
+ // eslint-disable-next-line
177
+ let res = await fetch(obj[link].mdUrl, { method: "HEAD" });
178
+ if (res.status > 399 && res.status < 500) {
179
+ counter.links.error++;
180
+ errors.push({
181
+ exercise: exercise.title,
182
+ msg: `This link is broken: ${obj[link].mdUrl}`,
183
+ });
184
+ }
185
+ }
186
+ catch (_g) {
187
+ counter.links.error++;
188
+ errors.push({
189
+ exercise: exercise.title,
190
+ msg: `This link is broken: ${obj[link].mdUrl}`,
191
+ });
192
+ }
193
+ }
194
+ }
195
+ }
196
+ }
197
+ }
198
+ return true;
199
+ };
200
+ // This function is being created because the find method doesn't work with promises.
201
+ const find = async (file, lang, exercise) => {
202
+ if (file.name === lang) {
203
+ await checkUrl(file, exercise);
204
+ return true;
205
+ }
206
+ return false;
207
+ };
208
+ console_1.default.debug('config', config);
209
+ console_1.default.info(' Checking if the config file is fine...');
210
+ // These two lines check if the 'slug' property is inside the configuration object.
211
+ console_1.default.debug('Checking if the slug property is inside the configuration object...');
212
+ if (!((_d = config.config) === null || _d === void 0 ? void 0 : _d.slug))
213
+ errors.push({
214
+ exercise: undefined,
215
+ msg: 'The slug property is not in the configuration object',
216
+ });
217
+ // These two lines check if the 'repository' property is inside the configuration object.
218
+ console_1.default.debug('Checking if the repository property is inside the configuration object...');
219
+ if (!((_e = config.config) === null || _e === void 0 ? void 0 : _e.repository))
220
+ errors.push({
221
+ exercise: undefined,
222
+ msg: 'The repository property is not in the configuration object',
223
+ });
224
+ else
225
+ audit_1.default.isUrl((_f = config.config) === null || _f === void 0 ? void 0 : _f.repository, errors, counter);
226
+ // These two lines check if the 'description' property is inside the configuration object.
227
+ console_1.default.debug('Checking if the description property is inside the configuration object...');
228
+ if (!((_g = config.config) === null || _g === void 0 ? void 0 : _g.description))
229
+ errors.push({
230
+ exercise: undefined,
231
+ msg: 'The description property is not in the configuration object',
232
+ });
233
+ if (errors.length === 0)
234
+ console_1.default.log('The config file is ok');
235
+ // Validates if images and links are working at every README file.
236
+ const exercises = config.exercises;
237
+ const readmeFiles = [];
238
+ if (exercises && exercises.length > 0) {
239
+ console_1.default.info(' Checking if the images are working...');
240
+ for (const index in exercises) {
241
+ if (Object.prototype.hasOwnProperty.call(exercises, index)) {
242
+ const exercise = exercises[index];
243
+ if (!exercise_1.validateExerciseDirectoryName(exercise.title))
244
+ errors.push({
245
+ exercise: exercise.title,
246
+ msg: `The exercise ${exercise.title} has an invalid name.`,
247
+ });
248
+ let readmeFilesCount = { exercise: exercise.title, count: 0 };
249
+ if (Object.keys(exercise.translations).length === 0)
250
+ errors.push({
251
+ exercise: exercise.title,
252
+ msg: `The exercise ${exercise.title} doesn't have a README.md file.`,
253
+ });
254
+ if (exercise.language === 'python3' ||
255
+ exercise.language === 'python') {
256
+ for (const f of exercise.files.map(f => f)) {
257
+ if (f.path.includes('test.py') || f.path.includes('tests.py')) {
258
+ const content = fs.readFileSync(f.path).toString();
259
+ const isEmpty = audit_1.default.checkForEmptySpaces(content);
260
+ if (isEmpty || !content)
261
+ errors.push({
262
+ exercise: exercise.title,
263
+ msg: `This file (${f.name}) doesn't have any content inside.`,
264
+ });
265
+ }
266
+ }
267
+ }
268
+ else {
269
+ for (const f of exercise.files.map(f => f)) {
270
+ if (f.path.includes('test.js') || f.path.includes('tests.js')) {
271
+ const content = fs.readFileSync(f.path).toString();
272
+ const isEmpty = audit_1.default.checkForEmptySpaces(content);
273
+ if (isEmpty || !content)
274
+ errors.push({
275
+ exercise: exercise.title,
276
+ msg: `This file (${f.name}) doesn't have any content inside.`,
277
+ });
278
+ }
279
+ }
280
+ }
281
+ for (const lang in exercise.translations) {
282
+ if (Object.prototype.hasOwnProperty.call(exercise.translations, lang)) {
283
+ const files = [];
284
+ const findResultPromises = [];
285
+ for (const file of exercise.files) {
286
+ const found = find(file, exercise.translations[lang], exercise);
287
+ findResultPromises.push(found);
288
+ }
289
+ // eslint-disable-next-line
290
+ let findResults = await Promise.all(findResultPromises);
291
+ for (const found of findResults) {
292
+ if (found) {
293
+ readmeFilesCount = Object.assign(Object.assign({}, readmeFilesCount), { count: readmeFilesCount.count + 1 });
294
+ files.push(found);
295
+ }
296
+ }
297
+ if (!files.includes(true))
298
+ errors.push({
299
+ exercise: exercise.title,
300
+ msg: "This exercise doesn't have a README.md file.",
301
+ });
302
+ }
303
+ }
304
+ readmeFiles.push(readmeFilesCount);
305
+ }
306
+ }
307
+ }
308
+ else
309
+ errors.push({
310
+ exercise: undefined,
311
+ msg: 'The exercises array is empty.',
312
+ });
313
+ console_1.default.log(`${counter.images.total - counter.images.error} images ok from ${counter.images.total}`);
314
+ console_1.default.info(" Checking if important files are missing... (README's, translations, gitignore...)");
315
+ // 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.
316
+ const files = [];
317
+ let count = 0;
318
+ for (const item of readmeFiles) {
319
+ if (count < item.count)
320
+ count = item.count;
321
+ }
322
+ for (const item of readmeFiles) {
323
+ if (item.count !== count)
324
+ files.push(` ${item.exercise}`);
325
+ }
326
+ if (files.length > 0) {
327
+ const filesString = files.join(',');
328
+ warnings.push({
329
+ exercise: undefined,
330
+ msg: files.length === 1 ?
331
+ `This exercise is missing translations:${filesString}` :
332
+ `These exercises are missing translations:${filesString}`,
333
+ });
334
+ }
335
+ // Checks if the .gitignore file exists.
336
+ if (!fs.existsSync('.gitignore'))
337
+ warnings.push({
338
+ exercise: undefined,
339
+ msg: ".gitignore file doesn't exist",
340
+ });
341
+ counter.exercises = exercises.length;
342
+ for (const readme of readmeFiles) {
343
+ counter.readmeFiles += readme.count;
344
+ }
345
+ await audit_1.default.showWarnings(warnings);
346
+ await audit_1.default.showErrors(errors, counter);
347
+ }
348
+ }
349
+ }
350
+ AuditCommand.description = `learnpack audit is the command in charge of creating an auditory of the repository
351
+ ...
352
+ learnpack audit checks for the following information in a repository:
353
+ 1. The configuration object has slug, repository and description. (Error)
354
+ 2. The command learnpack clean has been run. (Error)
355
+ 3. If a markdown or test file doesn't have any content. (Error)
356
+ 4. The links are accessing to valid servers. (Error)
357
+ 5. The relative images are working (If they have the shortest path to the image or if the images exists in the assets). (Error)
358
+ 6. The external images are working (If they are pointing to a valid server). (Error)
359
+ 7. The exercises directory names are valid. (Error)
360
+ 8. If an exercise doesn't have a README file. (Error)
361
+ 9. The exercises array (Of the config file) has content. (Error)
362
+ 10. The exercses have the same translations. (Warning)
363
+ 11. The .gitignore file exists. (Warning)
364
+ 12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)
365
+ `;
366
+ AuditCommand.flags = {
367
+ // name: flags.string({char: 'n', description: 'name to print'}),
368
+ };
369
+ exports.default = AuditCommand;
@@ -0,0 +1,8 @@
1
+ import SessionCommand from "../utils/SessionCommand";
2
+ declare class CleanCommand extends SessionCommand {
3
+ static description: string;
4
+ static flags: any;
5
+ init(): Promise<void>;
6
+ run(): Promise<void>;
7
+ }
8
+ export default CleanCommand;
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // import {flags} from '@oclif/command'
4
+ const console_1 = require("../utils/console");
5
+ const SessionCommand_1 = require("../utils/SessionCommand");
6
+ class CleanCommand extends SessionCommand_1.default {
7
+ async init() {
8
+ const { flags } = this.parse(CleanCommand);
9
+ await this.initSession(flags);
10
+ }
11
+ async run() {
12
+ var _a;
13
+ const { flags } = this.parse(CleanCommand);
14
+ (_a = this.configManager) === null || _a === void 0 ? void 0 : _a.clean();
15
+ console_1.default.success("Package cleaned successfully, ready to publish");
16
+ }
17
+ }
18
+ CleanCommand.description = `Clean the configuration object
19
+ ...
20
+ Extra documentation goes here
21
+ `;
22
+ CleanCommand.flags = {
23
+ // name: flags.string({char: 'n', description: 'name to print'}),
24
+ };
25
+ exports.default = CleanCommand;
@@ -0,0 +1,13 @@
1
+ import { Command } from "@oclif/command";
2
+ declare class DownloadCommand extends Command {
3
+ static description: string;
4
+ static flags: any;
5
+ static args: {
6
+ name: string;
7
+ required: boolean;
8
+ description: string;
9
+ hidden: boolean;
10
+ }[];
11
+ run(): Promise<null | undefined>;
12
+ }
13
+ export default DownloadCommand;
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const command_1 = require("@oclif/command");
4
+ // import fetch from 'node-fetch'
5
+ const file_1 = require("../managers/file");
6
+ const console_1 = require("../utils/console");
7
+ const api_1 = require("../utils/api");
8
+ const download_1 = require("../ui/download");
9
+ // const BaseCommand = require('../utils/BaseCommand');
10
+ class DownloadCommand extends command_1.Command {
11
+ // async init() {
12
+ // const {flags} = this.parse(DownloadCommand)
13
+ // await this.initSession(flags)
14
+ // }
15
+ async run() {
16
+ const { /* flags, */ args } = this.parse(DownloadCommand);
17
+ // start watching for file changes
18
+ let _package = args.package;
19
+ if (!_package) {
20
+ _package = (await download_1.askPackage());
21
+ }
22
+ if (!_package) {
23
+ return null;
24
+ }
25
+ try {
26
+ const packageInfo = await api_1.default.getAllPackages({ slug: _package });
27
+ if (packageInfo.results.length === 0)
28
+ console_1.default.error(`Package ${_package} not found`);
29
+ else
30
+ file_1.clone(packageInfo.results[0].repository)
31
+ .then(_result => {
32
+ console_1.default.success("Successfully downloaded");
33
+ console_1.default.info(`You can now CD into the folder like this: $ cd ${_package}`);
34
+ })
35
+ .catch(error => console_1.default.error(error.message || error));
36
+ }
37
+ catch (_a) { }
38
+ }
39
+ }
40
+ DownloadCommand.description = `Describe the command here
41
+ ...
42
+ Extra documentation goes here
43
+ `;
44
+ DownloadCommand.flags = {
45
+ // name: flags.string({char: 'n', description: 'name to print'}),
46
+ };
47
+ DownloadCommand.args = [
48
+ {
49
+ name: "package",
50
+ required: false,
51
+ description: "The unique string that identifies this package on learnpack",
52
+ hidden: false,
53
+ },
54
+ ];
55
+ exports.default = DownloadCommand;
@@ -0,0 +1,9 @@
1
+ import BaseCommand from "../utils/BaseCommand";
2
+ declare class InitComand extends BaseCommand {
3
+ static description: string;
4
+ static flags: {
5
+ grading: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
6
+ };
7
+ run(): Promise<void>;
8
+ }
9
+ export default InitComand;