@learnpack/learnpack 5.0.52 → 5.0.54

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/README.md CHANGED
@@ -21,7 +21,7 @@ $ npm install -g @learnpack/learnpack
21
21
  $ learnpack COMMAND
22
22
  running command...
23
23
  $ learnpack (-v|--version|version)
24
- @learnpack/learnpack/5.0.52 win32-x64 node-v22.14.0
24
+ @learnpack/learnpack/5.0.54 win32-x64 node-v22.14.0
25
25
  $ learnpack --help [COMMAND]
26
26
  USAGE
27
27
  $ learnpack COMMAND
@@ -79,7 +79,7 @@ DESCRIPTION
79
79
  12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)
80
80
  ```
81
81
 
82
- _See code: [src\commands\audit.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.52/src\commands\audit.ts)_
82
+ _See code: [src\commands\audit.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.54/src\commands\audit.ts)_
83
83
 
84
84
  ## `learnpack breakToken`
85
85
 
@@ -94,7 +94,7 @@ OPTIONS
94
94
  -y, --yes Skip all prompts and initialize an empty project
95
95
  ```
96
96
 
97
- _See code: [src\commands\breakToken.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.52/src\commands\breakToken.ts)_
97
+ _See code: [src\commands\breakToken.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.54/src\commands\breakToken.ts)_
98
98
 
99
99
  ## `learnpack clean`
100
100
 
@@ -109,7 +109,7 @@ DESCRIPTION
109
109
  Extra documentation goes here
110
110
  ```
111
111
 
112
- _See code: [src\commands\clean.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.52/src\commands\clean.ts)_
112
+ _See code: [src\commands\clean.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.54/src\commands\clean.ts)_
113
113
 
114
114
  ## `learnpack download [PACKAGE]`
115
115
 
@@ -127,7 +127,7 @@ DESCRIPTION
127
127
  Extra documentation goes here
128
128
  ```
129
129
 
130
- _See code: [src\commands\download.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.52/src\commands\download.ts)_
130
+ _See code: [src\commands\download.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.54/src\commands\download.ts)_
131
131
 
132
132
  ## `learnpack help [COMMAND]`
133
133
 
@@ -159,7 +159,7 @@ OPTIONS
159
159
  -y, --yes Skip all prompts and initialize an empty project
160
160
  ```
161
161
 
162
- _See code: [src\commands\init.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.52/src\commands\init.ts)_
162
+ _See code: [src\commands\init.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.54/src\commands\init.ts)_
163
163
 
164
164
  ## `learnpack login [PACKAGE]`
165
165
 
@@ -177,7 +177,7 @@ DESCRIPTION
177
177
  Extra documentation goes here
178
178
  ```
179
179
 
180
- _See code: [src\commands\login.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.52/src\commands\login.ts)_
180
+ _See code: [src\commands\login.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.54/src\commands\login.ts)_
181
181
 
182
182
  ## `learnpack logout [PACKAGE]`
183
183
 
@@ -195,7 +195,7 @@ DESCRIPTION
195
195
  Extra documentation goes here
196
196
  ```
197
197
 
198
- _See code: [src\commands\logout.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.52/src\commands\logout.ts)_
198
+ _See code: [src\commands\logout.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.54/src\commands\logout.ts)_
199
199
 
200
200
  ## `learnpack plugins`
201
201
 
@@ -327,7 +327,7 @@ OPTIONS
327
327
  -s, --strict strict mode
328
328
  ```
329
329
 
330
- _See code: [src\commands\publish.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.52/src\commands\publish.ts)_
330
+ _See code: [src\commands\publish.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.54/src\commands\publish.ts)_
331
331
 
332
332
  ## `learnpack start`
333
333
 
@@ -349,7 +349,7 @@ OPTIONS
349
349
  -y, --yes Skip all prompts and initialize an empty project
350
350
  ```
351
351
 
352
- _See code: [src\commands\start.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.52/src\commands\start.ts)_
352
+ _See code: [src\commands\start.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.54/src\commands\start.ts)_
353
353
 
354
354
  ## `learnpack test [EXERCISESLUG]`
355
355
 
@@ -366,7 +366,7 @@ OPTIONS
366
366
  -y, --yes Skip all prompts and initialize an empty project
367
367
  ```
368
368
 
369
- _See code: [src\commands\test.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.52/src\commands\test.ts)_
369
+ _See code: [src\commands\test.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.54/src\commands\test.ts)_
370
370
 
371
371
  ## `learnpack translate`
372
372
 
@@ -380,7 +380,7 @@ OPTIONS
380
380
  -y, --yes Skip all prompts and initialize an empty project
381
381
  ```
382
382
 
383
- _See code: [src\commands\translate.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.52/src\commands\translate.ts)_
383
+ _See code: [src\commands\translate.ts](https://github.com/learnpack/learnpack-cli/blob/v5.0.54/src\commands\translate.ts)_
384
384
  <!-- commandsstop -->
385
385
 
386
386
  > > > > > > > 0cb3e56d84c197f9d008836bb573eade212b7e57
@@ -18,7 +18,7 @@ const prompts = require("prompts");
18
18
  const rigoActions_1 = require("../utils/rigoActions");
19
19
  const misc_1 = require("../utils/misc");
20
20
  const uploadZipEndpont = api_1.RIGOBOT_HOST + "/v1/learnpack/upload";
21
- const handleAssetCreation = async (sessionPayload, academy, learnJson, learnpackDeployUrl) => {
21
+ const handleAssetCreation = async (sessionPayload, academy, learnJson, learnpackDeployUrl, category) => {
22
22
  try {
23
23
  const { exists, academyId } = await api_1.default.doesAssetExists(sessionPayload.token, learnJson.slug);
24
24
  if (!exists) {
@@ -31,6 +31,9 @@ const handleAssetCreation = async (sessionPayload, academy, learnJson, learnpack
31
31
  learnpack_deploy_url: learnpackDeployUrl,
32
32
  technologies: ["node", "bash"],
33
33
  url: "https://4geeksacademy.com",
34
+ category: category,
35
+ owner: sessionPayload.id,
36
+ author: sessionPayload.id,
34
37
  });
35
38
  console_1.default.info("Asset created with id", asset.id);
36
39
  }
@@ -70,12 +73,15 @@ const runAudit = (strict) => {
70
73
  // Continuar con el proceso de build solo si `learnpack publish` fue exitoso
71
74
  console_1.default.info("Learnpack publish completed successfully. Proceeding with build...");
72
75
  };
73
- const selectAcademy = async (academies) => {
76
+ function getCategoriesByAcademy(categories, academy) {
77
+ return categories.filter((cat) => cat.academy.id === academy.id);
78
+ }
79
+ const selectAcademy = async (academies, bcToken) => {
74
80
  if (academies.length === 0) {
75
- return null;
81
+ return { academy: null, category: 0 };
76
82
  }
77
83
  if (academies.length === 1) {
78
- return academies[0];
84
+ return { academy: academies[0], category: 0 };
79
85
  }
80
86
  // prompts the user to select an academy to upload the assets
81
87
  console_1.default.info("In which academy do you want to publish the asset?");
@@ -88,7 +94,21 @@ const selectAcademy = async (academies) => {
88
94
  value: academy,
89
95
  })),
90
96
  });
91
- return response.academy;
97
+ const categories = await api_1.default.getCategories(bcToken);
98
+ const categoriesByAcademy = getCategoriesByAcademy(categories, response.academy);
99
+ const categoriesPrompt = await prompts({
100
+ type: "select",
101
+ name: "category",
102
+ message: "Select a category",
103
+ choices: categoriesByAcademy.map((category) => ({
104
+ title: category.title,
105
+ value: category.id,
106
+ })),
107
+ });
108
+ return {
109
+ academy: response.academy,
110
+ category: categoriesPrompt.category,
111
+ };
92
112
  };
93
113
  class BuildCommand extends SessionCommand_1.default {
94
114
  async init() {
@@ -137,7 +157,7 @@ class BuildCommand extends SessionCommand_1.default {
137
157
  }
138
158
  const academies = await api_1.default.listUserAcademies(sessionPayload.token);
139
159
  // // console.log(academies, "academies")
140
- const academy = await selectAcademy(academies);
160
+ const { academy, category } = await selectAcademy(academies, sessionPayload.token);
141
161
  // Read learn.json to get the slug
142
162
  const learnJsonPath = path.join(process.cwd(), "learn.json");
143
163
  if (!fs.existsSync(learnJsonPath)) {
@@ -258,7 +278,9 @@ class BuildCommand extends SessionCommand_1.default {
258
278
  console.log(res.data);
259
279
  fs.unlinkSync(zipFilePath);
260
280
  this.removeDirectory(buildDir);
261
- await handleAssetCreation(sessionPayload, academy, learnJson, res.data.url);
281
+ if (academy) {
282
+ await handleAssetCreation(sessionPayload, academy, learnJson, res.data.url, category);
283
+ }
262
284
  }
263
285
  catch (error) {
264
286
  if (axios_1.default.isAxiosError(error)) {
@@ -18,6 +18,9 @@ type TAssetMissing = {
18
18
  description: string;
19
19
  learnpack_deploy_url: string;
20
20
  technologies: string[];
21
+ category: number;
22
+ owner: number;
23
+ author: number;
21
24
  };
22
25
  export declare const createAsset: (token: string, academyId: number, asset: TAssetMissing) => Promise<any>;
23
26
  export declare const doesAssetExists: (token: string, assetSlug: string) => Promise<{
@@ -44,5 +47,6 @@ declare const _default: {
44
47
  academyId?: number;
45
48
  }>;
46
49
  updateAsset: (token: string, academyId: number, assetSlug: string, asset: Partial<TAssetMissing>) => Promise<any>;
50
+ getCategories: (token: string) => Promise<any>;
47
51
  };
48
52
  export default _default;
package/lib/utils/api.js CHANGED
@@ -327,22 +327,24 @@ const createAsset = async (token, academyId, asset) => {
327
327
  title: asset.title,
328
328
  lang: asset.lang,
329
329
  asset_type: "EXERCISE",
330
- visibility: "PUBLIC",
331
- status: "PUBLISHED",
330
+ visibility: "UNLISTED",
331
+ status: "DRAFT",
332
332
  url: "https://4geeksacademy.com",
333
333
  readme_url: null,
334
334
  difficulty: null,
335
335
  duration: null,
336
336
  graded: false,
337
337
  gitpod: true,
338
- category: 7,
338
+ category: asset.category,
339
+ owner: asset.owner,
340
+ author: asset.author,
339
341
  preview: null,
340
342
  description: asset.description,
341
- external: true,
343
+ external: false,
342
344
  interactive: true,
343
345
  solution_video_url: null,
344
346
  intro_video_url: null,
345
- translations: ["us"],
347
+ translations: [asset.lang],
346
348
  learnpack_deploy_url: asset.learnpack_deploy_url,
347
349
  technologies: asset.technologies,
348
350
  };
@@ -375,8 +377,8 @@ const doesAssetExists = async (token, assetSlug) => {
375
377
  }
376
378
  return { exists: false };
377
379
  }
378
- catch (error) {
379
- console.error("Failed to get asset:", error);
380
+ catch (_a) {
381
+ // console.error("Failed to get asset:", error)
380
382
  return { exists: false };
381
383
  }
382
384
  };
@@ -398,6 +400,20 @@ const updateAsset = async (token, academyId, assetSlug, asset) => {
398
400
  throw error.response.data;
399
401
  }
400
402
  };
403
+ const getCategories = async (token) => {
404
+ const url = `${HOST}/v1/registry/category`;
405
+ const headers = {
406
+ Authorization: `Token ${token}`,
407
+ };
408
+ try {
409
+ const response = await axios_1.default.get(url, { headers });
410
+ return response.data;
411
+ }
412
+ catch (error) {
413
+ console.error("Failed to get categories:", error);
414
+ throw error;
415
+ }
416
+ };
401
417
  exports.default = {
402
418
  login,
403
419
  publish,
@@ -412,4 +428,5 @@ exports.default = {
412
428
  createAsset: exports.createAsset,
413
429
  doesAssetExists: exports.doesAssetExists,
414
430
  updateAsset,
431
+ getCategories,
415
432
  };
@@ -1 +1 @@
1
- {"version":"5.0.52","commands":{"audit":{"id":"audit","description":"learnpack audit is the command in charge of creating an auditory of the repository\n...\nlearnpack audit checks for the following information in a repository:\n 1. The configuration object has slug, repository and description. (Error)\n 2. The command learnpack clean has been run. (Error)\n 3. If a markdown or test file doesn't have any content. (Error)\n 4. The links are accessing to valid servers. (Error)\n 5. The relative images are working (If they have the shortest path to the image or if the images exists in the assets). (Error)\n 6. The external images are working (If they are pointing to a valid server). (Error)\n 7. The exercises directory names are valid. (Error)\n 8. If an exercise doesn't have a README file. (Error)\n 9. The exercises array (Of the config file) has content. (Error)\n 10. The exercses have the same translations. (Warning)\n 11. The .gitignore file exists. (Warning)\n 12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"strict":{"name":"strict","type":"boolean","char":"s","description":"strict mode","allowNo":false}},"args":[]},"breakToken":{"id":"breakToken","description":"Break the token","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"grading":{"name":"grading","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"clean":{"id":"clean","description":"Clean the configuration object\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[]},"download":{"id":"download","description":"Describe the command here\n...\nExtra documentation goes here\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"init":{"id":"init","description":"Create a new learning package: Book, Tutorial or Exercise","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"grading":{"name":"grading","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"login":{"id":"login","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"logout":{"id":"logout","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"publish":{"id":"publish","description":"Builds the project by copying necessary files and directories into a zip file","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"strict":{"name":"strict","type":"boolean","char":"s","description":"strict mode","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"start":{"id":"start","description":"Runs a small server with all the exercise instructions","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"port":{"name":"port","type":"option","char":"p","description":"server port"},"host":{"name":"host","type":"option","char":"h","description":"server host"},"disableGrading":{"name":"disableGrading","type":"boolean","char":"D","description":"disble grading functionality","allowNo":false},"watch":{"name":"watch","type":"boolean","char":"w","description":"Watch for file changes","allowNo":false},"editor":{"name":"editor","type":"option","char":"e","description":"[preview, extension]","options":["extension","preview"]},"version":{"name":"version","type":"option","char":"v","description":"E.g: 1.0.1"},"grading":{"name":"grading","type":"option","char":"g","description":"[isolated, incremental]","options":["isolated","incremental"]},"debug":{"name":"debug","type":"boolean","char":"d","description":"debugger mode for more verbage","allowNo":false}},"args":[]},"test":{"id":"test","description":"Test exercises","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false}},"args":[{"name":"exerciseSlug","description":"The name of the exercise to test","required":false,"hidden":false}]},"translate":{"id":"translate","description":"List all the lessons, the user is able of select many of them to translate to the given languages","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false}},"args":[]}}}
1
+ {"version":"5.0.54","commands":{"audit":{"id":"audit","description":"learnpack audit is the command in charge of creating an auditory of the repository\n...\nlearnpack audit checks for the following information in a repository:\n 1. The configuration object has slug, repository and description. (Error)\n 2. The command learnpack clean has been run. (Error)\n 3. If a markdown or test file doesn't have any content. (Error)\n 4. The links are accessing to valid servers. (Error)\n 5. The relative images are working (If they have the shortest path to the image or if the images exists in the assets). (Error)\n 6. The external images are working (If they are pointing to a valid server). (Error)\n 7. The exercises directory names are valid. (Error)\n 8. If an exercise doesn't have a README file. (Error)\n 9. The exercises array (Of the config file) has content. (Error)\n 10. The exercses have the same translations. (Warning)\n 11. The .gitignore file exists. (Warning)\n 12. If there is a file within the exercises folder but not inside of any particular exercise's folder. (Warning)\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"strict":{"name":"strict","type":"boolean","char":"s","description":"strict mode","allowNo":false}},"args":[]},"breakToken":{"id":"breakToken","description":"Break the token","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"grading":{"name":"grading","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"clean":{"id":"clean","description":"Clean the configuration object\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[]},"download":{"id":"download","description":"Describe the command here\n...\nExtra documentation goes here\n","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"init":{"id":"init","description":"Create a new learning package: Book, Tutorial or Exercise","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"grading":{"name":"grading","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"login":{"id":"login","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"logout":{"id":"logout","description":"Describe the command here\n ...\n Extra documentation goes here\n ","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{},"args":[{"name":"package","description":"The unique string that identifies this package on learnpack","required":false,"hidden":false}]},"publish":{"id":"publish","description":"Builds the project by copying necessary files and directories into a zip file","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"strict":{"name":"strict","type":"boolean","char":"s","description":"strict mode","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"start":{"id":"start","description":"Runs a small server with all the exercise instructions","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false},"port":{"name":"port","type":"option","char":"p","description":"server port"},"host":{"name":"host","type":"option","char":"h","description":"server host"},"disableGrading":{"name":"disableGrading","type":"boolean","char":"D","description":"disble grading functionality","allowNo":false},"watch":{"name":"watch","type":"boolean","char":"w","description":"Watch for file changes","allowNo":false},"editor":{"name":"editor","type":"option","char":"e","description":"[preview, extension]","options":["extension","preview"]},"version":{"name":"version","type":"option","char":"v","description":"E.g: 1.0.1"},"grading":{"name":"grading","type":"option","char":"g","description":"[isolated, incremental]","options":["isolated","incremental"]},"debug":{"name":"debug","type":"boolean","char":"d","description":"debugger mode for more verbage","allowNo":false}},"args":[]},"test":{"id":"test","description":"Test exercises","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false}},"args":[{"name":"exerciseSlug","description":"The name of the exercise to test","required":false,"hidden":false}]},"translate":{"id":"translate","description":"List all the lessons, the user is able of select many of them to translate to the given languages","pluginName":"@learnpack/learnpack","pluginType":"core","aliases":[],"flags":{"yes":{"name":"yes","type":"boolean","char":"y","description":"Skip all prompts and initialize an empty project","allowNo":false}},"args":[]}}}
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.52",
4
+ "version": "5.0.54",
5
5
  "author": "Alejandro Sanchez @alesanchezr",
6
6
  "contributors": [
7
7
  {
@@ -26,13 +26,15 @@ const handleAssetCreation = async (
26
26
  sessionPayload: any,
27
27
  academy: TAcademy,
28
28
  learnJson: any,
29
- learnpackDeployUrl: string
29
+ learnpackDeployUrl: string,
30
+ category: number
30
31
  ) => {
31
32
  try {
32
33
  const { exists, academyId } = await api.doesAssetExists(
33
34
  sessionPayload.token,
34
35
  learnJson.slug
35
36
  )
37
+
36
38
  if (!exists) {
37
39
  Console.info("Asset does not exist in this academy, creating it")
38
40
  const asset = await api.createAsset(sessionPayload.token, academy.id, {
@@ -43,6 +45,9 @@ const handleAssetCreation = async (
43
45
  learnpack_deploy_url: learnpackDeployUrl,
44
46
  technologies: ["node", "bash"],
45
47
  url: "https://4geeksacademy.com",
48
+ category: category,
49
+ owner: sessionPayload.id,
50
+ author: sessionPayload.id,
46
51
  })
47
52
  Console.info("Asset created with id", asset.id)
48
53
  } else {
@@ -90,13 +95,38 @@ const runAudit = (strict: boolean) => {
90
95
  )
91
96
  }
92
97
 
93
- const selectAcademy = async (academies: TAcademy[]) => {
98
+ type Academy = {
99
+ id: number
100
+ name: string
101
+ slug?: string
102
+ timezone?: string
103
+ }
104
+
105
+ type Category = {
106
+ id: number
107
+ slug: string
108
+ title: string
109
+ lang: string
110
+ academy: Academy
111
+ }
112
+
113
+ function getCategoriesByAcademy(
114
+ categories: Category[],
115
+ academy: Academy
116
+ ): Category[] {
117
+ return categories.filter((cat) => cat.academy.id === academy.id)
118
+ }
119
+
120
+ const selectAcademy = async (
121
+ academies: TAcademy[],
122
+ bcToken: string
123
+ ): Promise<{ academy: TAcademy | null; category: number }> => {
94
124
  if (academies.length === 0) {
95
- return null
125
+ return { academy: null, category: 0 }
96
126
  }
97
127
 
98
128
  if (academies.length === 1) {
99
- return academies[0]
129
+ return { academy: academies[0], category: 0 }
100
130
  }
101
131
 
102
132
  // prompts the user to select an academy to upload the assets
@@ -110,7 +140,27 @@ const selectAcademy = async (academies: TAcademy[]) => {
110
140
  value: academy,
111
141
  })),
112
142
  })
113
- return response.academy
143
+
144
+ const categories: Category[] = await api.getCategories(bcToken)
145
+ const categoriesByAcademy = getCategoriesByAcademy(
146
+ categories,
147
+ response.academy
148
+ )
149
+
150
+ const categoriesPrompt = await prompts({
151
+ type: "select",
152
+ name: "category",
153
+ message: "Select a category",
154
+ choices: categoriesByAcademy.map((category) => ({
155
+ title: category.title,
156
+ value: category.id,
157
+ })),
158
+ })
159
+
160
+ return {
161
+ academy: response.academy,
162
+ category: categoriesPrompt.category,
163
+ }
114
164
  }
115
165
 
116
166
  class BuildCommand extends SessionCommand {
@@ -193,7 +243,10 @@ class BuildCommand extends SessionCommand {
193
243
 
194
244
  const academies = await api.listUserAcademies(sessionPayload.token)
195
245
  // // console.log(academies, "academies")
196
- const academy = await selectAcademy(academies)
246
+ const { academy, category } = await selectAcademy(
247
+ academies,
248
+ sessionPayload.token
249
+ )
197
250
 
198
251
  // Read learn.json to get the slug
199
252
  const learnJsonPath = path.join(process.cwd(), "learn.json")
@@ -353,12 +406,15 @@ class BuildCommand extends SessionCommand {
353
406
  fs.unlinkSync(zipFilePath)
354
407
  this.removeDirectory(buildDir)
355
408
 
356
- await handleAssetCreation(
357
- sessionPayload,
358
- academy,
359
- learnJson,
360
- res.data.url
361
- )
409
+ if (academy) {
410
+ await handleAssetCreation(
411
+ sessionPayload,
412
+ academy,
413
+ learnJson,
414
+ res.data.url,
415
+ category
416
+ )
417
+ }
362
418
  } catch (error) {
363
419
  if (axios.isAxiosError(error)) {
364
420
  if (error.response && error.response.status === 403) {
package/src/utils/api.ts CHANGED
@@ -413,6 +413,9 @@ type TAssetMissing = {
413
413
  description: string
414
414
  learnpack_deploy_url: string
415
415
  technologies: string[]
416
+ category: number
417
+ owner: number
418
+ author: number
416
419
  }
417
420
 
418
421
  export const createAsset = async (
@@ -425,22 +428,24 @@ export const createAsset = async (
425
428
  title: asset.title,
426
429
  lang: asset.lang,
427
430
  asset_type: "EXERCISE",
428
- visibility: "PUBLIC",
429
- status: "PUBLISHED",
431
+ visibility: "UNLISTED",
432
+ status: "DRAFT",
430
433
  url: "https://4geeksacademy.com",
431
434
  readme_url: null,
432
435
  difficulty: null,
433
436
  duration: null,
434
437
  graded: false,
435
438
  gitpod: true,
436
- category: 7,
439
+ category: asset.category,
440
+ owner: asset.owner,
441
+ author: asset.author,
437
442
  preview: null,
438
443
  description: asset.description,
439
- external: true,
444
+ external: false,
440
445
  interactive: true,
441
446
  solution_video_url: null,
442
447
  intro_video_url: null,
443
- translations: ["us"],
448
+ translations: [asset.lang],
444
449
  learnpack_deploy_url: asset.learnpack_deploy_url,
445
450
  technologies: asset.technologies,
446
451
  }
@@ -475,11 +480,10 @@ export const doesAssetExists = async (
475
480
  const academy = data.academy.id
476
481
  return { exists: true, academyId: academy }
477
482
  }
478
-
479
- return { exists: false }
480
-
481
- } catch (error) {
482
- console.error("Failed to get asset:", error)
483
+
484
+ return { exists: false }
485
+ } catch {
486
+ // console.error("Failed to get asset:", error)
483
487
  return { exists: false }
484
488
  }
485
489
  }
@@ -506,6 +510,20 @@ const updateAsset = async (
506
510
  }
507
511
  }
508
512
 
513
+ const getCategories = async (token: string) => {
514
+ const url = `${HOST}/v1/registry/category`
515
+ const headers = {
516
+ Authorization: `Token ${token}`,
517
+ }
518
+ try {
519
+ const response = await axios.get(url, { headers })
520
+ return response.data
521
+ } catch (error) {
522
+ console.error("Failed to get categories:", error)
523
+ throw error
524
+ }
525
+ }
526
+
509
527
  export default {
510
528
  login,
511
529
  publish,
@@ -520,4 +538,5 @@ export default {
520
538
  createAsset,
521
539
  doesAssetExists,
522
540
  updateAsset,
541
+ getCategories,
523
542
  }