@learnpack/learnpack 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +51 -398
- package/bin/run +14 -2
- package/oclif.manifest.json +1 -1
- package/package.json +135 -111
- package/src/commands/audit.ts +462 -0
- package/src/commands/clean.ts +29 -0
- package/src/commands/download.ts +62 -0
- package/src/commands/init.ts +169 -0
- package/src/commands/login.ts +42 -0
- package/src/commands/logout.ts +43 -0
- package/src/commands/publish.ts +107 -0
- package/src/commands/start.ts +229 -0
- package/src/commands/{test.js → test.ts} +19 -21
- package/src/index.ts +1 -0
- package/src/managers/config/allowed_files.ts +29 -0
- package/src/managers/config/defaults.ts +33 -0
- package/src/managers/config/exercise.ts +295 -0
- package/src/managers/config/index.ts +411 -0
- package/src/managers/file.ts +169 -0
- package/src/managers/gitpod.ts +84 -0
- package/src/managers/server/{index.js → index.ts} +26 -19
- package/src/managers/server/routes.ts +250 -0
- package/src/managers/session.ts +118 -0
- package/src/managers/socket.ts +239 -0
- package/src/managers/test.ts +83 -0
- package/src/models/action.ts +3 -0
- package/src/models/audit-errors.ts +4 -0
- package/src/models/config-manager.ts +23 -0
- package/src/models/config.ts +74 -0
- package/src/models/counter.ts +11 -0
- package/src/models/errors.ts +22 -0
- package/src/models/exercise-obj.ts +26 -0
- package/src/models/file.ts +5 -0
- package/src/models/findings.ts +18 -0
- package/src/models/flags.ts +10 -0
- package/src/models/front-matter.ts +11 -0
- package/src/models/gitpod-data.ts +19 -0
- package/src/models/language.ts +4 -0
- package/src/models/package.ts +7 -0
- package/src/models/plugin-config.ts +17 -0
- package/src/models/session.ts +26 -0
- package/src/models/socket.ts +48 -0
- package/src/models/status.ts +15 -0
- package/src/models/success-types.ts +1 -0
- package/src/plugin/command/compile.ts +17 -0
- package/src/plugin/command/test.ts +30 -0
- package/src/plugin/index.ts +6 -0
- package/src/plugin/plugin.ts +94 -0
- package/src/plugin/utils.ts +87 -0
- package/src/types/node-fetch.d.ts +1 -0
- package/src/ui/download.ts +71 -0
- package/src/utils/BaseCommand.ts +48 -0
- package/src/utils/SessionCommand.ts +48 -0
- package/src/utils/api.ts +194 -0
- package/src/utils/audit.ts +162 -0
- package/src/utils/console.ts +24 -0
- package/src/utils/errors.ts +117 -0
- package/src/utils/{exercisesQueue.js → exercisesQueue.ts} +12 -6
- package/src/utils/fileQueue.ts +198 -0
- package/src/utils/misc.ts +23 -0
- package/src/utils/templates/incremental/.learn/exercises/01-hello-world/README.es.md +2 -4
- package/src/utils/templates/incremental/.learn/exercises/01-hello-world/README.md +1 -2
- package/src/utils/templates/isolated/01-hello-world/README.es.md +1 -2
- package/src/utils/templates/isolated/01-hello-world/README.md +1 -2
- package/src/utils/templates/isolated/README.ejs +1 -1
- package/src/utils/templates/isolated/README.es.ejs +1 -1
- package/src/utils/validators.ts +18 -0
- package/src/utils/watcher.ts +27 -0
- package/plugin/command/compile.js +0 -17
- package/plugin/command/test.js +0 -29
- package/plugin/index.js +0 -6
- package/plugin/plugin.js +0 -71
- package/plugin/utils.js +0 -78
- package/src/commands/audit.js +0 -243
- package/src/commands/clean.js +0 -27
- package/src/commands/download.js +0 -52
- package/src/commands/hello.js +0 -20
- package/src/commands/init.js +0 -133
- package/src/commands/login.js +0 -45
- package/src/commands/logout.js +0 -39
- package/src/commands/publish.js +0 -78
- package/src/commands/start.js +0 -169
- package/src/index.js +0 -1
- package/src/managers/config/allowed_files.js +0 -12
- package/src/managers/config/defaults.js +0 -32
- package/src/managers/config/exercise.js +0 -212
- package/src/managers/config/index.js +0 -342
- package/src/managers/file.js +0 -137
- package/src/managers/server/routes.js +0 -151
- package/src/managers/session.js +0 -83
- package/src/managers/socket.js +0 -185
- package/src/managers/test.js +0 -77
- package/src/ui/download.js +0 -48
- package/src/utils/BaseCommand.js +0 -34
- package/src/utils/SessionCommand.js +0 -46
- package/src/utils/api.js +0 -164
- package/src/utils/audit.js +0 -114
- package/src/utils/console.js +0 -16
- package/src/utils/errors.js +0 -90
- package/src/utils/fileQueue.js +0 -194
- package/src/utils/misc.js +0 -26
- package/src/utils/validators.js +0 -15
- package/src/utils/watcher.js +0 -24
package/src/managers/session.js
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
const Console = require('../utils/console');
|
2
|
-
const api = require('../utils/api');
|
3
|
-
|
4
|
-
const v = require('validator');
|
5
|
-
const { ValidationError, InternalError } = require('../utils/errors');
|
6
|
-
const moment = require('moment');
|
7
|
-
const fs = require('fs');
|
8
|
-
const cli = require("cli-ux").default
|
9
|
-
const storage = require('node-persist');
|
10
|
-
|
11
|
-
module.exports = {
|
12
|
-
sessionStarted: false,
|
13
|
-
token: null,
|
14
|
-
config: null,
|
15
|
-
currentCohort: null,
|
16
|
-
initialize: async function(){
|
17
|
-
if(!this.sessionStarted){
|
18
|
-
|
19
|
-
if(!this.config) throw InternalError('Configuration not found')
|
20
|
-
if(!fs.existsSync(this.config.dirPath)) fs.mkdirSync(this.config.dirPath)
|
21
|
-
await storage.init({ dir: `${this.config.dirPath}/.session` });
|
22
|
-
this.sessionStarted = true;
|
23
|
-
}
|
24
|
-
return true
|
25
|
-
},
|
26
|
-
setPayload: async function(value){
|
27
|
-
await this.initialize();
|
28
|
-
await storage.setItem('bc-payload', { token: this.token, ...value });
|
29
|
-
Console.debug("Payload successfuly found and set for "+value.email);
|
30
|
-
return true;
|
31
|
-
},
|
32
|
-
getPayload: async function(){
|
33
|
-
await this.initialize();
|
34
|
-
let payload = null;
|
35
|
-
try{
|
36
|
-
payload = await storage.getItem('bc-payload');
|
37
|
-
}
|
38
|
-
catch(err){
|
39
|
-
Console.debug("Error retriving session payload");
|
40
|
-
}
|
41
|
-
return payload;
|
42
|
-
},
|
43
|
-
isActive: function(){
|
44
|
-
if(this.token) return true;
|
45
|
-
else return false;
|
46
|
-
},
|
47
|
-
get: async function(configObj=null){
|
48
|
-
if(configObj) this.config = configObj.config;
|
49
|
-
|
50
|
-
await this.sync();
|
51
|
-
if(!this.isActive()) return null;
|
52
|
-
|
53
|
-
const payload = await this.getPayload();
|
54
|
-
return {
|
55
|
-
payload, token: this.token,
|
56
|
-
};
|
57
|
-
},
|
58
|
-
login: async function(){
|
59
|
-
|
60
|
-
var email = await cli.prompt('What is your email?')
|
61
|
-
if(!v.isEmail(email)) throw ValidationError('Invalid email');
|
62
|
-
|
63
|
-
var password = await cli.prompt('What is your password?', {type: 'hide'})
|
64
|
-
|
65
|
-
const data = await api.login(email, password);
|
66
|
-
if(data) this.start({ token: data.token, payload: data });
|
67
|
-
|
68
|
-
},
|
69
|
-
sync: async function(){
|
70
|
-
const payload = await this.getPayload();
|
71
|
-
if(payload) this.token = payload.token;
|
72
|
-
},
|
73
|
-
start: async function({ token, payload=null }){
|
74
|
-
if(!token) throw new Error("A token and email is needed to start a session");
|
75
|
-
this.token = token;
|
76
|
-
if(payload) if(await this.setPayload(payload)) Console.success(`Successfully logged in as ${payload.email}`);
|
77
|
-
},
|
78
|
-
destroy: async function(){
|
79
|
-
await storage.clear();
|
80
|
-
this.token = null;
|
81
|
-
Console.success('You have logged out');
|
82
|
-
}
|
83
|
-
};
|
package/src/managers/socket.js
DELETED
@@ -1,185 +0,0 @@
|
|
1
|
-
let connect = require("socket.io");
|
2
|
-
let Console = require("../utils/console");
|
3
|
-
const queue = require("../utils/fileQueue");
|
4
|
-
|
5
|
-
module.exports = {
|
6
|
-
socket: null,
|
7
|
-
config: null,
|
8
|
-
allowedActions: null,
|
9
|
-
isTestingEnvironment: false,
|
10
|
-
actionCallBacks: {
|
11
|
-
clean: (data, s) => {
|
12
|
-
s.logs = [];
|
13
|
-
},
|
14
|
-
},
|
15
|
-
addAllowed: function (actions) {
|
16
|
-
if (!Array.isArray(actions)) actions = [actions];
|
17
|
-
|
18
|
-
//avoid adding the "test" action if grading is disabled
|
19
|
-
if (actions.includes("test") && this.config.disable_grading)
|
20
|
-
actions = actions.filter((a) => a != "test");
|
21
|
-
|
22
|
-
//remove duplicates
|
23
|
-
this.allowedActions = this.allowedActions
|
24
|
-
.filter((a) => !actions.includes(a))
|
25
|
-
.concat(actions);
|
26
|
-
},
|
27
|
-
removeAllowed: function (actions) {
|
28
|
-
if (!Array.isArray(actions)) actions = [actions];
|
29
|
-
this.allowedActions = this.allowedActions.filter(
|
30
|
-
(a) => !actions.includes(a)
|
31
|
-
);
|
32
|
-
},
|
33
|
-
start: function (config, server, isTestingEnvironment = false) {
|
34
|
-
this.config = config;
|
35
|
-
this.isTestingEnvironment = isTestingEnvironment;
|
36
|
-
|
37
|
-
// remove test action if grading is disabled
|
38
|
-
this.allowedActions = config.actions.filter((act) =>
|
39
|
-
config.disable_grading ? act !== "test" : true
|
40
|
-
);
|
41
|
-
|
42
|
-
this.socket = connect(server);
|
43
|
-
this.socket.on("connection", (socket) => {
|
44
|
-
Console.debug(
|
45
|
-
"Connection with client successfully established",
|
46
|
-
this.allowedActions
|
47
|
-
);
|
48
|
-
|
49
|
-
if (!this.isTestingEnvironment) {
|
50
|
-
this.log("ready", ["Ready to compile or test..."]);
|
51
|
-
}
|
52
|
-
|
53
|
-
socket.on("compiler", ({ action, data }) => {
|
54
|
-
this.emit("clean", "pending", ["Working..."]);
|
55
|
-
|
56
|
-
if (typeof data.exerciseSlug == "undefined") {
|
57
|
-
this.log("internal-error", ["No exercise slug specified"]);
|
58
|
-
Console.error("No exercise slug especified");
|
59
|
-
return;
|
60
|
-
}
|
61
|
-
|
62
|
-
if (typeof this.actionCallBacks[action] == "function")
|
63
|
-
this.actionCallBacks[action](data);
|
64
|
-
else this.log("internal-error", ["Uknown action " + action]);
|
65
|
-
});
|
66
|
-
});
|
67
|
-
},
|
68
|
-
on: function (action, callBack) {
|
69
|
-
this.actionCallBacks[action] = callBack;
|
70
|
-
},
|
71
|
-
clean: function (status = "pending", logs = []) {
|
72
|
-
this.emit("clean", "pending", logs);
|
73
|
-
},
|
74
|
-
ask: function (questions = []) {
|
75
|
-
return new Promise((resolve, reject) => {
|
76
|
-
this.emit("ask", "pending", ["Waiting for input..."], questions);
|
77
|
-
this.on("input", ({ inputs }) => {
|
78
|
-
// Workaround to fix issue because null inputs
|
79
|
-
let isNull = false;
|
80
|
-
inputs.forEach((input) => {
|
81
|
-
if (input === null) {
|
82
|
-
isNull = true;
|
83
|
-
}
|
84
|
-
});
|
85
|
-
|
86
|
-
if (!isNull) {
|
87
|
-
resolve(inputs);
|
88
|
-
}
|
89
|
-
});
|
90
|
-
});
|
91
|
-
},
|
92
|
-
reload: function (files = null, exercises = null) {
|
93
|
-
this.emit("reload", files, exercises);
|
94
|
-
},
|
95
|
-
openWindow: function (url = "") {
|
96
|
-
queue.dispatcher().enqueue(queue.events.OPEN_WINDOW, url);
|
97
|
-
this.emit(
|
98
|
-
queue.events.OPEN_WINDOW,
|
99
|
-
(status = "ready"),
|
100
|
-
(logs = [`Opening ${url}`]),
|
101
|
-
(inputs = []),
|
102
|
-
(report = []),
|
103
|
-
(data = url)
|
104
|
-
);
|
105
|
-
},
|
106
|
-
log: function (status, messages = [], report = [], data = null) {
|
107
|
-
this.emit("log", status, messages, [], report, data);
|
108
|
-
Console.log(messages);
|
109
|
-
},
|
110
|
-
emit: function (
|
111
|
-
action,
|
112
|
-
status = "ready",
|
113
|
-
logs = [],
|
114
|
-
inputs = [],
|
115
|
-
report = [],
|
116
|
-
data = null
|
117
|
-
) {
|
118
|
-
if (
|
119
|
-
["webpack", "vanillajs", "vue", "react", "css", "html"].includes(
|
120
|
-
this.config.compiler
|
121
|
-
)
|
122
|
-
) {
|
123
|
-
if (["compiler-success", "compiler-warning"].includes(status))
|
124
|
-
this.addAllowed("preview");
|
125
|
-
if (["compiler-error"].includes(status) || action == "ready")
|
126
|
-
this.removeAllowed("preview");
|
127
|
-
}
|
128
|
-
|
129
|
-
if (this.config.grading === "incremental") {
|
130
|
-
this.removeAllowed("reset");
|
131
|
-
}
|
132
|
-
|
133
|
-
Console.debug("dactions", this.config)
|
134
|
-
this.config.disabledActions.forEach(a => this.removeAllowed(a))
|
135
|
-
|
136
|
-
this.socket.emit("compiler", {
|
137
|
-
action,
|
138
|
-
status,
|
139
|
-
logs,
|
140
|
-
allowed: this.allowedActions,
|
141
|
-
inputs,
|
142
|
-
report,
|
143
|
-
data,
|
144
|
-
});
|
145
|
-
},
|
146
|
-
|
147
|
-
ready: function (message) {
|
148
|
-
this.log("ready", [message]);
|
149
|
-
},
|
150
|
-
success: function (type, stdout = "") {
|
151
|
-
const types = ["compiler", "testing"];
|
152
|
-
if (!types.includes(type))
|
153
|
-
this.fatal(`Invalid socket success type "${type}" on socket`);
|
154
|
-
else {
|
155
|
-
if (stdout === "")
|
156
|
-
this.log(type + "-success", ["No stdout to display on the console"]);
|
157
|
-
else this.log(type + "-success", [stdout]);
|
158
|
-
}
|
159
|
-
|
160
|
-
if (this.isTestingEnvironment) {
|
161
|
-
this.onTestingFinised({
|
162
|
-
result: "success",
|
163
|
-
});
|
164
|
-
}
|
165
|
-
},
|
166
|
-
error: function (type, stdout) {
|
167
|
-
console.error("Socket error: " + type, stdout);
|
168
|
-
this.log(type, [stdout]);
|
169
|
-
|
170
|
-
if (this.isTestingEnvironment) {
|
171
|
-
this.onTestingFinised({
|
172
|
-
result: "failed",
|
173
|
-
});
|
174
|
-
}
|
175
|
-
},
|
176
|
-
fatal: function (msg) {
|
177
|
-
this.log("internal-error", [msg]);
|
178
|
-
throw msg;
|
179
|
-
},
|
180
|
-
onTestingFinised: function (result) {
|
181
|
-
if (this.config.testingFinishedCallback) {
|
182
|
-
this.config.testingFinishedCallback(result);
|
183
|
-
}
|
184
|
-
},
|
185
|
-
};
|
package/src/managers/test.js
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
const path = require('path');
|
2
|
-
let shell = require('shelljs');
|
3
|
-
const fs = require('fs');
|
4
|
-
let { TestingError } = require('./errors');
|
5
|
-
let Console = require('../utils/console');
|
6
|
-
const color = require('colors');
|
7
|
-
const bcActivity = require('./bcActivity.js');
|
8
|
-
|
9
|
-
module.exports = async function({ socket, files, config, slug }){
|
10
|
-
|
11
|
-
const configPath = path.resolve(__dirname,`./config/tester/${config.tester}/${config.language}.config.js`);
|
12
|
-
if (!fs.existsSync(configPath)) throw CompilerError(`Uknown testing engine for compiler: '${config.language}'`);
|
13
|
-
|
14
|
-
const testingConfig = require(configPath)(files, config, slug);
|
15
|
-
testingConfig.validate();
|
16
|
-
|
17
|
-
if(config.ignoreTests) throw TestingError('Grading is disabled on learn.json file.');
|
18
|
-
|
19
|
-
if (!fs.existsSync(`${config.dirPath}/reports`)){
|
20
|
-
fs.mkdirSync(`${config.dirPath}/reports`);
|
21
|
-
Console.debug(`Creating the ${config.dirPath}/reports directory`);
|
22
|
-
}
|
23
|
-
|
24
|
-
Console.info('Running tests...');
|
25
|
-
|
26
|
-
const command = await testingConfig.getCommand(socket)
|
27
|
-
const { stdout, stderr, code } = shell.exec(command);
|
28
|
-
|
29
|
-
if(code != 0){
|
30
|
-
const errors = typeof(testingConfig.getErrors === 'function') ? testingConfig.getErrors(stdout || stderr) : [];
|
31
|
-
socket.log('testing-error', errors);
|
32
|
-
console.log(errors.join('\n'))
|
33
|
-
|
34
|
-
Console.error("There was an error while testing");
|
35
|
-
bcActivity.error('exercise_error', {
|
36
|
-
message: errors,
|
37
|
-
name: `${config.tester}-error`,
|
38
|
-
framework: config.tester,
|
39
|
-
language: config.language,
|
40
|
-
data: slug,
|
41
|
-
compiler: config.compiler
|
42
|
-
});
|
43
|
-
}
|
44
|
-
else{
|
45
|
-
socket.log('testing-success',[ stdout || stderr ].concat(["😁Everything is amazing!"]));
|
46
|
-
Console.success("Everything is amazing!");
|
47
|
-
|
48
|
-
|
49
|
-
bcActivity.activity('exercise_success', {
|
50
|
-
language: config.language,
|
51
|
-
slug: slug,
|
52
|
-
editor: config.editor,
|
53
|
-
compiler: config.compiler
|
54
|
-
});
|
55
|
-
config.exercises = config.exercises.map(e => {
|
56
|
-
if(e.slug === slug) e.done = true;
|
57
|
-
return e;
|
58
|
-
});
|
59
|
-
}
|
60
|
-
|
61
|
-
|
62
|
-
if(typeof testingConfig.cleanup !== "undefined"){
|
63
|
-
if(typeof testingConfig.cleanup === 'function' || typeof testingConfig.cleanup === 'object'){
|
64
|
-
const clean = await testingConfig.cleanup(socket);
|
65
|
-
if(clean){
|
66
|
-
const { stdout, stderr, code } = shell.exec(clean);
|
67
|
-
if(code == 0){
|
68
|
-
Console.debug("The cleanup command runned successfully");
|
69
|
-
}
|
70
|
-
else Console.warning("There is an error on the cleanup command for the test");
|
71
|
-
}
|
72
|
-
|
73
|
-
}
|
74
|
-
}
|
75
|
-
|
76
|
-
return true;
|
77
|
-
};
|
package/src/ui/download.js
DELETED
@@ -1,48 +0,0 @@
|
|
1
|
-
const { prompt } = require("enquirer")
|
2
|
-
const Console = require('../utils/console')
|
3
|
-
const api = require('../utils/api')
|
4
|
-
const fetch = require('node-fetch')
|
5
|
-
|
6
|
-
const askPackage = () => new Promise(async (resolve, reject) => {
|
7
|
-
Console.info(`No package was specified`)
|
8
|
-
const languages = await api.getLangs()
|
9
|
-
if(languages.length === 0){
|
10
|
-
reject(new Error("No categories available"))
|
11
|
-
return null;
|
12
|
-
}
|
13
|
-
let packages = []
|
14
|
-
prompt([{
|
15
|
-
type: 'select',
|
16
|
-
name: 'lang',
|
17
|
-
message: 'What language do you want to practice?',
|
18
|
-
choices: languages.map(l => ({ message: l.title, name: l.slug })),
|
19
|
-
}])
|
20
|
-
.then(({ lang }) => {
|
21
|
-
return (async() => {
|
22
|
-
const response = await api.getAllPackages({ lang })
|
23
|
-
const packages = response.results
|
24
|
-
if(packages.length === 0){
|
25
|
-
const error = new Error(`No packages found for language ${lang}`)
|
26
|
-
Console.error(error)
|
27
|
-
return error
|
28
|
-
}
|
29
|
-
return await prompt([{
|
30
|
-
type: 'select',
|
31
|
-
name: 'pack',
|
32
|
-
message: 'Choose one of the packages available',
|
33
|
-
choices: packages.map(l => ({
|
34
|
-
message: `${l.title}, difficulty: ${l.difficulty}, downloads: ${l.downloads} ${l.skills.length > 0 ? `(Skills: ${l.skills.join(",")})` : ""}`,
|
35
|
-
value: l
|
36
|
-
})),
|
37
|
-
}])
|
38
|
-
})()
|
39
|
-
})
|
40
|
-
.then(resp => {
|
41
|
-
if(!resp) reject(resp.message || resp)
|
42
|
-
else resolve(resp)
|
43
|
-
})
|
44
|
-
.catch(error => {
|
45
|
-
Console.error(error.message || error)
|
46
|
-
})
|
47
|
-
})
|
48
|
-
module.exports = { askPackage }
|
package/src/utils/BaseCommand.js
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
const {Command, flags} = require('@oclif/command')
|
2
|
-
const Console = require('./console')
|
3
|
-
const SessionManager = require('../managers/session.js')
|
4
|
-
|
5
|
-
|
6
|
-
class BaseCommand extends Command {
|
7
|
-
constructor(...params){
|
8
|
-
super(...params)
|
9
|
-
}
|
10
|
-
async catch(err) {
|
11
|
-
Console.debug("COMMAND CATCH", err)
|
12
|
-
|
13
|
-
throw err
|
14
|
-
}
|
15
|
-
async init() {
|
16
|
-
const {flags, args} = this.parse(BaseCommand)
|
17
|
-
Console.debug("COMMAND INIT")
|
18
|
-
Console.debug("These are your flags: ",flags);
|
19
|
-
Console.debug("These are your args: ",args);
|
20
|
-
|
21
|
-
// quick fix for listening to the process termination on windows
|
22
|
-
process.on('SIGINT', function() {
|
23
|
-
Console.debug("Terminated (SIGINT)")
|
24
|
-
process.exit();
|
25
|
-
});
|
26
|
-
|
27
|
-
}
|
28
|
-
async finally() {
|
29
|
-
Console.debug("COMMAND FINALLY")
|
30
|
-
// called after run and catch regardless of whether or not the command errored
|
31
|
-
}
|
32
|
-
}
|
33
|
-
|
34
|
-
module.exports = BaseCommand
|
@@ -1,46 +0,0 @@
|
|
1
|
-
const {flags} = require('@oclif/command')
|
2
|
-
const BaseCommand = require("./BaseCommand")
|
3
|
-
const Console = require('./console')
|
4
|
-
const SessionManager = require('../managers/session.js')
|
5
|
-
const ConfigManager = require('../managers/config/index.js')
|
6
|
-
const { AuthError } = require('./errors.js')
|
7
|
-
|
8
|
-
class SessionCommand extends BaseCommand {
|
9
|
-
constructor(...args){
|
10
|
-
super(...args)
|
11
|
-
this.configManager = null
|
12
|
-
this.session = null
|
13
|
-
}
|
14
|
-
|
15
|
-
async initSession(flags, _private){
|
16
|
-
try{
|
17
|
-
if(!this.configManager) await this.buildConfig(flags)
|
18
|
-
|
19
|
-
this.session = await SessionManager.get(this.configManager.get())
|
20
|
-
if(this.session) Console.debug(`Session open for ${this.session.payload.email}.`)
|
21
|
-
else{
|
22
|
-
if(_private) throw AuthError("You need to log in, run the following command to continue: $ learnpack login");
|
23
|
-
Console.debug("No active session available", _private)
|
24
|
-
}
|
25
|
-
}
|
26
|
-
catch(error){
|
27
|
-
Console.error(error.message)
|
28
|
-
}
|
29
|
-
}
|
30
|
-
async buildConfig(flags){
|
31
|
-
Console.debug("Building configuration for the first time")
|
32
|
-
Console.debug("Flags", flags)
|
33
|
-
this.configManager = await ConfigManager(flags)
|
34
|
-
}
|
35
|
-
async catch(err) {
|
36
|
-
Console.debug("COMMAND CATCH", err)
|
37
|
-
throw err
|
38
|
-
}
|
39
|
-
}
|
40
|
-
|
41
|
-
// SessionCommand.description = `Describe the command here
|
42
|
-
// ...
|
43
|
-
// Extra documentation goes here
|
44
|
-
// `
|
45
|
-
|
46
|
-
module.exports = SessionCommand
|
package/src/utils/api.js
DELETED
@@ -1,164 +0,0 @@
|
|
1
|
-
const Console = require('../utils/console');
|
2
|
-
const _fetch = require('node-fetch');
|
3
|
-
const storage = require('node-persist');
|
4
|
-
const cli = require("cli-ux").default
|
5
|
-
const HOST = "https://learnpack.herokuapp.com";
|
6
|
-
|
7
|
-
const fetch = async (url, options={}) => {
|
8
|
-
|
9
|
-
let headers = { "Content-Type": "application/json" }
|
10
|
-
let session = null;
|
11
|
-
try{
|
12
|
-
session = await storage.getItem('bc-payload');
|
13
|
-
if(session.token && session.token != "" && !url.includes("/token")) headers["Authorization"] = "Token "+session.token;
|
14
|
-
}
|
15
|
-
catch(err){}
|
16
|
-
|
17
|
-
try{
|
18
|
-
const resp = await _fetch(url, {
|
19
|
-
...options,
|
20
|
-
headers: { ...headers, ...options.headers }
|
21
|
-
})
|
22
|
-
|
23
|
-
if(resp.status >= 200 && resp.status < 300) return await resp.json()
|
24
|
-
else if(resp.status === 401) throw APIError("Invalid authentication credentials", 401)
|
25
|
-
else if(resp.status === 404) throw APIError("Package not found", 404)
|
26
|
-
else if(resp.status >= 500) throw APIError("Impossible to connect with the server", 500)
|
27
|
-
else if(resp.status >= 400){
|
28
|
-
const error = await resp.json()
|
29
|
-
if(error.detail || error.error){
|
30
|
-
throw APIError(error.detail || error.error)
|
31
|
-
}else if(error.non_field_errors){
|
32
|
-
throw APIError(non_field_errors[0], error)
|
33
|
-
}else if (typeof error === "object"){
|
34
|
-
for(let key in error){
|
35
|
-
throw APIError(`${key}: ${error[key][0]}`, error)
|
36
|
-
}
|
37
|
-
}else{
|
38
|
-
throw APIError("Uknown error")
|
39
|
-
}
|
40
|
-
}
|
41
|
-
else throw APIError("Uknown error")
|
42
|
-
}
|
43
|
-
catch(error){
|
44
|
-
Console.error(error.message);
|
45
|
-
throw error;
|
46
|
-
}
|
47
|
-
}
|
48
|
-
const login = async (identification, password) => {
|
49
|
-
|
50
|
-
try{
|
51
|
-
cli.action.start('Looking for credentials...')
|
52
|
-
await cli.wait(1000)
|
53
|
-
const data = await fetch(`${HOST}/v1/auth/token/`, {
|
54
|
-
body: JSON.stringify({ identification, password }),
|
55
|
-
method: 'post'
|
56
|
-
});
|
57
|
-
cli.action.stop('ready')
|
58
|
-
return data
|
59
|
-
}
|
60
|
-
catch(err){
|
61
|
-
Console.error(err.message);
|
62
|
-
Console.debug(err);
|
63
|
-
}
|
64
|
-
}
|
65
|
-
const publish = async (config) => {
|
66
|
-
|
67
|
-
const keys = ['difficulty', 'language', 'skills', 'technologies', 'slug', 'repository', 'author', 'title'];
|
68
|
-
|
69
|
-
let payload = {}
|
70
|
-
keys.forEach(k => config[k] ? payload[k] = config[k] : null);
|
71
|
-
try{
|
72
|
-
Console.log("Package to publish: ", payload)
|
73
|
-
cli.action.start('Updating package information...')
|
74
|
-
await cli.wait(1000)
|
75
|
-
const data = await fetch(`${HOST}/v1/package/${config.slug}`,{
|
76
|
-
method: 'PUT',
|
77
|
-
body: JSON.stringify(payload)
|
78
|
-
})
|
79
|
-
cli.action.stop('ready')
|
80
|
-
return data
|
81
|
-
}
|
82
|
-
catch(err){
|
83
|
-
Console.log("payload", payload)
|
84
|
-
Console.error(err.message);
|
85
|
-
Console.debug(err);
|
86
|
-
throw err;
|
87
|
-
}
|
88
|
-
}
|
89
|
-
|
90
|
-
const update = async (config) => {
|
91
|
-
|
92
|
-
try{
|
93
|
-
cli.action.start('Updating package information...')
|
94
|
-
await cli.wait(1000)
|
95
|
-
const data = await fetch(`${HOST}/v1/package/`,{
|
96
|
-
method: 'POST',
|
97
|
-
body: JSON.stringify(config)
|
98
|
-
})
|
99
|
-
cli.action.stop('ready')
|
100
|
-
return data
|
101
|
-
}
|
102
|
-
catch(err){
|
103
|
-
Console.error(err.message);
|
104
|
-
Console.debug(err);
|
105
|
-
throw err;
|
106
|
-
}
|
107
|
-
}
|
108
|
-
|
109
|
-
const getPackage = async (slug) => {
|
110
|
-
try{
|
111
|
-
cli.action.start('Downloading package information...')
|
112
|
-
await cli.wait(1000)
|
113
|
-
const data = await fetch(`${HOST}/v1/package/${slug}`)
|
114
|
-
cli.action.stop('ready')
|
115
|
-
return data
|
116
|
-
}
|
117
|
-
catch(err){
|
118
|
-
if(err.status == 404) Console.error(`Package ${slug} does not exist`);
|
119
|
-
else Console.error(`Package ${slug} does not exist`);
|
120
|
-
Console.debug(err);
|
121
|
-
throw err;
|
122
|
-
}
|
123
|
-
}
|
124
|
-
|
125
|
-
const getLangs = async () => {
|
126
|
-
try{
|
127
|
-
cli.action.start('Downloading language options...')
|
128
|
-
await cli.wait(1000)
|
129
|
-
const data = await fetch(`${HOST}/v1/package/language`)
|
130
|
-
cli.action.stop('ready')
|
131
|
-
return data;
|
132
|
-
}
|
133
|
-
catch(err){
|
134
|
-
if(err.status == 404) Console.error(`Package ${slug} does not exist`);
|
135
|
-
else Console.error(`Package ${slug} does not exist`);
|
136
|
-
Console.debug(err);
|
137
|
-
throw err;
|
138
|
-
}
|
139
|
-
}
|
140
|
-
|
141
|
-
|
142
|
-
const getAllPackages = async ({ lang='', slug='' }) => {
|
143
|
-
try{
|
144
|
-
cli.action.start('Downloading packages...')
|
145
|
-
await cli.wait(1000)
|
146
|
-
const data = await fetch(`${HOST}/v1/package/all?limit=100&language=${lang}&slug=${slug}`)
|
147
|
-
cli.action.stop('ready')
|
148
|
-
return data;
|
149
|
-
}
|
150
|
-
catch(err){
|
151
|
-
Console.error(`Package ${slug} does not exist`);
|
152
|
-
Console.debug(err);
|
153
|
-
throw err;
|
154
|
-
}
|
155
|
-
}
|
156
|
-
|
157
|
-
const APIError = (error, code) => {
|
158
|
-
const message = error.message || error;
|
159
|
-
const _err = new Error(message);
|
160
|
-
_err.status = code || 400;
|
161
|
-
return _err;
|
162
|
-
}
|
163
|
-
|
164
|
-
module.exports = {login, publish, update, getPackage, getLangs, getAllPackages }
|