@learnpack/learnpack 5.0.7 → 5.0.9
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 +17 -17
- package/bin/run +17 -17
- package/bin/run.cmd +3 -3
- package/lib/commands/audit.js +34 -22
- package/lib/commands/clean.js +3 -3
- package/lib/commands/download.js +3 -3
- package/lib/commands/login.js +3 -3
- package/lib/commands/logout.js +3 -3
- package/lib/managers/config/index.d.ts +10 -0
- package/lib/managers/config/index.js +3 -1
- package/oclif.manifest.json +1 -1
- package/package.json +152 -152
- package/src/commands/audit.ts +449 -443
- package/src/commands/clean.ts +29 -29
- package/src/commands/download.ts +61 -61
- package/src/commands/login.ts +42 -42
- package/src/commands/logout.ts +43 -43
- package/src/commands/publish.ts +249 -249
- 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/index.ts +6 -4
- package/src/managers/gitpod.ts +84 -84
- package/src/managers/server/index.ts +78 -78
- package/src/managers/telemetry.ts +353 -353
- package/src/managers/test.ts +83 -83
- package/src/models/audit.ts +16 -16
- package/src/models/config-manager.ts +23 -23
- package/src/models/counter.ts +11 -11
- package/src/models/errors.ts +22 -22
- package/src/models/exercise-obj.ts +29 -29
- 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/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 +43 -43
- package/src/utils/audit.ts +393 -393
- package/src/utils/errors.ts +117 -117
- package/src/utils/exercisesQueue.ts +51 -51
- package/src/utils/fileQueue.ts +199 -199
- package/src/utils/misc.ts +23 -23
- package/src/utils/osOperations.ts +79 -79
- 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/.vscode/schema.json +121 -121
- package/src/utils/templates/incremental/.vscode/settings.json +13 -13
- package/src/utils/templates/incremental/README.ejs +4 -4
- package/src/utils/templates/incremental/README.es.ejs +4 -4
- package/src/utils/templates/isolated/.vscode/schema.json +121 -121
- package/src/utils/templates/isolated/.vscode/settings.json +13 -13
- 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 +27 -27
@@ -1,29 +1,29 @@
|
|
1
|
-
const extensions = {
|
2
|
-
extensions: [
|
3
|
-
"py",
|
4
|
-
"java",
|
5
|
-
"py",
|
6
|
-
"ruby",
|
7
|
-
"html",
|
8
|
-
"css",
|
9
|
-
"htm",
|
10
|
-
"php", // images
|
11
|
-
"js",
|
12
|
-
"jsx",
|
13
|
-
"ts", // images
|
14
|
-
"sh",
|
15
|
-
"bash", // images
|
16
|
-
"json",
|
17
|
-
"yml",
|
18
|
-
"yaml",
|
19
|
-
"csv",
|
20
|
-
"xml", // file storage extensions
|
21
|
-
"txt",
|
22
|
-
"text",
|
23
|
-
"markdown",
|
24
|
-
"readme", // compressed files
|
25
|
-
],
|
26
|
-
names: ["package.json", "package-lock.json"],
|
27
|
-
}
|
28
|
-
|
29
|
-
export default extensions
|
1
|
+
const extensions = {
|
2
|
+
extensions: [
|
3
|
+
"py",
|
4
|
+
"java",
|
5
|
+
"py",
|
6
|
+
"ruby",
|
7
|
+
"html",
|
8
|
+
"css",
|
9
|
+
"htm",
|
10
|
+
"php", // images
|
11
|
+
"js",
|
12
|
+
"jsx",
|
13
|
+
"ts", // images
|
14
|
+
"sh",
|
15
|
+
"bash", // images
|
16
|
+
"json",
|
17
|
+
"yml",
|
18
|
+
"yaml",
|
19
|
+
"csv",
|
20
|
+
"xml", // file storage extensions
|
21
|
+
"txt",
|
22
|
+
"text",
|
23
|
+
"markdown",
|
24
|
+
"readme", // compressed files
|
25
|
+
],
|
26
|
+
names: ["package.json", "package-lock.json"],
|
27
|
+
}
|
28
|
+
|
29
|
+
export default extensions
|
@@ -32,9 +32,9 @@ import { IFile } from "../../models/file"
|
|
32
32
|
const execAsync = promisify(exec)
|
33
33
|
|
34
34
|
// eslint-disable-next-line
|
35
|
-
const fetch = require("node-fetch")
|
35
|
+
const fetch = require("node-fetch");
|
36
36
|
// eslint-disable-next-line
|
37
|
-
const chalk = require("chalk")
|
37
|
+
const chalk = require("chalk");
|
38
38
|
|
39
39
|
/* exercise folder name standard */
|
40
40
|
|
@@ -44,7 +44,7 @@ const chalk = require("chalk")
|
|
44
44
|
* @returns An object containing the configuration file path and the base directory.
|
45
45
|
* @throws NotFoundError if the learn.json file is not found in the current folder.
|
46
46
|
*/
|
47
|
-
const getConfigPath = () => {
|
47
|
+
export const getConfigPath = () => {
|
48
48
|
const possibleFileNames = ["learn.json", ".learn/learn.json"]
|
49
49
|
const config = possibleFileNames.find(file => fs.existsSync(file)) || null
|
50
50
|
if (config && fs.existsSync(".breathecode"))
|
@@ -444,7 +444,9 @@ fs.unlinkSync(_path)
|
|
444
444
|
ex => ex.slug === slug
|
445
445
|
)
|
446
446
|
if (!exercise)
|
447
|
-
throw ValidationError(
|
447
|
+
throw ValidationError(
|
448
|
+
`Exercise ${slug} not found on the configuration`
|
449
|
+
)
|
448
450
|
|
449
451
|
if (configObj.config) {
|
450
452
|
for (const fileName of fs.readdirSync(
|
package/src/managers/gitpod.ts
CHANGED
@@ -1,84 +1,84 @@
|
|
1
|
-
import Console from '../utils/console'
|
2
|
-
import * as shell from 'shelljs'
|
3
|
-
import socket from './socket'
|
4
|
-
import * as fs from 'fs'
|
5
|
-
|
6
|
-
import {TFile, IGitpod} from '../models/gitpod-data'
|
7
|
-
import {IConfigObj} from '../models/config'
|
8
|
-
|
9
|
-
const Gitpod: IGitpod = {
|
10
|
-
socket: null,
|
11
|
-
config: null,
|
12
|
-
initialized: false,
|
13
|
-
hasGPCommand: false,
|
14
|
-
init: function (config?: IConfigObj) {
|
15
|
-
if (this.initialized) {
|
16
|
-
return
|
17
|
-
}
|
18
|
-
|
19
|
-
this.initialized = true
|
20
|
-
|
21
|
-
if (config) {
|
22
|
-
this.config = config
|
23
|
-
}
|
24
|
-
|
25
|
-
if (shell.exec('gp -h', {silent: true}).code === 0) {
|
26
|
-
this.hasGPCommand = true
|
27
|
-
if (config) {
|
28
|
-
config.address = shell
|
29
|
-
.exec('gp url', {silent: true})
|
30
|
-
.stdout.replace(/(\r\n|\n|\r)/gm, '')
|
31
|
-
}
|
32
|
-
} else {
|
33
|
-
Console.debug('Gitpod command line tool not found')
|
34
|
-
}
|
35
|
-
},
|
36
|
-
openFiles: async function (files: Array<TFile>) {
|
37
|
-
Console.debug('Attempting to open files in gitpod mode', files)
|
38
|
-
this.init() // initilize gitpod config
|
39
|
-
|
40
|
-
// gitpod will open files only on isolated mode
|
41
|
-
if (!this.config || this.config.config?.grading !== 'isolated') {
|
42
|
-
Console.debug(
|
43
|
-
'Files cannot be automatically opened because we are not on isolated grading (only for isolated)',
|
44
|
-
)
|
45
|
-
socket.log('ready', ['Ready to compile or test...'])
|
46
|
-
return true
|
47
|
-
}
|
48
|
-
|
49
|
-
if (this.hasGPCommand)
|
50
|
-
for (const f of files.reverse()) {
|
51
|
-
if (shell.exec(`gp open ${f}`).code > 0) {
|
52
|
-
Console.debug(`Error opening file ${f} on gitpod`)
|
53
|
-
}
|
54
|
-
}
|
55
|
-
|
56
|
-
socket.log('ready', ['Ready to compile or test...'])
|
57
|
-
},
|
58
|
-
setup(config?: IConfigObj) {
|
59
|
-
this.init(config) // initilize gitpod config
|
60
|
-
this.autosave('on')
|
61
|
-
},
|
62
|
-
autosave: async function (value = 'on') {
|
63
|
-
this.init() // initilize gitpod config
|
64
|
-
|
65
|
-
if (this.hasGPCommand) {
|
66
|
-
if (!fs.existsSync('./.theia'))
|
67
|
-
fs.mkdirSync('./.theia')
|
68
|
-
if (!fs.existsSync('./.theia/settings.json')) {
|
69
|
-
fs.writeFileSync(
|
70
|
-
'./.theia/settings.json',
|
71
|
-
JSON.stringify(
|
72
|
-
{
|
73
|
-
'editor.autoSave': value,
|
74
|
-
},
|
75
|
-
null,
|
76
|
-
4,
|
77
|
-
),
|
78
|
-
)
|
79
|
-
}
|
80
|
-
}
|
81
|
-
},
|
82
|
-
}
|
83
|
-
|
84
|
-
export default Gitpod
|
1
|
+
import Console from '../utils/console'
|
2
|
+
import * as shell from 'shelljs'
|
3
|
+
import socket from './socket'
|
4
|
+
import * as fs from 'fs'
|
5
|
+
|
6
|
+
import {TFile, IGitpod} from '../models/gitpod-data'
|
7
|
+
import {IConfigObj} from '../models/config'
|
8
|
+
|
9
|
+
const Gitpod: IGitpod = {
|
10
|
+
socket: null,
|
11
|
+
config: null,
|
12
|
+
initialized: false,
|
13
|
+
hasGPCommand: false,
|
14
|
+
init: function (config?: IConfigObj) {
|
15
|
+
if (this.initialized) {
|
16
|
+
return
|
17
|
+
}
|
18
|
+
|
19
|
+
this.initialized = true
|
20
|
+
|
21
|
+
if (config) {
|
22
|
+
this.config = config
|
23
|
+
}
|
24
|
+
|
25
|
+
if (shell.exec('gp -h', {silent: true}).code === 0) {
|
26
|
+
this.hasGPCommand = true
|
27
|
+
if (config) {
|
28
|
+
config.address = shell
|
29
|
+
.exec('gp url', {silent: true})
|
30
|
+
.stdout.replace(/(\r\n|\n|\r)/gm, '')
|
31
|
+
}
|
32
|
+
} else {
|
33
|
+
Console.debug('Gitpod command line tool not found')
|
34
|
+
}
|
35
|
+
},
|
36
|
+
openFiles: async function (files: Array<TFile>) {
|
37
|
+
Console.debug('Attempting to open files in gitpod mode', files)
|
38
|
+
this.init() // initilize gitpod config
|
39
|
+
|
40
|
+
// gitpod will open files only on isolated mode
|
41
|
+
if (!this.config || this.config.config?.grading !== 'isolated') {
|
42
|
+
Console.debug(
|
43
|
+
'Files cannot be automatically opened because we are not on isolated grading (only for isolated)',
|
44
|
+
)
|
45
|
+
socket.log('ready', ['Ready to compile or test...'])
|
46
|
+
return true
|
47
|
+
}
|
48
|
+
|
49
|
+
if (this.hasGPCommand)
|
50
|
+
for (const f of files.reverse()) {
|
51
|
+
if (shell.exec(`gp open ${f}`).code > 0) {
|
52
|
+
Console.debug(`Error opening file ${f} on gitpod`)
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
socket.log('ready', ['Ready to compile or test...'])
|
57
|
+
},
|
58
|
+
setup(config?: IConfigObj) {
|
59
|
+
this.init(config) // initilize gitpod config
|
60
|
+
this.autosave('on')
|
61
|
+
},
|
62
|
+
autosave: async function (value = 'on') {
|
63
|
+
this.init() // initilize gitpod config
|
64
|
+
|
65
|
+
if (this.hasGPCommand) {
|
66
|
+
if (!fs.existsSync('./.theia'))
|
67
|
+
fs.mkdirSync('./.theia')
|
68
|
+
if (!fs.existsSync('./.theia/settings.json')) {
|
69
|
+
fs.writeFileSync(
|
70
|
+
'./.theia/settings.json',
|
71
|
+
JSON.stringify(
|
72
|
+
{
|
73
|
+
'editor.autoSave': value,
|
74
|
+
},
|
75
|
+
null,
|
76
|
+
4,
|
77
|
+
),
|
78
|
+
)
|
79
|
+
}
|
80
|
+
}
|
81
|
+
},
|
82
|
+
}
|
83
|
+
|
84
|
+
export default Gitpod
|
@@ -1,78 +1,78 @@
|
|
1
|
-
import * as express from "express"
|
2
|
-
// eslint-disable-next-line
|
3
|
-
import * as cors from "cors";
|
4
|
-
import * as http from "http"
|
5
|
-
import Console from "../../utils/console"
|
6
|
-
import addRoutes from "./routes"
|
7
|
-
import cli from "cli-ux"
|
8
|
-
import { IConfigObj } from "../../models/config"
|
9
|
-
import { IConfigManager } from "../../models/config-manager"
|
10
|
-
|
11
|
-
export let TEST_SERVER: http.Server
|
12
|
-
|
13
|
-
export default async function (
|
14
|
-
configObj: IConfigObj,
|
15
|
-
configManager: IConfigManager,
|
16
|
-
isTestingEnvironment = false
|
17
|
-
) {
|
18
|
-
const { config } = configObj
|
19
|
-
const app = express()
|
20
|
-
let server: any
|
21
|
-
|
22
|
-
if (isTestingEnvironment) {
|
23
|
-
if (TEST_SERVER === undefined)
|
24
|
-
TEST_SERVER = require("http").Server(app)
|
25
|
-
server = TEST_SERVER
|
26
|
-
} else
|
27
|
-
server = require("http").Server(app)
|
28
|
-
|
29
|
-
app.use(cors())
|
30
|
-
|
31
|
-
// app.use(function(req, res, next) {
|
32
|
-
// res.header("Access-Control-Allow-Origin", "*")
|
33
|
-
// res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
|
34
|
-
// res.header("Access-Control-Allow-Methods", "GET,PUT")
|
35
|
-
// next()
|
36
|
-
// })
|
37
|
-
|
38
|
-
// add all needed endpoints
|
39
|
-
|
40
|
-
await addRoutes(app, configObj, configManager)
|
41
|
-
|
42
|
-
server.listen(isTestingEnvironment ? 5000 : config?.port, function () {
|
43
|
-
if (!isTestingEnvironment) {
|
44
|
-
Console.success(
|
45
|
-
`Exercises are running 😃 Open your browser to start practicing!`
|
46
|
-
)
|
47
|
-
Console.success(`\n Open the exercise on this link:`)
|
48
|
-
Console.log(` ${config?.publicUrl}`)
|
49
|
-
|
50
|
-
if (config?.editor.mode === "preview")
|
51
|
-
cli.open(`${config.publicUrl}`)
|
52
|
-
}
|
53
|
-
})
|
54
|
-
|
55
|
-
const sockets: any = new Set()
|
56
|
-
|
57
|
-
server.on("connection", (socket: any) => {
|
58
|
-
sockets.add(socket)
|
59
|
-
|
60
|
-
server.once("close", () => {
|
61
|
-
sockets.delete(socket)
|
62
|
-
})
|
63
|
-
})
|
64
|
-
|
65
|
-
/**
|
66
|
-
* Forcefully terminates HTTP server.
|
67
|
-
*/
|
68
|
-
server.terminate = (callback: void) => {
|
69
|
-
for (const socket of sockets) {
|
70
|
-
socket.destroy()
|
71
|
-
sockets.delete(socket)
|
72
|
-
}
|
73
|
-
|
74
|
-
server.close(callback)
|
75
|
-
}
|
76
|
-
|
77
|
-
return server
|
78
|
-
}
|
1
|
+
import * as express from "express"
|
2
|
+
// eslint-disable-next-line
|
3
|
+
import * as cors from "cors";
|
4
|
+
import * as http from "http"
|
5
|
+
import Console from "../../utils/console"
|
6
|
+
import addRoutes from "./routes"
|
7
|
+
import cli from "cli-ux"
|
8
|
+
import { IConfigObj } from "../../models/config"
|
9
|
+
import { IConfigManager } from "../../models/config-manager"
|
10
|
+
|
11
|
+
export let TEST_SERVER: http.Server
|
12
|
+
|
13
|
+
export default async function (
|
14
|
+
configObj: IConfigObj,
|
15
|
+
configManager: IConfigManager,
|
16
|
+
isTestingEnvironment = false
|
17
|
+
) {
|
18
|
+
const { config } = configObj
|
19
|
+
const app = express()
|
20
|
+
let server: any
|
21
|
+
|
22
|
+
if (isTestingEnvironment) {
|
23
|
+
if (TEST_SERVER === undefined)
|
24
|
+
TEST_SERVER = require("http").Server(app)
|
25
|
+
server = TEST_SERVER
|
26
|
+
} else
|
27
|
+
server = require("http").Server(app)
|
28
|
+
|
29
|
+
app.use(cors())
|
30
|
+
|
31
|
+
// app.use(function(req, res, next) {
|
32
|
+
// res.header("Access-Control-Allow-Origin", "*")
|
33
|
+
// res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
|
34
|
+
// res.header("Access-Control-Allow-Methods", "GET,PUT")
|
35
|
+
// next()
|
36
|
+
// })
|
37
|
+
|
38
|
+
// add all needed endpoints
|
39
|
+
|
40
|
+
await addRoutes(app, configObj, configManager)
|
41
|
+
|
42
|
+
server.listen(isTestingEnvironment ? 5000 : config?.port, function () {
|
43
|
+
if (!isTestingEnvironment) {
|
44
|
+
Console.success(
|
45
|
+
`Exercises are running 😃 Open your browser to start practicing!`
|
46
|
+
)
|
47
|
+
Console.success(`\n Open the exercise on this link:`)
|
48
|
+
Console.log(` ${config?.publicUrl}`)
|
49
|
+
|
50
|
+
if (config?.editor.mode === "preview")
|
51
|
+
cli.open(`${config.publicUrl}`)
|
52
|
+
}
|
53
|
+
})
|
54
|
+
|
55
|
+
const sockets: any = new Set()
|
56
|
+
|
57
|
+
server.on("connection", (socket: any) => {
|
58
|
+
sockets.add(socket)
|
59
|
+
|
60
|
+
server.once("close", () => {
|
61
|
+
sockets.delete(socket)
|
62
|
+
})
|
63
|
+
})
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Forcefully terminates HTTP server.
|
67
|
+
*/
|
68
|
+
server.terminate = (callback: void) => {
|
69
|
+
for (const socket of sockets) {
|
70
|
+
socket.destroy()
|
71
|
+
sockets.delete(socket)
|
72
|
+
}
|
73
|
+
|
74
|
+
server.close(callback)
|
75
|
+
}
|
76
|
+
|
77
|
+
return server
|
78
|
+
}
|