@learnpack/learnpack 5.0.346 → 5.0.348
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/publish.d.ts +1 -1
- package/lib/commands/publish.js +9 -2
- package/lib/commands/serve.js +120 -19
- package/lib/utils/api.d.ts +25 -1
- package/lib/utils/api.js +34 -1
- package/package.json +1 -1
- package/src/commands/publish.ts +15 -0
- package/src/commands/serve.ts +139 -36
- package/src/ui/_app/app.js +2076 -2076
- package/src/ui/app.tar.gz +0 -0
- package/src/utils/api.ts +43 -2
|
@@ -8,7 +8,7 @@ type ExistingAssetInfo = {
|
|
|
8
8
|
export declare const handleAssetCreation: (sessionPayload: {
|
|
9
9
|
token: string;
|
|
10
10
|
rigobotToken: string;
|
|
11
|
-
}, learnJson: any, selectedLang: string, learnpackDeployUrl: string, b64IndexReadme: string, academyId: number | undefined, preflightInfo?: ExistingAssetInfo, all_translations?: string[]) => Promise<any>;
|
|
11
|
+
}, learnJson: any, selectedLang: string, learnpackDeployUrl: string, b64IndexReadme: string, academyId: number | undefined, learnpackId: number, preflightInfo?: ExistingAssetInfo, all_translations?: string[]) => Promise<any>;
|
|
12
12
|
declare class BuildCommand extends SessionCommand {
|
|
13
13
|
static description: string;
|
|
14
14
|
static flags: {
|
package/lib/commands/publish.js
CHANGED
|
@@ -71,7 +71,7 @@ const determinePublishAcademyMode = (existingAssets) => {
|
|
|
71
71
|
return { type: "locked", academyId: unique[0] };
|
|
72
72
|
return { type: "conflict", academies: unique };
|
|
73
73
|
};
|
|
74
|
-
const handleAssetCreation = async (sessionPayload, learnJson, selectedLang, learnpackDeployUrl, b64IndexReadme, academyId, preflightInfo, all_translations = []) => {
|
|
74
|
+
const handleAssetCreation = async (sessionPayload, learnJson, selectedLang, learnpackDeployUrl, b64IndexReadme, academyId, learnpackId, preflightInfo, all_translations = []) => {
|
|
75
75
|
const category = "uncategorized";
|
|
76
76
|
try {
|
|
77
77
|
const user = await api_1.default.validateToken(sessionPayload.token);
|
|
@@ -107,6 +107,7 @@ const handleAssetCreation = async (sessionPayload, learnJson, selectedLang, lear
|
|
|
107
107
|
preview: learnJson.preview,
|
|
108
108
|
readme_raw: b64IndexReadme,
|
|
109
109
|
all_translations,
|
|
110
|
+
learnpack_id: learnpackId,
|
|
110
111
|
};
|
|
111
112
|
if (academyId !== undefined) {
|
|
112
113
|
assetPayload.academy_id = academyId;
|
|
@@ -131,6 +132,7 @@ const handleAssetCreation = async (sessionPayload, learnJson, selectedLang, lear
|
|
|
131
132
|
category: category,
|
|
132
133
|
description: assetDescription,
|
|
133
134
|
all_translations,
|
|
135
|
+
learnpack_id: learnpackId,
|
|
134
136
|
};
|
|
135
137
|
// Only set academy when the asset has none yet and the user selected one
|
|
136
138
|
if (existingAcademyId === undefined && academyId !== undefined) {
|
|
@@ -160,6 +162,11 @@ const createMultiLangAssetFromDisk = async (sessionPayload, learnJson, deployUrl
|
|
|
160
162
|
console_1.default.error("No languages found in learn.json.title. Add at least one language (e.g. title.en).");
|
|
161
163
|
return;
|
|
162
164
|
}
|
|
165
|
+
const learnpackId = await api_1.default.resolveLearnpackPackageId(sessionPayload.rigobotToken, learnJson.slug);
|
|
166
|
+
if (learnpackId === null) {
|
|
167
|
+
console_1.default.warning("Breathecode assets skipped: could not resolve Learnpack package id");
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
163
170
|
const all_translations = [];
|
|
164
171
|
for (const lang of availableLangs) {
|
|
165
172
|
const readmePath = path.join(process.cwd(), `README${(0, creatorUtilities_1.getReadmeExtension)(lang)}`);
|
|
@@ -177,7 +184,7 @@ const createMultiLangAssetFromDisk = async (sessionPayload, learnJson, deployUrl
|
|
|
177
184
|
const preflightInfo = existingAssetsInfo.find((a) => a.lang === lang);
|
|
178
185
|
try {
|
|
179
186
|
// eslint-disable-next-line no-await-in-loop
|
|
180
|
-
const asset = await (0, exports.handleAssetCreation)(sessionPayload, learnJson, lang, deployUrl, b64IndexReadme, selectedAcademyId, preflightInfo, all_translations);
|
|
187
|
+
const asset = await (0, exports.handleAssetCreation)(sessionPayload, learnJson, lang, deployUrl, b64IndexReadme, selectedAcademyId, learnpackId, preflightInfo, all_translations);
|
|
181
188
|
if (!asset) {
|
|
182
189
|
console_1.default.debug("Could not create/update asset for lang", lang);
|
|
183
190
|
continue;
|
package/lib/commands/serve.js
CHANGED
|
@@ -365,8 +365,33 @@ const getLocalizedValue = (translations, lang, fallbackLangs = ["en", "us"]) =>
|
|
|
365
365
|
const first = firstKey ? translations[firstKey] : "";
|
|
366
366
|
return typeof first === "string" ? first : "";
|
|
367
367
|
};
|
|
368
|
+
function assetSyncErrorDetail(err) {
|
|
369
|
+
if (typeof (err === null || err === void 0 ? void 0 : err.detail) === "string")
|
|
370
|
+
return err.detail;
|
|
371
|
+
if (typeof (err === null || err === void 0 ? void 0 : err.message) === "string")
|
|
372
|
+
return err.message;
|
|
373
|
+
try {
|
|
374
|
+
return JSON.stringify(err);
|
|
375
|
+
}
|
|
376
|
+
catch (_a) {
|
|
377
|
+
return String(err);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
368
380
|
const createMultiLangAsset = async (bucket, rigoToken, bcToken, courseSlug, courseJson, deployUrl, academyId) => {
|
|
369
381
|
var _a;
|
|
382
|
+
const learnpackId = await (0, api_1.resolveLearnpackPackageId)(rigoToken, courseSlug);
|
|
383
|
+
if (learnpackId === null) {
|
|
384
|
+
return {
|
|
385
|
+
errors: [
|
|
386
|
+
{
|
|
387
|
+
kind: "package_error",
|
|
388
|
+
error: {
|
|
389
|
+
detail: "Could not resolve Learnpack package id; assets not synced to Breathecode.",
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
],
|
|
393
|
+
};
|
|
394
|
+
}
|
|
370
395
|
const availableLangs = Object.keys(courseJson.title);
|
|
371
396
|
console.log("AVAILABLE LANGUAGES to upload asset", availableLangs);
|
|
372
397
|
const all_translations = [];
|
|
@@ -388,11 +413,12 @@ const createMultiLangAsset = async (bucket, rigoToken, bcToken, courseSlug, cour
|
|
|
388
413
|
const b64IndexReadme = buffer_1.Buffer.from(indexReadmeString).toString("base64");
|
|
389
414
|
try {
|
|
390
415
|
// eslint-disable-next-line no-await-in-loop
|
|
391
|
-
const asset = await (0, publish_1.handleAssetCreation)({ token: bcToken, rigobotToken: rigoToken.trim() }, courseJson, lang, deployUrl, b64IndexReadme, academyId, undefined, all_translations);
|
|
416
|
+
const asset = await (0, publish_1.handleAssetCreation)({ token: bcToken, rigobotToken: rigoToken.trim() }, courseJson, lang, deployUrl, b64IndexReadme, academyId, learnpackId, undefined, all_translations);
|
|
392
417
|
if (!asset) {
|
|
393
418
|
errors.push({
|
|
419
|
+
kind: "lang_error",
|
|
394
420
|
lang,
|
|
395
|
-
error: { detail: "Failed to create asset"
|
|
421
|
+
error: { detail: "Failed to create asset" },
|
|
396
422
|
});
|
|
397
423
|
console.log("No se pudo crear el asset, saltando idioma", lang);
|
|
398
424
|
continue;
|
|
@@ -403,7 +429,11 @@ const createMultiLangAsset = async (bucket, rigoToken, bcToken, courseSlug, cour
|
|
|
403
429
|
const errorData = error && typeof error === "object" && "response" in error ?
|
|
404
430
|
((_a = error.response) === null || _a === void 0 ? void 0 : _a.data) || error :
|
|
405
431
|
error;
|
|
406
|
-
errors.push({
|
|
432
|
+
errors.push({
|
|
433
|
+
kind: "lang_error",
|
|
434
|
+
lang,
|
|
435
|
+
error: { detail: assetSyncErrorDetail(errorData) },
|
|
436
|
+
});
|
|
407
437
|
console.error(`Error creating asset for language ${lang}:`, error);
|
|
408
438
|
}
|
|
409
439
|
}
|
|
@@ -3241,6 +3271,7 @@ class ServeCommand extends SessionCommand_1.default {
|
|
|
3241
3271
|
const addedLessons = [];
|
|
3242
3272
|
let repairedTranslationsInLessons = 0;
|
|
3243
3273
|
let repairedTranslationEntries = 0;
|
|
3274
|
+
let fixedLessons = 0;
|
|
3244
3275
|
console.log(`📋 Checking ${syllabus.lessons.length} lessons in syllabus...`);
|
|
3245
3276
|
// First pass: Check each lesson to see if it exists in the bucket and count files.
|
|
3246
3277
|
// We try two possible folder names because they can differ by source:
|
|
@@ -3438,15 +3469,39 @@ class ServeCommand extends SessionCommand_1.default {
|
|
|
3438
3469
|
repairedTranslationsInLessons += 1;
|
|
3439
3470
|
}
|
|
3440
3471
|
}
|
|
3472
|
+
// Fifth pass: fix lessons stuck in GENERATING or ERROR when the file exists in the bucket
|
|
3473
|
+
const primaryLanguage = syllabus.courseInfo.language || "en";
|
|
3474
|
+
for (const lesson of syllabus.lessons) {
|
|
3475
|
+
if (lesson.generated !== false)
|
|
3476
|
+
continue;
|
|
3477
|
+
if (lesson.status !== "GENERATING" && lesson.status !== "ERROR")
|
|
3478
|
+
continue;
|
|
3479
|
+
const candidateSlugs = [
|
|
3480
|
+
(0, creatorUtilities_2.slugify)(lesson.id + "-" + lesson.title),
|
|
3481
|
+
lesson.uid,
|
|
3482
|
+
].filter(Boolean);
|
|
3483
|
+
const matchedSlug = candidateSlugs.find(s => translationsBySlug.has(s));
|
|
3484
|
+
if (!matchedSlug)
|
|
3485
|
+
continue;
|
|
3486
|
+
const langs = translationsBySlug.get(matchedSlug) || [];
|
|
3487
|
+
if (!langs.includes(primaryLanguage))
|
|
3488
|
+
continue;
|
|
3489
|
+
const prevStatus = lesson.status;
|
|
3490
|
+
lesson.generated = true;
|
|
3491
|
+
lesson.status = "DONE";
|
|
3492
|
+
fixedLessons += 1;
|
|
3493
|
+
console.log(`🔧 Fixed lesson: ${lesson.id} - "${lesson.title}" (was generated:false status:${prevStatus}, primary language "${primaryLanguage}" exists in bucket)`);
|
|
3494
|
+
}
|
|
3441
3495
|
}
|
|
3442
3496
|
catch (error) {
|
|
3443
3497
|
console.error("⚠️ Could not reconcile lesson translations during syllabus sync:", error);
|
|
3444
3498
|
}
|
|
3445
3499
|
if (totalRemoved > 0 ||
|
|
3446
3500
|
addedLessons.length > 0 ||
|
|
3447
|
-
repairedTranslationsInLessons > 0
|
|
3501
|
+
repairedTranslationsInLessons > 0 ||
|
|
3502
|
+
fixedLessons > 0) {
|
|
3448
3503
|
await saveSyllabus(courseSlug, syllabus, bucket);
|
|
3449
|
-
console.log(`✅ Syllabus synchronized. Removed ${removedLessons.length} non-existent, ${duplicatesRemoved.length} duplicate(s); added ${addedLessons.length} from bucket; repaired translations in ${repairedTranslationsInLessons} lesson(s).`);
|
|
3504
|
+
console.log(`✅ Syllabus synchronized. Removed ${removedLessons.length} non-existent, ${duplicatesRemoved.length} duplicate(s); added ${addedLessons.length} from bucket; repaired translations in ${repairedTranslationsInLessons} lesson(s); fixed ${fixedLessons} stuck lesson(s).`);
|
|
3450
3505
|
}
|
|
3451
3506
|
else {
|
|
3452
3507
|
console.log(`✅ Syllabus is already in sync. No changes.`);
|
|
@@ -3459,6 +3514,7 @@ class ServeCommand extends SessionCommand_1.default {
|
|
|
3459
3514
|
removedLessons: removedLessons.length,
|
|
3460
3515
|
duplicatesResolved: duplicatesRemoved.length,
|
|
3461
3516
|
addedLessons: addedLessons.length,
|
|
3517
|
+
fixedLessons,
|
|
3462
3518
|
repairedTranslationsInLessons,
|
|
3463
3519
|
repairedTranslationEntries,
|
|
3464
3520
|
removed: removedLessons,
|
|
@@ -3913,20 +3969,65 @@ class ServeCommand extends SessionCommand_1.default {
|
|
|
3913
3969
|
const output = fs.createWriteStream(zipPath);
|
|
3914
3970
|
const archive = archiver("zip", { zlib: { level: 9 } });
|
|
3915
3971
|
output.on("close", async () => {
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3972
|
+
let rigoPublishUrl;
|
|
3973
|
+
try {
|
|
3974
|
+
// 10) Subir ZIP a RigoBot
|
|
3975
|
+
const form = new FormData();
|
|
3976
|
+
form.append("file", fs.createReadStream(zipPath));
|
|
3977
|
+
form.append("config", JSON.stringify(config));
|
|
3978
|
+
const rigoRes = await axios_1.default.post(`${api_1.RIGOBOT_HOST}/v1/learnpack/upload`, form, {
|
|
3979
|
+
headers: Object.assign(Object.assign({}, form.getHeaders()), { Authorization: "Token " + rigoToken.trim() }),
|
|
3980
|
+
});
|
|
3981
|
+
rigoPublishUrl = rigoRes.data.url;
|
|
3982
|
+
let errors;
|
|
3983
|
+
try {
|
|
3984
|
+
const assetResults = await createMultiLangAsset(bucket, rigoToken, bcToken, slug, fullConfig.config, rigoRes.data.url, academyId);
|
|
3985
|
+
errors = assetResults.errors;
|
|
3986
|
+
}
|
|
3987
|
+
catch (error) {
|
|
3988
|
+
console.error("Asset sync failed unexpectedly:", error);
|
|
3989
|
+
errors = [
|
|
3990
|
+
{
|
|
3991
|
+
kind: "package_error",
|
|
3992
|
+
error: { detail: "Asset sync failed unexpectedly." },
|
|
3993
|
+
},
|
|
3994
|
+
];
|
|
3995
|
+
}
|
|
3996
|
+
if (res.headersSent)
|
|
3997
|
+
return;
|
|
3998
|
+
console.log("RigoRes", rigoRes.data);
|
|
3999
|
+
res.json({
|
|
4000
|
+
url: rigoPublishUrl,
|
|
4001
|
+
errors,
|
|
4002
|
+
});
|
|
4003
|
+
}
|
|
4004
|
+
catch (error) {
|
|
4005
|
+
console.error(error);
|
|
4006
|
+
if (res.headersSent)
|
|
4007
|
+
return;
|
|
4008
|
+
if (rigoPublishUrl !== undefined) {
|
|
4009
|
+
res.json({
|
|
4010
|
+
url: rigoPublishUrl,
|
|
4011
|
+
errors: [
|
|
4012
|
+
{
|
|
4013
|
+
kind: "package_error",
|
|
4014
|
+
error: { detail: "Asset sync failed unexpectedly." },
|
|
4015
|
+
},
|
|
4016
|
+
],
|
|
4017
|
+
});
|
|
4018
|
+
}
|
|
4019
|
+
else {
|
|
4020
|
+
res.status(500).json({ error: error.message });
|
|
4021
|
+
}
|
|
4022
|
+
}
|
|
4023
|
+
finally {
|
|
4024
|
+
try {
|
|
4025
|
+
rimraf.sync(tmpRoot);
|
|
4026
|
+
}
|
|
4027
|
+
catch (error) {
|
|
4028
|
+
console.error("rimraf tmpRoot:", error);
|
|
4029
|
+
}
|
|
4030
|
+
}
|
|
3930
4031
|
});
|
|
3931
4032
|
archive.on("error", err => {
|
|
3932
4033
|
console.error("ZIP Error:", err);
|
package/lib/utils/api.d.ts
CHANGED
|
@@ -11,6 +11,26 @@ export interface TAcademy {
|
|
|
11
11
|
}
|
|
12
12
|
export declare const listUserAcademies: (breathecodeToken: string) => Promise<TAcademy[]>;
|
|
13
13
|
export declare const validateToken: (token: string) => Promise<any>;
|
|
14
|
+
/** keep in sync with ide/src/components/Creator/PublishButton.tsx AssetSyncError */
|
|
15
|
+
export type AssetSyncError = {
|
|
16
|
+
kind: "lang_error";
|
|
17
|
+
lang: string;
|
|
18
|
+
error: {
|
|
19
|
+
detail: string;
|
|
20
|
+
};
|
|
21
|
+
} | {
|
|
22
|
+
kind: "package_error";
|
|
23
|
+
error: {
|
|
24
|
+
detail: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* GET Rigobot package by slug after a successful upload. Does not throw.
|
|
29
|
+
* @param rigoToken Rigobot API token (Bearer-style `Token` header value).
|
|
30
|
+
* @param courseSlug Learnpack package slug used in the Rigobot URL path.
|
|
31
|
+
* @returns Resolved numeric package id from Rigobot, or `null` if the request fails, the id is missing, or it is not a finite integer.
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveLearnpackPackageId(rigoToken: string, courseSlug: string): Promise<number | null>;
|
|
14
34
|
type TAssetMissing = {
|
|
15
35
|
slug: string;
|
|
16
36
|
title: string;
|
|
@@ -27,6 +47,7 @@ type TAssetMissing = {
|
|
|
27
47
|
readme_raw: string;
|
|
28
48
|
all_translations: string[];
|
|
29
49
|
academy_id?: number;
|
|
50
|
+
learnpack_id: number;
|
|
30
51
|
};
|
|
31
52
|
export declare const createAsset: (token: string, asset: TAssetMissing) => Promise<any>;
|
|
32
53
|
export declare const doesAssetExists: (token: string, assetSlug: string) => Promise<{
|
|
@@ -59,7 +80,10 @@ declare const _default: {
|
|
|
59
80
|
exists: boolean;
|
|
60
81
|
academyId?: number;
|
|
61
82
|
}>;
|
|
62
|
-
updateAsset: (token: string, assetSlug: string, asset: Partial<TAssetMissing>
|
|
83
|
+
updateAsset: (token: string, assetSlug: string, asset: Partial<TAssetMissing> & {
|
|
84
|
+
learnpack_id: number;
|
|
85
|
+
}) => Promise<any>;
|
|
86
|
+
resolveLearnpackPackageId: typeof resolveLearnpackPackageId;
|
|
63
87
|
getCategories: (token: string) => Promise<any>;
|
|
64
88
|
updateRigoPackage: (token: string, slug: string, updates: {
|
|
65
89
|
asset_id?: number;
|
package/lib/utils/api.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getCurrentTechnologies = exports.fetchTechnologies = exports.doesAssetExists = exports.createAsset = exports.validateToken = exports.listUserAcademies = exports.getConsumable = exports.countConsumables = exports.RIGOBOT_REALTIME_HOST = exports.RIGOBOT_HOST = void 0;
|
|
4
|
+
exports.resolveLearnpackPackageId = resolveLearnpackPackageId;
|
|
4
5
|
const console_1 = require("../utils/console");
|
|
5
6
|
const storage = require("node-persist");
|
|
6
7
|
const cli_ux_1 = require("cli-ux");
|
|
@@ -341,6 +342,35 @@ const validateToken = async (token) => {
|
|
|
341
342
|
}
|
|
342
343
|
};
|
|
343
344
|
exports.validateToken = validateToken;
|
|
345
|
+
function parseLearnpackPackageId(raw) {
|
|
346
|
+
if (raw === undefined || raw === null)
|
|
347
|
+
return null;
|
|
348
|
+
const n = typeof raw === "number" ? raw : Number(raw);
|
|
349
|
+
if (!Number.isFinite(n) || !Number.isInteger(n))
|
|
350
|
+
return null;
|
|
351
|
+
return n;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* GET Rigobot package by slug after a successful upload. Does not throw.
|
|
355
|
+
* @param rigoToken Rigobot API token (Bearer-style `Token` header value).
|
|
356
|
+
* @param courseSlug Learnpack package slug used in the Rigobot URL path.
|
|
357
|
+
* @returns Resolved numeric package id from Rigobot, or `null` if the request fails, the id is missing, or it is not a finite integer.
|
|
358
|
+
*/
|
|
359
|
+
async function resolveLearnpackPackageId(rigoToken, courseSlug) {
|
|
360
|
+
var _a;
|
|
361
|
+
if (!(rigoToken === null || rigoToken === void 0 ? void 0 : rigoToken.trim()) || !courseSlug)
|
|
362
|
+
return null;
|
|
363
|
+
const url = `${exports.RIGOBOT_HOST}/v1/learnpack/package/${encodeURIComponent(courseSlug)}/`;
|
|
364
|
+
try {
|
|
365
|
+
const response = await axios_1.default.get(url, {
|
|
366
|
+
headers: { Authorization: `Token ${rigoToken.trim()}` },
|
|
367
|
+
});
|
|
368
|
+
return parseLearnpackPackageId((_a = response.data) === null || _a === void 0 ? void 0 : _a.id);
|
|
369
|
+
}
|
|
370
|
+
catch (_b) {
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
344
374
|
const createAsset = async (token, asset) => {
|
|
345
375
|
var _a;
|
|
346
376
|
const body = {
|
|
@@ -367,6 +397,7 @@ const createAsset = async (token, asset) => {
|
|
|
367
397
|
intro_video_url: null,
|
|
368
398
|
translations: [asset.lang],
|
|
369
399
|
learnpack_deploy_url: asset.learnpack_deploy_url,
|
|
400
|
+
learnpack_id: asset.learnpack_id,
|
|
370
401
|
technologies: asset.technologies,
|
|
371
402
|
readme_raw: asset.readme_raw,
|
|
372
403
|
all_translations: asset.all_translations,
|
|
@@ -417,9 +448,10 @@ const updateAsset = async (token, assetSlug, asset) => {
|
|
|
417
448
|
const headers = {
|
|
418
449
|
Authorization: `Token ${token}`,
|
|
419
450
|
};
|
|
451
|
+
const body = Object.assign(Object.assign({}, asset), { learnpack_id: asset.learnpack_id });
|
|
420
452
|
console.log("[BC] PUT", url, "| academy_id:", (_a = asset.academy_id) !== null && _a !== void 0 ? _a : "none");
|
|
421
453
|
try {
|
|
422
|
-
const response = await axios_1.default.put(url,
|
|
454
|
+
const response = await axios_1.default.put(url, body, { headers });
|
|
423
455
|
return response.data;
|
|
424
456
|
}
|
|
425
457
|
catch (error) {
|
|
@@ -551,6 +583,7 @@ exports.default = {
|
|
|
551
583
|
createAsset: exports.createAsset,
|
|
552
584
|
doesAssetExists: exports.doesAssetExists,
|
|
553
585
|
updateAsset,
|
|
586
|
+
resolveLearnpackPackageId,
|
|
554
587
|
getCategories,
|
|
555
588
|
updateRigoPackage,
|
|
556
589
|
createRigoPackage,
|
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.348",
|
|
5
5
|
"author": "Alejandro Sanchez @alesanchezr",
|
|
6
6
|
"contributors": [
|
|
7
7
|
{
|
package/src/commands/publish.ts
CHANGED
|
@@ -109,6 +109,7 @@ export const handleAssetCreation = async (
|
|
|
109
109
|
learnpackDeployUrl: string,
|
|
110
110
|
b64IndexReadme: string,
|
|
111
111
|
academyId: number | undefined,
|
|
112
|
+
learnpackId: number,
|
|
112
113
|
preflightInfo?: ExistingAssetInfo,
|
|
113
114
|
all_translations: string[] = []
|
|
114
115
|
) => {
|
|
@@ -160,6 +161,7 @@ export const handleAssetCreation = async (
|
|
|
160
161
|
preview: learnJson.preview,
|
|
161
162
|
readme_raw: b64IndexReadme,
|
|
162
163
|
all_translations,
|
|
164
|
+
learnpack_id: learnpackId,
|
|
163
165
|
}
|
|
164
166
|
if (academyId !== undefined) {
|
|
165
167
|
assetPayload.academy_id = academyId
|
|
@@ -190,6 +192,7 @@ export const handleAssetCreation = async (
|
|
|
190
192
|
category: category,
|
|
191
193
|
description: assetDescription,
|
|
192
194
|
all_translations,
|
|
195
|
+
learnpack_id: learnpackId,
|
|
193
196
|
}
|
|
194
197
|
// Only set academy when the asset has none yet and the user selected one
|
|
195
198
|
if (existingAcademyId === undefined && academyId !== undefined) {
|
|
@@ -237,6 +240,17 @@ const createMultiLangAssetFromDisk = async (
|
|
|
237
240
|
return
|
|
238
241
|
}
|
|
239
242
|
|
|
243
|
+
const learnpackId = await api.resolveLearnpackPackageId(
|
|
244
|
+
sessionPayload.rigobotToken,
|
|
245
|
+
learnJson.slug
|
|
246
|
+
)
|
|
247
|
+
if (learnpackId === null) {
|
|
248
|
+
Console.warning(
|
|
249
|
+
"Breathecode assets skipped: could not resolve Learnpack package id"
|
|
250
|
+
)
|
|
251
|
+
return
|
|
252
|
+
}
|
|
253
|
+
|
|
240
254
|
const all_translations: string[] = []
|
|
241
255
|
for (const lang of availableLangs) {
|
|
242
256
|
const readmePath = path.join(
|
|
@@ -266,6 +280,7 @@ const createMultiLangAssetFromDisk = async (
|
|
|
266
280
|
deployUrl,
|
|
267
281
|
b64IndexReadme,
|
|
268
282
|
selectedAcademyId,
|
|
283
|
+
learnpackId,
|
|
269
284
|
preflightInfo,
|
|
270
285
|
all_translations
|
|
271
286
|
)
|