@learnpack/learnpack 5.0.361 → 5.0.362
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.
- package/lib/commands/serve.js +44 -1
- package/lib/creatorDist/assets/{index-CqVEKiJR.js → index-CKg5uuoj.js} +8049 -8007
- package/lib/creatorDist/index.html +1 -1
- package/lib/utils/lessonRecovery.d.ts +18 -0
- package/lib/utils/lessonRecovery.js +31 -0
- package/package.json +1 -1
- package/src/commands/serve.ts +65 -9
- package/src/creatorDist/assets/{index-CqVEKiJR.js → index-CKg5uuoj.js} +8049 -8007
- package/src/creatorDist/index.html +1 -1
- package/src/utils/lessonRecovery.ts +32 -0
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
/>
|
|
11
11
|
|
|
12
12
|
<title>Learnpack Creator: Craft tutorials in seconds!</title>
|
|
13
|
-
<script type="module" crossorigin src="/creator/assets/index-
|
|
13
|
+
<script type="module" crossorigin src="/creator/assets/index-CKg5uuoj.js"></script>
|
|
14
14
|
<link rel="stylesheet" crossorigin href="/creator/assets/index-B7s5Nmq8.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a lesson README holds generated content. The file starts as a
|
|
3
|
+
* `loader` block, and the generated content replaces it.
|
|
4
|
+
* @param readme - The README text, or null when the file does not exist.
|
|
5
|
+
* @returns True when the lesson has its generated content.
|
|
6
|
+
*/
|
|
7
|
+
export declare const hasGeneratedContent: (readme: string | null) => boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Finds the lessons marked as ERROR that were generated anyway. Publishing and
|
|
10
|
+
* translating wait for every lesson, and the retry screen only shows while the
|
|
11
|
+
* README has its `loader`, so these lessons would otherwise stay stuck.
|
|
12
|
+
* @param lessons - The lessons of the syllabus.
|
|
13
|
+
* @param readReadme - Reads the README of a lesson, or null if it has none.
|
|
14
|
+
* @returns The lessons to mark as done.
|
|
15
|
+
*/
|
|
16
|
+
export declare const findFinishedLessons: <T extends {
|
|
17
|
+
status?: string;
|
|
18
|
+
}>(lessons: T[], readReadme: (lesson: T) => Promise<string | null>) => Promise<T[]>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.findFinishedLessons = exports.hasGeneratedContent = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Whether a lesson README holds generated content. The file starts as a
|
|
6
|
+
* `loader` block, and the generated content replaces it.
|
|
7
|
+
* @param readme - The README text, or null when the file does not exist.
|
|
8
|
+
* @returns True when the lesson has its generated content.
|
|
9
|
+
*/
|
|
10
|
+
const hasGeneratedContent = (readme) => readme !== null && readme.trim() !== "" && !readme.includes("```loader");
|
|
11
|
+
exports.hasGeneratedContent = hasGeneratedContent;
|
|
12
|
+
/**
|
|
13
|
+
* Finds the lessons marked as ERROR that were generated anyway. Publishing and
|
|
14
|
+
* translating wait for every lesson, and the retry screen only shows while the
|
|
15
|
+
* README has its `loader`, so these lessons would otherwise stay stuck.
|
|
16
|
+
* @param lessons - The lessons of the syllabus.
|
|
17
|
+
* @param readReadme - Reads the README of a lesson, or null if it has none.
|
|
18
|
+
* @returns The lessons to mark as done.
|
|
19
|
+
*/
|
|
20
|
+
const findFinishedLessons = async (lessons, readReadme) => {
|
|
21
|
+
const finished = [];
|
|
22
|
+
for (const lesson of lessons) {
|
|
23
|
+
if (lesson.status !== "ERROR")
|
|
24
|
+
continue;
|
|
25
|
+
// eslint-disable-next-line no-await-in-loop
|
|
26
|
+
if ((0, exports.hasGeneratedContent)(await readReadme(lesson)))
|
|
27
|
+
finished.push(lesson);
|
|
28
|
+
}
|
|
29
|
+
return finished;
|
|
30
|
+
};
|
|
31
|
+
exports.findFinishedLessons = findFinishedLessons;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@learnpack/learnpack",
|
|
3
3
|
"description": "Seamlessly build, sell and/or take interactive & auto-graded tutorials, start learning now or build a new tutorial to your audience.",
|
|
4
|
-
"version": "5.0.
|
|
4
|
+
"version": "5.0.362",
|
|
5
5
|
"author": "Alejandro Sanchez @alesanchezr",
|
|
6
6
|
"contributors": [
|
|
7
7
|
{
|
package/src/commands/serve.ts
CHANGED
|
@@ -48,6 +48,7 @@ import {
|
|
|
48
48
|
getReadmeExtension,
|
|
49
49
|
insertStepInCorrectPosition,
|
|
50
50
|
} from "../utils/creatorUtilities"
|
|
51
|
+
import { findFinishedLessons } from "../utils/lessonRecovery"
|
|
51
52
|
// import { handleAssetCreation } from "./publish"
|
|
52
53
|
import axios from "axios"
|
|
53
54
|
import * as FormData from "form-data"
|
|
@@ -680,6 +681,10 @@ async function startInitialContentGeneration(
|
|
|
680
681
|
)
|
|
681
682
|
|
|
682
683
|
console.log("INITIAL CONTENT GENERATOR RES", res)
|
|
684
|
+
if (!res) {
|
|
685
|
+
throw new Error(`Could not start generating lesson ${exSlug}`)
|
|
686
|
+
}
|
|
687
|
+
|
|
683
688
|
return res.id
|
|
684
689
|
}
|
|
685
690
|
|
|
@@ -1020,6 +1025,45 @@ async function updateLessonStatusToDone(
|
|
|
1020
1025
|
}
|
|
1021
1026
|
}
|
|
1022
1027
|
|
|
1028
|
+
const lessonSlug = (lesson: Lesson) => slugify(lesson.id + "-" + lesson.title)
|
|
1029
|
+
|
|
1030
|
+
async function repairFinishedLessons(
|
|
1031
|
+
courseSlug: string,
|
|
1032
|
+
syllabus: Syllabus,
|
|
1033
|
+
bucket: Bucket
|
|
1034
|
+
): Promise<void> {
|
|
1035
|
+
const language = syllabus.courseInfo.language || "en"
|
|
1036
|
+
|
|
1037
|
+
try {
|
|
1038
|
+
const finished = await findFinishedLessons(
|
|
1039
|
+
syllabus.lessons ?? [],
|
|
1040
|
+
async lesson => {
|
|
1041
|
+
const readme = bucket.file(
|
|
1042
|
+
`courses/${courseSlug}/exercises/${lessonSlug(
|
|
1043
|
+
lesson
|
|
1044
|
+
)}/README${getReadmeExtension(language)}`
|
|
1045
|
+
)
|
|
1046
|
+
const [exists] = await readme.exists()
|
|
1047
|
+
if (!exists) return null
|
|
1048
|
+
|
|
1049
|
+
const [content] = await readme.download()
|
|
1050
|
+
return content.toString()
|
|
1051
|
+
}
|
|
1052
|
+
)
|
|
1053
|
+
|
|
1054
|
+
for (const lesson of finished) {
|
|
1055
|
+
// eslint-disable-next-line no-await-in-loop
|
|
1056
|
+
await updateLessonStatusToDone(courseSlug, lessonSlug(lesson), bucket)
|
|
1057
|
+
lesson.status = "DONE"
|
|
1058
|
+
lesson.generated = true
|
|
1059
|
+
}
|
|
1060
|
+
} catch (error) {
|
|
1061
|
+
// Loading the course matters more than repairing it now. The next load
|
|
1062
|
+
// tries again.
|
|
1063
|
+
console.error(`Error repairing lessons of ${courseSlug}:`, error)
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1023
1067
|
async function continueWithNextLesson(
|
|
1024
1068
|
courseSlug: string,
|
|
1025
1069
|
currentExerciseIndex: number,
|
|
@@ -1043,15 +1087,26 @@ async function continueWithNextLesson(
|
|
|
1043
1087
|
feedback = `\n\nThe user added the following feedback with relation to the previous generations: ${syllabus.feedback}`
|
|
1044
1088
|
}
|
|
1045
1089
|
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1090
|
+
try {
|
|
1091
|
+
nextCompletionId = await startInitialContentGeneration(
|
|
1092
|
+
rigoToken,
|
|
1093
|
+
syllabus.lessons,
|
|
1094
|
+
syllabus.courseInfo,
|
|
1095
|
+
nextExercise,
|
|
1096
|
+
courseSlug,
|
|
1097
|
+
syllabus.courseInfo.purpose,
|
|
1098
|
+
finalContent + "\n\n" + feedback
|
|
1099
|
+
)
|
|
1100
|
+
} catch (error) {
|
|
1101
|
+
// The current lesson is finished either way. The next one stays PENDING,
|
|
1102
|
+
// and its screen offers to continue.
|
|
1103
|
+
console.error("Error starting the next lesson:", error)
|
|
1104
|
+
emitToCourse(courseSlug, "course-creation", {
|
|
1105
|
+
lesson: slugify(nextExercise.id + "-" + nextExercise.title),
|
|
1106
|
+
status: "error",
|
|
1107
|
+
log: `❌ Could not start lesson ${nextExercise.title}`,
|
|
1108
|
+
})
|
|
1109
|
+
}
|
|
1055
1110
|
} else {
|
|
1056
1111
|
console.log(
|
|
1057
1112
|
"Stopping generation process at",
|
|
@@ -5239,6 +5294,7 @@ class ServeCommand extends SessionCommand {
|
|
|
5239
5294
|
const [content] = await syllabus.download()
|
|
5240
5295
|
const syllabusJson: Syllabus = JSON.parse(content.toString())
|
|
5241
5296
|
sanitizeSyllabusFromUnknown(syllabusJson)
|
|
5297
|
+
await repairFinishedLessons(courseSlug, syllabusJson, bucket)
|
|
5242
5298
|
res.json(syllabusJson)
|
|
5243
5299
|
} catch (error) {
|
|
5244
5300
|
console.error("Error getting syllabus:", error)
|