@learnpack/learnpack 5.0.31 → 5.0.33

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.
@@ -58,7 +58,7 @@ export default async function (
58
58
 
59
59
  // Added this line to parse the json body
60
60
 
61
- const jsonBodyParser = bodyParser.json()
61
+ const jsonBodyParser = bodyParser.json({ limit: "10mb" })
62
62
  // Trying to log in from frontend
63
63
  app.post(
64
64
  "/login",
@@ -172,10 +172,15 @@ export default async function (
172
172
  })
173
173
  )
174
174
 
175
- app.get("/telemetry/step/:stepPosition", (req, res) => {
176
- const stepPosition = parseInt(req.params.stepPosition)
177
- const step = TelemetryManager.getStep(stepPosition)
178
- res.json(step)
175
+ app.get("/telemetry", async (req, res) => {
176
+ const telemetry = await TelemetryManager.retrieve()
177
+ res.json(telemetry)
178
+ })
179
+
180
+ app.post("/telemetry", jsonBodyParser, async (req, res) => {
181
+ const telemetry = req.body
182
+ await TelemetryManager.save(telemetry)
183
+ res.json({ message: "Telemetry saved successfully" })
179
184
  })
180
185
 
181
186
  app.get(
@@ -185,12 +190,6 @@ export default async function (
185
190
 
186
191
  if (payload && payload.rigobot && payload.rigobot.key) {
187
192
  res.json({ rigoToken: payload.rigobot.key, payload: payload })
188
-
189
- TelemetryManager.setStudent({
190
- user_id: payload.user_id,
191
- email: payload.email,
192
- token: payload.token,
193
- })
194
193
  } else {
195
194
  res
196
195
  .status(400)
@@ -137,11 +137,6 @@ const Session: ISession = {
137
137
  if (data) {
138
138
  this.start({ token: data.token, payload: data })
139
139
 
140
- TelemetryManager.setStudent({
141
- user_id: data.user_id,
142
- email: data.email,
143
- token: data.token,
144
- })
145
140
  return data
146
141
  }
147
142
  },
@@ -1,274 +1,274 @@
1
- import { Socket, Server } from "socket.io"
2
- import Console from "../utils/console"
3
- import queue from "../utils/fileQueue"
4
-
5
- import { ISocket, TPossibleActions } from "../models/socket"
6
- import { IConfig } from "../models/config"
7
- import { ICallback, TAction } from "../models/action"
8
- import { IExercise, IExerciseData } from "../models/exercise-obj"
9
- import { TStatus } from "../models/status"
10
- import { TSuccessType } from "../models/success-types"
11
- import * as http from "http"
12
-
13
- const languageToMessage: Record<string, string> = {
14
- python3:
15
- "Your code executed without erros, but no output is shown on the terminal. Maybe you forgot to include a print statement in your code?",
16
- node: "Your code executed without erros, but no output is shown on the terminal. Maybe you forgot to include a console.log statement in your code?",
17
- }
18
-
19
- const SocketManager: ISocket = {
20
- socket: null,
21
- config: null,
22
- allowedActions: [],
23
- possibleActions: ["build", "reset", "test", "tutorial"],
24
- isTestingEnvironment: false,
25
- actionCallBacks: {
26
- clean: (_, s: { logs: Array<string> }) => {
27
- s.logs = []
28
- },
29
- },
30
- addAllowed: function (actions: Array<TPossibleActions> | TPossibleActions) {
31
- if (!Array.isArray(actions))
32
- actions = [actions]
33
-
34
- // avoid adding the "test" action if grading is disabled
35
- if (
36
- actions.includes("test") &&
37
- this.config?.disabledActions?.includes("test")
38
- ) {
39
- actions = actions.filter((a: TPossibleActions) => a !== "test")
40
- }
41
-
42
- this.allowedActions = [
43
- ...(this.allowedActions || []).filter(
44
- (a: TPossibleActions) => !actions.includes(a)
45
- ),
46
- ...actions,
47
- ]
48
- },
49
- removeAllowed: function (
50
- actions: Array<TPossibleActions> | TPossibleActions
51
- ) {
52
- if (!Array.isArray(actions)) {
53
- actions = [actions]
54
- }
55
-
56
- this.allowedActions = (this.allowedActions || []).filter(
57
- (a: TPossibleActions) => !actions.includes(a)
58
- )
59
- },
60
- start: function (
61
- config: IConfig,
62
- server: http.Server,
63
- isTestingEnvironment = false
64
- ) {
65
- this.config = config
66
- this.isTestingEnvironment = isTestingEnvironment
67
- this.socket = new Server(server, {
68
- allowEIO3: true,
69
- cors: {
70
- origin: "http://localhost:5173",
71
- methods: ["GET", "POST"],
72
- },
73
- })
74
-
75
- this.allowedActions =
76
- this.config?.disabledActions?.includes("test") ||
77
- this.config?.disableGrading ?
78
- this.possibleActions.filter(
79
- a => !this.config?.disabledActions?.includes(a) && a !== "test"
80
- ) :
81
- this.possibleActions.filter(a => !this.allowedActions?.includes(a))
82
-
83
- if (this.config?.grading === "incremental") {
84
- this.removeAllowed("reset")
85
- }
86
-
87
- if (this.socket) {
88
- this.socket.on("connection", (socket: Socket) => {
89
- Console.debug(
90
- "Connection with client successfully established",
91
- this.allowedActions
92
- )
93
- if (!this.isTestingEnvironment) {
94
- this.log("ready", ["Ready to compile or test..."])
95
- }
96
-
97
- socket.on(
98
- "compiler",
99
- ({ action, data }: { action: string; data: IExerciseData }) => {
100
- this.emit("clean", "pending", ["Working..."])
101
- if (typeof data.exerciseSlug === "undefined") {
102
- this.log("internal-error", ["No exercise slug specified"])
103
- Console.error("No exercise slug especified")
104
- return
105
- }
106
-
107
- if (
108
- this.actionCallBacks &&
109
- typeof this.actionCallBacks[action] === "function"
110
- ) {
111
- this.actionCallBacks[action](data)
112
- } else {
113
- this.log("internal-error", ["Uknown action " + action])
114
- }
115
- }
116
- )
117
- })
118
- }
119
- },
120
- on: function (action: TAction, callBack: ICallback) {
121
- if (this.actionCallBacks) {
122
- this.actionCallBacks[action] = callBack
123
- }
124
- },
125
- clean: function (_ = "pending", logs = []) {
126
- this.emit("clean", "pending", logs)
127
- },
128
- ask: function (questions = []) {
129
- return new Promise((resolve, _) => {
130
- this.emit("ask", "pending", ["Waiting for input..."], questions)
131
-
132
- this.on("input", ({ inputs }: any) => {
133
- // Workaround to fix issue because null inputs
134
-
135
- let isNull = false
136
- // eslint-disable-next-line
137
- inputs.forEach((input: any) => {
138
- if (input === null) {
139
- isNull = true
140
- }
141
- })
142
-
143
- if (!isNull) {
144
- resolve(inputs)
145
- }
146
- })
147
- })
148
- },
149
- sessionRefreshed: function (data) {
150
- this.emit("session-refreshed", "", [data])
151
- },
152
-
153
- reload: function (
154
- files: Array<string> | null = null,
155
- exercises: Array<string> | null = null
156
- ) {
157
- this.emit("reload", files?.join("") || "", exercises!)
158
- },
159
- openWindow: function (url = "") {
160
- queue.dispatcher().enqueue(queue.events.OPEN_WINDOW, url)
161
- this.emit(
162
- queue.events.OPEN_WINDOW as TAction,
163
- "ready",
164
- [`Opening ${url}`],
165
- [],
166
- [],
167
- url
168
- )
169
- },
170
- log: function (
171
- status: TStatus,
172
- messages: string | Array<string> = [],
173
- report: Array<string> = [],
174
- data: any = null
175
- ) {
176
- this.emit("log", status, messages, [], report, data)
177
- Console.log(messages)
178
- },
179
- emit: function (
180
- action: TAction,
181
- status: TStatus | string = "ready",
182
- logs: string | Array<string> = [],
183
- inputs: Array<string> = [],
184
- report: Array<string> = [],
185
- data: any = null
186
- ) {
187
- if (
188
- this.config?.compiler &&
189
- ["webpack", "vanillajs", "vue", "react", "css", "html"].includes(
190
- this.config?.compiler
191
- )
192
- ) {
193
- if (["compiler-success", "compiler-warning"].includes(status))
194
- this.addAllowed("preview")
195
- if (["compiler-error"].includes(status) || action === "ready")
196
- this.removeAllowed("preview")
197
- }
198
-
199
- if (this.config?.grading === "incremental") {
200
- this.removeAllowed("reset")
201
- }
202
-
203
- // eslint-disable-next-line
204
- this.config?.disabledActions?.forEach((a) => this.removeAllowed(a))
205
-
206
- this.socket?.emit("compiler", {
207
- action,
208
- status,
209
- logs,
210
- allowed: this.allowedActions,
211
- inputs,
212
- report,
213
- data,
214
- })
215
- },
216
-
217
- ready: function (message: string) {
218
- this.log("ready", [message])
219
- },
220
- success: function (type: TSuccessType, stdout: string, lang) {
221
- const types = ["compiler", "testing"]
222
-
223
- if (!types.includes(type))
224
- this.fatal(`Invalid socket success type "${type}" on socket`)
225
- else if (
226
- stdout === "" &&
227
- lang &&
228
- Object.keys(languageToMessage).includes(lang)
229
- ) {
230
- this.log((type + "-success") as TSuccessType, [languageToMessage[lang]])
231
- } else if (stdout === "") {
232
- this.log((type + "-success") as TSuccessType, [
233
- "No stdout to display on the console",
234
- ])
235
- } else
236
- this.log((type + "-success") as TSuccessType, [stdout])
237
- },
238
- error: function (type: TStatus, stdout: string) {
239
- if (!this.config?.editor.hideTerminal) {
240
- queue.dispatcher().enqueue(queue.events.OPEN_TERMINAL, "")
241
- }
242
-
243
- this.log(type, [stdout])
244
-
245
- if (this.isTestingEnvironment) {
246
- this.onTestingFinished({
247
- result: "failed",
248
- })
249
- }
250
- },
251
- complete: function () {
252
- console.log("complete")
253
- },
254
- dialog: function (message: string, format = "md") {
255
- if (!this.socket) {
256
- this.fatal("Socket is not initialized")
257
- return
258
- }
259
-
260
- this.emit("dialog", "talk", [], undefined, undefined, { message, format })
261
- },
262
-
263
- fatal: function (msg: string) {
264
- this.log("internal-error", [msg])
265
- throw msg
266
- },
267
- onTestingFinished: function (result: any) {
268
- if (this.config?.testingFinishedCallback) {
269
- this.config.testingFinishedCallback(result)
270
- }
271
- },
272
- }
273
-
274
- export default SocketManager
1
+ import { Socket, Server } from "socket.io"
2
+ import Console from "../utils/console"
3
+ import queue from "../utils/fileQueue"
4
+
5
+ import { ISocket, TPossibleActions } from "../models/socket"
6
+ import { IConfig } from "../models/config"
7
+ import { ICallback, TAction } from "../models/action"
8
+ import { IExercise, IExerciseData } from "../models/exercise-obj"
9
+ import { TStatus } from "../models/status"
10
+ import { TSuccessType } from "../models/success-types"
11
+ import * as http from "http"
12
+
13
+ const languageToMessage: Record<string, string> = {
14
+ python3:
15
+ "Your code executed without erros, but no output is shown on the terminal. Maybe you forgot to include a print statement in your code?",
16
+ node: "Your code executed without erros, but no output is shown on the terminal. Maybe you forgot to include a console.log statement in your code?",
17
+ }
18
+
19
+ const SocketManager: ISocket = {
20
+ socket: null,
21
+ config: null,
22
+ allowedActions: [],
23
+ possibleActions: ["build", "reset", "test", "tutorial"],
24
+ isTestingEnvironment: false,
25
+ actionCallBacks: {
26
+ clean: (_, s: { logs: Array<string> }) => {
27
+ s.logs = []
28
+ },
29
+ },
30
+ addAllowed: function (actions: Array<TPossibleActions> | TPossibleActions) {
31
+ if (!Array.isArray(actions))
32
+ actions = [actions]
33
+
34
+ // avoid adding the "test" action if grading is disabled
35
+ if (
36
+ actions.includes("test") &&
37
+ this.config?.disabledActions?.includes("test")
38
+ ) {
39
+ actions = actions.filter((a: TPossibleActions) => a !== "test")
40
+ }
41
+
42
+ this.allowedActions = [
43
+ ...(this.allowedActions || []).filter(
44
+ (a: TPossibleActions) => !actions.includes(a)
45
+ ),
46
+ ...actions,
47
+ ]
48
+ },
49
+ removeAllowed: function (
50
+ actions: Array<TPossibleActions> | TPossibleActions
51
+ ) {
52
+ if (!Array.isArray(actions)) {
53
+ actions = [actions]
54
+ }
55
+
56
+ this.allowedActions = (this.allowedActions || []).filter(
57
+ (a: TPossibleActions) => !actions.includes(a)
58
+ )
59
+ },
60
+ start: function (
61
+ config: IConfig,
62
+ server: http.Server,
63
+ isTestingEnvironment = false
64
+ ) {
65
+ this.config = config
66
+ this.isTestingEnvironment = isTestingEnvironment
67
+ this.socket = new Server(server, {
68
+ allowEIO3: true,
69
+ cors: {
70
+ origin: "http://localhost:5173",
71
+ methods: ["GET", "POST"],
72
+ },
73
+ })
74
+
75
+ this.allowedActions =
76
+ this.config?.disabledActions?.includes("test") ||
77
+ this.config?.disableGrading ?
78
+ this.possibleActions.filter(
79
+ a => !this.config?.disabledActions?.includes(a) && a !== "test"
80
+ ) :
81
+ this.possibleActions.filter(a => !this.allowedActions?.includes(a))
82
+
83
+ if (this.config?.grading === "incremental") {
84
+ this.removeAllowed("reset")
85
+ }
86
+
87
+ if (this.socket) {
88
+ this.socket.on("connection", (socket: Socket) => {
89
+ Console.debug(
90
+ "Connection with client successfully established",
91
+ this.allowedActions
92
+ )
93
+ if (!this.isTestingEnvironment) {
94
+ this.log("ready", ["Ready to compile or test..."])
95
+ }
96
+
97
+ socket.on(
98
+ "compiler",
99
+ ({ action, data }: { action: string; data: IExerciseData }) => {
100
+ this.emit("clean", "pending", ["Working..."])
101
+ if (typeof data.exerciseSlug === "undefined") {
102
+ this.log("internal-error", ["No exercise slug specified"])
103
+ Console.error("No exercise slug especified")
104
+ return
105
+ }
106
+
107
+ if (
108
+ this.actionCallBacks &&
109
+ typeof this.actionCallBacks[action] === "function"
110
+ ) {
111
+ this.actionCallBacks[action](data)
112
+ } else {
113
+ this.log("internal-error", ["Uknown action " + action])
114
+ }
115
+ }
116
+ )
117
+ })
118
+ }
119
+ },
120
+ on: function (action: TAction, callBack: ICallback) {
121
+ if (this.actionCallBacks) {
122
+ this.actionCallBacks[action] = callBack
123
+ }
124
+ },
125
+ clean: function (_ = "pending", logs = []) {
126
+ this.emit("clean", "pending", logs)
127
+ },
128
+ ask: function (questions = []) {
129
+ return new Promise((resolve, _) => {
130
+ this.emit("ask", "pending", ["Waiting for input..."], questions)
131
+
132
+ this.on("input", ({ inputs }: any) => {
133
+ // Workaround to fix issue because null inputs
134
+
135
+ let isNull = false
136
+ // eslint-disable-next-line
137
+ inputs.forEach((input: any) => {
138
+ if (input === null) {
139
+ isNull = true
140
+ }
141
+ })
142
+
143
+ if (!isNull) {
144
+ resolve(inputs)
145
+ }
146
+ })
147
+ })
148
+ },
149
+ sessionRefreshed: function (data) {
150
+ this.emit("session-refreshed", "", [data])
151
+ },
152
+
153
+ reload: function (
154
+ files: Array<string> | null = null,
155
+ exercises: Array<string> | null = null
156
+ ) {
157
+ this.emit("reload", files?.join("") || "", exercises!)
158
+ },
159
+ openWindow: function (url = "") {
160
+ queue.dispatcher().enqueue(queue.events.OPEN_WINDOW, url)
161
+ this.emit(
162
+ queue.events.OPEN_WINDOW as TAction,
163
+ "ready",
164
+ [`Opening ${url}`],
165
+ [],
166
+ [],
167
+ url
168
+ )
169
+ },
170
+ log: function (
171
+ status: TStatus,
172
+ messages: string | Array<string> = [],
173
+ report: Array<string> = [],
174
+ data: any = null
175
+ ) {
176
+ this.emit("log", status, messages, [], report, data)
177
+ Console.log(messages)
178
+ },
179
+ emit: function (
180
+ action: TAction,
181
+ status: TStatus | string = "ready",
182
+ logs: string | Array<string> = [],
183
+ inputs: Array<string> = [],
184
+ report: Array<string> = [],
185
+ data: any = null
186
+ ) {
187
+ if (
188
+ this.config?.compiler &&
189
+ ["webpack", "vanillajs", "vue", "react", "css", "html"].includes(
190
+ this.config?.compiler
191
+ )
192
+ ) {
193
+ if (["compiler-success", "compiler-warning"].includes(status))
194
+ this.addAllowed("preview")
195
+ if (["compiler-error"].includes(status) || action === "ready")
196
+ this.removeAllowed("preview")
197
+ }
198
+
199
+ if (this.config?.grading === "incremental") {
200
+ this.removeAllowed("reset")
201
+ }
202
+
203
+ // eslint-disable-next-line
204
+ this.config?.disabledActions?.forEach((a) => this.removeAllowed(a))
205
+
206
+ this.socket?.emit("compiler", {
207
+ action,
208
+ status,
209
+ logs,
210
+ allowed: this.allowedActions,
211
+ inputs,
212
+ report,
213
+ data,
214
+ })
215
+ },
216
+
217
+ ready: function (message: string) {
218
+ this.log("ready", [message])
219
+ },
220
+ success: function (type: TSuccessType, stdout: string, lang) {
221
+ const types = ["compiler", "testing"]
222
+
223
+ if (!types.includes(type))
224
+ this.fatal(`Invalid socket success type "${type}" on socket`)
225
+ else if (
226
+ stdout === "" &&
227
+ lang &&
228
+ Object.keys(languageToMessage).includes(lang)
229
+ ) {
230
+ this.log((type + "-success") as TSuccessType, [languageToMessage[lang]])
231
+ } else if (stdout === "") {
232
+ this.log((type + "-success") as TSuccessType, [
233
+ "No stdout to display on the console",
234
+ ])
235
+ } else
236
+ this.log((type + "-success") as TSuccessType, [stdout])
237
+ },
238
+ error: function (type: TStatus, stdout: string) {
239
+ if (!this.config?.editor.hideTerminal) {
240
+ queue.dispatcher().enqueue(queue.events.OPEN_TERMINAL, "")
241
+ }
242
+
243
+ this.log(type, [stdout])
244
+
245
+ if (this.isTestingEnvironment) {
246
+ this.onTestingFinished({
247
+ result: "failed",
248
+ })
249
+ }
250
+ },
251
+ complete: function () {
252
+ console.log("complete")
253
+ },
254
+ dialog: function (message: string, format = "md") {
255
+ if (!this.socket) {
256
+ this.fatal("Socket is not initialized")
257
+ return
258
+ }
259
+
260
+ this.emit("dialog", "talk", [], undefined, undefined, { message, format })
261
+ },
262
+
263
+ fatal: function (msg: string) {
264
+ this.log("internal-error", [msg])
265
+ throw msg
266
+ },
267
+ onTestingFinished: function (result: any) {
268
+ if (this.config?.testingFinishedCallback) {
269
+ this.config.testingFinishedCallback(result)
270
+ }
271
+ },
272
+ }
273
+
274
+ export default SocketManager