@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
@@ -1,78 +1,117 @@
|
|
1
|
-
import Console from "../../utils/console"
|
2
|
-
import * as express from "express"
|
3
|
-
import * as fs from "fs"
|
4
|
-
import * as bodyParser from "body-parser"
|
5
|
-
import socket from "../socket"
|
6
|
-
import queue from "../../utils/fileQueue"
|
1
|
+
import Console from "../../utils/console"
|
2
|
+
import * as express from "express"
|
3
|
+
import * as fs from "fs"
|
4
|
+
import * as bodyParser from "body-parser"
|
5
|
+
import socket from "../socket"
|
6
|
+
import queue from "../../utils/fileQueue"
|
7
7
|
// import gitpod from '../gitpod'
|
8
|
-
import { detect, filterFiles } from "../config/exercise"
|
9
|
-
import { IFile } from "../../models/file"
|
10
|
-
import { IConfigObj, TEntries } from "../../models/config"
|
11
|
-
import { IConfigManager } from "../../models/config-manager"
|
12
|
-
import { IExercise } from "../../models/exercise-obj"
|
8
|
+
import { detect, filterFiles } from "../config/exercise"
|
9
|
+
import { IFile } from "../../models/file"
|
10
|
+
import { IConfigObj, TEntries } from "../../models/config"
|
11
|
+
import { IConfigManager } from "../../models/config-manager"
|
12
|
+
import { IExercise } from "../../models/exercise-obj"
|
13
|
+
import SessionManager from "../../managers/session"
|
13
14
|
|
14
15
|
const withHandler =
|
15
16
|
(func: (req: express.Request, res: express.Response) => void) =>
|
16
17
|
(req: express.Request, res: express.Response) => {
|
17
18
|
try {
|
18
|
-
func(req, res)
|
19
|
+
func(req, res)
|
19
20
|
} catch (error) {
|
20
|
-
Console.debug(error)
|
21
|
+
Console.debug(error)
|
21
22
|
const _err = {
|
22
23
|
message: (error as TypeError).message || "There has been an error",
|
23
24
|
status: (error as any).status || 500,
|
24
25
|
type: (error as any).type || null,
|
25
|
-
}
|
26
|
-
Console.error(_err.message)
|
26
|
+
}
|
27
|
+
Console.error(_err.message)
|
27
28
|
|
28
29
|
// send rep to the server
|
29
|
-
res.status(_err.status)
|
30
|
-
res.json(_err)
|
30
|
+
res.status(_err.status)
|
31
|
+
res.json(_err)
|
31
32
|
}
|
32
|
-
}
|
33
|
+
}
|
33
34
|
|
34
35
|
export default async function (
|
35
36
|
app: express.Application,
|
36
37
|
configObject: IConfigObj,
|
37
38
|
configManager: IConfigManager
|
38
39
|
) {
|
39
|
-
const { config, exercises } = configObject
|
40
|
+
const { config, exercises } = configObject
|
41
|
+
const session = await SessionManager.get(configManager?.get())
|
40
42
|
|
41
43
|
const dispatcher = queue.dispatcher({
|
42
44
|
create: true,
|
43
45
|
path: `${config?.dirPath}/vscode_queue.json`,
|
44
|
-
})
|
46
|
+
})
|
45
47
|
app.get(
|
46
48
|
"/config",
|
47
49
|
withHandler((_: express.Request, res: express.Response) => {
|
48
|
-
res.json(configObject)
|
50
|
+
res.json(configObject)
|
49
51
|
})
|
50
|
-
)
|
52
|
+
)
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
54
|
+
// Added this line to parse the json body
|
55
|
+
|
56
|
+
const jsonBodyParser = bodyParser.json()
|
57
|
+
// Trying to log in from frontend
|
58
|
+
app.post(
|
59
|
+
"/login",
|
60
|
+
jsonBodyParser,
|
61
|
+
withHandler(async (req: express.Request, res: express.Response) => {
|
62
|
+
const email = req.body.email
|
63
|
+
const password = req.body.password
|
64
|
+
|
65
|
+
SessionManager.destroy()
|
66
|
+
const payload = await SessionManager.loginWeb(email, password)
|
67
|
+
|
68
|
+
res.json(payload)
|
69
|
+
})
|
70
|
+
)
|
71
|
+
app.post(
|
72
|
+
"/set-openai-token",
|
73
|
+
jsonBodyParser,
|
74
|
+
withHandler(async (req: express.Request, res: express.Response) => {
|
75
|
+
const token = req.body.token
|
76
|
+
console.log("Setting openai token")
|
77
|
+
|
78
|
+
const tokenSaved = await SessionManager.setOpenAIToken(token)
|
79
|
+
if (tokenSaved) {
|
80
|
+
res.json({ status: "ok" })
|
81
|
+
} else {
|
82
|
+
res.status(400)
|
83
|
+
}
|
84
|
+
})
|
85
|
+
)
|
86
|
+
|
87
|
+
app.get(
|
88
|
+
"/check/rigo/status",
|
89
|
+
withHandler(async (_: express.Request, res: express.Response) => {
|
90
|
+
const payload = await SessionManager.getPayload()
|
91
|
+
const openaiToken = await SessionManager.getOpenAIToken()
|
92
|
+
// console.log("Looking Rigo creds");
|
93
|
+
|
94
|
+
if (payload && payload.rigobot && payload.rigobot.key) {
|
95
|
+
res.json({ rigoToken: payload.rigobot.key })
|
96
|
+
} else if (openaiToken) {
|
97
|
+
res.json({ openaiToken })
|
98
|
+
} else {
|
99
|
+
res
|
100
|
+
.status(400)
|
101
|
+
.json({ details: `Rigobot token not found, please log in first!` })
|
102
|
+
}
|
103
|
+
})
|
104
|
+
)
|
66
105
|
|
67
106
|
// symbolic link to maintain path compatiblity
|
68
107
|
const fetchStaticAsset = withHandler((req, res) => {
|
69
|
-
const filePath = `${config?.dirPath}/assets/${req.params.filePath}
|
108
|
+
const filePath = `${config?.dirPath}/assets/${req.params.filePath}`
|
70
109
|
if (!fs.existsSync(filePath))
|
71
|
-
throw new Error("File not found: " + filePath)
|
72
|
-
const content = fs.readFileSync(filePath)
|
73
|
-
res.write(content)
|
74
|
-
res.end()
|
75
|
-
})
|
110
|
+
throw new Error("File not found: " + filePath)
|
111
|
+
const content = fs.readFileSync(filePath)
|
112
|
+
res.write(content)
|
113
|
+
res.end()
|
114
|
+
})
|
76
115
|
|
77
116
|
app.get(
|
78
117
|
`${
|
@@ -81,16 +120,16 @@ export default async function (
|
|
81
120
|
config?.dirPath
|
82
121
|
}/assets/:filePath`,
|
83
122
|
fetchStaticAsset
|
84
|
-
)
|
123
|
+
)
|
85
124
|
|
86
|
-
app.get("/assets/:filePath", fetchStaticAsset)
|
125
|
+
app.get("/assets/:filePath", fetchStaticAsset)
|
87
126
|
|
88
127
|
app.get(
|
89
128
|
"/exercise",
|
90
129
|
withHandler((_: express.Request, res: express.Response) => {
|
91
|
-
res.json(exercises)
|
130
|
+
res.json(exercises)
|
92
131
|
})
|
93
|
-
)
|
132
|
+
)
|
94
133
|
|
95
134
|
app.get(
|
96
135
|
"/exercise/:slug/readme",
|
@@ -99,30 +138,30 @@ export default async function (
|
|
99
138
|
{ params: { slug }, query: { lang } }: express.Request,
|
100
139
|
res: express.Response
|
101
140
|
) => {
|
102
|
-
const exercise: IExercise = configManager.getExercise(slug)
|
141
|
+
const exercise: IExercise = configManager.getExercise(slug)
|
103
142
|
|
104
143
|
if (exercise && exercise.getReadme) {
|
105
|
-
const readme = exercise.getReadme((lang as string) || null)
|
106
|
-
res.json(readme)
|
144
|
+
const readme = exercise.getReadme((lang as string) || null)
|
145
|
+
res.json(readme)
|
107
146
|
} else {
|
108
|
-
res.status(400)
|
147
|
+
res.status(400)
|
109
148
|
}
|
110
149
|
}
|
111
150
|
)
|
112
|
-
)
|
151
|
+
)
|
113
152
|
|
114
153
|
app.get(
|
115
154
|
"/exercise/:slug/report",
|
116
155
|
withHandler(
|
117
156
|
({ params: { slug } }: express.Request, res: express.Response) => {
|
118
|
-
const exercise = configManager.getExercise(slug)
|
157
|
+
const exercise = configManager.getExercise(slug)
|
119
158
|
if (exercise && exercise.getTestReport) {
|
120
|
-
const report = exercise.getTestReport()
|
121
|
-
res.json(JSON.stringify(report))
|
159
|
+
const report = exercise.getTestReport()
|
160
|
+
res.json(JSON.stringify(report))
|
122
161
|
}
|
123
162
|
}
|
124
163
|
)
|
125
|
-
)
|
164
|
+
)
|
126
165
|
|
127
166
|
app.get(
|
128
167
|
"/exercise/:slug",
|
@@ -132,13 +171,13 @@ export default async function (
|
|
132
171
|
configObject.currentExercise &&
|
133
172
|
req.params.slug === configObject.currentExercise
|
134
173
|
) {
|
135
|
-
const exercise = configManager.getExercise(req.params.slug)
|
136
|
-
res.json(exercise)
|
137
|
-
return
|
174
|
+
const exercise = configManager.getExercise(req.params.slug)
|
175
|
+
res.json(exercise)
|
176
|
+
return
|
138
177
|
}
|
139
178
|
|
140
|
-
const exercise = configManager.startExercise(req.params.slug)
|
141
|
-
dispatcher.enqueue(dispatcher.events.START_EXERCISE, req.params.slug)
|
179
|
+
const exercise = configManager.startExercise(req.params.slug)
|
180
|
+
dispatcher.enqueue(dispatcher.events.START_EXERCISE, req.params.slug)
|
142
181
|
|
143
182
|
type TEntry = "python3" | "html" | "node" | "react" | "java";
|
144
183
|
|
@@ -146,19 +185,19 @@ export default async function (
|
|
146
185
|
Object.keys(config?.entries!).map(
|
147
186
|
lang => config?.entries[lang as TEntry]
|
148
187
|
)
|
149
|
-
)
|
188
|
+
)
|
150
189
|
|
151
190
|
// if we are in incremental grading, the entry file can by dinamically detected
|
152
191
|
// based on the changes the student is making during the exercise
|
153
192
|
if (config?.grading === "incremental") {
|
154
|
-
const scanedFiles = fs.readdirSync("./")
|
193
|
+
const scanedFiles = fs.readdirSync("./")
|
155
194
|
|
156
195
|
// update the file hierarchy with updates
|
157
196
|
exercise.files = [
|
158
197
|
...exercise.files.filter(f => f.name.includes("test.")),
|
159
198
|
...filterFiles(scanedFiles),
|
160
|
-
]
|
161
|
-
Console.debug(`Exercise updated files: `, exercise.files)
|
199
|
+
]
|
200
|
+
Console.debug(`Exercise updated files: `, exercise.files)
|
162
201
|
}
|
163
202
|
|
164
203
|
const detected = detect(
|
@@ -166,31 +205,31 @@ export default async function (
|
|
166
205
|
exercise.files
|
167
206
|
.filter(fileName => entries.has(fileName.name))
|
168
207
|
.map(f => f.name || f) as string[]
|
169
|
-
)
|
208
|
+
)
|
170
209
|
|
171
210
|
// if a new language for the testing engine is detected, we replace it
|
172
211
|
// if not we leave it as it was before
|
173
212
|
if (config?.language && !["", "auto"].includes(config?.language)) {
|
174
213
|
Console.debug(
|
175
214
|
`Exercise language ignored, instead imported from configuration ${config?.language}`
|
176
|
-
)
|
177
|
-
exercise.language = detected?.language
|
215
|
+
)
|
216
|
+
exercise.language = detected?.language
|
178
217
|
} else if (
|
179
218
|
detected?.language &&
|
180
219
|
(!config?.language || config?.language === "auto")
|
181
220
|
) {
|
182
221
|
Console.debug(
|
183
222
|
`Switching to ${detected.language} engine in this exercise`
|
184
|
-
)
|
185
|
-
exercise.language = detected.language
|
223
|
+
)
|
224
|
+
exercise.language = detected.language
|
186
225
|
}
|
187
226
|
|
188
227
|
// WARNING: has to be the FULL PATH to the entry path
|
189
228
|
// We need to detect entry in both gradings: Incremental and Isolate
|
190
|
-
exercise.entry = detected?.entry
|
229
|
+
exercise.entry = detected?.entry
|
191
230
|
Console.debug(
|
192
231
|
`Exercise detected entry: ${detected?.entry} and language ${exercise.language}`
|
193
|
-
)
|
232
|
+
)
|
194
233
|
|
195
234
|
// exercises.graded and exercises.disableGrading deprecated.
|
196
235
|
if (
|
@@ -198,15 +237,15 @@ export default async function (
|
|
198
237
|
config?.disableGrading ||
|
199
238
|
config?.disabledActions?.includes("test")
|
200
239
|
) {
|
201
|
-
socket.removeAllowed("test")
|
240
|
+
socket.removeAllowed("test")
|
202
241
|
} else {
|
203
|
-
socket.addAllowed("test")
|
242
|
+
socket.addAllowed("test")
|
204
243
|
}
|
205
244
|
|
206
245
|
if (!exercise.entry || config?.disabledActions?.includes("build")) {
|
207
|
-
socket.removeAllowed("build")
|
246
|
+
socket.removeAllowed("build")
|
208
247
|
} else {
|
209
|
-
socket.addAllowed("build")
|
248
|
+
socket.addAllowed("build")
|
210
249
|
}
|
211
250
|
|
212
251
|
if (
|
@@ -217,44 +256,54 @@ export default async function (
|
|
217
256
|
).length === 0 ||
|
218
257
|
config?.disabledActions?.includes("reset")
|
219
258
|
) {
|
220
|
-
socket.removeAllowed("reset")
|
259
|
+
socket.removeAllowed("reset")
|
221
260
|
} else if (!config?.disabledActions?.includes("reset")) {
|
222
|
-
socket.addAllowed("reset")
|
261
|
+
socket.addAllowed("reset")
|
223
262
|
}
|
224
263
|
|
225
|
-
socket.log("ready")
|
264
|
+
socket.log("ready")
|
226
265
|
|
227
|
-
res.json(exercise)
|
266
|
+
res.json(exercise)
|
228
267
|
})
|
229
|
-
)
|
268
|
+
)
|
230
269
|
|
231
270
|
app.get(
|
232
271
|
"/exercise/:slug/file/:fileName",
|
233
272
|
withHandler((req: express.Request, res: express.Response) => {
|
234
|
-
const exercise = configManager.getExercise(req.params.slug)
|
273
|
+
const exercise = configManager.getExercise(req.params.slug)
|
235
274
|
if (exercise && exercise.getFile) {
|
236
|
-
res.write(exercise.getFile(req.params.fileName))
|
237
|
-
res.end()
|
275
|
+
res.write(exercise.getFile(req.params.fileName))
|
276
|
+
res.end()
|
238
277
|
}
|
239
278
|
})
|
279
|
+
)
|
280
|
+
|
281
|
+
/*
|
282
|
+
app.post(
|
283
|
+
"/exercise/:slug/file/:fileName",
|
284
|
+
withHandler((req: express.Request, res: express.Response) => {
|
285
|
+
get tokens but also, add allowed action for 'generate'
|
286
|
+
use the sessionManager to keep compatibility with the cli login command.
|
287
|
+
})
|
240
288
|
);
|
289
|
+
*/
|
241
290
|
|
242
|
-
const textBodyParser = bodyParser.text()
|
291
|
+
const textBodyParser = bodyParser.text()
|
243
292
|
app.put(
|
244
293
|
"/exercise/:slug/file/:fileName",
|
245
294
|
textBodyParser,
|
246
295
|
withHandler((req: express.Request, res: express.Response) => {
|
247
|
-
const exercise = configManager.getExercise(req.params.slug)
|
296
|
+
const exercise = configManager.getExercise(req.params.slug)
|
248
297
|
if (exercise && exercise.saveFile) {
|
249
|
-
exercise.saveFile(req.params.fileName, req.body)
|
250
|
-
res.end()
|
298
|
+
exercise.saveFile(req.params.fileName, req.body)
|
299
|
+
res.end()
|
251
300
|
}
|
252
301
|
})
|
253
|
-
)
|
302
|
+
)
|
254
303
|
|
255
304
|
if (config?.outputPath) {
|
256
|
-
app.use("/preview", express.static(config.outputPath))
|
305
|
+
app.use("/preview", express.static(config.outputPath))
|
257
306
|
}
|
258
307
|
|
259
|
-
app.use("/", express.static(`${config?.dirPath}/_app`))
|
308
|
+
app.use("/", express.static(`${config?.dirPath}/_app`))
|
260
309
|
}
|
package/src/managers/session.ts
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
import Console from
|
2
|
-
import api from
|
1
|
+
import Console from "../utils/console"
|
2
|
+
import api from "../utils/api"
|
3
3
|
|
4
|
-
import v from
|
5
|
-
import {ValidationError, InternalError} from
|
6
|
-
// import moment from 'moment'
|
7
|
-
import * as fs from 'fs'
|
8
|
-
import cli from 'cli-ux'
|
9
|
-
import * as storage from 'node-persist'
|
4
|
+
import v from "validator"
|
5
|
+
import { ValidationError, InternalError } from "../utils/errors"
|
10
6
|
|
11
|
-
import
|
12
|
-
import
|
7
|
+
import * as fs from "fs"
|
8
|
+
import cli from "cli-ux"
|
9
|
+
import * as storage from "node-persist"
|
10
|
+
|
11
|
+
import { IPayload, ISession, IStartProps } from "../models/session"
|
12
|
+
import { IConfigObj } from "../models/config"
|
13
13
|
|
14
14
|
const Session: ISession = {
|
15
15
|
sessionStarted: false,
|
@@ -19,34 +19,51 @@ const Session: ISession = {
|
|
19
19
|
initialize: async function () {
|
20
20
|
if (!this.sessionStarted) {
|
21
21
|
if (!this.config) {
|
22
|
-
throw InternalError(
|
22
|
+
throw InternalError("Configuration not found")
|
23
23
|
}
|
24
24
|
|
25
25
|
if (!fs.existsSync(this.config.dirPath)) {
|
26
26
|
fs.mkdirSync(this.config.dirPath)
|
27
27
|
}
|
28
28
|
|
29
|
-
await storage.init({dir: `${this.config.dirPath}/.session`})
|
29
|
+
await storage.init({ dir: `${this.config.dirPath}/.session` })
|
30
30
|
this.sessionStarted = true
|
31
31
|
}
|
32
32
|
|
33
33
|
return true
|
34
34
|
},
|
35
|
+
getOpenAIToken: async function () {
|
36
|
+
await this.initialize()
|
37
|
+
let token = null
|
38
|
+
try {
|
39
|
+
token = await storage.getItem("openai-token")
|
40
|
+
} catch {
|
41
|
+
Console.debug("Error retriving openai token")
|
42
|
+
}
|
43
|
+
|
44
|
+
return token
|
45
|
+
},
|
46
|
+
setOpenAIToken: async function (token: string) {
|
47
|
+
await this.initialize()
|
48
|
+
await storage.setItem("openai-token", token)
|
49
|
+
Console.debug("OpenAI token successfuly set")
|
50
|
+
return true
|
51
|
+
},
|
35
52
|
setPayload: async function (value: IPayload) {
|
36
53
|
await this.initialize()
|
37
|
-
await storage.setItem(
|
38
|
-
Console.debug(
|
54
|
+
await storage.setItem("bc-payload", { token: this.token, ...value })
|
55
|
+
Console.debug("Payload successfuly found and set for " + value.email)
|
39
56
|
return true
|
40
57
|
},
|
41
58
|
getPayload: async function () {
|
42
59
|
await this.initialize()
|
43
60
|
let payload = null
|
44
61
|
try {
|
45
|
-
payload = await storage.getItem(
|
62
|
+
payload = await storage.getItem("bc-payload")
|
46
63
|
} catch (error) {
|
47
64
|
// TODO: Remove it
|
48
65
|
console.log(error)
|
49
|
-
Console.debug(
|
66
|
+
Console.debug("Error retriving session payload")
|
50
67
|
}
|
51
68
|
|
52
69
|
return payload
|
@@ -77,18 +94,30 @@ const Session: ISession = {
|
|
77
94
|
}
|
78
95
|
},
|
79
96
|
login: async function () {
|
80
|
-
const email = await cli.prompt(
|
97
|
+
const email = await cli.prompt("What is your email?")
|
81
98
|
if (!v.isEmail(email)) {
|
82
|
-
throw ValidationError(
|
99
|
+
throw ValidationError("Invalid email")
|
83
100
|
}
|
84
101
|
|
85
|
-
const password = await cli.prompt(
|
86
|
-
type:
|
102
|
+
const password = await cli.prompt("What is your password?", {
|
103
|
+
type: "hide",
|
87
104
|
})
|
88
105
|
|
89
106
|
const data = await api.login(email, password)
|
90
107
|
if (data) {
|
91
|
-
|
108
|
+
cli.log(data)
|
109
|
+
this.start({ token: data.token, payload: data })
|
110
|
+
}
|
111
|
+
},
|
112
|
+
loginWeb: async function (email, password) {
|
113
|
+
if (!v.isEmail(email)) {
|
114
|
+
throw ValidationError("Invalid email")
|
115
|
+
}
|
116
|
+
|
117
|
+
const data = await api.login(email, password)
|
118
|
+
if (data) {
|
119
|
+
this.start({ token: data.token, payload: data })
|
120
|
+
return data
|
92
121
|
}
|
93
122
|
},
|
94
123
|
sync: async function () {
|
@@ -97,9 +126,9 @@ const Session: ISession = {
|
|
97
126
|
this.token = payload.token
|
98
127
|
}
|
99
128
|
},
|
100
|
-
start: async function ({token, payload = null}: IStartProps) {
|
129
|
+
start: async function ({ token, payload = null }: IStartProps) {
|
101
130
|
if (!token) {
|
102
|
-
throw new Error(
|
131
|
+
throw new Error("A token and email is needed to start a session")
|
103
132
|
}
|
104
133
|
|
105
134
|
this.token = token
|
@@ -111,7 +140,7 @@ const Session: ISession = {
|
|
111
140
|
destroy: async function () {
|
112
141
|
await storage.clear()
|
113
142
|
this.token = null
|
114
|
-
Console.success(
|
143
|
+
Console.success("You have logged out")
|
115
144
|
},
|
116
145
|
}
|
117
146
|
|