@learnpack/learnpack 2.1.25 → 2.1.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -16
- package/bin/run +17 -17
- package/bin/run.cmd +3 -3
- package/oclif.manifest.json +1 -1
- package/package.json +139 -138
- package/src/commands/audit.ts +134 -109
- package/src/commands/clean.ts +29 -29
- package/src/commands/download.ts +62 -62
- package/src/commands/init.ts +39 -39
- package/src/commands/login.ts +42 -42
- package/src/commands/logout.ts +43 -43
- package/src/commands/publish.ts +107 -107
- package/src/commands/start.ts +264 -234
- package/src/commands/test.ts +85 -85
- package/src/index.ts +1 -1
- package/src/managers/config/allowed_files.ts +29 -29
- package/src/managers/config/defaults.ts +4 -2
- package/src/managers/config/exercise.ts +309 -302
- package/src/managers/config/index.ts +159 -138
- package/src/managers/file.ts +178 -169
- package/src/managers/gitpod.ts +84 -84
- package/src/managers/server/index.ts +78 -69
- package/src/managers/server/routes.ts +139 -90
- package/src/managers/session.ts +147 -118
- package/src/managers/socket.ts +252 -239
- package/src/managers/test.ts +83 -83
- package/src/models/action.ts +10 -3
- package/src/models/config-manager.ts +23 -23
- package/src/models/config.ts +9 -2
- package/src/models/counter.ts +11 -11
- package/src/models/errors.ts +22 -22
- package/src/models/exercise-obj.ts +6 -3
- package/src/models/file.ts +5 -5
- package/src/models/findings.ts +18 -18
- package/src/models/flags.ts +10 -10
- package/src/models/front-matter.ts +11 -11
- package/src/models/gitpod-data.ts +19 -19
- package/src/models/language.ts +4 -4
- package/src/models/package.ts +7 -7
- package/src/models/plugin-config.ts +17 -17
- package/src/models/session.ts +29 -26
- package/src/models/socket.ts +54 -48
- package/src/models/status.ts +16 -15
- package/src/models/success-types.ts +1 -1
- package/src/plugin/command/compile.ts +17 -17
- package/src/plugin/command/test.ts +30 -30
- package/src/plugin/index.ts +6 -6
- package/src/plugin/plugin.ts +94 -94
- package/src/plugin/utils.ts +87 -87
- package/src/types/node-fetch.d.ts +1 -1
- package/src/ui/download.ts +71 -71
- package/src/utils/BaseCommand.ts +48 -48
- package/src/utils/SessionCommand.ts +48 -48
- package/src/utils/api.ts +246 -194
- package/src/utils/audit.ts +392 -395
- package/src/utils/console.ts +24 -24
- package/src/utils/errors.ts +117 -117
- package/src/utils/exercisesQueue.ts +51 -51
- package/src/utils/fileQueue.ts +198 -198
- package/src/utils/misc.ts +23 -23
- package/src/utils/templates/gitignore.txt +19 -19
- package/src/utils/templates/incremental/.learn/exercises/01-hello-world/README.es.md +24 -24
- package/src/utils/templates/incremental/.learn/exercises/01-hello-world/README.md +24 -24
- package/src/utils/templates/incremental/README.ejs +4 -4
- package/src/utils/templates/incremental/README.es.ejs +4 -4
- package/src/utils/templates/isolated/01-hello-world/README.es.md +26 -26
- package/src/utils/templates/isolated/01-hello-world/README.md +26 -26
- package/src/utils/templates/isolated/README.ejs +4 -4
- package/src/utils/templates/isolated/README.es.ejs +4 -4
- package/src/utils/templates/no-grading/README.ejs +4 -4
- package/src/utils/templates/no-grading/README.es.ejs +4 -4
- package/src/utils/validators.ts +18 -18
- package/src/utils/watcher.ts +14 -14
- package/lib/commands/audit.d.ts +0 -6
- package/lib/commands/audit.js +0 -317
- package/lib/commands/clean.d.ts +0 -8
- package/lib/commands/clean.js +0 -25
- package/lib/commands/download.d.ts +0 -13
- package/lib/commands/download.js +0 -55
- package/lib/commands/init.d.ts +0 -9
- package/lib/commands/init.js +0 -123
- package/lib/commands/login.d.ts +0 -14
- package/lib/commands/login.js +0 -37
- package/lib/commands/logout.d.ts +0 -14
- package/lib/commands/logout.js +0 -37
- package/lib/commands/publish.d.ts +0 -14
- package/lib/commands/publish.js +0 -82
- package/lib/commands/start.d.ts +0 -7
- package/lib/commands/start.js +0 -165
- package/lib/commands/test.d.ts +0 -6
- package/lib/commands/test.js +0 -62
- package/lib/index.d.ts +0 -1
- package/lib/index.js +0 -4
- package/lib/managers/config/allowed_files.d.ts +0 -5
- package/lib/managers/config/allowed_files.js +0 -30
- package/lib/managers/config/defaults.d.ts +0 -37
- package/lib/managers/config/defaults.js +0 -38
- package/lib/managers/config/exercise.d.ts +0 -36
- package/lib/managers/config/exercise.js +0 -230
- package/lib/managers/config/index.d.ts +0 -3
- package/lib/managers/config/index.js +0 -302
- package/lib/managers/file.d.ts +0 -13
- package/lib/managers/file.js +0 -134
- package/lib/managers/gitpod.d.ts +0 -3
- package/lib/managers/gitpod.js +0 -67
- package/lib/managers/server/index.d.ts +0 -6
- package/lib/managers/server/index.js +0 -51
- package/lib/managers/server/routes.d.ts +0 -4
- package/lib/managers/server/routes.js +0 -167
- package/lib/managers/session.d.ts +0 -3
- package/lib/managers/session.js +0 -104
- package/lib/managers/socket.d.ts +0 -3
- package/lib/managers/socket.js +0 -164
- package/lib/managers/test.d.ts +0 -0
- package/lib/managers/test.js +0 -84
- package/lib/models/action.d.ts +0 -2
- package/lib/models/action.js +0 -2
- package/lib/models/audit.d.ts +0 -15
- package/lib/models/audit.js +0 -2
- package/lib/models/config-manager.d.ts +0 -21
- package/lib/models/config-manager.js +0 -2
- package/lib/models/config.d.ts +0 -60
- package/lib/models/config.js +0 -2
- package/lib/models/counter.d.ts +0 -11
- package/lib/models/counter.js +0 -2
- package/lib/models/errors.d.ts +0 -15
- package/lib/models/errors.js +0 -2
- package/lib/models/exercise-obj.d.ts +0 -27
- package/lib/models/exercise-obj.js +0 -2
- package/lib/models/file.d.ts +0 -5
- package/lib/models/file.js +0 -2
- package/lib/models/findings.d.ts +0 -17
- package/lib/models/findings.js +0 -2
- package/lib/models/flags.d.ts +0 -10
- package/lib/models/flags.js +0 -2
- package/lib/models/front-matter.d.ts +0 -11
- package/lib/models/front-matter.js +0 -2
- package/lib/models/gitpod-data.d.ts +0 -16
- package/lib/models/gitpod-data.js +0 -2
- package/lib/models/language.d.ts +0 -4
- package/lib/models/language.js +0 -2
- package/lib/models/package.d.ts +0 -7
- package/lib/models/package.js +0 -2
- package/lib/models/plugin-config.d.ts +0 -16
- package/lib/models/plugin-config.js +0 -2
- package/lib/models/session.d.ts +0 -23
- package/lib/models/session.js +0 -2
- package/lib/models/socket.d.ts +0 -31
- package/lib/models/socket.js +0 -2
- package/lib/models/status.d.ts +0 -1
- package/lib/models/status.js +0 -2
- package/lib/models/success-types.d.ts +0 -1
- package/lib/models/success-types.js +0 -2
- package/lib/plugin/command/compile.d.ts +0 -6
- package/lib/plugin/command/compile.js +0 -18
- package/lib/plugin/command/test.d.ts +0 -6
- package/lib/plugin/command/test.js +0 -25
- package/lib/plugin/index.d.ts +0 -27
- package/lib/plugin/index.js +0 -7
- package/lib/plugin/plugin.d.ts +0 -8
- package/lib/plugin/plugin.js +0 -68
- package/lib/plugin/utils.d.ts +0 -16
- package/lib/plugin/utils.js +0 -58
- package/lib/ui/download.d.ts +0 -5
- package/lib/ui/download.js +0 -61
- package/lib/utils/BaseCommand.d.ts +0 -8
- package/lib/utils/BaseCommand.js +0 -41
- package/lib/utils/SessionCommand.d.ts +0 -10
- package/lib/utils/SessionCommand.js +0 -47
- package/lib/utils/api.d.ts +0 -12
- package/lib/utils/api.js +0 -173
- package/lib/utils/audit.d.ts +0 -16
- package/lib/utils/audit.js +0 -302
- package/lib/utils/console.d.ts +0 -12
- package/lib/utils/console.js +0 -19
- package/lib/utils/errors.d.ts +0 -17
- package/lib/utils/errors.js +0 -100
- package/lib/utils/exercisesQueue.d.ts +0 -9
- package/lib/utils/exercisesQueue.js +0 -38
- package/lib/utils/fileQueue.d.ts +0 -40
- package/lib/utils/fileQueue.js +0 -168
- package/lib/utils/misc.d.ts +0 -1
- package/lib/utils/misc.js +0 -23
- package/lib/utils/validators.d.ts +0 -5
- package/lib/utils/validators.js +0 -17
- package/lib/utils/watcher.d.ts +0 -2
- package/lib/utils/watcher.js +0 -23
package/src/commands/audit.ts
CHANGED
|
@@ -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,71 +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
|
+
// check if the slug property is in the configuration object
|
|
98
99
|
if (!config!.config?.slug)
|
|
99
100
|
errors.push({
|
|
100
101
|
exercise: undefined,
|
|
101
102
|
msg: "The slug property is not in the configuration object",
|
|
102
|
-
})
|
|
103
|
+
})
|
|
104
|
+
// check if the duration property is in the configuration object
|
|
105
|
+
if (!config!.config?.duration)
|
|
106
|
+
warnings.push({
|
|
107
|
+
exercise: undefined,
|
|
108
|
+
msg: "The duration property is not in the configuration object",
|
|
109
|
+
})
|
|
110
|
+
// check if the difficulty property is in the configuration object
|
|
111
|
+
if (!config!.config?.difficulty)
|
|
112
|
+
warnings.push({
|
|
113
|
+
exercise: undefined,
|
|
114
|
+
msg: "The difficulty property is not in the configuration object",
|
|
115
|
+
})
|
|
116
|
+
// check if the bugs_link property is in the configuration object
|
|
117
|
+
if (!config!.config?.bugsLink)
|
|
118
|
+
errors.push({
|
|
119
|
+
exercise: undefined,
|
|
120
|
+
msg: "The bugsLink property is not in the configuration object",
|
|
121
|
+
})
|
|
122
|
+
// check if the video_solutions property is in the configuration object
|
|
123
|
+
if (config!.config?.videoSolutions === undefined)
|
|
124
|
+
warnings.push({
|
|
125
|
+
exercise: undefined,
|
|
126
|
+
msg: "The videoSolutions property is not in the configuration object",
|
|
127
|
+
})
|
|
103
128
|
|
|
104
129
|
// These two lines check if the 'repository' property is inside the configuration object.
|
|
105
130
|
Console.debug(
|
|
106
131
|
"Checking if the repository property is inside the configuration object..."
|
|
107
|
-
)
|
|
132
|
+
)
|
|
108
133
|
if (!config!.config?.repository)
|
|
109
134
|
errors.push({
|
|
110
135
|
exercise: undefined,
|
|
111
136
|
msg: "The repository property is not in the configuration object",
|
|
112
|
-
})
|
|
137
|
+
})
|
|
113
138
|
else
|
|
114
|
-
Audit.isUrl(config!.config?.repository, errors, counter)
|
|
139
|
+
Audit.isUrl(config!.config?.repository, errors, counter)
|
|
115
140
|
|
|
116
141
|
// These two lines check if the 'description' property is inside the configuration object.
|
|
117
142
|
Console.debug(
|
|
118
143
|
"Checking if the description property is inside the configuration object..."
|
|
119
|
-
)
|
|
144
|
+
)
|
|
120
145
|
if (!config!.config?.description)
|
|
121
146
|
errors.push({
|
|
122
147
|
exercise: undefined,
|
|
123
148
|
msg: "The description property is not in the configuration object",
|
|
124
|
-
})
|
|
149
|
+
})
|
|
125
150
|
|
|
126
151
|
if (errors.length === 0)
|
|
127
|
-
Console.log("The config file is ok")
|
|
152
|
+
Console.log("The config file is ok")
|
|
128
153
|
|
|
129
154
|
// Validates if images and links are working at every README file.
|
|
130
|
-
const exercises = config!.exercises
|
|
131
|
-
const readmeFiles = []
|
|
155
|
+
const exercises = config!.exercises
|
|
156
|
+
const readmeFiles = []
|
|
132
157
|
|
|
133
158
|
if (exercises && exercises.length > 0) {
|
|
134
|
-
Console.info(" Checking if the images are working...")
|
|
159
|
+
Console.info(" Checking if the images are working...")
|
|
135
160
|
for (const index in exercises) {
|
|
136
161
|
if (Object.prototype.hasOwnProperty.call(exercises, index)) {
|
|
137
|
-
const exercise = exercises[index]
|
|
162
|
+
const exercise = exercises[index]
|
|
138
163
|
if (!validateExerciseDirectoryName(exercise.title))
|
|
139
164
|
errors.push({
|
|
140
165
|
exercise: exercise.title,
|
|
141
166
|
msg: `The exercise ${exercise.title} has an invalid name.`,
|
|
142
|
-
})
|
|
143
|
-
let readmeFilesCount = { exercise: exercise.title, count: 0 }
|
|
167
|
+
})
|
|
168
|
+
let readmeFilesCount = { exercise: exercise.title, count: 0 }
|
|
144
169
|
if (Object.keys(exercise.translations!).length === 0)
|
|
145
170
|
errors.push({
|
|
146
171
|
exercise: exercise.title,
|
|
147
172
|
msg: `The exercise ${exercise.title} doesn't have a README.md file.`,
|
|
148
|
-
})
|
|
173
|
+
})
|
|
149
174
|
|
|
150
175
|
if (
|
|
151
176
|
exercise.language === "python3" ||
|
|
@@ -156,13 +181,13 @@ Console.log("The config file is ok");
|
|
|
156
181
|
f.path.includes("test.py") ||
|
|
157
182
|
f.path.includes("tests.py")
|
|
158
183
|
) {
|
|
159
|
-
const content = fs.readFileSync(f.path).toString()
|
|
160
|
-
const isEmpty = Audit.checkForEmptySpaces(content)
|
|
184
|
+
const content = fs.readFileSync(f.path).toString()
|
|
185
|
+
const isEmpty = Audit.checkForEmptySpaces(content)
|
|
161
186
|
if (isEmpty || !content)
|
|
162
187
|
errors.push({
|
|
163
188
|
exercise: exercise.title,
|
|
164
189
|
msg: `This file (${f.name}) doesn't have any content inside.`,
|
|
165
|
-
})
|
|
190
|
+
})
|
|
166
191
|
}
|
|
167
192
|
}
|
|
168
193
|
} else {
|
|
@@ -171,13 +196,13 @@ Console.log("The config file is ok");
|
|
|
171
196
|
f.path.includes("test.js") ||
|
|
172
197
|
f.path.includes("tests.js")
|
|
173
198
|
) {
|
|
174
|
-
const content = fs.readFileSync(f.path).toString()
|
|
175
|
-
const isEmpty: boolean = Audit.checkForEmptySpaces(content)
|
|
199
|
+
const content = fs.readFileSync(f.path).toString()
|
|
200
|
+
const isEmpty: boolean = Audit.checkForEmptySpaces(content)
|
|
176
201
|
if (isEmpty || !content)
|
|
177
202
|
errors.push({
|
|
178
203
|
exercise: exercise.title,
|
|
179
204
|
msg: `This file (${f.name}) doesn't have any content inside.`,
|
|
180
|
-
})
|
|
205
|
+
})
|
|
181
206
|
}
|
|
182
207
|
}
|
|
183
208
|
}
|
|
@@ -189,15 +214,15 @@ Console.log("The config file is ok");
|
|
|
189
214
|
lang
|
|
190
215
|
)
|
|
191
216
|
) {
|
|
192
|
-
const files: any[] = []
|
|
193
|
-
const findResultPromises = []
|
|
217
|
+
const files: any[] = []
|
|
218
|
+
const findResultPromises = []
|
|
194
219
|
for (const file of exercise.files) {
|
|
195
220
|
const found = find(
|
|
196
221
|
file,
|
|
197
222
|
exercise.translations[lang],
|
|
198
223
|
exercise
|
|
199
|
-
)
|
|
200
|
-
findResultPromises.push(found)
|
|
224
|
+
)
|
|
225
|
+
findResultPromises.push(found)
|
|
201
226
|
}
|
|
202
227
|
// eslint-disable-next-line
|
|
203
228
|
let findResults = await Promise.all(findResultPromises);
|
|
@@ -206,8 +231,8 @@ Console.log("The config file is ok");
|
|
|
206
231
|
readmeFilesCount = {
|
|
207
232
|
...readmeFilesCount,
|
|
208
233
|
count: readmeFilesCount.count + 1,
|
|
209
|
-
}
|
|
210
|
-
files.push(found)
|
|
234
|
+
}
|
|
235
|
+
files.push(found)
|
|
211
236
|
}
|
|
212
237
|
}
|
|
213
238
|
|
|
@@ -215,50 +240,50 @@ Console.log("The config file is ok");
|
|
|
215
240
|
errors.push({
|
|
216
241
|
exercise: exercise.title,
|
|
217
242
|
msg: "This exercise doesn't have a README.md file.",
|
|
218
|
-
})
|
|
243
|
+
})
|
|
219
244
|
}
|
|
220
245
|
}
|
|
221
246
|
|
|
222
|
-
readmeFiles.push(readmeFilesCount)
|
|
247
|
+
readmeFiles.push(readmeFilesCount)
|
|
223
248
|
}
|
|
224
249
|
}
|
|
225
250
|
} else
|
|
226
251
|
errors.push({
|
|
227
252
|
exercise: undefined,
|
|
228
253
|
msg: "The exercises array is empty.",
|
|
229
|
-
})
|
|
254
|
+
})
|
|
230
255
|
|
|
231
256
|
Console.log(
|
|
232
257
|
`${counter.images.total - counter.images.error} images ok from ${
|
|
233
258
|
counter.images.total
|
|
234
259
|
}`
|
|
235
|
-
)
|
|
260
|
+
)
|
|
236
261
|
|
|
237
262
|
Console.info(
|
|
238
263
|
" Checking if important files are missing... (README's, translations, gitignore...)"
|
|
239
|
-
)
|
|
264
|
+
)
|
|
240
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.
|
|
241
|
-
const files: string[] = []
|
|
242
|
-
let count = 0
|
|
266
|
+
const files: string[] = []
|
|
267
|
+
let count = 0
|
|
243
268
|
for (const item of readmeFiles) {
|
|
244
269
|
if (count < item.count)
|
|
245
|
-
count = item.count
|
|
270
|
+
count = item.count
|
|
246
271
|
}
|
|
247
272
|
|
|
248
273
|
for (const item of readmeFiles) {
|
|
249
274
|
if (item.count !== count)
|
|
250
|
-
files.push(` ${item.exercise}`)
|
|
275
|
+
files.push(` ${item.exercise}`)
|
|
251
276
|
}
|
|
252
277
|
|
|
253
278
|
if (files.length > 0) {
|
|
254
|
-
const filesString: string = files.join(",")
|
|
279
|
+
const filesString: string = files.join(",")
|
|
255
280
|
warnings.push({
|
|
256
281
|
exercise: undefined,
|
|
257
282
|
msg:
|
|
258
283
|
files.length === 1 ?
|
|
259
284
|
`This exercise is missing translations:${filesString}` :
|
|
260
285
|
`These exercises are missing translations:${filesString}`,
|
|
261
|
-
})
|
|
286
|
+
})
|
|
262
287
|
}
|
|
263
288
|
|
|
264
289
|
// Checks if the .gitignore file exists.
|
|
@@ -266,11 +291,11 @@ files.push(` ${item.exercise}`);
|
|
|
266
291
|
warnings.push({
|
|
267
292
|
exercise: undefined,
|
|
268
293
|
msg: ".gitignore file doesn't exist",
|
|
269
|
-
})
|
|
294
|
+
})
|
|
270
295
|
|
|
271
|
-
counter.exercises = exercises!.length
|
|
296
|
+
counter.exercises = exercises!.length
|
|
272
297
|
for (const readme of readmeFiles) {
|
|
273
|
-
counter.readmeFiles += readme.count
|
|
298
|
+
counter.readmeFiles += readme.count
|
|
274
299
|
}
|
|
275
300
|
} else {
|
|
276
301
|
// This is the audit code for Projects
|
|
@@ -278,68 +303,68 @@ files.push(` ${item.exercise}`);
|
|
|
278
303
|
// Getting the learn.json schema
|
|
279
304
|
const schemaResponse = await fetch(
|
|
280
305
|
"https://raw.githubusercontent.com/tommygonzaleza/project-template/main/.github/learn-schema.json"
|
|
281
|
-
)
|
|
282
|
-
const schema = await schemaResponse.json()
|
|
306
|
+
)
|
|
307
|
+
const schema = await schemaResponse.json()
|
|
283
308
|
|
|
284
309
|
// Checking the "learn.json" file:
|
|
285
310
|
const learnjson = JSON.parse(
|
|
286
311
|
fs.readFileSync("./learn.json").toString()
|
|
287
|
-
)
|
|
312
|
+
)
|
|
288
313
|
|
|
289
314
|
if (!learnjson) {
|
|
290
315
|
Console.error(
|
|
291
316
|
"There is no learn.json file located in the root of the project."
|
|
292
|
-
)
|
|
293
|
-
process.exit(1)
|
|
317
|
+
)
|
|
318
|
+
process.exit(1)
|
|
294
319
|
}
|
|
295
320
|
|
|
296
321
|
// Checking the README.md files and possible translations.
|
|
297
|
-
let readmeFiles: any[] = []
|
|
298
|
-
const translations: string[] = []
|
|
299
|
-
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/
|
|
300
325
|
|
|
301
326
|
try {
|
|
302
|
-
const data = await fs.promises.readdir("./")
|
|
303
|
-
readmeFiles = data.filter(file => file.includes("README"))
|
|
327
|
+
const data = await fs.promises.readdir("./")
|
|
328
|
+
readmeFiles = data.filter(file => file.includes("README"))
|
|
304
329
|
if (readmeFiles.length === 0)
|
|
305
330
|
errors.push({
|
|
306
331
|
exercise: undefined!,
|
|
307
332
|
msg: `There is no README file in the repository.`,
|
|
308
|
-
})
|
|
333
|
+
})
|
|
309
334
|
} catch (error) {
|
|
310
335
|
if (error)
|
|
311
336
|
Console.error(
|
|
312
337
|
"There was an error getting the directory files",
|
|
313
338
|
error
|
|
314
|
-
)
|
|
339
|
+
)
|
|
315
340
|
}
|
|
316
341
|
|
|
317
342
|
for (const readmeFile of readmeFiles) {
|
|
318
343
|
// Checking the language of each README file.
|
|
319
344
|
if (readmeFile === "README.md")
|
|
320
|
-
translations.push("us")
|
|
345
|
+
translations.push("us")
|
|
321
346
|
else {
|
|
322
|
-
const regexGroups = translationRegex.exec(readmeFile)
|
|
347
|
+
const regexGroups = translationRegex.exec(readmeFile)
|
|
323
348
|
if (regexGroups)
|
|
324
|
-
translations.push(regexGroups[1])
|
|
349
|
+
translations.push(regexGroups[1])
|
|
325
350
|
}
|
|
326
351
|
|
|
327
|
-
const readme = fs.readFileSync(path.resolve(readmeFile)).toString()
|
|
352
|
+
const readme = fs.readFileSync(path.resolve(readmeFile)).toString()
|
|
328
353
|
|
|
329
|
-
const isEmpty = Audit.checkForEmptySpaces(readme)
|
|
354
|
+
const isEmpty = Audit.checkForEmptySpaces(readme)
|
|
330
355
|
if (isEmpty || !readme) {
|
|
331
356
|
errors.push({
|
|
332
357
|
exercise: undefined!,
|
|
333
358
|
msg: `This file "${readmeFile}" doesn't have any content inside.`,
|
|
334
|
-
})
|
|
335
|
-
continue
|
|
359
|
+
})
|
|
360
|
+
continue
|
|
336
361
|
}
|
|
337
362
|
|
|
338
363
|
if (readme.length < 800)
|
|
339
364
|
errors.push({
|
|
340
365
|
exercise: undefined,
|
|
341
366
|
msg: `The "${readmeFile}" file should have at least 800 characters (It currently have: ${readme.length}).`,
|
|
342
|
-
})
|
|
367
|
+
})
|
|
343
368
|
|
|
344
369
|
// eslint-disable-next-line
|
|
345
370
|
await Audit.checkUrl(
|
|
@@ -351,43 +376,43 @@ translations.push(regexGroups[1]);
|
|
|
351
376
|
warnings,
|
|
352
377
|
// eslint-disable-next-line
|
|
353
378
|
undefined
|
|
354
|
-
)
|
|
379
|
+
)
|
|
355
380
|
}
|
|
356
381
|
|
|
357
382
|
// Adding the translations to the learn.json
|
|
358
|
-
learnjson.translations = translations
|
|
383
|
+
learnjson.translations = translations
|
|
359
384
|
|
|
360
385
|
// Checking if the preview image (from the learn.json) is OK.
|
|
361
386
|
try {
|
|
362
|
-
const res = await fetch(learnjson.preview, { method: "HEAD" })
|
|
387
|
+
const res = await fetch(learnjson.preview, { method: "HEAD" })
|
|
363
388
|
if (res.status > 399 && res.status < 500) {
|
|
364
389
|
errors.push({
|
|
365
390
|
exercise: undefined,
|
|
366
391
|
msg: `The link of the "preview" is broken: ${learnjson.preview}`,
|
|
367
|
-
})
|
|
392
|
+
})
|
|
368
393
|
}
|
|
369
394
|
} catch {
|
|
370
395
|
errors.push({
|
|
371
396
|
exercise: undefined,
|
|
372
397
|
msg: `The link of the "preview" is broken: ${learnjson.preview}`,
|
|
373
|
-
})
|
|
398
|
+
})
|
|
374
399
|
}
|
|
375
400
|
|
|
376
|
-
const date = new Date()
|
|
377
|
-
learnjson.validationAt = date.getTime()
|
|
401
|
+
const date = new Date()
|
|
402
|
+
learnjson.validationAt = date.getTime()
|
|
378
403
|
|
|
379
404
|
if (errors.length > 0)
|
|
380
|
-
learnjson.validationStatus = "error"
|
|
405
|
+
learnjson.validationStatus = "error"
|
|
381
406
|
else if (warnings.length > 0)
|
|
382
|
-
learnjson.validationStatus = "warning"
|
|
407
|
+
learnjson.validationStatus = "warning"
|
|
383
408
|
else
|
|
384
|
-
learnjson.validationStatus = "success"
|
|
409
|
+
learnjson.validationStatus = "success"
|
|
385
410
|
|
|
386
411
|
// Writes the "learn.json" file with all the new properties
|
|
387
|
-
await fs.promises.writeFile("./learn.json", JSON.stringify(learnjson))
|
|
412
|
+
await fs.promises.writeFile("./learn.json", JSON.stringify(learnjson))
|
|
388
413
|
}
|
|
389
414
|
|
|
390
|
-
await Audit.showWarnings(warnings)
|
|
415
|
+
await Audit.showWarnings(warnings)
|
|
391
416
|
// eslint-disable-next-line
|
|
392
417
|
await Audit.showErrors(errors, undefined);
|
|
393
418
|
}
|
|
@@ -409,10 +434,10 @@ learnpack audit checks for the following information in a repository:
|
|
|
409
434
|
10. The exercses have the same translations. (Warning)
|
|
410
435
|
11. The .gitignore file exists. (Warning)
|
|
411
436
|
12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)
|
|
412
|
-
|
|
437
|
+
`
|
|
413
438
|
|
|
414
439
|
AuditCommand.flags = {
|
|
415
440
|
// name: flags.string({char: 'n', description: 'name to print'}),
|
|
416
|
-
}
|
|
441
|
+
}
|
|
417
442
|
|
|
418
|
-
export default AuditCommand
|
|
443
|
+
export default AuditCommand
|
package/src/commands/clean.ts
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
// import {flags} from '@oclif/command'
|
|
2
|
-
import Console from "../utils/console"
|
|
3
|
-
import SessionCommand from "../utils/SessionCommand"
|
|
4
|
-
|
|
5
|
-
class CleanCommand extends SessionCommand {
|
|
6
|
-
static description = `Clean the configuration object
|
|
7
|
-
...
|
|
8
|
-
Extra documentation goes here
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
static flags: any = {
|
|
12
|
-
// name: flags.string({char: 'n', description: 'name to print'}),
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async init() {
|
|
16
|
-
const { flags } = this.parse(CleanCommand)
|
|
17
|
-
await this.initSession(flags)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
async run() {
|
|
21
|
-
const { flags } = this.parse(CleanCommand)
|
|
22
|
-
|
|
23
|
-
this.configManager?.clean()
|
|
24
|
-
|
|
25
|
-
Console.success("Package cleaned successfully, ready to publish")
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export default CleanCommand
|
|
1
|
+
// import {flags} from '@oclif/command'
|
|
2
|
+
import Console from "../utils/console"
|
|
3
|
+
import SessionCommand from "../utils/SessionCommand"
|
|
4
|
+
|
|
5
|
+
class CleanCommand extends SessionCommand {
|
|
6
|
+
static description = `Clean the configuration object
|
|
7
|
+
...
|
|
8
|
+
Extra documentation goes here
|
|
9
|
+
`
|
|
10
|
+
|
|
11
|
+
static flags: any = {
|
|
12
|
+
// name: flags.string({char: 'n', description: 'name to print'}),
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async init() {
|
|
16
|
+
const { flags } = this.parse(CleanCommand)
|
|
17
|
+
await this.initSession(flags)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async run() {
|
|
21
|
+
const { flags } = this.parse(CleanCommand)
|
|
22
|
+
|
|
23
|
+
this.configManager?.clean()
|
|
24
|
+
|
|
25
|
+
Console.success("Package cleaned successfully, ready to publish")
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default CleanCommand
|