@learnpack/learnpack 4.0.9 → 4.0.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. package/README.md +25 -10
  2. package/lib/commands/audit.d.ts +6 -6
  3. package/lib/commands/audit.js +327 -327
  4. package/lib/commands/build.d.ts +11 -0
  5. package/lib/commands/build.js +160 -0
  6. package/lib/commands/clean.d.ts +8 -8
  7. package/lib/commands/clean.js +22 -22
  8. package/lib/commands/download.d.ts +13 -13
  9. package/lib/commands/download.js +52 -52
  10. package/lib/commands/init.d.ts +9 -9
  11. package/lib/commands/init.js +127 -127
  12. package/lib/commands/login.d.ts +14 -14
  13. package/lib/commands/login.js +34 -34
  14. package/lib/commands/logout.d.ts +14 -14
  15. package/lib/commands/logout.js +34 -34
  16. package/lib/commands/publish.d.ts +14 -14
  17. package/lib/commands/publish.js +79 -79
  18. package/lib/commands/start.d.ts +7 -7
  19. package/lib/commands/start.js +252 -250
  20. package/lib/commands/test.d.ts +6 -6
  21. package/lib/commands/test.js +62 -62
  22. package/lib/index.d.ts +1 -1
  23. package/lib/index.js +4 -4
  24. package/lib/managers/config/allowed_files.d.ts +5 -5
  25. package/lib/managers/config/allowed_files.js +30 -30
  26. package/lib/managers/config/defaults.d.ts +47 -48
  27. package/lib/managers/config/defaults.js +51 -51
  28. package/lib/managers/config/exercise.d.ts +36 -36
  29. package/lib/managers/config/exercise.js +243 -236
  30. package/lib/managers/config/index.d.ts +3 -3
  31. package/lib/managers/config/index.js +464 -459
  32. package/lib/managers/file.d.ts +14 -14
  33. package/lib/managers/file.js +190 -184
  34. package/lib/managers/gitpod.d.ts +3 -3
  35. package/lib/managers/gitpod.js +67 -67
  36. package/lib/managers/server/index.d.ts +5 -6
  37. package/lib/managers/server/index.js +58 -58
  38. package/lib/managers/server/routes.d.ts +4 -4
  39. package/lib/managers/server/routes.js +228 -220
  40. package/lib/managers/session.d.ts +3 -3
  41. package/lib/managers/session.js +125 -125
  42. package/lib/managers/socket.d.ts +3 -3
  43. package/lib/managers/socket.js +188 -186
  44. package/lib/managers/telemetry.d.ts +74 -74
  45. package/lib/managers/telemetry.js +215 -214
  46. package/lib/managers/test.js +84 -84
  47. package/lib/models/action.d.ts +2 -2
  48. package/lib/models/action.js +2 -2
  49. package/lib/models/audit.d.ts +15 -15
  50. package/lib/models/audit.js +2 -2
  51. package/lib/models/config-manager.d.ts +21 -21
  52. package/lib/models/config-manager.js +2 -2
  53. package/lib/models/config.d.ts +86 -86
  54. package/lib/models/config.js +2 -2
  55. package/lib/models/counter.d.ts +11 -11
  56. package/lib/models/counter.js +2 -2
  57. package/lib/models/errors.d.ts +15 -15
  58. package/lib/models/errors.js +2 -2
  59. package/lib/models/exercise-obj.d.ts +29 -30
  60. package/lib/models/exercise-obj.js +2 -2
  61. package/lib/models/file.d.ts +5 -5
  62. package/lib/models/file.js +2 -2
  63. package/lib/models/findings.d.ts +17 -17
  64. package/lib/models/findings.js +2 -2
  65. package/lib/models/flags.d.ts +10 -10
  66. package/lib/models/flags.js +2 -2
  67. package/lib/models/front-matter.d.ts +11 -11
  68. package/lib/models/front-matter.js +2 -2
  69. package/lib/models/gitpod-data.d.ts +16 -16
  70. package/lib/models/gitpod-data.js +2 -2
  71. package/lib/models/language.d.ts +4 -4
  72. package/lib/models/language.js +2 -2
  73. package/lib/models/package.d.ts +7 -7
  74. package/lib/models/package.js +2 -2
  75. package/lib/models/plugin-config.d.ts +16 -16
  76. package/lib/models/plugin-config.js +2 -2
  77. package/lib/models/session.d.ts +31 -31
  78. package/lib/models/session.js +2 -2
  79. package/lib/models/socket.d.ts +37 -37
  80. package/lib/models/socket.js +2 -2
  81. package/lib/models/status.d.ts +1 -1
  82. package/lib/models/status.js +2 -2
  83. package/lib/models/success-types.d.ts +1 -1
  84. package/lib/models/success-types.js +2 -2
  85. package/lib/plugin/command/compile.d.ts +6 -6
  86. package/lib/plugin/command/compile.js +18 -18
  87. package/lib/plugin/command/test.d.ts +6 -6
  88. package/lib/plugin/command/test.js +25 -25
  89. package/lib/plugin/index.d.ts +27 -27
  90. package/lib/plugin/index.js +7 -7
  91. package/lib/plugin/plugin.d.ts +8 -8
  92. package/lib/plugin/plugin.js +68 -68
  93. package/lib/plugin/utils.d.ts +16 -16
  94. package/lib/plugin/utils.js +58 -58
  95. package/lib/ui/download.d.ts +5 -5
  96. package/lib/ui/download.js +62 -61
  97. package/lib/utils/BaseCommand.d.ts +8 -8
  98. package/lib/utils/BaseCommand.js +41 -41
  99. package/lib/utils/SessionCommand.d.ts +10 -10
  100. package/lib/utils/SessionCommand.js +43 -43
  101. package/lib/utils/api.d.ts +14 -14
  102. package/lib/utils/api.js +255 -255
  103. package/lib/utils/audit.d.ts +16 -16
  104. package/lib/utils/audit.js +303 -303
  105. package/lib/utils/checkNotInstalled.d.ts +8 -8
  106. package/lib/utils/checkNotInstalled.js +185 -181
  107. package/lib/utils/console.d.ts +12 -12
  108. package/lib/utils/console.js +19 -19
  109. package/lib/utils/errors.d.ts +17 -17
  110. package/lib/utils/errors.js +107 -100
  111. package/lib/utils/exercisesQueue.d.ts +9 -9
  112. package/lib/utils/exercisesQueue.js +38 -38
  113. package/lib/utils/fileQueue.d.ts +43 -43
  114. package/lib/utils/fileQueue.js +169 -169
  115. package/lib/utils/misc.d.ts +1 -1
  116. package/lib/utils/misc.js +24 -23
  117. package/lib/utils/osOperations.d.ts +5 -5
  118. package/lib/utils/osOperations.js +72 -72
  119. package/lib/utils/validators.d.ts +5 -5
  120. package/lib/utils/validators.js +16 -17
  121. package/lib/utils/watcher.d.ts +2 -2
  122. package/lib/utils/watcher.js +25 -25
  123. package/oclif.manifest.json +1 -1
  124. package/package.json +6 -4
  125. package/src/commands/build.ts +181 -0
  126. package/src/managers/config/index.ts +5 -0
  127. package/src/managers/server/routes.ts +11 -1
  128. package/src/managers/session.ts +1 -1
@@ -0,0 +1,11 @@
1
+ import SessionCommand from "../utils/SessionCommand";
2
+ export default class BuildCommand extends SessionCommand {
3
+ static description: string;
4
+ static flags: {
5
+ help: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
6
+ };
7
+ init(): Promise<void>;
8
+ run(): Promise<void>;
9
+ copyDirectory(src: string, dest: string): void;
10
+ removeDirectory(dir: string): void;
11
+ }
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /* eslint-disable arrow-parens */
4
+ /* eslint-disable unicorn/no-array-for-each */
5
+ const command_1 = require("@oclif/command");
6
+ const SessionCommand_1 = require("../utils/SessionCommand");
7
+ const session_1 = require("../managers/session");
8
+ const fs = require("fs");
9
+ const path = require("path");
10
+ const archiver = require("archiver");
11
+ const axios_1 = require("axios");
12
+ const FormData = require("form-data");
13
+ const console_1 = require("../utils/console");
14
+ // const RIGOBOT_HOST = "https://rigobot-test-cca7d841c9d8.herokuapp.com"
15
+ const RIGOBOT_HOST =
16
+ // "https://8000-charlytoc-rigobot-bmwdeam7cev.ws-us116.gitpod.io"
17
+ "https://rigobot.herokuapp.com";
18
+ const uploadZipEndpont = RIGOBOT_HOST + "/v1/learnpack/upload";
19
+ class BuildCommand extends SessionCommand_1.default {
20
+ async init() {
21
+ const { flags } = this.parse(BuildCommand);
22
+ await this.initSession(flags);
23
+ }
24
+ async run() {
25
+ const buildDir = path.join(process.cwd(), "build");
26
+ const sessionPayload = await session_1.default.getPayload();
27
+ if (!sessionPayload || !sessionPayload.rigobot) {
28
+ console_1.default.error("You must be logged in to upload a LearnPack packge, please run: \n$ learnpack login");
29
+ return;
30
+ }
31
+ const rigoToken = sessionPayload.rigobot.key;
32
+ // const rigoToken = "417d612d226a1606ad3a4e94b1881a9f0124b667"
33
+ // Read learn.json to get the slug
34
+ const learnJsonPath = path.join(process.cwd(), "learn.json");
35
+ if (!fs.existsSync(learnJsonPath)) {
36
+ this.error("learn.json not found");
37
+ }
38
+ const learnJson = JSON.parse(fs.readFileSync(learnJsonPath, "utf-8"));
39
+ const zipFilePath = path.join(process.cwd(), `${learnJson.slug}.zip`);
40
+ // Ensure build directory exists
41
+ if (!fs.existsSync(buildDir)) {
42
+ fs.mkdirSync(buildDir);
43
+ }
44
+ // Copy config.json
45
+ const configPath = path.join(process.cwd(), ".learn", "config.json");
46
+ if (fs.existsSync(configPath)) {
47
+ fs.copyFileSync(configPath, path.join(buildDir, "config.json"));
48
+ }
49
+ else {
50
+ this.error("config.json not found");
51
+ }
52
+ // Copy .learn/assets directory
53
+ const assetsDir = path.join(process.cwd(), ".learn", "assets");
54
+ if (fs.existsSync(assetsDir)) {
55
+ this.copyDirectory(assetsDir, path.join(buildDir, ".learn", "assets"));
56
+ }
57
+ else {
58
+ this.error(".learn/assets directory not found");
59
+ }
60
+ // Copy .learn/_app directory files to the same level as config.json
61
+ const appDir = path.join(process.cwd(), ".learn", "_app");
62
+ if (fs.existsSync(appDir)) {
63
+ this.copyDirectory(appDir, buildDir);
64
+ }
65
+ else {
66
+ this.error(".learn/_app directory not found");
67
+ }
68
+ // Copy exercises directory
69
+ const exercisesDir = path.join(process.cwd(), "exercises");
70
+ const learnExercisesDir = path.join(process.cwd(), ".learn", "exercises");
71
+ if (fs.existsSync(exercisesDir)) {
72
+ this.copyDirectory(exercisesDir, path.join(buildDir, "exercises"));
73
+ }
74
+ else if (fs.existsSync(learnExercisesDir)) {
75
+ this.copyDirectory(learnExercisesDir, path.join(buildDir, "exercises"));
76
+ }
77
+ else {
78
+ this.error("exercises directory not found in either location");
79
+ }
80
+ // Copy learn.json
81
+ fs.copyFileSync(learnJsonPath, path.join(buildDir, "learn.json"));
82
+ // Create zip file
83
+ const output = fs.createWriteStream(zipFilePath);
84
+ const archive = archiver("zip", {
85
+ zlib: { level: 9 },
86
+ });
87
+ output.on("close", async () => {
88
+ this.log(`Build completed: ${zipFilePath} (${archive.pointer()} total bytes)`);
89
+ // Remove build directory after zip is created
90
+ this.removeDirectory(buildDir);
91
+ console.log("Zip file saved in project root");
92
+ const formData = new FormData();
93
+ formData.append("file", fs.createReadStream(zipFilePath));
94
+ formData.append("config", JSON.stringify(learnJson));
95
+ try {
96
+ const res = await axios_1.default.post(uploadZipEndpont, formData, {
97
+ headers: Object.assign(Object.assign({}, formData.getHeaders()), { Authorization: `Token ${rigoToken}` }),
98
+ });
99
+ console.log(res.data);
100
+ }
101
+ catch (error) {
102
+ if (axios_1.default.isAxiosError(error)) {
103
+ if (error.response && error.response.status === 403) {
104
+ console.error("Error 403:", error.response.data.error);
105
+ }
106
+ else if (error.response && error.response.status === 400) {
107
+ console.error(error.response.data.error);
108
+ }
109
+ else {
110
+ console.error("Error uploading file:", error.message);
111
+ }
112
+ }
113
+ else {
114
+ console.error("Error uploading file:", error);
115
+ }
116
+ }
117
+ });
118
+ archive.on("error", (err) => {
119
+ throw err;
120
+ });
121
+ archive.pipe(output);
122
+ archive.directory(buildDir, false);
123
+ await archive.finalize();
124
+ }
125
+ copyDirectory(src, dest) {
126
+ if (!fs.existsSync(dest)) {
127
+ fs.mkdirSync(dest, { recursive: true });
128
+ }
129
+ const entries = fs.readdirSync(src, { withFileTypes: true });
130
+ for (const entry of entries) {
131
+ const srcPath = path.join(src, entry.name);
132
+ const destPath = path.join(dest, entry.name);
133
+ if (entry.isDirectory()) {
134
+ this.copyDirectory(srcPath, destPath);
135
+ }
136
+ else {
137
+ fs.copyFileSync(srcPath, destPath);
138
+ }
139
+ }
140
+ }
141
+ removeDirectory(dir) {
142
+ if (fs.existsSync(dir)) {
143
+ fs.readdirSync(dir).forEach((file) => {
144
+ const currentPath = path.join(dir, file);
145
+ if (fs.lstatSync(currentPath).isDirectory()) {
146
+ this.removeDirectory(currentPath);
147
+ }
148
+ else {
149
+ fs.unlinkSync(currentPath);
150
+ }
151
+ });
152
+ fs.rmdirSync(dir);
153
+ }
154
+ }
155
+ }
156
+ BuildCommand.description = "Builds the project by copying necessary files and directories into a zip file";
157
+ BuildCommand.flags = {
158
+ help: command_1.flags.help({ char: "h" }),
159
+ };
160
+ exports.default = BuildCommand;
@@ -1,8 +1,8 @@
1
- import SessionCommand from "../utils/SessionCommand";
2
- declare class CleanCommand extends SessionCommand {
3
- static description: string;
4
- static flags: any;
5
- init(): Promise<void>;
6
- run(): Promise<void>;
7
- }
8
- export default CleanCommand;
1
+ import SessionCommand from "../utils/SessionCommand";
2
+ declare class CleanCommand extends SessionCommand {
3
+ static description: string;
4
+ static flags: any;
5
+ init(): Promise<void>;
6
+ run(): Promise<void>;
7
+ }
8
+ export default CleanCommand;
@@ -1,25 +1,25 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- // import {flags} from '@oclif/command'
4
- const console_1 = require("../utils/console");
5
- const SessionCommand_1 = require("../utils/SessionCommand");
6
- class CleanCommand extends SessionCommand_1.default {
7
- async init() {
8
- const { flags } = this.parse(CleanCommand);
9
- await this.initSession(flags);
10
- }
11
- async run() {
12
- var _a;
13
- const { flags } = this.parse(CleanCommand);
14
- (_a = this.configManager) === null || _a === void 0 ? void 0 : _a.clean();
15
- console_1.default.success("Package cleaned successfully, ready to publish");
16
- }
17
- }
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // import {flags} from '@oclif/command'
4
+ const console_1 = require("../utils/console");
5
+ const SessionCommand_1 = require("../utils/SessionCommand");
6
+ class CleanCommand extends SessionCommand_1.default {
7
+ async init() {
8
+ const { flags } = this.parse(CleanCommand);
9
+ await this.initSession(flags);
10
+ }
11
+ async run() {
12
+ var _a;
13
+ const { flags } = this.parse(CleanCommand);
14
+ (_a = this.configManager) === null || _a === void 0 ? void 0 : _a.clean();
15
+ console_1.default.success("Package cleaned successfully, ready to publish");
16
+ }
17
+ }
18
18
  CleanCommand.description = `Clean the configuration object
19
19
  ...
20
20
  Extra documentation goes here
21
- `;
22
- CleanCommand.flags = {
23
- // name: flags.string({char: 'n', description: 'name to print'}),
24
- };
25
- exports.default = CleanCommand;
21
+ `;
22
+ CleanCommand.flags = {
23
+ // name: flags.string({char: 'n', description: 'name to print'}),
24
+ };
25
+ exports.default = CleanCommand;
@@ -1,13 +1,13 @@
1
- import { Command } from "@oclif/command";
2
- declare class DownloadCommand extends Command {
3
- static description: string;
4
- static flags: any;
5
- static args: {
6
- name: string;
7
- required: boolean;
8
- description: string;
9
- hidden: boolean;
10
- }[];
11
- run(): Promise<null | undefined>;
12
- }
13
- export default DownloadCommand;
1
+ import { Command } from "@oclif/command";
2
+ declare class DownloadCommand extends Command {
3
+ static description: string;
4
+ static flags: any;
5
+ static args: {
6
+ name: string;
7
+ required: boolean;
8
+ description: string;
9
+ hidden: boolean;
10
+ }[];
11
+ run(): Promise<null | undefined>;
12
+ }
13
+ export default DownloadCommand;
@@ -1,55 +1,55 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const command_1 = require("@oclif/command");
4
- // import fetch from 'node-fetch'
5
- const file_1 = require("../managers/file");
6
- const console_1 = require("../utils/console");
7
- const api_1 = require("../utils/api");
8
- const download_1 = require("../ui/download");
9
- // const BaseCommand = require('../utils/BaseCommand');
10
- class DownloadCommand extends command_1.Command {
11
- // async init() {
12
- // const {flags} = this.parse(DownloadCommand)
13
- // await this.initSession(flags)
14
- // }
15
- async run() {
16
- const { /* flags, */ args } = this.parse(DownloadCommand);
17
- // start watching for file changes
18
- let _package = args.package;
19
- if (!_package) {
20
- _package = (await download_1.askPackage());
21
- }
22
- if (!_package) {
23
- return null;
24
- }
25
- try {
26
- const packageInfo = await api_1.default.getAllPackages({ slug: _package });
27
- if (packageInfo.results.length === 0)
28
- console_1.default.error(`Package ${_package} not found`);
29
- else
30
- file_1.clone(packageInfo.results[0].repository)
31
- .then(_result => {
32
- console_1.default.success("Successfully downloaded");
33
- console_1.default.info(`You can now CD into the folder like this: $ cd ${_package}`);
34
- })
35
- .catch(error => console_1.default.error(error.message || error));
36
- }
37
- catch (_a) { }
38
- }
39
- }
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const command_1 = require("@oclif/command");
4
+ // import fetch from 'node-fetch'
5
+ const file_1 = require("../managers/file");
6
+ const console_1 = require("../utils/console");
7
+ const api_1 = require("../utils/api");
8
+ const download_1 = require("../ui/download");
9
+ // const BaseCommand = require('../utils/BaseCommand');
10
+ class DownloadCommand extends command_1.Command {
11
+ // async init() {
12
+ // const {flags} = this.parse(DownloadCommand)
13
+ // await this.initSession(flags)
14
+ // }
15
+ async run() {
16
+ const { /* flags, */ args } = this.parse(DownloadCommand);
17
+ // start watching for file changes
18
+ let _package = args.package;
19
+ if (!_package) {
20
+ _package = (await (0, download_1.askPackage)());
21
+ }
22
+ if (!_package) {
23
+ return null;
24
+ }
25
+ try {
26
+ const packageInfo = await api_1.default.getAllPackages({ slug: _package });
27
+ if (packageInfo.results.length === 0)
28
+ console_1.default.error(`Package ${_package} not found`);
29
+ else
30
+ (0, file_1.clone)(packageInfo.results[0].repository)
31
+ .then(_result => {
32
+ console_1.default.success("Successfully downloaded");
33
+ console_1.default.info(`You can now CD into the folder like this: $ cd ${_package}`);
34
+ })
35
+ .catch(error => console_1.default.error(error.message || error));
36
+ }
37
+ catch (_a) { }
38
+ }
39
+ }
40
40
  DownloadCommand.description = `Describe the command here
41
41
  ...
42
42
  Extra documentation goes here
43
- `;
44
- DownloadCommand.flags = {
45
- // name: flags.string({char: 'n', description: 'name to print'}),
46
- };
47
- DownloadCommand.args = [
48
- {
49
- name: "package",
50
- required: false,
51
- description: "The unique string that identifies this package on learnpack",
52
- hidden: false,
53
- },
54
- ];
55
- exports.default = DownloadCommand;
43
+ `;
44
+ DownloadCommand.flags = {
45
+ // name: flags.string({char: 'n', description: 'name to print'}),
46
+ };
47
+ DownloadCommand.args = [
48
+ {
49
+ name: "package", // name of arg to show in help and reference with args[name]
50
+ required: false, // make the arg required with `required: true`
51
+ description: "The unique string that identifies this package on learnpack", // help description
52
+ hidden: false, // hide this arg from help
53
+ },
54
+ ];
55
+ exports.default = DownloadCommand;
@@ -1,9 +1,9 @@
1
- import BaseCommand from "../utils/BaseCommand";
2
- declare class InitComand extends BaseCommand {
3
- static description: string;
4
- static flags: {
5
- grading: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
6
- };
7
- run(): Promise<void>;
8
- }
9
- export default InitComand;
1
+ import BaseCommand from "../utils/BaseCommand";
2
+ declare class InitComand extends BaseCommand {
3
+ static description: string;
4
+ static flags: {
5
+ grading: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
6
+ };
7
+ run(): Promise<void>;
8
+ }
9
+ export default InitComand;
@@ -1,127 +1,127 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const command_1 = require("@oclif/command");
4
- const BaseCommand_1 = require("../utils/BaseCommand");
5
- // eslint-disable-next-line
6
- const fs = require("fs-extra");
7
- const prompts = require("prompts");
8
- const cli_ux_1 = require("cli-ux");
9
- const eta = require("eta");
10
- const console_1 = require("../utils/console");
11
- const errors_1 = require("../utils/errors");
12
- const path = require("path");
13
- class InitComand extends BaseCommand_1.default {
14
- async run() {
15
- const { flags } = this.parse(InitComand);
16
- // if the folder/file .learn or .breathecode aleady exists
17
- await alreadyInitialized();
18
- const choices = await prompts([
19
- {
20
- type: "select",
21
- name: "grading",
22
- message: "Is the auto-grading going to be isolated or incremental?",
23
- choices: [
24
- {
25
- title: "Incremental: Build on top of each other like a tutorial",
26
- value: "incremental",
27
- },
28
- { title: "Isolated: Small separated exercises", value: "isolated" },
29
- {
30
- title: "No grading: No feedback or testing whatsoever",
31
- value: null,
32
- },
33
- ],
34
- },
35
- {
36
- type: "text",
37
- name: "title",
38
- initial: "My Interactive Tutorial",
39
- message: "Title for your tutorial? Press enter to leave as it is",
40
- },
41
- {
42
- type: "text",
43
- name: "description",
44
- initial: "",
45
- message: "Description for your tutorial? Press enter to leave blank",
46
- },
47
- {
48
- type: "select",
49
- name: "difficulty",
50
- message: "How difficulty will be to complete the tutorial?",
51
- choices: [
52
- { title: "Begginer (no previous experience)", value: "beginner" },
53
- { title: "Easy (just a bit of experience required)", value: "easy" },
54
- {
55
- title: "Intermediate (you need experience)",
56
- value: "intermediate",
57
- },
58
- { title: "Hard (master the topic)", value: "hard" },
59
- ],
60
- },
61
- {
62
- type: "text",
63
- name: "duration",
64
- initial: "1",
65
- message: "How many hours avg it takes to complete (number)?",
66
- validate: (value) => {
67
- const n = Math.floor(Number(value));
68
- return n !== Number.POSITIVE_INFINITY && String(n) === value && n >= 0;
69
- },
70
- },
71
- ]);
72
- const packageInfo = {
73
- grading: choices.grading,
74
- difficulty: choices.difficulty,
75
- duration: parseInt(choices.duration),
76
- description: choices.description,
77
- title: choices.title,
78
- slug: choices.title
79
- .toLowerCase()
80
- .replace(/ /g, "-")
81
- .replace(/[^\w-]+/g, ""),
82
- };
83
- const tutorialDir = `./${packageInfo.slug}`;
84
- fs.ensureDirSync(tutorialDir); // Ensure the directory exists
85
- cli_ux_1.default.action.start("Initializing package");
86
- const languages = ["en", "es"];
87
- const templatesDir = path.resolve(__dirname, "../../src/utils/templates/" + (choices.grading || "no-grading"));
88
- if (!fs.existsSync(templatesDir))
89
- throw errors_1.ValidationError(`Template ${templatesDir} does not exists`);
90
- await fs.copySync(templatesDir, tutorialDir);
91
- // Creating README files
92
- for (const language of languages) {
93
- const readmeFilename = `README${language !== "en" ? `.${language}` : ""}`;
94
- const readmeTemplatePath = path.resolve(templatesDir, `${readmeFilename}.ejs`);
95
- const readmeContent = eta.render(fs.readFileSync(readmeTemplatePath, "utf-8"), packageInfo);
96
- fs.writeFileSync(path.join(tutorialDir, `${readmeFilename}.md`), readmeContent);
97
- if (fs.existsSync(path.join(tutorialDir, `${readmeFilename}.ejs`)))
98
- fs.removeSync(path.join(tutorialDir, `${readmeFilename}.ejs`));
99
- }
100
- if (!fs.existsSync(path.join(tutorialDir, ".gitignore")))
101
- fs.copyFile(path.resolve(__dirname, "../../src/utils/templates/gitignore.txt"), path.join(tutorialDir, ".gitignore"));
102
- fs.writeFileSync(path.join(tutorialDir, "learn.json"), JSON.stringify(packageInfo, null, 2));
103
- cli_ux_1.default.action.stop();
104
- console_1.default.success(`😋 Package initialized successfully in ${tutorialDir}`);
105
- console_1.default.help(`Get inside the tutorial with the command: $ cd ${tutorialDir}`);
106
- console_1.default.help(`Start the exercises by running the following command on your terminal: $ learnpack start`);
107
- }
108
- }
109
- InitComand.description = "Create a new learning package: Book, Tutorial or Exercise";
110
- InitComand.flags = Object.assign(Object.assign({}, BaseCommand_1.default.flags), { grading: command_1.flags.help({ char: "h" }) });
111
- const alreadyInitialized = () => new Promise((resolve, reject) => {
112
- fs.readdir("./", function (err, files) {
113
- files = files.filter((f) => [".learn", "learn.json", "bc.json", ".breathecode"].includes(f));
114
- if (err) {
115
- reject(errors_1.ValidationError(err.message));
116
- throw errors_1.ValidationError(err.message);
117
- }
118
- else if (files.length > 0) {
119
- reject(errors_1.ValidationError("It seems the package is already initialized because we've found the following files: " +
120
- files.join(",")));
121
- throw errors_1.ValidationError("It seems the package is already initialized because we've found the following files: " +
122
- files.join(","));
123
- }
124
- resolve(false);
125
- });
126
- });
127
- exports.default = InitComand;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const command_1 = require("@oclif/command");
4
+ const BaseCommand_1 = require("../utils/BaseCommand");
5
+ // eslint-disable-next-line
6
+ const fs = require("fs-extra");
7
+ const prompts = require("prompts");
8
+ const cli_ux_1 = require("cli-ux");
9
+ const eta = require("eta");
10
+ const console_1 = require("../utils/console");
11
+ const errors_1 = require("../utils/errors");
12
+ const path = require("path");
13
+ class InitComand extends BaseCommand_1.default {
14
+ async run() {
15
+ const { flags } = this.parse(InitComand);
16
+ // if the folder/file .learn or .breathecode aleady exists
17
+ await alreadyInitialized();
18
+ const choices = await prompts([
19
+ {
20
+ type: "select",
21
+ name: "grading",
22
+ message: "Is the auto-grading going to be isolated or incremental?",
23
+ choices: [
24
+ {
25
+ title: "Incremental: Build on top of each other like a tutorial",
26
+ value: "incremental",
27
+ },
28
+ { title: "Isolated: Small separated exercises", value: "isolated" },
29
+ {
30
+ title: "No grading: No feedback or testing whatsoever",
31
+ value: null,
32
+ },
33
+ ],
34
+ },
35
+ {
36
+ type: "text",
37
+ name: "title",
38
+ initial: "My Interactive Tutorial",
39
+ message: "Title for your tutorial? Press enter to leave as it is",
40
+ },
41
+ {
42
+ type: "text",
43
+ name: "description",
44
+ initial: "",
45
+ message: "Description for your tutorial? Press enter to leave blank",
46
+ },
47
+ {
48
+ type: "select",
49
+ name: "difficulty",
50
+ message: "How difficulty will be to complete the tutorial?",
51
+ choices: [
52
+ { title: "Begginer (no previous experience)", value: "beginner" },
53
+ { title: "Easy (just a bit of experience required)", value: "easy" },
54
+ {
55
+ title: "Intermediate (you need experience)",
56
+ value: "intermediate",
57
+ },
58
+ { title: "Hard (master the topic)", value: "hard" },
59
+ ],
60
+ },
61
+ {
62
+ type: "text",
63
+ name: "duration",
64
+ initial: "1",
65
+ message: "How many hours avg it takes to complete (number)?",
66
+ validate: (value) => {
67
+ const n = Math.floor(Number(value));
68
+ return n !== Number.POSITIVE_INFINITY && String(n) === value && n >= 0;
69
+ },
70
+ },
71
+ ]);
72
+ const packageInfo = {
73
+ grading: choices.grading,
74
+ difficulty: choices.difficulty,
75
+ duration: parseInt(choices.duration),
76
+ description: choices.description,
77
+ title: choices.title,
78
+ slug: choices.title
79
+ .toLowerCase()
80
+ .replace(/ /g, "-")
81
+ .replace(/[^\w-]+/g, ""),
82
+ };
83
+ const tutorialDir = `./${packageInfo.slug}`;
84
+ fs.ensureDirSync(tutorialDir); // Ensure the directory exists
85
+ cli_ux_1.default.action.start("Initializing package");
86
+ const languages = ["en", "es"];
87
+ const templatesDir = path.resolve(__dirname, "../../src/utils/templates/" + (choices.grading || "no-grading"));
88
+ if (!fs.existsSync(templatesDir))
89
+ throw (0, errors_1.ValidationError)(`Template ${templatesDir} does not exists`);
90
+ await fs.copySync(templatesDir, tutorialDir);
91
+ // Creating README files
92
+ for (const language of languages) {
93
+ const readmeFilename = `README${language !== "en" ? `.${language}` : ""}`;
94
+ const readmeTemplatePath = path.resolve(templatesDir, `${readmeFilename}.ejs`);
95
+ const readmeContent = eta.render(fs.readFileSync(readmeTemplatePath, "utf-8"), packageInfo);
96
+ fs.writeFileSync(path.join(tutorialDir, `${readmeFilename}.md`), readmeContent);
97
+ if (fs.existsSync(path.join(tutorialDir, `${readmeFilename}.ejs`)))
98
+ fs.removeSync(path.join(tutorialDir, `${readmeFilename}.ejs`));
99
+ }
100
+ if (!fs.existsSync(path.join(tutorialDir, ".gitignore")))
101
+ fs.copyFile(path.resolve(__dirname, "../../src/utils/templates/gitignore.txt"), path.join(tutorialDir, ".gitignore"));
102
+ fs.writeFileSync(path.join(tutorialDir, "learn.json"), JSON.stringify(packageInfo, null, 2));
103
+ cli_ux_1.default.action.stop();
104
+ console_1.default.success(`😋 Package initialized successfully in ${tutorialDir}`);
105
+ console_1.default.help(`Get inside the tutorial with the command: $ cd ${tutorialDir}`);
106
+ console_1.default.help(`Start the exercises by running the following command on your terminal: $ learnpack start`);
107
+ }
108
+ }
109
+ InitComand.description = "Create a new learning package: Book, Tutorial or Exercise";
110
+ InitComand.flags = Object.assign(Object.assign({}, BaseCommand_1.default.flags), { grading: command_1.flags.help({ char: "h" }) });
111
+ const alreadyInitialized = () => new Promise((resolve, reject) => {
112
+ fs.readdir("./", function (err, files) {
113
+ files = files.filter((f) => [".learn", "learn.json", "bc.json", ".breathecode"].includes(f));
114
+ if (err) {
115
+ reject((0, errors_1.ValidationError)(err.message));
116
+ throw (0, errors_1.ValidationError)(err.message);
117
+ }
118
+ else if (files.length > 0) {
119
+ reject((0, errors_1.ValidationError)("It seems the package is already initialized because we've found the following files: " +
120
+ files.join(",")));
121
+ throw (0, errors_1.ValidationError)("It seems the package is already initialized because we've found the following files: " +
122
+ files.join(","));
123
+ }
124
+ resolve(false);
125
+ });
126
+ });
127
+ exports.default = InitComand;