@learnpack/learnpack 5.0.7 → 5.0.9

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.
Files changed (70) hide show
  1. package/README.md +17 -17
  2. package/bin/run +17 -17
  3. package/bin/run.cmd +3 -3
  4. package/lib/commands/audit.js +34 -22
  5. package/lib/commands/clean.js +3 -3
  6. package/lib/commands/download.js +3 -3
  7. package/lib/commands/login.js +3 -3
  8. package/lib/commands/logout.js +3 -3
  9. package/lib/managers/config/index.d.ts +10 -0
  10. package/lib/managers/config/index.js +3 -1
  11. package/oclif.manifest.json +1 -1
  12. package/package.json +152 -152
  13. package/src/commands/audit.ts +449 -443
  14. package/src/commands/clean.ts +29 -29
  15. package/src/commands/download.ts +61 -61
  16. package/src/commands/login.ts +42 -42
  17. package/src/commands/logout.ts +43 -43
  18. package/src/commands/publish.ts +249 -249
  19. package/src/commands/test.ts +85 -85
  20. package/src/index.ts +1 -1
  21. package/src/managers/config/allowed_files.ts +29 -29
  22. package/src/managers/config/index.ts +6 -4
  23. package/src/managers/gitpod.ts +84 -84
  24. package/src/managers/server/index.ts +78 -78
  25. package/src/managers/telemetry.ts +353 -353
  26. package/src/managers/test.ts +83 -83
  27. package/src/models/audit.ts +16 -16
  28. package/src/models/config-manager.ts +23 -23
  29. package/src/models/counter.ts +11 -11
  30. package/src/models/errors.ts +22 -22
  31. package/src/models/exercise-obj.ts +29 -29
  32. package/src/models/file.ts +5 -5
  33. package/src/models/findings.ts +18 -18
  34. package/src/models/flags.ts +10 -10
  35. package/src/models/front-matter.ts +11 -11
  36. package/src/models/gitpod-data.ts +19 -19
  37. package/src/models/language.ts +4 -4
  38. package/src/models/package.ts +7 -7
  39. package/src/models/plugin-config.ts +17 -17
  40. package/src/models/success-types.ts +1 -1
  41. package/src/plugin/command/compile.ts +17 -17
  42. package/src/plugin/command/test.ts +30 -30
  43. package/src/plugin/index.ts +6 -6
  44. package/src/plugin/plugin.ts +94 -94
  45. package/src/plugin/utils.ts +87 -87
  46. package/src/types/node-fetch.d.ts +1 -1
  47. package/src/ui/download.ts +71 -71
  48. package/src/utils/BaseCommand.ts +48 -48
  49. package/src/utils/SessionCommand.ts +43 -43
  50. package/src/utils/audit.ts +393 -393
  51. package/src/utils/errors.ts +117 -117
  52. package/src/utils/exercisesQueue.ts +51 -51
  53. package/src/utils/fileQueue.ts +199 -199
  54. package/src/utils/misc.ts +23 -23
  55. package/src/utils/osOperations.ts +79 -79
  56. package/src/utils/templates/gitignore.txt +19 -19
  57. package/src/utils/templates/incremental/.learn/exercises/01-hello-world/README.es.md +24 -24
  58. package/src/utils/templates/incremental/.learn/exercises/01-hello-world/README.md +24 -24
  59. package/src/utils/templates/incremental/.vscode/schema.json +121 -121
  60. package/src/utils/templates/incremental/.vscode/settings.json +13 -13
  61. package/src/utils/templates/incremental/README.ejs +4 -4
  62. package/src/utils/templates/incremental/README.es.ejs +4 -4
  63. package/src/utils/templates/isolated/.vscode/schema.json +121 -121
  64. package/src/utils/templates/isolated/.vscode/settings.json +13 -13
  65. package/src/utils/templates/isolated/README.ejs +4 -4
  66. package/src/utils/templates/isolated/README.es.ejs +4 -4
  67. package/src/utils/templates/no-grading/README.ejs +4 -4
  68. package/src/utils/templates/no-grading/README.es.ejs +4 -4
  69. package/src/utils/validators.ts +18 -18
  70. package/src/utils/watcher.ts +27 -27
@@ -1,29 +1,29 @@
1
- const extensions = {
2
- extensions: [
3
- "py",
4
- "java",
5
- "py",
6
- "ruby",
7
- "html",
8
- "css",
9
- "htm",
10
- "php", // images
11
- "js",
12
- "jsx",
13
- "ts", // images
14
- "sh",
15
- "bash", // images
16
- "json",
17
- "yml",
18
- "yaml",
19
- "csv",
20
- "xml", // file storage extensions
21
- "txt",
22
- "text",
23
- "markdown",
24
- "readme", // compressed files
25
- ],
26
- names: ["package.json", "package-lock.json"],
27
- }
28
-
29
- export default extensions
1
+ const extensions = {
2
+ extensions: [
3
+ "py",
4
+ "java",
5
+ "py",
6
+ "ruby",
7
+ "html",
8
+ "css",
9
+ "htm",
10
+ "php", // images
11
+ "js",
12
+ "jsx",
13
+ "ts", // images
14
+ "sh",
15
+ "bash", // images
16
+ "json",
17
+ "yml",
18
+ "yaml",
19
+ "csv",
20
+ "xml", // file storage extensions
21
+ "txt",
22
+ "text",
23
+ "markdown",
24
+ "readme", // compressed files
25
+ ],
26
+ names: ["package.json", "package-lock.json"],
27
+ }
28
+
29
+ export default extensions
@@ -32,9 +32,9 @@ import { IFile } from "../../models/file"
32
32
  const execAsync = promisify(exec)
33
33
 
34
34
  // eslint-disable-next-line
35
- const fetch = require("node-fetch")
35
+ const fetch = require("node-fetch");
36
36
  // eslint-disable-next-line
37
- const chalk = require("chalk")
37
+ const chalk = require("chalk");
38
38
 
39
39
  /* exercise folder name standard */
40
40
 
@@ -44,7 +44,7 @@ const chalk = require("chalk")
44
44
  * @returns An object containing the configuration file path and the base directory.
45
45
  * @throws NotFoundError if the learn.json file is not found in the current folder.
46
46
  */
47
- const getConfigPath = () => {
47
+ export const getConfigPath = () => {
48
48
  const possibleFileNames = ["learn.json", ".learn/learn.json"]
49
49
  const config = possibleFileNames.find(file => fs.existsSync(file)) || null
50
50
  if (config && fs.existsSync(".breathecode"))
@@ -444,7 +444,9 @@ fs.unlinkSync(_path)
444
444
  ex => ex.slug === slug
445
445
  )
446
446
  if (!exercise)
447
- throw ValidationError(`Exercise ${slug} not found on the configuration`)
447
+ throw ValidationError(
448
+ `Exercise ${slug} not found on the configuration`
449
+ )
448
450
 
449
451
  if (configObj.config) {
450
452
  for (const fileName of fs.readdirSync(
@@ -1,84 +1,84 @@
1
- import Console from '../utils/console'
2
- import * as shell from 'shelljs'
3
- import socket from './socket'
4
- import * as fs from 'fs'
5
-
6
- import {TFile, IGitpod} from '../models/gitpod-data'
7
- import {IConfigObj} from '../models/config'
8
-
9
- const Gitpod: IGitpod = {
10
- socket: null,
11
- config: null,
12
- initialized: false,
13
- hasGPCommand: false,
14
- init: function (config?: IConfigObj) {
15
- if (this.initialized) {
16
- return
17
- }
18
-
19
- this.initialized = true
20
-
21
- if (config) {
22
- this.config = config
23
- }
24
-
25
- if (shell.exec('gp -h', {silent: true}).code === 0) {
26
- this.hasGPCommand = true
27
- if (config) {
28
- config.address = shell
29
- .exec('gp url', {silent: true})
30
- .stdout.replace(/(\r\n|\n|\r)/gm, '')
31
- }
32
- } else {
33
- Console.debug('Gitpod command line tool not found')
34
- }
35
- },
36
- openFiles: async function (files: Array<TFile>) {
37
- Console.debug('Attempting to open files in gitpod mode', files)
38
- this.init() // initilize gitpod config
39
-
40
- // gitpod will open files only on isolated mode
41
- if (!this.config || this.config.config?.grading !== 'isolated') {
42
- Console.debug(
43
- 'Files cannot be automatically opened because we are not on isolated grading (only for isolated)',
44
- )
45
- socket.log('ready', ['Ready to compile or test...'])
46
- return true
47
- }
48
-
49
- if (this.hasGPCommand)
50
- for (const f of files.reverse()) {
51
- if (shell.exec(`gp open ${f}`).code > 0) {
52
- Console.debug(`Error opening file ${f} on gitpod`)
53
- }
54
- }
55
-
56
- socket.log('ready', ['Ready to compile or test...'])
57
- },
58
- setup(config?: IConfigObj) {
59
- this.init(config) // initilize gitpod config
60
- this.autosave('on')
61
- },
62
- autosave: async function (value = 'on') {
63
- this.init() // initilize gitpod config
64
-
65
- if (this.hasGPCommand) {
66
- if (!fs.existsSync('./.theia'))
67
- fs.mkdirSync('./.theia')
68
- if (!fs.existsSync('./.theia/settings.json')) {
69
- fs.writeFileSync(
70
- './.theia/settings.json',
71
- JSON.stringify(
72
- {
73
- 'editor.autoSave': value,
74
- },
75
- null,
76
- 4,
77
- ),
78
- )
79
- }
80
- }
81
- },
82
- }
83
-
84
- export default Gitpod
1
+ import Console from '../utils/console'
2
+ import * as shell from 'shelljs'
3
+ import socket from './socket'
4
+ import * as fs from 'fs'
5
+
6
+ import {TFile, IGitpod} from '../models/gitpod-data'
7
+ import {IConfigObj} from '../models/config'
8
+
9
+ const Gitpod: IGitpod = {
10
+ socket: null,
11
+ config: null,
12
+ initialized: false,
13
+ hasGPCommand: false,
14
+ init: function (config?: IConfigObj) {
15
+ if (this.initialized) {
16
+ return
17
+ }
18
+
19
+ this.initialized = true
20
+
21
+ if (config) {
22
+ this.config = config
23
+ }
24
+
25
+ if (shell.exec('gp -h', {silent: true}).code === 0) {
26
+ this.hasGPCommand = true
27
+ if (config) {
28
+ config.address = shell
29
+ .exec('gp url', {silent: true})
30
+ .stdout.replace(/(\r\n|\n|\r)/gm, '')
31
+ }
32
+ } else {
33
+ Console.debug('Gitpod command line tool not found')
34
+ }
35
+ },
36
+ openFiles: async function (files: Array<TFile>) {
37
+ Console.debug('Attempting to open files in gitpod mode', files)
38
+ this.init() // initilize gitpod config
39
+
40
+ // gitpod will open files only on isolated mode
41
+ if (!this.config || this.config.config?.grading !== 'isolated') {
42
+ Console.debug(
43
+ 'Files cannot be automatically opened because we are not on isolated grading (only for isolated)',
44
+ )
45
+ socket.log('ready', ['Ready to compile or test...'])
46
+ return true
47
+ }
48
+
49
+ if (this.hasGPCommand)
50
+ for (const f of files.reverse()) {
51
+ if (shell.exec(`gp open ${f}`).code > 0) {
52
+ Console.debug(`Error opening file ${f} on gitpod`)
53
+ }
54
+ }
55
+
56
+ socket.log('ready', ['Ready to compile or test...'])
57
+ },
58
+ setup(config?: IConfigObj) {
59
+ this.init(config) // initilize gitpod config
60
+ this.autosave('on')
61
+ },
62
+ autosave: async function (value = 'on') {
63
+ this.init() // initilize gitpod config
64
+
65
+ if (this.hasGPCommand) {
66
+ if (!fs.existsSync('./.theia'))
67
+ fs.mkdirSync('./.theia')
68
+ if (!fs.existsSync('./.theia/settings.json')) {
69
+ fs.writeFileSync(
70
+ './.theia/settings.json',
71
+ JSON.stringify(
72
+ {
73
+ 'editor.autoSave': value,
74
+ },
75
+ null,
76
+ 4,
77
+ ),
78
+ )
79
+ }
80
+ }
81
+ },
82
+ }
83
+
84
+ export default Gitpod
@@ -1,78 +1,78 @@
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
- let server: any
21
-
22
- if (isTestingEnvironment) {
23
- if (TEST_SERVER === undefined)
24
- TEST_SERVER = require("http").Server(app)
25
- server = TEST_SERVER
26
- } else
27
- server = require("http").Server(app)
28
-
29
- app.use(cors())
30
-
31
- // app.use(function(req, res, next) {
32
- // res.header("Access-Control-Allow-Origin", "*")
33
- // res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
34
- // res.header("Access-Control-Allow-Methods", "GET,PUT")
35
- // next()
36
- // })
37
-
38
- // add all needed endpoints
39
-
40
- await addRoutes(app, configObj, configManager)
41
-
42
- server.listen(isTestingEnvironment ? 5000 : config?.port, function () {
43
- if (!isTestingEnvironment) {
44
- Console.success(
45
- `Exercises are running 😃 Open your browser to start practicing!`
46
- )
47
- Console.success(`\n Open the exercise on this link:`)
48
- Console.log(` ${config?.publicUrl}`)
49
-
50
- if (config?.editor.mode === "preview")
51
- cli.open(`${config.publicUrl}`)
52
- }
53
- })
54
-
55
- const sockets: any = new Set()
56
-
57
- server.on("connection", (socket: any) => {
58
- sockets.add(socket)
59
-
60
- server.once("close", () => {
61
- sockets.delete(socket)
62
- })
63
- })
64
-
65
- /**
66
- * Forcefully terminates HTTP server.
67
- */
68
- server.terminate = (callback: void) => {
69
- for (const socket of sockets) {
70
- socket.destroy()
71
- sockets.delete(socket)
72
- }
73
-
74
- server.close(callback)
75
- }
76
-
77
- return server
78
- }
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
+ let server: any
21
+
22
+ if (isTestingEnvironment) {
23
+ if (TEST_SERVER === undefined)
24
+ TEST_SERVER = require("http").Server(app)
25
+ server = TEST_SERVER
26
+ } else
27
+ server = require("http").Server(app)
28
+
29
+ app.use(cors())
30
+
31
+ // app.use(function(req, res, next) {
32
+ // res.header("Access-Control-Allow-Origin", "*")
33
+ // res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
34
+ // res.header("Access-Control-Allow-Methods", "GET,PUT")
35
+ // next()
36
+ // })
37
+
38
+ // add all needed endpoints
39
+
40
+ await addRoutes(app, configObj, configManager)
41
+
42
+ server.listen(isTestingEnvironment ? 5000 : config?.port, function () {
43
+ if (!isTestingEnvironment) {
44
+ Console.success(
45
+ `Exercises are running 😃 Open your browser to start practicing!`
46
+ )
47
+ Console.success(`\n Open the exercise on this link:`)
48
+ Console.log(` ${config?.publicUrl}`)
49
+
50
+ if (config?.editor.mode === "preview")
51
+ cli.open(`${config.publicUrl}`)
52
+ }
53
+ })
54
+
55
+ const sockets: any = new Set()
56
+
57
+ server.on("connection", (socket: any) => {
58
+ sockets.add(socket)
59
+
60
+ server.once("close", () => {
61
+ sockets.delete(socket)
62
+ })
63
+ })
64
+
65
+ /**
66
+ * Forcefully terminates HTTP server.
67
+ */
68
+ server.terminate = (callback: void) => {
69
+ for (const socket of sockets) {
70
+ socket.destroy()
71
+ sockets.delete(socket)
72
+ }
73
+
74
+ server.close(callback)
75
+ }
76
+
77
+ return server
78
+ }