@learnpack/learnpack 2.1.26 → 2.1.28
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 +10 -10
- package/lib/commands/start.js +15 -4
- package/lib/managers/file.d.ts +1 -0
- package/lib/managers/file.js +8 -1
- package/lib/managers/server/routes.js +48 -14
- package/lib/managers/session.d.ts +1 -1
- package/lib/managers/session.js +39 -12
- package/lib/managers/socket.d.ts +1 -1
- package/lib/managers/socket.js +57 -43
- package/lib/models/action.d.ts +1 -1
- package/lib/models/config.d.ts +1 -1
- package/lib/models/exercise-obj.d.ts +3 -0
- package/lib/models/session.d.ts +4 -1
- package/lib/models/socket.d.ts +7 -6
- package/lib/models/status.d.ts +1 -1
- package/lib/utils/api.d.ts +2 -0
- package/lib/utils/api.js +51 -6
- package/oclif.manifest.json +1 -1
- package/package.json +3 -1
- package/src/commands/audit.ts +113 -113
- package/src/commands/clean.ts +10 -10
- package/src/commands/download.ts +18 -18
- package/src/commands/init.ts +39 -39
- package/src/commands/login.ts +13 -13
- package/src/commands/logout.ts +9 -9
- package/src/commands/publish.ts +25 -25
- package/src/commands/start.ts +101 -75
- package/src/commands/test.ts +34 -34
- package/src/managers/config/allowed_files.ts +2 -2
- package/src/managers/config/defaults.ts +2 -2
- package/src/managers/config/exercise.ts +79 -79
- package/src/managers/config/index.ts +145 -145
- package/src/managers/file.ts +74 -65
- package/src/managers/server/index.ts +32 -31
- package/src/managers/server/routes.ts +139 -90
- package/src/managers/session.ts +53 -24
- package/src/managers/socket.ts +92 -79
- package/src/models/action.ts +8 -1
- package/src/models/config-manager.ts +2 -2
- package/src/models/config.ts +7 -2
- package/src/models/exercise-obj.ts +6 -3
- package/src/models/plugin-config.ts +2 -2
- package/src/models/session.ts +5 -2
- package/src/models/socket.ts +12 -6
- package/src/models/status.ts +15 -14
- package/src/plugin/command/compile.ts +10 -10
- package/src/plugin/command/test.ts +14 -14
- package/src/plugin/index.ts +5 -5
- package/src/plugin/plugin.ts +26 -26
- package/src/plugin/utils.ts +23 -23
- package/src/utils/BaseCommand.ts +16 -16
- package/src/utils/api.ts +143 -91
- package/src/utils/audit.ts +93 -96
- package/src/utils/exercisesQueue.ts +15 -15
- package/src/utils/fileQueue.ts +85 -85
- package/src/utils/watcher.ts +14 -14
package/src/managers/file.ts
CHANGED
@@ -1,18 +1,18 @@
|
|
1
|
-
import * as fs from "fs"
|
2
|
-
import * as p from "path"
|
3
|
-
import * as shell from "shelljs"
|
4
|
-
import { cli } from "cli-ux"
|
5
|
-
import * as targz from "targz"
|
6
|
-
import Console from "../utils/console"
|
7
|
-
import * as https from "https"
|
8
|
-
import { InternalError } from "../utils/errors"
|
1
|
+
import * as fs from "fs"
|
2
|
+
import * as p from "path"
|
3
|
+
import * as shell from "shelljs"
|
4
|
+
import { cli } from "cli-ux"
|
5
|
+
import * as targz from "targz"
|
6
|
+
import Console from "../utils/console"
|
7
|
+
import * as https from "https"
|
8
|
+
import { InternalError } from "../utils/errors"
|
9
9
|
|
10
10
|
// eslint-disable-next-line
|
11
11
|
const fetch = require("node-fetch");
|
12
12
|
|
13
13
|
export const decompress = (sourcePath: string, destinationPath: string) =>
|
14
14
|
new Promise((resolve, reject) => {
|
15
|
-
Console.debug("Decompressing " + sourcePath)
|
15
|
+
Console.debug("Decompressing " + sourcePath)
|
16
16
|
targz.decompress(
|
17
17
|
{
|
18
18
|
src: sourcePath,
|
@@ -20,15 +20,15 @@ export const decompress = (sourcePath: string, destinationPath: string) =>
|
|
20
20
|
},
|
21
21
|
function (err: string | Error | null) {
|
22
22
|
if (err) {
|
23
|
-
Console.error("Error when trying to decompress")
|
24
|
-
reject(err)
|
23
|
+
Console.error("Error when trying to decompress")
|
24
|
+
reject(err)
|
25
25
|
} else {
|
26
|
-
Console.info("Decompression finished successfully")
|
27
|
-
resolve(/* */ "")
|
26
|
+
Console.info("Decompression finished successfully")
|
27
|
+
resolve(/* */ "")
|
28
28
|
}
|
29
29
|
}
|
30
|
-
)
|
31
|
-
})
|
30
|
+
)
|
31
|
+
})
|
32
32
|
|
33
33
|
export const downloadEditor = async (
|
34
34
|
version: string | undefined,
|
@@ -39,41 +39,41 @@ export const downloadEditor = async (
|
|
39
39
|
const resp2 = await fetch(
|
40
40
|
`https://github.com/learnpack/coding-ide/blob/${version}/dist`,
|
41
41
|
{ method: "HEAD" }
|
42
|
-
)
|
42
|
+
)
|
43
43
|
if (!resp2.ok)
|
44
44
|
throw InternalError(
|
45
45
|
`Coding Editor ${version} was not found on learnpack repository, check the config.editor.version property on learn.json`
|
46
|
-
)
|
46
|
+
)
|
47
47
|
|
48
48
|
Console.info(
|
49
49
|
"Downloading the LearnPack coding UI, this may take a minute..."
|
50
|
-
)
|
50
|
+
)
|
51
51
|
return download(
|
52
52
|
`https://github.com/learnpack/coding-ide/blob/${version}/dist/app.tar.gz?raw=true`,
|
53
53
|
destination
|
54
|
-
)
|
55
|
-
}
|
54
|
+
)
|
55
|
+
}
|
56
56
|
|
57
57
|
export const download = (url: string, dest: string) => {
|
58
|
-
Console.debug("Downloading " + url)
|
58
|
+
Console.debug("Downloading " + url)
|
59
59
|
return new Promise((resolve, reject) => {
|
60
60
|
const request = https.get(url, response => {
|
61
61
|
if (response.statusCode === 200) {
|
62
|
-
const file = fs.createWriteStream(dest, { flags: "wx" })
|
62
|
+
const file = fs.createWriteStream(dest, { flags: "wx" })
|
63
63
|
file.on("finish", () => {
|
64
|
-
resolve(true)
|
65
|
-
})
|
64
|
+
resolve(true)
|
65
|
+
})
|
66
66
|
file.on("error", err => {
|
67
|
-
file.close()
|
67
|
+
file.close()
|
68
68
|
if (err.code === "EEXIST") {
|
69
|
-
Console.debug("File already exists")
|
70
|
-
resolve("File already exists")
|
69
|
+
Console.debug("File already exists")
|
70
|
+
resolve("File already exists")
|
71
71
|
} else {
|
72
|
-
Console.debug("Error ", err.message)
|
73
|
-
fs.unlink(dest, () => reject(err.message))
|
72
|
+
Console.debug("Error ", err.message)
|
73
|
+
fs.unlink(dest, () => reject(err.message)) // Delete temp file
|
74
74
|
}
|
75
|
-
})
|
76
|
-
response.pipe(file)
|
75
|
+
})
|
76
|
+
response.pipe(file)
|
77
77
|
} else if (response.statusCode === 302 || response.statusCode === 301) {
|
78
78
|
// Console.debug("Servers redirected to "+response.headers.location)
|
79
79
|
// Recursively follow redirects, only a 200 will resolve.
|
@@ -81,89 +81,98 @@ export const download = (url: string, dest: string) => {
|
|
81
81
|
download(response.headers.location, dest)
|
82
82
|
.then(() => resolve(/* */ ""))
|
83
83
|
.catch(error => {
|
84
|
-
Console.error(error)
|
85
|
-
reject(error)
|
86
|
-
})
|
84
|
+
Console.error(error)
|
85
|
+
reject(error)
|
86
|
+
})
|
87
87
|
}
|
88
88
|
} else {
|
89
89
|
Console.debug(
|
90
90
|
`Server responded with ${response.statusCode}: ${response.statusMessage}`
|
91
|
-
)
|
91
|
+
)
|
92
92
|
reject(
|
93
93
|
`Server responded with ${response.statusCode}: ${response.statusMessage}`
|
94
|
-
)
|
94
|
+
)
|
95
95
|
}
|
96
|
-
})
|
96
|
+
})
|
97
97
|
|
98
98
|
request.on("error", err => {
|
99
|
-
reject(err.message)
|
100
|
-
})
|
101
|
-
})
|
102
|
-
}
|
99
|
+
reject(err.message)
|
100
|
+
})
|
101
|
+
})
|
102
|
+
}
|
103
103
|
|
104
104
|
export const clone = (repository = "", folder = "./") =>
|
105
105
|
new Promise((resolve, reject) => {
|
106
106
|
if (!repository) {
|
107
|
-
reject("Missing repository url for this package")
|
107
|
+
reject("Missing repository url for this package")
|
108
108
|
// return false
|
109
109
|
}
|
110
110
|
|
111
|
-
cli.action.start("Verifying GIT...")
|
111
|
+
cli.action.start("Verifying GIT...")
|
112
112
|
if (!shell.which("git")) {
|
113
|
-
reject("Sorry, this script requires git")
|
113
|
+
reject("Sorry, this script requires git")
|
114
114
|
// return false
|
115
115
|
}
|
116
116
|
|
117
|
-
cli.action.stop()
|
117
|
+
cli.action.stop()
|
118
118
|
|
119
|
-
let fileName = p.basename(repository)
|
119
|
+
let fileName = p.basename(repository)
|
120
120
|
if (!fileName) {
|
121
|
-
reject("Invalid repository information on package: " + repository)
|
121
|
+
reject("Invalid repository information on package: " + repository)
|
122
122
|
// return false
|
123
123
|
}
|
124
124
|
|
125
|
-
fileName = fileName.split(".")[0]
|
125
|
+
fileName = fileName.split(".")[0]
|
126
126
|
if (fs.existsSync("./" + fileName)) {
|
127
127
|
reject(
|
128
128
|
`Directory ${fileName} already exists; Did you download this package already?`
|
129
|
-
)
|
129
|
+
)
|
130
130
|
// return false
|
131
131
|
}
|
132
132
|
|
133
|
-
cli.action.start(`Cloning repository ${repository}...`)
|
133
|
+
cli.action.start(`Cloning repository ${repository}...`)
|
134
134
|
if (shell.exec(`git clone ${repository}`).code !== 0) {
|
135
|
-
reject("Error: Installation failed")
|
135
|
+
reject("Error: Installation failed")
|
136
136
|
}
|
137
137
|
|
138
|
-
cli.action.stop()
|
138
|
+
cli.action.stop()
|
139
139
|
|
140
|
-
cli.action.start("Cleaning installation...")
|
140
|
+
cli.action.start("Cleaning installation...")
|
141
141
|
if (shell.exec(`rm -R -f ${folder}${fileName}/.git`).code !== 0) {
|
142
|
-
reject("Error: removing .git directory")
|
142
|
+
reject("Error: removing .git directory")
|
143
143
|
}
|
144
144
|
|
145
|
-
cli.action.stop()
|
145
|
+
cli.action.stop()
|
146
146
|
|
147
|
-
resolve("Done")
|
148
|
-
})
|
147
|
+
resolve("Done")
|
148
|
+
})
|
149
149
|
|
150
150
|
export const rmSync = function (path: string) {
|
151
|
-
let files = []
|
151
|
+
let files = []
|
152
152
|
if (fs.existsSync(path)) {
|
153
|
-
files = fs.readdirSync(path)
|
153
|
+
files = fs.readdirSync(path)
|
154
154
|
for (const [, file] of files.entries()) {
|
155
|
-
const curPath = path + "/" + file
|
155
|
+
const curPath = path + "/" + file
|
156
156
|
if (fs.lstatSync(curPath).isDirectory()) {
|
157
157
|
// recurse
|
158
|
-
rmSync(curPath)
|
158
|
+
rmSync(curPath)
|
159
159
|
} else {
|
160
160
|
// delete file
|
161
|
-
fs.unlinkSync(curPath)
|
161
|
+
fs.unlinkSync(curPath)
|
162
162
|
}
|
163
163
|
}
|
164
164
|
|
165
|
-
fs.rmdirSync(path)
|
165
|
+
fs.rmdirSync(path)
|
166
166
|
}
|
167
|
-
}
|
167
|
+
}
|
168
168
|
|
169
|
-
export
|
169
|
+
export const checkIfDirectoryExists = (path: string) => {
|
170
|
+
const fs = require("fs")
|
171
|
+
if (fs.existsSync(path)) {
|
172
|
+
return true
|
173
|
+
}
|
174
|
+
|
175
|
+
return false
|
176
|
+
}
|
177
|
+
|
178
|
+
export default { download, decompress, downloadEditor, clone, rmSync }
|
@@ -1,32 +1,32 @@
|
|
1
|
-
import * as express from "express"
|
1
|
+
import * as express from "express"
|
2
2
|
// eslint-disable-next-line
|
3
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"
|
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
10
|
|
11
|
-
export let TEST_SERVER: http.Server
|
11
|
+
export let TEST_SERVER: http.Server
|
12
12
|
|
13
13
|
export default async function (
|
14
14
|
configObj: IConfigObj,
|
15
15
|
configManager: IConfigManager,
|
16
16
|
isTestingEnvironment = false
|
17
17
|
) {
|
18
|
-
const { config } = configObj
|
19
|
-
const app = express()
|
20
|
-
let server: any
|
18
|
+
const { config } = configObj
|
19
|
+
const app = express()
|
20
|
+
let server: any
|
21
21
|
|
22
22
|
if (isTestingEnvironment) {
|
23
23
|
if (TEST_SERVER === undefined)
|
24
|
-
TEST_SERVER = require("http").Server(app)
|
25
|
-
server = TEST_SERVER
|
24
|
+
TEST_SERVER = require("http").Server(app)
|
25
|
+
server = TEST_SERVER
|
26
26
|
} else
|
27
|
-
server = require("http").Server(app)
|
27
|
+
server = require("http").Server(app)
|
28
28
|
|
29
|
-
app.use(cors())
|
29
|
+
app.use(cors())
|
30
30
|
|
31
31
|
// app.use(function(req, res, next) {
|
32
32
|
// res.header("Access-Control-Allow-Origin", "*")
|
@@ -36,42 +36,43 @@ server = require("http").Server(app);
|
|
36
36
|
// })
|
37
37
|
|
38
38
|
// add all needed endpoints
|
39
|
-
|
39
|
+
|
40
|
+
await addRoutes(app, configObj, configManager)
|
40
41
|
|
41
42
|
server.listen(isTestingEnvironment ? 5000 : config?.port, function () {
|
42
43
|
if (!isTestingEnvironment) {
|
43
44
|
Console.success(
|
44
45
|
`Exercises are running 😃 Open your browser to start practicing!`
|
45
|
-
)
|
46
|
-
Console.success(`\n Open the exercise on this link:`)
|
47
|
-
Console.log(` ${config?.publicUrl}`)
|
46
|
+
)
|
47
|
+
Console.success(`\n Open the exercise on this link:`)
|
48
|
+
Console.log(` ${config?.publicUrl}`)
|
48
49
|
if (config?.editor.mode === "standalone")
|
49
|
-
cli.open(`${config.publicUrl}`)
|
50
|
+
cli.open(`${config.publicUrl}`)
|
50
51
|
}
|
51
|
-
})
|
52
|
+
})
|
52
53
|
|
53
|
-
const sockets: any = new Set()
|
54
|
+
const sockets: any = new Set()
|
54
55
|
|
55
56
|
server.on("connection", (socket: any) => {
|
56
|
-
sockets.add(socket)
|
57
|
+
sockets.add(socket)
|
57
58
|
|
58
59
|
server.once("close", () => {
|
59
|
-
sockets.delete(socket)
|
60
|
-
})
|
61
|
-
})
|
60
|
+
sockets.delete(socket)
|
61
|
+
})
|
62
|
+
})
|
62
63
|
|
63
64
|
/**
|
64
65
|
* Forcefully terminates HTTP server.
|
65
66
|
*/
|
66
67
|
server.terminate = (callback: void) => {
|
67
68
|
for (const socket of sockets) {
|
68
|
-
socket.destroy()
|
69
|
+
socket.destroy()
|
69
70
|
|
70
|
-
sockets.delete(socket)
|
71
|
+
sockets.delete(socket)
|
71
72
|
}
|
72
73
|
|
73
|
-
server.close(callback)
|
74
|
-
}
|
74
|
+
server.close(callback)
|
75
|
+
}
|
75
76
|
|
76
|
-
return server
|
77
|
+
return server
|
77
78
|
}
|