@learnpack/learnpack 2.0.2 → 2.0.5

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