@learnpack/learnpack 5.0.270 → 5.0.274

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 (77) hide show
  1. package/README.md +409 -409
  2. package/lib/commands/audit.js +15 -15
  3. package/lib/commands/breakToken.js +19 -19
  4. package/lib/commands/clean.js +3 -3
  5. package/lib/commands/init.js +41 -41
  6. package/lib/commands/logout.js +3 -3
  7. package/lib/commands/serve.js +48 -20
  8. package/lib/creatorDist/assets/{index-CQXTTbaZ.js → index-BfLyIQVh.js} +11535 -11409
  9. package/lib/creatorDist/assets/{index-B4khtb0r.css → index-C39zeF3W.css} +3 -3
  10. package/lib/creatorDist/index.html +2 -2
  11. package/lib/managers/config/index.js +77 -77
  12. package/lib/models/creator.d.ts +1 -0
  13. package/lib/utils/api.js +1 -0
  14. package/lib/utils/creatorUtilities.js +14 -14
  15. package/package.json +1 -1
  16. package/src/commands/audit.ts +487 -487
  17. package/src/commands/breakToken.ts +67 -67
  18. package/src/commands/clean.ts +30 -30
  19. package/src/commands/init.ts +650 -650
  20. package/src/commands/logout.ts +38 -38
  21. package/src/commands/publish.ts +522 -522
  22. package/src/commands/serve.ts +64 -33
  23. package/src/commands/start.ts +333 -333
  24. package/src/commands/translate.ts +123 -123
  25. package/src/creator/README.md +54 -54
  26. package/src/creator/eslint.config.js +28 -28
  27. package/src/creator/src/components/syllabus/ContentIndex.tsx +1 -1
  28. package/src/creator/src/components/syllabus/SyllabusEditor.tsx +3 -1
  29. package/src/creator/src/i18n.ts +28 -28
  30. package/src/creator/src/index.css +217 -217
  31. package/src/creator/src/locales/en.json +1 -0
  32. package/src/creator/src/locales/es.json +1 -0
  33. package/src/creator/src/utils/configTypes.ts +122 -122
  34. package/src/creator/src/utils/constants.ts +13 -13
  35. package/src/creator/src/utils/creatorUtils.ts +46 -46
  36. package/src/creator/src/utils/eventBus.ts +2 -2
  37. package/src/creator/src/utils/lib.ts +468 -468
  38. package/src/creator/src/utils/rigo.ts +26 -26
  39. package/src/creator/src/utils/socket.ts +61 -61
  40. package/src/creator/src/utils/store.ts +222 -222
  41. package/src/creator/src/vite-env.d.ts +1 -1
  42. package/src/creator/vite.config.ts +13 -13
  43. package/src/creatorDist/assets/{index-CQXTTbaZ.js → index-BfLyIQVh.js} +11535 -11409
  44. package/src/creatorDist/assets/{index-B4khtb0r.css → index-C39zeF3W.css} +3 -3
  45. package/src/creatorDist/index.html +2 -2
  46. package/src/managers/config/defaults.ts +49 -49
  47. package/src/managers/config/exercise.ts +364 -364
  48. package/src/managers/config/index.ts +775 -775
  49. package/src/managers/file.ts +236 -236
  50. package/src/managers/server/routes.ts +554 -554
  51. package/src/managers/session.ts +182 -182
  52. package/src/managers/telemetry.ts +188 -188
  53. package/src/models/action.ts +13 -13
  54. package/src/models/config-manager.ts +28 -28
  55. package/src/models/config.ts +106 -106
  56. package/src/models/creator.ts +40 -39
  57. package/src/models/exercise-obj.ts +30 -30
  58. package/src/models/session.ts +39 -39
  59. package/src/models/socket.ts +61 -61
  60. package/src/models/status.ts +16 -16
  61. package/src/ui/_app/app.css +1 -1
  62. package/src/ui/_app/app.js +435 -414
  63. package/src/ui/_app/learnpack.svg +7 -7
  64. package/src/ui/app.tar.gz +0 -0
  65. package/src/utils/BaseCommand.ts +56 -56
  66. package/src/utils/api.ts +31 -30
  67. package/src/utils/audit.ts +392 -392
  68. package/src/utils/checkNotInstalled.ts +267 -267
  69. package/src/utils/configBuilder.ts +82 -82
  70. package/src/utils/convertCreds.js +34 -34
  71. package/src/utils/creatorUtilities.ts +504 -504
  72. package/src/utils/incrementVersion.js +74 -74
  73. package/src/utils/misc.ts +58 -58
  74. package/src/utils/rigoActions.ts +500 -500
  75. package/src/utils/sidebarGenerator.ts +195 -195
  76. package/src/utils/templates/isolated/exercises/01-hello-world/README.es.md +26 -26
  77. package/src/utils/templates/isolated/exercises/01-hello-world/README.md +26 -26
@@ -1,195 +1,195 @@
1
- import path = require("path")
2
-
3
- import Console from "./console"
4
- import fs = require("fs")
5
- import { IExercise, IExerciseData } from "../models/exercise-obj"
6
- import { IConfigObj } from "../models/config"
7
- import SessionManager from "../managers/session"
8
- import { fillSidebarJSON } from "./rigoActions"
9
-
10
- type TTitleTranslations = {
11
- [key: string]: string
12
- }
13
-
14
- export type TSidebar = {
15
- [key: string]: TTitleTranslations
16
- }
17
-
18
- export const generateSidebar = (exercises: IExercise[], learnPath: string) => {
19
- const sidebarPath = path.join(learnPath, "sidebar.json")
20
- let sidebar: TSidebar = {}
21
- if (fs.existsSync(sidebarPath)) {
22
- sidebar = JSON.parse(fs.readFileSync(sidebarPath, "utf8"))
23
- }
24
-
25
- for (const exercise of exercises) {
26
- sidebar[exercise.slug] = {
27
- ...sidebar[exercise.slug],
28
- us: exercise.title,
29
- }
30
- }
31
-
32
- fs.writeFileSync(sidebarPath, JSON.stringify(sidebar, null, 2))
33
-
34
- return sidebar
35
- }
36
-
37
- export const addExerciseToSidebar = (
38
- exerciseSlug: string,
39
- targetLanguage: string,
40
- translatedSlug: string,
41
- learnPath: string
42
- ) => {
43
- const sidebarPath = path.join(learnPath, "sidebar.json")
44
- let sidebar: TSidebar = {}
45
- if (fs.existsSync(sidebarPath)) {
46
- sidebar = JSON.parse(fs.readFileSync(sidebarPath, "utf8"))
47
- }
48
-
49
- sidebar[exerciseSlug] = {
50
- ...sidebar[exerciseSlug],
51
- [targetLanguage]: translatedSlug,
52
- }
53
-
54
- fs.writeFileSync(sidebarPath, JSON.stringify(sidebar, null, 2))
55
-
56
- return sidebar
57
- }
58
-
59
- export const checkAndFixSidebar = async (
60
- configObj: IConfigObj,
61
- autoFix = false
62
- ): Promise<boolean> => {
63
- if (
64
- configObj.config &&
65
- fs.existsSync(configObj.config.dirPath + "/sidebar.json")
66
- ) {
67
- let hasErrors = false
68
- const sidebar = fs.readFileSync(
69
- configObj.config.dirPath + "/sidebar.json",
70
- "utf8"
71
- )
72
- // parse the sidebar.json file
73
- const sidebarJson = JSON.parse(sidebar)
74
-
75
- const exerciseTranslations: Set<string> = new Set()
76
- configObj.exercises?.map(e =>
77
- // eslint-disable-next-line
78
- Object.keys((e.translations || {}) as any).forEach((t) =>
79
- exerciseTranslations.add(t)
80
- )
81
- )
82
- // Validation
83
- for (const [key, value] of Object.entries(sidebarJson) as [
84
- string,
85
- TTitleTranslations
86
- ][]) {
87
- for (const lang of exerciseTranslations) {
88
- if (!Object.prototype.hasOwnProperty.call(value, lang)) {
89
- hasErrors = true
90
- }
91
- }
92
- }
93
-
94
- if (hasErrors && autoFix) {
95
- Console.warning("Filling sidebar.json file with missing translations")
96
- const sessionPayload = await SessionManager.getPayload()
97
-
98
- const rigoToken = sessionPayload.rigobot.key
99
-
100
- if (!rigoToken) {
101
- Console.error("No Rigobot token found, please login first!")
102
- return false
103
- }
104
-
105
- const response = await fillSidebarJSON(rigoToken, {
106
- needed_translations: JSON.stringify(exerciseTranslations),
107
- sidebar_json: JSON.stringify(sidebarJson),
108
- })
109
-
110
- const newSidebarJson = JSON.parse(response.parsed.new_sidebar_file)
111
- fs.writeFileSync(
112
- configObj.config.dirPath + "/sidebar.json",
113
- JSON.stringify(newSidebarJson, null, 4)
114
- )
115
- Console.info("Sidebar.json was filled with missing translations")
116
- return true
117
- }
118
-
119
- if (hasErrors && !autoFix) {
120
- return false
121
- }
122
-
123
- return true
124
- }
125
-
126
- return false
127
- }
128
-
129
- export const checkAndFixSidebarPure = async (
130
- sidebarJson: Record<string, Record<string, string>>,
131
- exercises: any[],
132
- rigoToken: string,
133
- autoFix = true
134
- ): Promise<{
135
- valid: boolean
136
- fixedSidebar?: Record<string, Record<string, string>>
137
- }> => {
138
- const exerciseTranslations: Set<string> = new Set()
139
- for (const e of exercises) {
140
- for (const lang of Object.keys(e.translations || {})) {
141
- exerciseTranslations.add(lang)
142
- }
143
- }
144
-
145
- let hasErrors = false
146
- const fixedSidebar: Record<string, Record<string, string>> = {
147
- ...sidebarJson,
148
- }
149
-
150
- for (const exercise of exercises) {
151
- const slug = exercise.slug
152
- const existingEntry = fixedSidebar[slug]
153
-
154
- if (!existingEntry) {
155
- hasErrors = true
156
- fixedSidebar[slug] = { us: exercise.slug }
157
- continue
158
- }
159
-
160
- for (const lang of exerciseTranslations) {
161
- if (!Object.prototype.hasOwnProperty.call(existingEntry, lang)) {
162
- hasErrors = true
163
- }
164
- }
165
- }
166
-
167
- if (hasErrors && autoFix) {
168
- if (!rigoToken) {
169
- Console.error("No Rigobot token provided!")
170
- return { valid: false }
171
- }
172
-
173
- Console.warning(
174
- "Filling sidebar JSON with missing translations or exercises"
175
- )
176
-
177
- const response = await fillSidebarJSON(rigoToken, {
178
- needed_translations: JSON.stringify([...exerciseTranslations]),
179
- sidebar_json: JSON.stringify(fixedSidebar),
180
- })
181
-
182
- const newSidebarJson = JSON.parse(response.parsed.new_sidebar_file)
183
-
184
- Console.info("Sidebar JSON was fixed")
185
- return {
186
- valid: true,
187
- fixedSidebar: newSidebarJson,
188
- }
189
- }
190
-
191
- return {
192
- valid: !hasErrors,
193
- fixedSidebar: hasErrors ? fixedSidebar : undefined,
194
- }
195
- }
1
+ import path = require("path")
2
+
3
+ import Console from "./console"
4
+ import fs = require("fs")
5
+ import { IExercise, IExerciseData } from "../models/exercise-obj"
6
+ import { IConfigObj } from "../models/config"
7
+ import SessionManager from "../managers/session"
8
+ import { fillSidebarJSON } from "./rigoActions"
9
+
10
+ type TTitleTranslations = {
11
+ [key: string]: string
12
+ }
13
+
14
+ export type TSidebar = {
15
+ [key: string]: TTitleTranslations
16
+ }
17
+
18
+ export const generateSidebar = (exercises: IExercise[], learnPath: string) => {
19
+ const sidebarPath = path.join(learnPath, "sidebar.json")
20
+ let sidebar: TSidebar = {}
21
+ if (fs.existsSync(sidebarPath)) {
22
+ sidebar = JSON.parse(fs.readFileSync(sidebarPath, "utf8"))
23
+ }
24
+
25
+ for (const exercise of exercises) {
26
+ sidebar[exercise.slug] = {
27
+ ...sidebar[exercise.slug],
28
+ us: exercise.title,
29
+ }
30
+ }
31
+
32
+ fs.writeFileSync(sidebarPath, JSON.stringify(sidebar, null, 2))
33
+
34
+ return sidebar
35
+ }
36
+
37
+ export const addExerciseToSidebar = (
38
+ exerciseSlug: string,
39
+ targetLanguage: string,
40
+ translatedSlug: string,
41
+ learnPath: string
42
+ ) => {
43
+ const sidebarPath = path.join(learnPath, "sidebar.json")
44
+ let sidebar: TSidebar = {}
45
+ if (fs.existsSync(sidebarPath)) {
46
+ sidebar = JSON.parse(fs.readFileSync(sidebarPath, "utf8"))
47
+ }
48
+
49
+ sidebar[exerciseSlug] = {
50
+ ...sidebar[exerciseSlug],
51
+ [targetLanguage]: translatedSlug,
52
+ }
53
+
54
+ fs.writeFileSync(sidebarPath, JSON.stringify(sidebar, null, 2))
55
+
56
+ return sidebar
57
+ }
58
+
59
+ export const checkAndFixSidebar = async (
60
+ configObj: IConfigObj,
61
+ autoFix = false
62
+ ): Promise<boolean> => {
63
+ if (
64
+ configObj.config &&
65
+ fs.existsSync(configObj.config.dirPath + "/sidebar.json")
66
+ ) {
67
+ let hasErrors = false
68
+ const sidebar = fs.readFileSync(
69
+ configObj.config.dirPath + "/sidebar.json",
70
+ "utf8"
71
+ )
72
+ // parse the sidebar.json file
73
+ const sidebarJson = JSON.parse(sidebar)
74
+
75
+ const exerciseTranslations: Set<string> = new Set()
76
+ configObj.exercises?.map(e =>
77
+ // eslint-disable-next-line
78
+ Object.keys((e.translations || {}) as any).forEach((t) =>
79
+ exerciseTranslations.add(t)
80
+ )
81
+ )
82
+ // Validation
83
+ for (const [key, value] of Object.entries(sidebarJson) as [
84
+ string,
85
+ TTitleTranslations
86
+ ][]) {
87
+ for (const lang of exerciseTranslations) {
88
+ if (!Object.prototype.hasOwnProperty.call(value, lang)) {
89
+ hasErrors = true
90
+ }
91
+ }
92
+ }
93
+
94
+ if (hasErrors && autoFix) {
95
+ Console.warning("Filling sidebar.json file with missing translations")
96
+ const sessionPayload = await SessionManager.getPayload()
97
+
98
+ const rigoToken = sessionPayload.rigobot.key
99
+
100
+ if (!rigoToken) {
101
+ Console.error("No Rigobot token found, please login first!")
102
+ return false
103
+ }
104
+
105
+ const response = await fillSidebarJSON(rigoToken, {
106
+ needed_translations: JSON.stringify(exerciseTranslations),
107
+ sidebar_json: JSON.stringify(sidebarJson),
108
+ })
109
+
110
+ const newSidebarJson = JSON.parse(response.parsed.new_sidebar_file)
111
+ fs.writeFileSync(
112
+ configObj.config.dirPath + "/sidebar.json",
113
+ JSON.stringify(newSidebarJson, null, 4)
114
+ )
115
+ Console.info("Sidebar.json was filled with missing translations")
116
+ return true
117
+ }
118
+
119
+ if (hasErrors && !autoFix) {
120
+ return false
121
+ }
122
+
123
+ return true
124
+ }
125
+
126
+ return false
127
+ }
128
+
129
+ export const checkAndFixSidebarPure = async (
130
+ sidebarJson: Record<string, Record<string, string>>,
131
+ exercises: any[],
132
+ rigoToken: string,
133
+ autoFix = true
134
+ ): Promise<{
135
+ valid: boolean
136
+ fixedSidebar?: Record<string, Record<string, string>>
137
+ }> => {
138
+ const exerciseTranslations: Set<string> = new Set()
139
+ for (const e of exercises) {
140
+ for (const lang of Object.keys(e.translations || {})) {
141
+ exerciseTranslations.add(lang)
142
+ }
143
+ }
144
+
145
+ let hasErrors = false
146
+ const fixedSidebar: Record<string, Record<string, string>> = {
147
+ ...sidebarJson,
148
+ }
149
+
150
+ for (const exercise of exercises) {
151
+ const slug = exercise.slug
152
+ const existingEntry = fixedSidebar[slug]
153
+
154
+ if (!existingEntry) {
155
+ hasErrors = true
156
+ fixedSidebar[slug] = { us: exercise.slug }
157
+ continue
158
+ }
159
+
160
+ for (const lang of exerciseTranslations) {
161
+ if (!Object.prototype.hasOwnProperty.call(existingEntry, lang)) {
162
+ hasErrors = true
163
+ }
164
+ }
165
+ }
166
+
167
+ if (hasErrors && autoFix) {
168
+ if (!rigoToken) {
169
+ Console.error("No Rigobot token provided!")
170
+ return { valid: false }
171
+ }
172
+
173
+ Console.warning(
174
+ "Filling sidebar JSON with missing translations or exercises"
175
+ )
176
+
177
+ const response = await fillSidebarJSON(rigoToken, {
178
+ needed_translations: JSON.stringify([...exerciseTranslations]),
179
+ sidebar_json: JSON.stringify(fixedSidebar),
180
+ })
181
+
182
+ const newSidebarJson = JSON.parse(response.parsed.new_sidebar_file)
183
+
184
+ Console.info("Sidebar JSON was fixed")
185
+ return {
186
+ valid: true,
187
+ fixedSidebar: newSidebarJson,
188
+ }
189
+ }
190
+
191
+ return {
192
+ valid: !hasErrors,
193
+ fixedSidebar: hasErrors ? fixedSidebar : undefined,
194
+ }
195
+ }
@@ -1,26 +1,26 @@
1
- # `01` Primer Ejercicio
2
-
3
- Hemos creado este primer ejercicio como ejemplo. Lo puedes ubicar en la carpeta `./01-hello-world`.
4
-
5
- 1. Cada ejercicio debe estar ubicado en carpetas separadas y debe tener un archivo README.md con las instrucciones del ejercicio escrito en markdown.
6
- 2. Puedes tener un archivo README el cual será como una página de un libro, sin archivos de código.
7
- 3. También puedes agregar un archivo `README.[lenguaje].md` para traducciones, por ejemplo `README.es.md` para español.
8
-
9
- ## Inserta videos
10
-
11
- Si quieres incluir algún video introductorio para cada ejercicio, agrega la propiedad `intro` en el inicio del README.md para ese ejercicio en particular:
12
-
13
- ```markdown
14
- ---
15
- intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
16
- ---
17
- ```
18
-
19
- Tambien puedes agregar un video explicando la solución para cada ejercicio agregando la propiedad `tutorial` al inicio del markdown del README.md correspondiente:
20
-
21
- ```markdown
22
- ---
23
- intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
24
- tutorial: "https://www.youtube.com/watch?v=YkgkThdzX-8"
25
- ---
26
- ```
1
+ # `01` Primer Ejercicio
2
+
3
+ Hemos creado este primer ejercicio como ejemplo. Lo puedes ubicar en la carpeta `./01-hello-world`.
4
+
5
+ 1. Cada ejercicio debe estar ubicado en carpetas separadas y debe tener un archivo README.md con las instrucciones del ejercicio escrito en markdown.
6
+ 2. Puedes tener un archivo README el cual será como una página de un libro, sin archivos de código.
7
+ 3. También puedes agregar un archivo `README.[lenguaje].md` para traducciones, por ejemplo `README.es.md` para español.
8
+
9
+ ## Inserta videos
10
+
11
+ Si quieres incluir algún video introductorio para cada ejercicio, agrega la propiedad `intro` en el inicio del README.md para ese ejercicio en particular:
12
+
13
+ ```markdown
14
+ ---
15
+ intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
16
+ ---
17
+ ```
18
+
19
+ Tambien puedes agregar un video explicando la solución para cada ejercicio agregando la propiedad `tutorial` al inicio del markdown del README.md correspondiente:
20
+
21
+ ```markdown
22
+ ---
23
+ intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
24
+ tutorial: "https://www.youtube.com/watch?v=YkgkThdzX-8"
25
+ ---
26
+ ```
@@ -1,26 +1,26 @@
1
- # `01` First Exercise
2
-
3
- We created this first exercise as an example, you can find it located in the folder `./01-hello-world`.
4
-
5
- 1. Every exercise must be located on a separate folder and it must have a README.md file inside with the exercise instructions written in markdown.
6
- 2. You can have just a README file and it will be like a page in a book, no code files.
7
- 3. You can also add a `README.[lang].md` file for translations, for example: `README.es.md` for spanish.
8
-
9
- ## Video compatibility
10
-
11
- If you want to include some video introduction for each exercise, add a `intro` property in the markdown frontmatter of the README.md for that particular exercise:
12
-
13
- ```markdown
14
- ---
15
- intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
16
- ---
17
- ```
18
-
19
- You can also add a video solution for each exercise by adding a `tutorial` property on the markdown frontmatter of it's README.md:
20
-
21
- ```markdown
22
- ---
23
- intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
24
- tutorial: "https://www.youtube.com/watch?v=YkgkThdzX-8"
25
- ---
26
- ```
1
+ # `01` First Exercise
2
+
3
+ We created this first exercise as an example, you can find it located in the folder `./01-hello-world`.
4
+
5
+ 1. Every exercise must be located on a separate folder and it must have a README.md file inside with the exercise instructions written in markdown.
6
+ 2. You can have just a README file and it will be like a page in a book, no code files.
7
+ 3. You can also add a `README.[lang].md` file for translations, for example: `README.es.md` for spanish.
8
+
9
+ ## Video compatibility
10
+
11
+ If you want to include some video introduction for each exercise, add a `intro` property in the markdown frontmatter of the README.md for that particular exercise:
12
+
13
+ ```markdown
14
+ ---
15
+ intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
16
+ ---
17
+ ```
18
+
19
+ You can also add a video solution for each exercise by adding a `tutorial` property on the markdown frontmatter of it's README.md:
20
+
21
+ ```markdown
22
+ ---
23
+ intro: "https://www.youtube.com/watch?v=YkgkThdzX-8"
24
+ tutorial: "https://www.youtube.com/watch?v=YkgkThdzX-8"
25
+ ---
26
+ ```