@learnpack/learnpack 5.0.275 → 5.0.277

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 (95) 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/publish.js +5 -10
  8. package/lib/commands/serve.js +55 -2
  9. package/lib/creatorDist/assets/index-BfLyIQVh.js +10343 -10224
  10. package/lib/managers/config/index.js +77 -77
  11. package/lib/utils/api.d.ts +1 -1
  12. package/lib/utils/api.js +12 -9
  13. package/lib/utils/creatorUtilities.js +14 -14
  14. package/lib/utils/export/epub.d.ts +2 -0
  15. package/lib/utils/export/epub.js +298 -0
  16. package/lib/utils/export/index.d.ts +3 -0
  17. package/lib/utils/export/index.js +7 -0
  18. package/lib/utils/export/scorm.d.ts +2 -0
  19. package/lib/utils/export/scorm.js +84 -0
  20. package/lib/utils/export/shared.d.ts +4 -0
  21. package/lib/utils/export/shared.js +61 -0
  22. package/lib/utils/export/types.d.ts +15 -0
  23. package/lib/utils/export/types.js +2 -0
  24. package/package.json +2 -1
  25. package/src/commands/audit.ts +487 -487
  26. package/src/commands/breakToken.ts +67 -67
  27. package/src/commands/clean.ts +30 -30
  28. package/src/commands/init.ts +650 -650
  29. package/src/commands/logout.ts +38 -38
  30. package/src/commands/publish.ts +20 -25
  31. package/src/commands/serve.ts +69 -4
  32. package/src/commands/start.ts +333 -333
  33. package/src/commands/translate.ts +123 -123
  34. package/src/creator/README.md +54 -54
  35. package/src/creator/eslint.config.js +7 -7
  36. package/src/creator/src/components/syllabus/ContentIndex.tsx +312 -312
  37. package/src/creator/src/i18n.ts +28 -28
  38. package/src/creator/src/index.css +217 -217
  39. package/src/creator/src/locales/en.json +126 -126
  40. package/src/creator/src/locales/es.json +126 -126
  41. package/src/creator/src/utils/configTypes.ts +122 -122
  42. package/src/creator/src/utils/constants.ts +13 -13
  43. package/src/creator/src/utils/creatorUtils.ts +46 -46
  44. package/src/creator/src/utils/eventBus.ts +2 -2
  45. package/src/creator/src/utils/lib.ts +468 -468
  46. package/src/creator/src/utils/socket.ts +61 -61
  47. package/src/creator/src/utils/store.ts +222 -222
  48. package/src/creator/src/vite-env.d.ts +1 -1
  49. package/src/creator/vite.config.ts +13 -13
  50. package/src/creatorDist/assets/index-BfLyIQVh.js +10343 -10224
  51. package/src/managers/config/defaults.ts +49 -49
  52. package/src/managers/config/exercise.ts +364 -364
  53. package/src/managers/config/index.ts +775 -775
  54. package/src/managers/file.ts +236 -236
  55. package/src/managers/server/routes.ts +554 -554
  56. package/src/managers/session.ts +182 -182
  57. package/src/managers/telemetry.ts +188 -188
  58. package/src/models/action.ts +13 -13
  59. package/src/models/config-manager.ts +28 -28
  60. package/src/models/config.ts +106 -106
  61. package/src/models/creator.ts +47 -47
  62. package/src/models/exercise-obj.ts +30 -30
  63. package/src/models/session.ts +39 -39
  64. package/src/models/socket.ts +61 -61
  65. package/src/models/status.ts +16 -16
  66. package/src/ui/_app/app.css +1 -1
  67. package/src/ui/_app/app.js +400 -397
  68. package/src/ui/app.tar.gz +0 -0
  69. package/src/utils/BaseCommand.ts +56 -56
  70. package/src/utils/api.ts +53 -39
  71. package/src/utils/audit.ts +392 -392
  72. package/src/utils/checkNotInstalled.ts +267 -267
  73. package/src/utils/configBuilder.ts +82 -82
  74. package/src/utils/convertCreds.js +34 -34
  75. package/src/utils/creatorUtilities.ts +504 -504
  76. package/src/utils/export/README.md +178 -0
  77. package/src/utils/export/epub.ts +400 -0
  78. package/src/utils/export/index.ts +3 -0
  79. package/src/utils/export/scorm.ts +121 -0
  80. package/src/utils/export/shared.ts +61 -0
  81. package/src/utils/export/types.ts +17 -0
  82. package/src/utils/incrementVersion.js +74 -74
  83. package/src/utils/misc.ts +58 -58
  84. package/src/utils/rigoActions.ts +500 -500
  85. package/src/utils/sidebarGenerator.ts +195 -195
  86. package/src/utils/templates/epub/epub.css +133 -0
  87. package/src/utils/templates/isolated/exercises/01-hello-world/README.es.md +26 -26
  88. package/src/utils/templates/isolated/exercises/01-hello-world/README.md +26 -26
  89. package/src/utils/templates/scorm/adlcp_rootv1p2.xsd +110 -0
  90. package/src/utils/templates/scorm/config/api.js +175 -0
  91. package/src/utils/templates/scorm/config/index.html +210 -0
  92. package/src/utils/templates/scorm/ims_xml.xsd +1 -0
  93. package/src/utils/templates/scorm/imscp_rootv1p1p2.xsd +345 -0
  94. package/src/utils/templates/scorm/imsmanifest.xml +38 -0
  95. package/src/utils/templates/scorm/imsmd_rootv1p2p1.xsd +573 -0
@@ -1,38 +1,38 @@
1
- import SessionCommand from "../utils/SessionCommand"
2
- import SessionManager from "../managers/session"
3
- import Console from "../utils/console"
4
-
5
- class LogoutCommand extends SessionCommand {
6
- static description = `Describe the command here
7
- ...
8
- Extra documentation goes here
9
- `
10
-
11
- static flags: any = {
12
- // name: flags.string({char: 'n', description: 'name to print'}),
13
- }
14
-
15
- static args = [
16
- {
17
- name: "package", // name of arg to show in help and reference with args[name]
18
- required: false, // make the arg required with `required: true`
19
- description:
20
- "The unique string that identifies this package on learnpack", // help description
21
- hidden: false, // hide this arg from help
22
- },
23
- ]
24
-
25
- async init() {
26
- const { flags } = this.parse(LogoutCommand)
27
- // await this.initSession(flags)
28
- Console.debug("Logout command")
29
- }
30
-
31
- async run() {
32
- // const {flags, args} = this.parse(LogoutCommand)
33
-
34
- SessionManager.destroy()
35
- }
36
- }
37
-
38
- export default LogoutCommand
1
+ import SessionCommand from "../utils/SessionCommand"
2
+ import SessionManager from "../managers/session"
3
+ import Console from "../utils/console"
4
+
5
+ class LogoutCommand extends SessionCommand {
6
+ static description = `Describe the command here
7
+ ...
8
+ Extra documentation goes here
9
+ `
10
+
11
+ static flags: any = {
12
+ // name: flags.string({char: 'n', description: 'name to print'}),
13
+ }
14
+
15
+ static args = [
16
+ {
17
+ name: "package", // name of arg to show in help and reference with args[name]
18
+ required: false, // make the arg required with `required: true`
19
+ description:
20
+ "The unique string that identifies this package on learnpack", // help description
21
+ hidden: false, // hide this arg from help
22
+ },
23
+ ]
24
+
25
+ async init() {
26
+ const { flags } = this.parse(LogoutCommand)
27
+ // await this.initSession(flags)
28
+ Console.debug("Logout command")
29
+ }
30
+
31
+ async run() {
32
+ // const {flags, args} = this.parse(LogoutCommand)
33
+
34
+ SessionManager.destroy()
35
+ }
36
+ }
37
+
38
+ export default LogoutCommand
@@ -8,7 +8,7 @@ import * as fs from "fs"
8
8
  import * as path from "path"
9
9
  import * as archiver from "archiver"
10
10
  import axios from "axios"
11
- import FormData = require("form-data")
11
+ import FormData = require("form-data");
12
12
  import Console from "../utils/console"
13
13
  import {
14
14
  decompress,
@@ -31,17 +31,7 @@ export const handleAssetCreation = async (
31
31
  b64IndexReadme: string,
32
32
  all_translations: string[] = []
33
33
  ) => {
34
- const categories: Record<string, number> = {
35
- en: 9,
36
- us: 9,
37
- es: 10,
38
- }
39
-
40
- let category = categories[selectedLang]
41
-
42
- if (!category) {
43
- category = 91
44
- }
34
+ const category = "uncategorized"
45
35
 
46
36
  try {
47
37
  const user = await api.validateToken(sessionPayload.token)
@@ -81,6 +71,7 @@ export const handleAssetCreation = async (
81
71
  const asset = await api.updateAsset(sessionPayload.token, slug, {
82
72
  learnpack_deploy_url: learnpackDeployUrl,
83
73
  title: learnJson.title[selectedLang],
74
+ category: category,
84
75
  description: learnJson.description[selectedLang],
85
76
  all_translations,
86
77
  })
@@ -124,19 +115,19 @@ const runAudit = (strict: boolean) => {
124
115
  }
125
116
 
126
117
  type Academy = {
127
- id: number
128
- name: string
129
- slug?: string
130
- timezone?: string
131
- }
118
+ id: number;
119
+ name: string;
120
+ slug?: string;
121
+ timezone?: string;
122
+ };
132
123
 
133
124
  type Category = {
134
- id: number
135
- slug: string
136
- title: string
137
- lang: string
138
- academy: Academy
139
- }
125
+ id: number;
126
+ slug: string;
127
+ title: string;
128
+ lang: string;
129
+ academy: Academy;
130
+ };
140
131
 
141
132
  function getCategoriesByAcademy(
142
133
  categories: Category[],
@@ -299,7 +290,9 @@ class BuildCommand extends SessionCommand {
299
290
 
300
291
  if (configObject) {
301
292
  const { config } = configObject
302
- const appAlreadyExists = checkIfDirectoryExists(`${config?.dirPath}/_app`)
293
+ const appAlreadyExists = checkIfDirectoryExists(
294
+ `${config?.dirPath}/_app`
295
+ )
303
296
 
304
297
  if (!appAlreadyExists) {
305
298
  // download app and decompress
@@ -329,7 +322,9 @@ class BuildCommand extends SessionCommand {
329
322
  if (fs.existsSync(assetsDir)) {
330
323
  this.copyDirectory(assetsDir, path.join(buildDir, ".learn", "assets"))
331
324
  } else {
332
- fs.mkdirSync(path.join(buildDir, ".learn", "assets"), { recursive: true })
325
+ fs.mkdirSync(path.join(buildDir, ".learn", "assets"), {
326
+ recursive: true,
327
+ })
333
328
  }
334
329
 
335
330
  // Copy .learn/_app directory files to the same level as config.json
@@ -2,7 +2,6 @@ import { flags } from "@oclif/command"
2
2
 
3
3
  import { Buffer } from "buffer"
4
4
 
5
- import { YoutubeTranscript } from "youtube-transcript"
6
5
  import * as express from "express"
7
6
  import * as cors from "cors"
8
7
  import * as path from "path"
@@ -19,6 +18,7 @@ import * as archiver from "archiver"
19
18
  import * as mkdirp from "mkdirp"
20
19
  import { convert } from "html-to-text"
21
20
  import * as rimraf from "rimraf"
21
+ import { v4 as uuidv4 } from "uuid"
22
22
  import SessionCommand from "../utils/SessionCommand"
23
23
  import { Bucket, Storage } from "@google-cloud/storage"
24
24
  import { downloadEditor, decompress } from "../managers/file"
@@ -36,6 +36,8 @@ import {
36
36
  getLanguageCodes,
37
37
  } from "../utils/rigoActions"
38
38
  import * as dotenv from "dotenv"
39
+
40
+ // import { v4 as uuidv4 } from "uuid"
39
41
  import {
40
42
  extractImagesFromMarkdown,
41
43
  getFilenameFromUrl,
@@ -45,16 +47,24 @@ import {
45
47
  import axios from "axios"
46
48
  import * as FormData from "form-data"
47
49
  import api, { RIGOBOT_HOST, RIGOBOT_REALTIME_HOST } from "../utils/api"
48
- import { createUploadMiddleware, minutesToISO8601Duration } from "../utils/misc"
50
+ import {
51
+ createUploadMiddleware,
52
+ minutesToISO8601Duration,
53
+ } from "../utils/misc"
49
54
  import { buildConfig, ConfigResponse } from "../utils/configBuilder"
50
55
  import { checkReadability, slugify } from "../utils/creatorUtilities"
51
56
  import { checkAndFixSidebarPure } from "../utils/sidebarGenerator"
52
57
  import { handleAssetCreation } from "./publish"
53
58
  import { FormState, Lesson, Syllabus } from "../models/creator"
59
+ import { exportToScorm, exportToEpub } from "../utils/export"
60
+
54
61
  const frontMatter = require("front-matter")
55
62
 
56
63
  dotenv.config()
57
64
 
65
+ // Asegúrate de tener uuid instalado
66
+ // npm install uuid
67
+
58
68
  function findLast<T>(
59
69
  array: T[],
60
70
  predicate: (item: T) => boolean
@@ -992,6 +1002,12 @@ export default class ServeCommand extends SessionCommand {
992
1002
  const { config, exercises } = await buildConfig(bucket, courseSlug)
993
1003
  res.set("X-Creator-Web", "true")
994
1004
  res.set("Access-Control-Expose-Headers", "X-Creator-Web")
1005
+
1006
+ await uploadFileToBucket(
1007
+ bucket,
1008
+ JSON.stringify({ config, exercises }),
1009
+ `courses/${courseSlug}/.learn/config.json`
1010
+ )
995
1011
  res.json({ config, exercises })
996
1012
  } catch (error) {
997
1013
  console.error(error)
@@ -1829,7 +1845,7 @@ export default class ServeCommand extends SessionCommand {
1829
1845
  const resFromRigo = await axios.get(
1830
1846
  `${RIGOBOT_REALTIME_HOST}/actions/youtube-transcript/${videoId}`
1831
1847
  )
1832
- console.log("RES FROM RIGO", resFromRigo.data)
1848
+
1833
1849
  const transcript = resFromRigo.data.transcript
1834
1850
 
1835
1851
  // let meta: any = null
@@ -1869,7 +1885,9 @@ export default class ServeCommand extends SessionCommand {
1869
1885
  })
1870
1886
  } catch (error: any) {
1871
1887
  console.error("❌ /actions/fetch error:", error.message || error)
1872
- res.status(500).json({ error: error.message || "Failed to fetch link" })
1888
+ res
1889
+ .status(500)
1890
+ .json({ error: error.message || "Failed to fetch link" })
1873
1891
  }
1874
1892
  })
1875
1893
  app.delete("/packages/:slug", async (req, res) => {
@@ -1934,6 +1952,53 @@ export default class ServeCommand extends SessionCommand {
1934
1952
  }
1935
1953
  })
1936
1954
 
1955
+ app.get("/export/:course_slug/:format", async (req, res) => {
1956
+ const { course_slug, format } = req.params
1957
+ const { language } = req.query
1958
+
1959
+ try {
1960
+ let outputPath: string
1961
+ let filename: string
1962
+
1963
+ if (format === "scorm") {
1964
+ outputPath = await exportToScorm({
1965
+ courseSlug: course_slug,
1966
+ format: "scorm",
1967
+ bucket,
1968
+ outDir: path.join(__dirname, "../output/directory"),
1969
+ })
1970
+ filename = `${course_slug}-scorm.zip`
1971
+ } else if (format === "epub") {
1972
+ outputPath = await exportToEpub({
1973
+ courseSlug: course_slug,
1974
+ format: "epub",
1975
+ bucket,
1976
+ outDir: path.join(__dirname, "../output/directory"),
1977
+ language: (language as string) || "en",
1978
+ })
1979
+ filename = `${course_slug}.epub`
1980
+ } else {
1981
+ return res
1982
+ .status(400)
1983
+ .json({ error: "Invalid format. Supported formats: scorm, epub" })
1984
+ }
1985
+
1986
+ // Send the file and clean up
1987
+ res.download(outputPath, filename, err => {
1988
+ if (err) console.error("Error sending file:", err)
1989
+ // Clean up the generated file
1990
+ if (fs.existsSync(outputPath)) {
1991
+ fs.unlinkSync(outputPath)
1992
+ }
1993
+ })
1994
+ } catch (error: any) {
1995
+ console.error("Export error:", error)
1996
+ res
1997
+ .status(500)
1998
+ .json({ error: "Export failed", details: error.message })
1999
+ }
2000
+ })
2001
+
1937
2002
  server.listen(PORT, () => {
1938
2003
  console.log(
1939
2004
  `🚀 Creator UI server running at http://localhost:${PORT}/creator`