@learnpack/learnpack 4.0.10 → 4.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. package/README.md +16 -20
  2. package/lib/commands/audit.d.ts +6 -6
  3. package/lib/commands/audit.js +327 -327
  4. package/lib/commands/clean.d.ts +8 -8
  5. package/lib/commands/clean.js +22 -22
  6. package/lib/commands/download.d.ts +13 -13
  7. package/lib/commands/download.js +52 -52
  8. package/lib/commands/init.d.ts +9 -9
  9. package/lib/commands/init.js +127 -127
  10. package/lib/commands/login.d.ts +14 -14
  11. package/lib/commands/login.js +34 -34
  12. package/lib/commands/logout.d.ts +14 -14
  13. package/lib/commands/logout.js +34 -34
  14. package/lib/commands/publish.d.ts +11 -14
  15. package/lib/commands/publish.js +160 -82
  16. package/lib/commands/start.d.ts +7 -7
  17. package/lib/commands/start.js +252 -250
  18. package/lib/commands/test.d.ts +6 -6
  19. package/lib/commands/test.js +62 -62
  20. package/lib/index.d.ts +1 -1
  21. package/lib/index.js +4 -4
  22. package/lib/managers/config/allowed_files.d.ts +5 -5
  23. package/lib/managers/config/allowed_files.js +30 -30
  24. package/lib/managers/config/defaults.d.ts +47 -48
  25. package/lib/managers/config/defaults.js +51 -51
  26. package/lib/managers/config/exercise.d.ts +36 -36
  27. package/lib/managers/config/exercise.js +243 -236
  28. package/lib/managers/config/index.d.ts +3 -3
  29. package/lib/managers/config/index.js +464 -459
  30. package/lib/managers/file.d.ts +14 -14
  31. package/lib/managers/file.js +190 -184
  32. package/lib/managers/gitpod.d.ts +3 -3
  33. package/lib/managers/gitpod.js +67 -67
  34. package/lib/managers/server/index.d.ts +5 -6
  35. package/lib/managers/server/index.js +58 -58
  36. package/lib/managers/server/routes.d.ts +4 -4
  37. package/lib/managers/server/routes.js +228 -220
  38. package/lib/managers/session.d.ts +3 -3
  39. package/lib/managers/session.js +125 -125
  40. package/lib/managers/socket.d.ts +3 -3
  41. package/lib/managers/socket.js +188 -186
  42. package/lib/managers/telemetry.d.ts +74 -74
  43. package/lib/managers/telemetry.js +215 -214
  44. package/lib/managers/test.js +84 -84
  45. package/lib/models/action.d.ts +2 -2
  46. package/lib/models/action.js +2 -2
  47. package/lib/models/audit.d.ts +15 -15
  48. package/lib/models/audit.js +2 -2
  49. package/lib/models/config-manager.d.ts +21 -21
  50. package/lib/models/config-manager.js +2 -2
  51. package/lib/models/config.d.ts +86 -86
  52. package/lib/models/config.js +2 -2
  53. package/lib/models/counter.d.ts +11 -11
  54. package/lib/models/counter.js +2 -2
  55. package/lib/models/errors.d.ts +15 -15
  56. package/lib/models/errors.js +2 -2
  57. package/lib/models/exercise-obj.d.ts +29 -30
  58. package/lib/models/exercise-obj.js +2 -2
  59. package/lib/models/file.d.ts +5 -5
  60. package/lib/models/file.js +2 -2
  61. package/lib/models/findings.d.ts +17 -17
  62. package/lib/models/findings.js +2 -2
  63. package/lib/models/flags.d.ts +10 -10
  64. package/lib/models/flags.js +2 -2
  65. package/lib/models/front-matter.d.ts +11 -11
  66. package/lib/models/front-matter.js +2 -2
  67. package/lib/models/gitpod-data.d.ts +16 -16
  68. package/lib/models/gitpod-data.js +2 -2
  69. package/lib/models/language.d.ts +4 -4
  70. package/lib/models/language.js +2 -2
  71. package/lib/models/package.d.ts +7 -7
  72. package/lib/models/package.js +2 -2
  73. package/lib/models/plugin-config.d.ts +16 -16
  74. package/lib/models/plugin-config.js +2 -2
  75. package/lib/models/session.d.ts +31 -31
  76. package/lib/models/session.js +2 -2
  77. package/lib/models/socket.d.ts +37 -37
  78. package/lib/models/socket.js +2 -2
  79. package/lib/models/status.d.ts +1 -1
  80. package/lib/models/status.js +2 -2
  81. package/lib/models/success-types.d.ts +1 -1
  82. package/lib/models/success-types.js +2 -2
  83. package/lib/plugin/command/compile.d.ts +6 -6
  84. package/lib/plugin/command/compile.js +18 -18
  85. package/lib/plugin/command/test.d.ts +6 -6
  86. package/lib/plugin/command/test.js +25 -25
  87. package/lib/plugin/index.d.ts +27 -27
  88. package/lib/plugin/index.js +7 -7
  89. package/lib/plugin/plugin.d.ts +8 -8
  90. package/lib/plugin/plugin.js +68 -68
  91. package/lib/plugin/utils.d.ts +16 -16
  92. package/lib/plugin/utils.js +58 -58
  93. package/lib/ui/download.d.ts +5 -5
  94. package/lib/ui/download.js +62 -61
  95. package/lib/utils/BaseCommand.d.ts +8 -8
  96. package/lib/utils/BaseCommand.js +41 -41
  97. package/lib/utils/SessionCommand.d.ts +10 -10
  98. package/lib/utils/SessionCommand.js +43 -43
  99. package/lib/utils/api.d.ts +14 -14
  100. package/lib/utils/api.js +255 -255
  101. package/lib/utils/audit.d.ts +16 -16
  102. package/lib/utils/audit.js +303 -303
  103. package/lib/utils/checkNotInstalled.d.ts +8 -8
  104. package/lib/utils/checkNotInstalled.js +185 -181
  105. package/lib/utils/console.d.ts +12 -12
  106. package/lib/utils/console.js +19 -19
  107. package/lib/utils/errors.d.ts +17 -17
  108. package/lib/utils/errors.js +107 -100
  109. package/lib/utils/exercisesQueue.d.ts +9 -9
  110. package/lib/utils/exercisesQueue.js +38 -38
  111. package/lib/utils/fileQueue.d.ts +43 -43
  112. package/lib/utils/fileQueue.js +169 -169
  113. package/lib/utils/misc.d.ts +1 -1
  114. package/lib/utils/misc.js +24 -23
  115. package/lib/utils/osOperations.d.ts +5 -5
  116. package/lib/utils/osOperations.js +72 -72
  117. package/lib/utils/validators.d.ts +5 -5
  118. package/lib/utils/validators.js +16 -17
  119. package/lib/utils/watcher.d.ts +2 -2
  120. package/lib/utils/watcher.js +25 -25
  121. package/oclif.manifest.json +1 -1
  122. package/package.json +6 -4
  123. package/src/commands/publish.ts +181 -107
  124. package/src/managers/config/index.ts +5 -0
  125. package/src/managers/server/routes.ts +10 -0
  126. package/src/managers/session.ts +145 -145
@@ -1,303 +1,303 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const console_1 = require("./console");
4
- const fs = require("fs");
5
- const path = require("path");
6
- // eslint-disable-next-line
7
- const fetch = require("node-fetch");
8
- // eslint-disable-next-line
9
- const fm = require("front-matter");
10
- // This function checks if a url is valid.
11
- const isUrl = async (url, errors, counter) => {
12
- const regexUrl = /(https?:\/\/[\w./-]+)/gm;
13
- counter.links.total++;
14
- if (!regexUrl.test(url)) {
15
- counter.links.error++;
16
- errors.push({
17
- exercise: undefined,
18
- msg: `The repository value of the configuration file is not a link: ${url}`,
19
- });
20
- return false;
21
- }
22
- const res = await fetch(url, { method: "HEAD" });
23
- if (!res.ok) {
24
- counter.links.error++;
25
- errors.push({
26
- exercise: undefined,
27
- msg: `The link of the repository is broken: ${url}`,
28
- });
29
- }
30
- return true;
31
- };
32
- const checkForEmptySpaces = (str) => {
33
- const isEmpty = true;
34
- for (const letter of str) {
35
- if (letter !== " ") {
36
- return false;
37
- }
38
- }
39
- return isEmpty;
40
- };
41
- const checkLearnpackClean = (configObj, errors) => {
42
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
43
- if ((((_a = configObj.config) === null || _a === void 0 ? void 0 : _a.outputPath) &&
44
- fs.existsSync((_b = configObj.config) === null || _b === void 0 ? void 0 : _b.outputPath)) ||
45
- fs.existsSync(`${(_c = configObj.config) === null || _c === void 0 ? void 0 : _c.dirPath}/_app`) ||
46
- fs.existsSync(`${(_d = configObj.config) === null || _d === void 0 ? void 0 : _d.dirPath}/reports`) ||
47
- fs.existsSync(`${(_e = configObj.config) === null || _e === void 0 ? void 0 : _e.dirPath}/resets`) ||
48
- fs.existsSync(`${(_f = configObj.config) === null || _f === void 0 ? void 0 : _f.dirPath}/app.tar.gz`) ||
49
- fs.existsSync(`${(_g = configObj.config) === null || _g === void 0 ? void 0 : _g.dirPath}/config.json`) ||
50
- fs.existsSync(`${(_h = configObj.config) === null || _h === void 0 ? void 0 : _h.dirPath}/vscode_queue.json`) ||
51
- fs.existsSync(`${(_j = configObj.config) === null || _j === void 0 ? void 0 : _j.dirPath}/telemetry.json`)) {
52
- errors.push({
53
- exercise: undefined,
54
- msg: "You have to run learnpack clean command",
55
- });
56
- }
57
- };
58
- const findInFile = (types, content) => {
59
- const regex = {
60
- relativeImages: /!\[.*]\s*\((((\.\/)?(\.{2}\/){1,5})(.*\/)*(.[^\s/]*\.[A-Za-z]{2,4})\S*)\)/gm,
61
- externalImages: /!\[.*]\((https?:\/(\/[^)/]+)+\/?)\)/gm,
62
- markdownLinks: /(\s)+\[.*]\((https?:\/(\/[^)/]+)+\/?)\)/gm,
63
- url: /(https?:\/\/[\w./-]+)/gm,
64
- uploadcare: /https:\/\/ucarecdn.com\/(?:.*\/)*([\w./-]+)/gm,
65
- };
66
- const validTypes = Object.keys(regex);
67
- if (!Array.isArray(types))
68
- types = [types];
69
- const findings = {};
70
- for (const type of types) {
71
- if (!validTypes.includes(type))
72
- throw new Error("Invalid type: " + type);
73
- else
74
- findings[type] = {};
75
- }
76
- for (const type of types) {
77
- let m;
78
- while ((m = regex[type].exec(content)) !== null) {
79
- // This is necessary to avoid infinite loops with zero-width matches
80
- if (m.index === regex.lastIndex) {
81
- regex.lastIndex++;
82
- }
83
- // The result can be accessed through the `m`-variable.
84
- // m.forEach((match, groupIndex) => values.push(match));
85
- findings[type][m[0]] = {
86
- content: m[0],
87
- absUrl: m[1],
88
- mdUrl: m[2],
89
- relUrl: m[6],
90
- };
91
- }
92
- }
93
- return findings;
94
- };
95
- // This function checks that each of the url's are working.
96
- const checkUrl = async (config, filePath, fileName, exercise, errors, warnings, counter) => {
97
- var _a, _b, _c, _d;
98
- if (!fs.existsSync(filePath))
99
- return false;
100
- const content = fs.readFileSync(filePath).toString();
101
- const isEmpty = checkForEmptySpaces(content);
102
- if (isEmpty || !content)
103
- errors.push({
104
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
105
- msg: `This file (${fileName}) doesn't have any content inside.`,
106
- });
107
- const frontmatter = fm(content);
108
- for (const attribute in frontmatter.attributes) {
109
- if (Object.prototype.hasOwnProperty.call(frontmatter.attributes, attribute) &&
110
- (attribute === "intro" || attribute === "tutorial")) {
111
- counter && counter.links.total++;
112
- try {
113
- // eslint-disable-next-line
114
- let res = await fetch(frontmatter.attributes[attribute], {
115
- method: "HEAD",
116
- });
117
- if (!res.ok) {
118
- counter && counter.links.error++;
119
- errors.push({
120
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
121
- msg: `This link is broken (${res.ok}): ${frontmatter.attributes[attribute]}`,
122
- });
123
- }
124
- }
125
- catch (_e) {
126
- counter && counter.links.error++;
127
- errors.push({
128
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
129
- msg: `This link is broken: ${frontmatter.attributes[attribute]}`,
130
- });
131
- }
132
- }
133
- }
134
- // Check url's of each README file.
135
- const findings = findInFile(["relativeImages", "externalImages", "markdownLinks"], content);
136
- for (const finding in findings) {
137
- if (Object.prototype.hasOwnProperty.call(findings, finding)) {
138
- const obj = findings[finding];
139
- // Valdites all the relative path images.
140
- if (finding === "relativeImages" && Object.keys(obj).length > 0) {
141
- for (const img in obj) {
142
- if (Object.prototype.hasOwnProperty.call(obj, img)) {
143
- // Validates if the image is in the assets folder.
144
- counter && counter.images.total++;
145
- const relativePath = path
146
- .relative(exercise ? exercise.path.replace(/\\/gm, "/") : "./", `${(_a = config.config) === null || _a === void 0 ? void 0 : _a.dirPath}/assets/${obj[img].relUrl}`)
147
- .replace(/\\/gm, "/");
148
- if (relativePath !== obj[img].absUrl.split("?").shift()) {
149
- counter && counter.images.error++;
150
- errors.push({
151
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
152
- msg: `This relative path (${obj[img].relUrl}) is not pointing to the assets folder.`,
153
- });
154
- }
155
- if (!fs.existsSync(`${(_b = config.config) === null || _b === void 0 ? void 0 : _b.dirPath}/assets/${obj[img].relUrl}`)) {
156
- counter && counter.images.error++;
157
- errors.push({
158
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
159
- msg: `The file ${obj[img].relUrl} doesn't exist in the assets folder.`,
160
- });
161
- }
162
- }
163
- }
164
- }
165
- else if (finding === "externalImages" && Object.keys(obj).length > 0) {
166
- // Valdites all the aboslute path images.
167
- for (const img in obj) {
168
- if (Object.prototype.hasOwnProperty.call(obj, img)) {
169
- counter && counter.images.total++;
170
- if (fs.existsSync(`${(_c = config.config) === null || _c === void 0 ? void 0 : _c.dirPath}/assets${obj[img].mdUrl
171
- .split("?")
172
- .shift()}`)) {
173
- const relativePath = path
174
- .relative(exercise ? exercise.path.replace(/\\/gm, "/") : "./", `${(_d = config.config) === null || _d === void 0 ? void 0 : _d.dirPath}/assets/${obj[img].mdUrl}`)
175
- .replace(/\\/gm, "/");
176
- warnings.push({
177
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
178
- 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}".`,
179
- });
180
- }
181
- try {
182
- // eslint-disable-next-line
183
- let res = await fetch(obj[img].absUrl, {
184
- method: "HEAD",
185
- });
186
- if (!res.ok) {
187
- counter && counter.images.error++;
188
- errors.push({
189
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
190
- msg: `This link is broken: ${obj[img].absUrl}`,
191
- });
192
- }
193
- }
194
- catch (_f) {
195
- counter && counter.images.error++;
196
- errors.push({
197
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
198
- msg: `This link is broken: ${obj[img].absUrl}`,
199
- });
200
- }
201
- }
202
- }
203
- }
204
- else if (finding === "markdownLinks" && Object.keys(obj).length > 0) {
205
- for (const link in obj) {
206
- if (Object.prototype.hasOwnProperty.call(obj, link)) {
207
- counter && counter.links.total++;
208
- if (!obj[link].mdUrl.includes("twitter")) {
209
- try {
210
- // eslint-disable-next-line
211
- let res = await fetch(obj[link].mdUrl, {
212
- method: "HEAD",
213
- });
214
- if (res.status > 399 && res.status < 500) {
215
- counter && counter.links.error++;
216
- errors.push({
217
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
218
- msg: `This link is broken: ${obj[link].mdUrl}`,
219
- });
220
- }
221
- }
222
- catch (_g) {
223
- counter && counter.links.error++;
224
- errors.push({
225
- exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
226
- msg: `This link is broken: ${obj[link].mdUrl}`,
227
- });
228
- }
229
- }
230
- }
231
- }
232
- }
233
- }
234
- }
235
- return true;
236
- };
237
- // This function writes a given file with the given content.
238
- const writeFile = async (content, filePath) => {
239
- try {
240
- await fs.promises.writeFile(filePath, content);
241
- }
242
- catch (error) {
243
- if (error)
244
- console_1.default.error(`We weren't able to write the file in this path "${filePath}".`, error);
245
- }
246
- };
247
- // This function checks if there are errors, and show them in the console at the end.
248
- const showErrors = (errors, counter) => {
249
- return new Promise((resolve, reject) => {
250
- if (errors) {
251
- if (errors.length > 0) {
252
- console_1.default.log("Checking for errors...");
253
- for (const [i, error] of errors.entries())
254
- console_1.default.error(`${i + 1}) ${error.msg} ${error.exercise ? `(Exercise: ${error.exercise})` : ""}`);
255
- if (counter) {
256
- console_1.default.error(` We found ${errors.length} error${errors.length > 1 ? "s" : ""} among ${counter.images.total} images, ${counter.links.total} link, ${counter.readmeFiles} README files and ${counter.exercises} exercises.`);
257
- }
258
- else {
259
- console_1.default.error(` We found ${errors.length} error${errors.length > 1 ? "s" : ""} related with the project integrity.`);
260
- }
261
- process.exit(1);
262
- }
263
- else {
264
- if (counter) {
265
- console_1.default.success(`We didn't find any errors in this repository among ${counter.images.total} images, ${counter.links.total} link, ${counter.readmeFiles} README files and ${counter.exercises} exercises.`);
266
- }
267
- else {
268
- console_1.default.success(`We didn't find any errors in this repository.`);
269
- }
270
- process.exit(0);
271
- }
272
- }
273
- else {
274
- reject("Failed");
275
- }
276
- });
277
- };
278
- // This function checks if there are warnings, and show them in the console at the end.
279
- const showWarnings = (warnings) => {
280
- return new Promise((resolve, reject) => {
281
- if (warnings) {
282
- if (warnings.length > 0) {
283
- console_1.default.log("Checking for warnings...");
284
- for (const [i, warning] of warnings.entries())
285
- console_1.default.warning(`${i + 1}) ${warning.msg} ${warning.exercise ? `File: ${warning.exercise}` : ""}`);
286
- }
287
- resolve("SUCCESS");
288
- }
289
- else {
290
- reject("Failed");
291
- }
292
- });
293
- };
294
- exports.default = {
295
- isUrl,
296
- checkForEmptySpaces,
297
- checkLearnpackClean,
298
- findInFile,
299
- checkUrl,
300
- writeFile,
301
- showErrors,
302
- showWarnings,
303
- };
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const console_1 = require("./console");
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+ // eslint-disable-next-line
7
+ const fetch = require("node-fetch");
8
+ // eslint-disable-next-line
9
+ const fm = require("front-matter");
10
+ // This function checks if a url is valid.
11
+ const isUrl = async (url, errors, counter) => {
12
+ const regexUrl = /(https?:\/\/[\w./-]+)/gm;
13
+ counter.links.total++;
14
+ if (!regexUrl.test(url)) {
15
+ counter.links.error++;
16
+ errors.push({
17
+ exercise: undefined,
18
+ msg: `The repository value of the configuration file is not a link: ${url}`,
19
+ });
20
+ return false;
21
+ }
22
+ const res = await fetch(url, { method: "HEAD" });
23
+ if (!res.ok) {
24
+ counter.links.error++;
25
+ errors.push({
26
+ exercise: undefined,
27
+ msg: `The link of the repository is broken: ${url}`,
28
+ });
29
+ }
30
+ return true;
31
+ };
32
+ const checkForEmptySpaces = (str) => {
33
+ const isEmpty = true;
34
+ for (const letter of str) {
35
+ if (letter !== " ") {
36
+ return false;
37
+ }
38
+ }
39
+ return isEmpty;
40
+ };
41
+ const checkLearnpackClean = (configObj, errors) => {
42
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
43
+ if ((((_a = configObj.config) === null || _a === void 0 ? void 0 : _a.outputPath) &&
44
+ fs.existsSync((_b = configObj.config) === null || _b === void 0 ? void 0 : _b.outputPath)) ||
45
+ fs.existsSync(`${(_c = configObj.config) === null || _c === void 0 ? void 0 : _c.dirPath}/_app`) ||
46
+ fs.existsSync(`${(_d = configObj.config) === null || _d === void 0 ? void 0 : _d.dirPath}/reports`) ||
47
+ fs.existsSync(`${(_e = configObj.config) === null || _e === void 0 ? void 0 : _e.dirPath}/resets`) ||
48
+ fs.existsSync(`${(_f = configObj.config) === null || _f === void 0 ? void 0 : _f.dirPath}/app.tar.gz`) ||
49
+ fs.existsSync(`${(_g = configObj.config) === null || _g === void 0 ? void 0 : _g.dirPath}/config.json`) ||
50
+ fs.existsSync(`${(_h = configObj.config) === null || _h === void 0 ? void 0 : _h.dirPath}/vscode_queue.json`) ||
51
+ fs.existsSync(`${(_j = configObj.config) === null || _j === void 0 ? void 0 : _j.dirPath}/telemetry.json`)) {
52
+ errors.push({
53
+ exercise: undefined,
54
+ msg: "You have to run learnpack clean command",
55
+ });
56
+ }
57
+ };
58
+ const findInFile = (types, content) => {
59
+ const regex = {
60
+ relativeImages: /!\[.*]\s*\((((\.\/)?(\.{2}\/){1,5})(.*\/)*(.[^\s/]*\.[A-Za-z]{2,4})\S*)\)/gm,
61
+ externalImages: /!\[.*]\((https?:\/(\/[^)/]+)+\/?)\)/gm,
62
+ markdownLinks: /(\s)+\[.*]\((https?:\/(\/[^)/]+)+\/?)\)/gm,
63
+ url: /(https?:\/\/[\w./-]+)/gm,
64
+ uploadcare: /https:\/\/ucarecdn.com\/(?:.*\/)*([\w./-]+)/gm,
65
+ };
66
+ const validTypes = Object.keys(regex);
67
+ if (!Array.isArray(types))
68
+ types = [types];
69
+ const findings = {};
70
+ for (const type of types) {
71
+ if (!validTypes.includes(type))
72
+ throw new Error("Invalid type: " + type);
73
+ else
74
+ findings[type] = {};
75
+ }
76
+ for (const type of types) {
77
+ let m;
78
+ while ((m = regex[type].exec(content)) !== null) {
79
+ // This is necessary to avoid infinite loops with zero-width matches
80
+ if (m.index === regex.lastIndex) {
81
+ regex.lastIndex++;
82
+ }
83
+ // The result can be accessed through the `m`-variable.
84
+ // m.forEach((match, groupIndex) => values.push(match));
85
+ findings[type][m[0]] = {
86
+ content: m[0],
87
+ absUrl: m[1],
88
+ mdUrl: m[2],
89
+ relUrl: m[6],
90
+ };
91
+ }
92
+ }
93
+ return findings;
94
+ };
95
+ // This function checks that each of the url's are working.
96
+ const checkUrl = async (config, filePath, fileName, exercise, errors, warnings, counter) => {
97
+ var _a, _b, _c, _d;
98
+ if (!fs.existsSync(filePath))
99
+ return false;
100
+ const content = fs.readFileSync(filePath).toString();
101
+ const isEmpty = checkForEmptySpaces(content);
102
+ if (isEmpty || !content)
103
+ errors.push({
104
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
105
+ msg: `This file (${fileName}) doesn't have any content inside.`,
106
+ });
107
+ const frontmatter = fm(content);
108
+ for (const attribute in frontmatter.attributes) {
109
+ if (Object.prototype.hasOwnProperty.call(frontmatter.attributes, attribute) &&
110
+ (attribute === "intro" || attribute === "tutorial")) {
111
+ counter && counter.links.total++;
112
+ try {
113
+ // eslint-disable-next-line
114
+ let res = await fetch(frontmatter.attributes[attribute], {
115
+ method: "HEAD",
116
+ });
117
+ if (!res.ok) {
118
+ counter && counter.links.error++;
119
+ errors.push({
120
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
121
+ msg: `This link is broken (${res.ok}): ${frontmatter.attributes[attribute]}`,
122
+ });
123
+ }
124
+ }
125
+ catch (_e) {
126
+ counter && counter.links.error++;
127
+ errors.push({
128
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
129
+ msg: `This link is broken: ${frontmatter.attributes[attribute]}`,
130
+ });
131
+ }
132
+ }
133
+ }
134
+ // Check url's of each README file.
135
+ const findings = findInFile(["relativeImages", "externalImages", "markdownLinks"], content);
136
+ for (const finding in findings) {
137
+ if (Object.prototype.hasOwnProperty.call(findings, finding)) {
138
+ const obj = findings[finding];
139
+ // Valdites all the relative path images.
140
+ if (finding === "relativeImages" && Object.keys(obj).length > 0) {
141
+ for (const img in obj) {
142
+ if (Object.prototype.hasOwnProperty.call(obj, img)) {
143
+ // Validates if the image is in the assets folder.
144
+ counter && counter.images.total++;
145
+ const relativePath = path
146
+ .relative(exercise ? exercise.path.replace(/\\/gm, "/") : "./", `${(_a = config.config) === null || _a === void 0 ? void 0 : _a.dirPath}/assets/${obj[img].relUrl}`)
147
+ .replace(/\\/gm, "/");
148
+ if (relativePath !== obj[img].absUrl.split("?").shift()) {
149
+ counter && counter.images.error++;
150
+ errors.push({
151
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
152
+ msg: `This relative path (${obj[img].relUrl}) is not pointing to the assets folder.`,
153
+ });
154
+ }
155
+ if (!fs.existsSync(`${(_b = config.config) === null || _b === void 0 ? void 0 : _b.dirPath}/assets/${obj[img].relUrl}`)) {
156
+ counter && counter.images.error++;
157
+ errors.push({
158
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
159
+ msg: `The file ${obj[img].relUrl} doesn't exist in the assets folder.`,
160
+ });
161
+ }
162
+ }
163
+ }
164
+ }
165
+ else if (finding === "externalImages" && Object.keys(obj).length > 0) {
166
+ // Valdites all the aboslute path images.
167
+ for (const img in obj) {
168
+ if (Object.prototype.hasOwnProperty.call(obj, img)) {
169
+ counter && counter.images.total++;
170
+ if (fs.existsSync(`${(_c = config.config) === null || _c === void 0 ? void 0 : _c.dirPath}/assets${obj[img].mdUrl
171
+ .split("?")
172
+ .shift()}`)) {
173
+ const relativePath = path
174
+ .relative(exercise ? exercise.path.replace(/\\/gm, "/") : "./", `${(_d = config.config) === null || _d === void 0 ? void 0 : _d.dirPath}/assets/${obj[img].mdUrl}`)
175
+ .replace(/\\/gm, "/");
176
+ warnings.push({
177
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
178
+ 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}".`,
179
+ });
180
+ }
181
+ try {
182
+ // eslint-disable-next-line
183
+ let res = await fetch(obj[img].absUrl, {
184
+ method: "HEAD",
185
+ });
186
+ if (!res.ok) {
187
+ counter && counter.images.error++;
188
+ errors.push({
189
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
190
+ msg: `This link is broken: ${obj[img].absUrl}`,
191
+ });
192
+ }
193
+ }
194
+ catch (_f) {
195
+ counter && counter.images.error++;
196
+ errors.push({
197
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
198
+ msg: `This link is broken: ${obj[img].absUrl}`,
199
+ });
200
+ }
201
+ }
202
+ }
203
+ }
204
+ else if (finding === "markdownLinks" && Object.keys(obj).length > 0) {
205
+ for (const link in obj) {
206
+ if (Object.prototype.hasOwnProperty.call(obj, link)) {
207
+ counter && counter.links.total++;
208
+ if (!obj[link].mdUrl.includes("twitter")) {
209
+ try {
210
+ // eslint-disable-next-line
211
+ let res = await fetch(obj[link].mdUrl, {
212
+ method: "HEAD",
213
+ });
214
+ if (res.status > 399 && res.status < 500) {
215
+ counter && counter.links.error++;
216
+ errors.push({
217
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
218
+ msg: `This link is broken: ${obj[link].mdUrl}`,
219
+ });
220
+ }
221
+ }
222
+ catch (_g) {
223
+ counter && counter.links.error++;
224
+ errors.push({
225
+ exercise: exercise === null || exercise === void 0 ? void 0 : exercise.title,
226
+ msg: `This link is broken: ${obj[link].mdUrl}`,
227
+ });
228
+ }
229
+ }
230
+ }
231
+ }
232
+ }
233
+ }
234
+ }
235
+ return true;
236
+ };
237
+ // This function writes a given file with the given content.
238
+ const writeFile = async (content, filePath) => {
239
+ try {
240
+ await fs.promises.writeFile(filePath, content);
241
+ }
242
+ catch (error) {
243
+ if (error)
244
+ console_1.default.error(`We weren't able to write the file in this path "${filePath}".`, error);
245
+ }
246
+ };
247
+ // This function checks if there are errors, and show them in the console at the end.
248
+ const showErrors = (errors, counter) => {
249
+ return new Promise((resolve, reject) => {
250
+ if (errors) {
251
+ if (errors.length > 0) {
252
+ console_1.default.log("Checking for errors...");
253
+ for (const [i, error] of errors.entries())
254
+ console_1.default.error(`${i + 1}) ${error.msg} ${error.exercise ? `(Exercise: ${error.exercise})` : ""}`);
255
+ if (counter) {
256
+ console_1.default.error(` We found ${errors.length} error${errors.length > 1 ? "s" : ""} among ${counter.images.total} images, ${counter.links.total} link, ${counter.readmeFiles} README files and ${counter.exercises} exercises.`);
257
+ }
258
+ else {
259
+ console_1.default.error(` We found ${errors.length} error${errors.length > 1 ? "s" : ""} related with the project integrity.`);
260
+ }
261
+ process.exit(1);
262
+ }
263
+ else {
264
+ if (counter) {
265
+ console_1.default.success(`We didn't find any errors in this repository among ${counter.images.total} images, ${counter.links.total} link, ${counter.readmeFiles} README files and ${counter.exercises} exercises.`);
266
+ }
267
+ else {
268
+ console_1.default.success(`We didn't find any errors in this repository.`);
269
+ }
270
+ process.exit(0);
271
+ }
272
+ }
273
+ else {
274
+ reject("Failed");
275
+ }
276
+ });
277
+ };
278
+ // This function checks if there are warnings, and show them in the console at the end.
279
+ const showWarnings = (warnings) => {
280
+ return new Promise((resolve, reject) => {
281
+ if (warnings) {
282
+ if (warnings.length > 0) {
283
+ console_1.default.log("Checking for warnings...");
284
+ for (const [i, warning] of warnings.entries())
285
+ console_1.default.warning(`${i + 1}) ${warning.msg} ${warning.exercise ? `File: ${warning.exercise}` : ""}`);
286
+ }
287
+ resolve("SUCCESS");
288
+ }
289
+ else {
290
+ reject("Failed");
291
+ }
292
+ });
293
+ };
294
+ exports.default = {
295
+ isUrl,
296
+ checkForEmptySpaces,
297
+ checkLearnpackClean,
298
+ findInFile,
299
+ checkUrl,
300
+ writeFile,
301
+ showErrors,
302
+ showWarnings,
303
+ };
@@ -1,8 +1,8 @@
1
- import { IExercise } from "../models/exercise-obj";
2
- declare type TNeededPlugins = {
3
- needed: string[];
4
- notInstalled: string[];
5
- };
6
- export declare const checkNotInstalledPlugins: (exercises: IExercise[], installedPlugins: string[], command: any) => Promise<TNeededPlugins>;
7
- export declare const checkNotInstalledDependencies: (neededPlugins: string[]) => Promise<boolean | undefined>;
8
- export {};
1
+ import { IExercise } from "../models/exercise-obj";
2
+ type TNeededPlugins = {
3
+ needed: string[];
4
+ notInstalled: string[];
5
+ };
6
+ export declare const checkNotInstalledPlugins: (exercises: IExercise[], installedPlugins: string[], command: any) => Promise<TNeededPlugins>;
7
+ export declare const checkNotInstalledDependencies: (neededPlugins: string[]) => Promise<boolean | undefined>;
8
+ export {};