@learnpack/learnpack 5.0.334 → 5.0.335

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.
@@ -155,6 +155,21 @@ const cleanFormState = (formState) => {
155
155
  const cleanFormStateForSyllabus = (formState) => {
156
156
  return Object.assign(Object.assign({}, formState), { description: formState.description, technologies: formState.technologies, contentIndex: formState.contentIndex, purposse: undefined, duration: undefined, hasContentIndex: undefined, variables: undefined, currentStep: undefined, language: undefined, isCompleted: undefined });
157
157
  };
158
+ const getLocalizedValue = (translations, lang, fallbackLangs = ["en", "us"]) => {
159
+ if (!translations || typeof translations !== "object")
160
+ return "";
161
+ const direct = translations[lang];
162
+ if (typeof direct === "string" && direct.trim().length > 0)
163
+ return direct;
164
+ for (const fb of fallbackLangs) {
165
+ const v = translations[fb];
166
+ if (typeof v === "string" && v.trim().length > 0)
167
+ return v;
168
+ }
169
+ const firstKey = Object.keys(translations)[0];
170
+ const first = firstKey ? translations[firstKey] : "";
171
+ return typeof first === "string" ? first : "";
172
+ };
158
173
  const createMultiLangAsset = async (bucket, rigoToken, bcToken, courseSlug, courseJson, deployUrl, academyId) => {
159
174
  var _a;
160
175
  const availableLangs = Object.keys(courseJson.title);
@@ -2927,9 +2942,7 @@ class ServeCommand extends SessionCommand_1.default {
2927
2942
  try {
2928
2943
  const bcToken = req.header("x-breathecode-token");
2929
2944
  if (!bcToken) {
2930
- return res
2931
- .status(400)
2932
- .json({
2945
+ return res.status(400).json({
2933
2946
  error: "Authentication failed, missing breathecode token",
2934
2947
  });
2935
2948
  }
@@ -2941,6 +2954,46 @@ class ServeCommand extends SessionCommand_1.default {
2941
2954
  return res.status(500).json({ error: error.message });
2942
2955
  }
2943
2956
  });
2957
+ app.get("/actions/package-academy/:slug", async (req, res) => {
2958
+ try {
2959
+ const { slug } = req.params;
2960
+ const bcToken = req.header("x-breathecode-token");
2961
+ if (!bcToken) {
2962
+ return res.status(400).json({
2963
+ error: "Authentication failed, missing breathecode token",
2964
+ });
2965
+ }
2966
+ const configFile = await bucket.file(`courses/${slug}/.learn/config.json`);
2967
+ const [configContent] = await configFile.download();
2968
+ const configJson = JSON.parse(configContent.toString());
2969
+ const { config } = configJson;
2970
+ const availableLangs = Object.keys(config.title || {});
2971
+ let academyId = null;
2972
+ let isPublished = false;
2973
+ for (const lang of availableLangs) {
2974
+ const assetTitle = getLocalizedValue(config.title, lang);
2975
+ if (!assetTitle)
2976
+ continue;
2977
+ let assetSlug = (0, creatorUtilities_2.slugify)(assetTitle).slice(0, 47);
2978
+ assetSlug = `${assetSlug}-${lang}`;
2979
+ const { exists, academyId: existingAcademyId } =
2980
+ // eslint-disable-next-line no-await-in-loop
2981
+ await (0, api_1.doesAssetExists)(bcToken, assetSlug);
2982
+ if (exists) {
2983
+ isPublished = true;
2984
+ if (existingAcademyId !== undefined) {
2985
+ academyId = existingAcademyId;
2986
+ break;
2987
+ }
2988
+ }
2989
+ }
2990
+ return res.json({ academyId, isPublished });
2991
+ }
2992
+ catch (error) {
2993
+ console.error("Error fetching package academy:", error);
2994
+ return res.status(500).json({ error: error.message });
2995
+ }
2996
+ });
2944
2997
  app.post("/actions/publish/:slug", async (req, res) => {
2945
2998
  try {
2946
2999
  const { slug } = req.params;
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.334",
4
+ "version": "5.0.335",
5
5
  "author": "Alejandro Sanchez @alesanchezr",
6
6
  "contributors": [
7
7
  {
@@ -53,6 +53,7 @@ import api, {
53
53
  RIGOBOT_HOST,
54
54
  RIGOBOT_REALTIME_HOST,
55
55
  listUserAcademies,
56
+ doesAssetExists,
56
57
  } from "../utils/api"
57
58
  import {
58
59
  createUploadMiddleware,
@@ -277,6 +278,26 @@ const cleanFormStateForSyllabus = (formState: FormState) => {
277
278
  }
278
279
  }
279
280
 
281
+ const getLocalizedValue = (
282
+ translations: Record<string, any> | undefined,
283
+ lang: string,
284
+ fallbackLangs: string[] = ["en", "us"]
285
+ ): string => {
286
+ if (!translations || typeof translations !== "object") return ""
287
+
288
+ const direct = translations[lang]
289
+ if (typeof direct === "string" && direct.trim().length > 0) return direct
290
+
291
+ for (const fb of fallbackLangs) {
292
+ const v = translations[fb]
293
+ if (typeof v === "string" && v.trim().length > 0) return v
294
+ }
295
+
296
+ const firstKey = Object.keys(translations)[0]
297
+ const first = firstKey ? translations[firstKey] : ""
298
+ return typeof first === "string" ? first : ""
299
+ }
300
+
280
301
  const createMultiLangAsset = async (
281
302
  bucket: Bucket,
282
303
  rigoToken: string,
@@ -4260,11 +4281,9 @@ class ServeCommand extends SessionCommand {
4260
4281
  const bcToken = req.header("x-breathecode-token")
4261
4282
 
4262
4283
  if (!bcToken) {
4263
- return res
4264
- .status(400)
4265
- .json({
4266
- error: "Authentication failed, missing breathecode token",
4267
- })
4284
+ return res.status(400).json({
4285
+ error: "Authentication failed, missing breathecode token",
4286
+ })
4268
4287
  }
4269
4288
 
4270
4289
  const academies = await listUserAcademies(bcToken)
@@ -4275,6 +4294,55 @@ class ServeCommand extends SessionCommand {
4275
4294
  }
4276
4295
  })
4277
4296
 
4297
+ app.get("/actions/package-academy/:slug", async (req, res) => {
4298
+ try {
4299
+ const { slug } = req.params
4300
+ const bcToken = req.header("x-breathecode-token")
4301
+
4302
+ if (!bcToken) {
4303
+ return res.status(400).json({
4304
+ error: "Authentication failed, missing breathecode token",
4305
+ })
4306
+ }
4307
+
4308
+ const configFile = await bucket.file(
4309
+ `courses/${slug}/.learn/config.json`
4310
+ )
4311
+ const [configContent] = await configFile.download()
4312
+ const configJson = JSON.parse(configContent.toString())
4313
+ const { config } = configJson
4314
+
4315
+ const availableLangs = Object.keys(config.title || {})
4316
+ let academyId: number | null = null
4317
+ let isPublished = false
4318
+
4319
+ for (const lang of availableLangs) {
4320
+ const assetTitle = getLocalizedValue(config.title, lang)
4321
+ if (!assetTitle) continue
4322
+
4323
+ let assetSlug = slugify(assetTitle).slice(0, 47)
4324
+ assetSlug = `${assetSlug}-${lang}`
4325
+
4326
+ const { exists, academyId: existingAcademyId } =
4327
+ // eslint-disable-next-line no-await-in-loop
4328
+ await doesAssetExists(bcToken, assetSlug)
4329
+
4330
+ if (exists) {
4331
+ isPublished = true
4332
+ if (existingAcademyId !== undefined) {
4333
+ academyId = existingAcademyId
4334
+ break
4335
+ }
4336
+ }
4337
+ }
4338
+
4339
+ return res.json({ academyId, isPublished })
4340
+ } catch (error) {
4341
+ console.error("Error fetching package academy:", error)
4342
+ return res.status(500).json({ error: (error as Error).message })
4343
+ }
4344
+ })
4345
+
4278
4346
  app.post("/actions/publish/:slug", async (req, res) => {
4279
4347
  try {
4280
4348
  const { slug } = req.params