@learnpack/learnpack 5.0.14 → 5.0.16

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/package.json CHANGED
@@ -1,152 +1,152 @@
1
- {
2
- "name": "@learnpack/learnpack",
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.14",
5
- "author": "Alejandro Sanchez @alesanchezr",
6
- "contributors": [
7
- {
8
- "name": "Alejandro Sanchez",
9
- "url": "https://www.x.com/alesanchezr"
10
- },
11
- {
12
- "name": "Charly Chacón",
13
- "email": "charlyjchaconc@gmail.com",
14
- "url": "https://www.linkedin.com/in/charlytoc/"
15
- }
16
- ],
17
- "bin": {
18
- "learnpack": "bin/run"
19
- },
20
- "bugs": {
21
- "url": "https://github.com/learnpack/learnpack-cli/issues"
22
- },
23
- "dependencies": {
24
- "@oclif/command": "^1.6.1",
25
- "@oclif/config": "^1.15.1",
26
- "@oclif/plugin-help": "^3.1.0",
27
- "@oclif/plugin-plugins": "^1.8.0",
28
- "@oclif/plugin-warn-if-update-available": "^1.7.0",
29
- "@types/archiver": "^6.0.2",
30
- "archiver": "^7.0.1",
31
- "axios": "^1.7.7",
32
- "body-parser": "^1.19.0",
33
- "chalk": "^4.1.0",
34
- "chokidar": "^3.4.0",
35
- "cli-ux": "^5.4.6",
36
- "debounce": "^1.2.0",
37
- "dotenv": "^8.2.0",
38
- "enquirer": "^2.3.6",
39
- "eslint-plugin-unicorn": "^38.0.1",
40
- "espree": "^9.3.2",
41
- "eta": "^1.2.0",
42
- "express": "^4.17.1",
43
- "front-matter": "^4.0.2",
44
- "moment": "^2.27.0",
45
- "node-emoji": "^1.10.0",
46
- "node-fetch": "^2.7.0",
47
- "node-persist": "^3.1.0",
48
- "prompts": "^2.3.2",
49
- "shelljs": "^0.8.4",
50
- "socket.io": "^4.4.1",
51
- "targz": "^1.0.1",
52
- "tslib": "^1",
53
- "validator": "^13.1.1",
54
- "xxhashjs": "^0.2.2"
55
- },
56
- "devDependencies": {
57
- "@oclif/dev-cli": "^1.22.2",
58
- "@oclif/test": "^1.2.6",
59
- "@types/chai": "^4",
60
- "@types/debounce": "^1.2.1",
61
- "@types/express": "^4.17.13",
62
- "@types/fs-extra": "^8.1.0",
63
- "@types/mocha": "^5",
64
- "@types/mock-fs": "^4.13.1",
65
- "@types/node": "^10.17.60",
66
- "@types/node-persist": "^3.1.2",
67
- "@types/prompts": "^2.0.14",
68
- "@types/shelljs": "^0.8.9",
69
- "@types/socket.io": "^3.0.2",
70
- "@types/targz": "^1.0.1",
71
- "@types/validator": "^13.7.0",
72
- "@types/xxhashjs": "^0.2.2",
73
- "@typescript-eslint/eslint-plugin": "^5.4.0",
74
- "@typescript-eslint/parser": "^5.4.0",
75
- "chai": "^4.2.0",
76
- "chai-http": "^4.3.0",
77
- "eslint": "^8.12.0",
78
- "eslint-config-oclif": "^4.0",
79
- "eslint-config-oclif-typescript": "^1.0.2",
80
- "fs-extra": "^10.0.1",
81
- "globby": "^10.0.2",
82
- "husky": ">=6",
83
- "lint-staged": ">=10",
84
- "mocha": "^5.2.0",
85
- "mock-fs": "^5.1.2",
86
- "nock": "^13.2.2",
87
- "nyc": "^14.1.1",
88
- "pre-commit": "^1.2.2",
89
- "prettier": "^2.4.1",
90
- "ts-node": "^8",
91
- "typescript": "^5.6.2"
92
- },
93
- "engines": {
94
- "node": ">=14.0.0"
95
- },
96
- "files": [
97
- "/bin",
98
- "/npm-shrinkwrap.json",
99
- "/oclif.manifest.json",
100
- "/src",
101
- "/lib"
102
- ],
103
- "homepage": "https://github.com/learnpack/learnpack-cli",
104
- "keywords": [
105
- "oclif"
106
- ],
107
- "license": "UNLICENSED",
108
- "main": "lib/index.js",
109
- "types": "lib/index.d.ts",
110
- "oclif": {
111
- "commands": "./lib/commands",
112
- "bin": "learnpack",
113
- "plugins": [
114
- "@oclif/plugin-help",
115
- "@oclif/plugin-plugins",
116
- "@oclif/plugin-warn-if-update-available"
117
- ],
118
- "permanent_plugins": [
119
- "@oclif/plugin-help",
120
- "@oclif/plugin-plugins",
121
- "@oclif/plugin-warn-if-update-available"
122
- ]
123
- },
124
- "repository": {
125
- "type": "git",
126
- "url": "git+https://github.com/learnpack/learnpack-cli.git"
127
- },
128
- "pre-commit": {
129
- "silent": true,
130
- "run": [
131
- "pre"
132
- ]
133
- },
134
- "scripts": {
135
- "tsc": "tsc -b",
136
- "postpack": "rm -f oclif.manifest.json && eslint . --ext .ts --config .eslintrc",
137
- "prepack": "rm -rf lib && tsc -b && oclif-dev manifest && oclif-dev readme",
138
- "pre": "node ./test/precommit/index.ts",
139
- "test": "NODE_ENV=test nyc --extension .ts mocha --forbid-only \"test/**/*.test.ts\"",
140
- "version": "oclif-dev readme && git add README.md",
141
- "prepare": "husky install"
142
- },
143
- "lint-staged": {
144
- "*.{js,ts}": [
145
- "eslint --cache --fix"
146
- ],
147
- "*.{js,css,md,ts}": "prettier --write"
148
- },
149
- "directories": {
150
- "test": "test"
151
- }
152
- }
1
+ {
2
+ "name": "@learnpack/learnpack",
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.16",
5
+ "author": "Alejandro Sanchez @alesanchezr",
6
+ "contributors": [
7
+ {
8
+ "name": "Alejandro Sanchez",
9
+ "url": "https://www.x.com/alesanchezr"
10
+ },
11
+ {
12
+ "name": "Charly Chacón",
13
+ "email": "charlyjchaconc@gmail.com",
14
+ "url": "https://www.linkedin.com/in/charlytoc/"
15
+ }
16
+ ],
17
+ "bin": {
18
+ "learnpack": "bin/run"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/learnpack/learnpack-cli/issues"
22
+ },
23
+ "dependencies": {
24
+ "@oclif/command": "^1.6.1",
25
+ "@oclif/config": "^1.15.1",
26
+ "@oclif/plugin-help": "^3.1.0",
27
+ "@oclif/plugin-plugins": "^1.8.0",
28
+ "@oclif/plugin-warn-if-update-available": "^1.7.0",
29
+ "@types/archiver": "^6.0.2",
30
+ "archiver": "^7.0.1",
31
+ "axios": "^1.7.7",
32
+ "body-parser": "^1.19.0",
33
+ "chalk": "^4.1.0",
34
+ "chokidar": "^3.4.0",
35
+ "cli-ux": "^5.4.6",
36
+ "debounce": "^1.2.0",
37
+ "dotenv": "^8.2.0",
38
+ "enquirer": "^2.3.6",
39
+ "eslint-plugin-unicorn": "^38.0.1",
40
+ "espree": "^9.3.2",
41
+ "eta": "^1.2.0",
42
+ "express": "^4.17.1",
43
+ "front-matter": "^4.0.2",
44
+ "moment": "^2.27.0",
45
+ "node-emoji": "^1.10.0",
46
+ "node-fetch": "^2.7.0",
47
+ "node-persist": "^3.1.0",
48
+ "prompts": "^2.3.2",
49
+ "shelljs": "^0.8.4",
50
+ "socket.io": "^4.4.1",
51
+ "targz": "^1.0.1",
52
+ "tslib": "^1",
53
+ "validator": "^13.1.1",
54
+ "xxhashjs": "^0.2.2"
55
+ },
56
+ "devDependencies": {
57
+ "@oclif/dev-cli": "^1.22.2",
58
+ "@oclif/test": "^1.2.6",
59
+ "@types/chai": "^4",
60
+ "@types/debounce": "^1.2.1",
61
+ "@types/express": "^4.17.13",
62
+ "@types/fs-extra": "^8.1.0",
63
+ "@types/mocha": "^5",
64
+ "@types/mock-fs": "^4.13.1",
65
+ "@types/node": "^10.17.60",
66
+ "@types/node-persist": "^3.1.2",
67
+ "@types/prompts": "^2.0.14",
68
+ "@types/shelljs": "^0.8.9",
69
+ "@types/socket.io": "^3.0.2",
70
+ "@types/targz": "^1.0.1",
71
+ "@types/validator": "^13.7.0",
72
+ "@types/xxhashjs": "^0.2.2",
73
+ "@typescript-eslint/eslint-plugin": "^5.4.0",
74
+ "@typescript-eslint/parser": "^5.4.0",
75
+ "chai": "^4.2.0",
76
+ "chai-http": "^4.3.0",
77
+ "eslint": "^8.12.0",
78
+ "eslint-config-oclif": "^4.0",
79
+ "eslint-config-oclif-typescript": "^1.0.2",
80
+ "fs-extra": "^10.0.1",
81
+ "globby": "^10.0.2",
82
+ "husky": ">=6",
83
+ "lint-staged": ">=10",
84
+ "mocha": "^5.2.0",
85
+ "mock-fs": "^5.1.2",
86
+ "nock": "^13.2.2",
87
+ "nyc": "^14.1.1",
88
+ "pre-commit": "^1.2.2",
89
+ "prettier": "^2.4.1",
90
+ "ts-node": "^8",
91
+ "typescript": "^5.6.2"
92
+ },
93
+ "engines": {
94
+ "node": ">=14.0.0"
95
+ },
96
+ "files": [
97
+ "/bin",
98
+ "/npm-shrinkwrap.json",
99
+ "/oclif.manifest.json",
100
+ "/src",
101
+ "/lib"
102
+ ],
103
+ "homepage": "https://github.com/learnpack/learnpack-cli",
104
+ "keywords": [
105
+ "oclif"
106
+ ],
107
+ "license": "UNLICENSED",
108
+ "main": "lib/index.js",
109
+ "types": "lib/index.d.ts",
110
+ "oclif": {
111
+ "commands": "./lib/commands",
112
+ "bin": "learnpack",
113
+ "plugins": [
114
+ "@oclif/plugin-help",
115
+ "@oclif/plugin-plugins",
116
+ "@oclif/plugin-warn-if-update-available"
117
+ ],
118
+ "permanent_plugins": [
119
+ "@oclif/plugin-help",
120
+ "@oclif/plugin-plugins",
121
+ "@oclif/plugin-warn-if-update-available"
122
+ ]
123
+ },
124
+ "repository": {
125
+ "type": "git",
126
+ "url": "git+https://github.com/learnpack/learnpack-cli.git"
127
+ },
128
+ "pre-commit": {
129
+ "silent": true,
130
+ "run": [
131
+ "pre"
132
+ ]
133
+ },
134
+ "scripts": {
135
+ "tsc": "tsc -b",
136
+ "postpack": "rm -f oclif.manifest.json && eslint . --ext .ts --config .eslintrc",
137
+ "prepack": "rm -rf lib && tsc -b && oclif-dev manifest && oclif-dev readme",
138
+ "pre": "node ./test/precommit/index.ts",
139
+ "test": "NODE_ENV=test nyc --extension .ts mocha --forbid-only \"test/**/*.test.ts\"",
140
+ "version": "oclif-dev readme && git add README.md",
141
+ "prepare": "husky install"
142
+ },
143
+ "lint-staged": {
144
+ "*.{js,ts}": [
145
+ "eslint --cache --fix"
146
+ ],
147
+ "*.{js,css,md,ts}": "prettier --write"
148
+ },
149
+ "directories": {
150
+ "test": "test"
151
+ }
152
+ }
@@ -19,7 +19,7 @@ import {
19
19
  downloadImage,
20
20
  generateCourseIntroduction,
21
21
  } from "../utils/rigoActions"
22
-
22
+ import { getConsumables } from "../utils/api"
23
23
  const slugify = (text: string) => {
24
24
  return text
25
25
  .toString()
@@ -53,6 +53,25 @@ function getFilenameFromUrl(url: string) {
53
53
  return path.basename(url)
54
54
  }
55
55
 
56
+ const makePackageInfo = (choices: any) => {
57
+ const packageInfo = {
58
+ grading: choices.grading,
59
+ difficulty: choices.difficulty,
60
+ duration: parseInt(choices.duration),
61
+ description: {
62
+ us: choices.description,
63
+ },
64
+ title: {
65
+ us: choices.title,
66
+ },
67
+ slug: choices.title
68
+ .toLowerCase()
69
+ .replace(/ /g, "-")
70
+ .replace(/[^\w-]+/g, ""),
71
+ }
72
+ return packageInfo
73
+ }
74
+
56
75
  async function createPreviewReadme(
57
76
  tutorialDir: string,
58
77
  packageInfo: PackageInfo,
@@ -81,7 +100,9 @@ type PackageInfo = {
81
100
  }
82
101
 
83
102
  const handleAILogic = async (tutorialDir: string, packageInfo: PackageInfo) => {
84
- Console.info("Almost there! First you need to login to use the AI creator")
103
+ Console.info(
104
+ "Almost there! First you need to login with 4Geeks.com to use AI Generation tool for creators. You can create a new account here: https://4geeks.com/creators"
105
+ )
85
106
 
86
107
  fs.removeSync(path.join(tutorialDir, "exercises", "01-hello-world"))
87
108
 
@@ -115,12 +136,23 @@ const handleAILogic = async (tutorialDir: string, packageInfo: PackageInfo) => {
115
136
 
116
137
  const rigoToken = sessionPayload.rigobot.key
117
138
 
139
+ const consumables = await getConsumables(sessionPayload.token)
140
+
141
+ if (consumables.ai_tutorial_generation === 0) {
142
+ Console.error(
143
+ "It seems you cannot generate tutorials with AI. Make sure you creator subscription is up to date here: https://4geeks.com/profile/subscriptions?token=" +
144
+ sessionPayload.token +
145
+ ". If you believe there is an issue you can always contact support@4geeks.com"
146
+ )
147
+ process.exit(1)
148
+ }
149
+
118
150
  const isCreator = await hasCreatorPermission(rigoToken)
119
151
  if (!isCreator) {
120
152
  Console.error(
121
153
  "👀 Oops! You need to be a creator to use our specialized AI. Please contact support"
122
154
  )
123
- return
155
+ process.exit(1)
124
156
  }
125
157
 
126
158
  Console.success("🎉 Let's begin this learning journey!")
@@ -236,6 +268,91 @@ const handleAILogic = async (tutorialDir: string, packageInfo: PackageInfo) => {
236
268
  return true
237
269
  }
238
270
 
271
+ const getChoices = async (empty: boolean) => {
272
+ const defaultChoices = {
273
+ title: "My Interactive Tutorial",
274
+ description: "",
275
+ difficulty: "beginner",
276
+ duration: 1,
277
+ useAI: "no",
278
+ grading: "isolated",
279
+ }
280
+
281
+ if (empty) {
282
+ return defaultChoices
283
+ }
284
+
285
+ const choices = await prompts([
286
+ {
287
+ type: "select",
288
+ name: "grading",
289
+ message: "Is the auto-grading going to be isolated or incremental?",
290
+ choices: [
291
+ {
292
+ title: "Incremental: Build on top of each other like a tutorial",
293
+ value: "incremental",
294
+ },
295
+ { title: "Isolated: Small separated exercises", value: "isolated" },
296
+ {
297
+ title: "No grading: No feedback or testing whatsoever",
298
+ value: null,
299
+ },
300
+ ],
301
+ },
302
+ {
303
+ type: "text",
304
+ name: "title",
305
+ initial: "My Interactive Tutorial",
306
+ message: "Title for your tutorial? Press enter to leave as it is",
307
+ },
308
+ {
309
+ type: "text",
310
+ name: "description",
311
+ initial: "",
312
+ message: "Description for your tutorial? Press enter to leave blank",
313
+ },
314
+ {
315
+ type: "select",
316
+ name: "difficulty",
317
+ message: "How difficulty will be to complete the tutorial?",
318
+ choices: [
319
+ { title: "Begginer (no previous experience)", value: "beginner" },
320
+ { title: "Easy (just a bit of experience required)", value: "easy" },
321
+ {
322
+ title: "Intermediate (you need experience)",
323
+ value: "intermediate",
324
+ },
325
+ { title: "Hard (master the topic)", value: "hard" },
326
+ ],
327
+ },
328
+ {
329
+ type: "text",
330
+ name: "duration",
331
+ initial: "1",
332
+ message: "How many hours avg it takes to complete (number)?",
333
+ validate: (value: string) => {
334
+ const n = Math.floor(Number(value))
335
+ return n !== Number.POSITIVE_INFINITY && String(n) === value && n >= 0
336
+ },
337
+ },
338
+ {
339
+ type: "select",
340
+ name: "useAI",
341
+ message:
342
+ "Want a little bit of AI magic to help you? Our AI can craft the tutorial for you",
343
+ choices: [
344
+ {
345
+ title: "Yes, please help me",
346
+ value: "yes",
347
+ },
348
+ { title: "No, thanks, I prefer to do it manually", value: "no" },
349
+ ],
350
+ },
351
+ ])
352
+
353
+ return choices
354
+ }
355
+
239
356
  class InitComand extends BaseCommand {
240
357
  static description =
241
358
  "Create a new learning package: Book, Tutorial or Exercise"
@@ -250,89 +367,9 @@ class InitComand extends BaseCommand {
250
367
 
251
368
  await alreadyInitialized()
252
369
 
253
- const choices = await prompts([
254
- {
255
- type: "select",
256
- name: "grading",
257
- message: "Is the auto-grading going to be isolated or incremental?",
258
- choices: [
259
- {
260
- title: "Incremental: Build on top of each other like a tutorial",
261
- value: "incremental",
262
- },
263
- { title: "Isolated: Small separated exercises", value: "isolated" },
264
- {
265
- title: "No grading: No feedback or testing whatsoever",
266
- value: null,
267
- },
268
- ],
269
- },
270
- {
271
- type: "text",
272
- name: "title",
273
- initial: "My Interactive Tutorial",
274
- message: "Title for your tutorial? Press enter to leave as it is",
275
- },
276
- {
277
- type: "text",
278
- name: "description",
279
- initial: "",
280
- message: "Description for your tutorial? Press enter to leave blank",
281
- },
282
- {
283
- type: "select",
284
- name: "difficulty",
285
- message: "How difficulty will be to complete the tutorial?",
286
- choices: [
287
- { title: "Begginer (no previous experience)", value: "beginner" },
288
- { title: "Easy (just a bit of experience required)", value: "easy" },
289
- {
290
- title: "Intermediate (you need experience)",
291
- value: "intermediate",
292
- },
293
- { title: "Hard (master the topic)", value: "hard" },
294
- ],
295
- },
296
- {
297
- type: "text",
298
- name: "duration",
299
- initial: "1",
300
- message: "How many hours avg it takes to complete (number)?",
301
- validate: (value: string) => {
302
- const n = Math.floor(Number(value))
303
- return n !== Number.POSITIVE_INFINITY && String(n) === value && n >= 0
304
- },
305
- },
306
- {
307
- type: "select",
308
- name: "useAI",
309
- message:
310
- "Want a little bit of AI magic to help you? Our AI can craft the tutorial for you",
311
- choices: [
312
- {
313
- title: "Yes, please help me",
314
- value: "yes",
315
- },
316
- { title: "No, thanks, I prefer to do it manually", value: "no" },
317
- ],
318
- },
319
- ])
320
-
321
- const packageInfo = {
322
- grading: choices.grading,
323
- difficulty: choices.difficulty,
324
- duration: parseInt(choices.duration),
325
- description: {
326
- us: choices.description,
327
- },
328
- title: {
329
- us: choices.title,
330
- },
331
- slug: choices.title
332
- .toLowerCase()
333
- .replace(/ /g, "-")
334
- .replace(/[^\w-]+/g, ""),
335
- }
370
+ const choices = await getChoices(flags.yes)
371
+
372
+ const packageInfo = makePackageInfo(choices)
336
373
 
337
374
  const tutorialDir = `./${packageInfo.slug}`
338
375
  fs.ensureDirSync(tutorialDir)
@@ -354,26 +391,26 @@ class InitComand extends BaseCommand {
354
391
  // Creating README files
355
392
  for (const language of languages) {
356
393
  const readmeFilename = `README${language !== "en" ? `.${language}` : ""}`
357
- // const readmeTemplatePath = path.resolve(
358
- // templatesDir,
359
- // `${readmeFilename}.ejs`
360
- // )
361
-
362
- // const readmeObject = {
363
- // title: packageInfo.title.us,
364
- // description: packageInfo.description.us,
365
- // grading: packageInfo.grading,
366
- // difficulty: packageInfo.difficulty,
367
- // duration: packageInfo.duration,
368
- // }
369
- // const readmeContent = eta.render(
370
- // fs.readFileSync(readmeTemplatePath, "utf-8"),
371
- // readmeObject
372
- // )
373
- // fs.writeFileSync(
374
- // path.join(tutorialDir, `${readmeFilename}.md`),
375
- // readmeContent
376
- // )
394
+ const readmeTemplatePath = path.resolve(
395
+ templatesDir,
396
+ `${readmeFilename}.ejs`
397
+ )
398
+
399
+ const readmeObject = {
400
+ title: packageInfo.title.us,
401
+ description: packageInfo.description.us,
402
+ grading: packageInfo.grading,
403
+ difficulty: packageInfo.difficulty,
404
+ duration: packageInfo.duration,
405
+ }
406
+ const readmeContent = eta.render(
407
+ fs.readFileSync(readmeTemplatePath, "utf-8"),
408
+ readmeObject
409
+ )
410
+ fs.writeFileSync(
411
+ path.join(tutorialDir, `${readmeFilename}.md`),
412
+ readmeContent
413
+ )
377
414
  if (fs.existsSync(path.join(tutorialDir, `${readmeFilename}.ejs`)))
378
415
  fs.removeSync(path.join(tutorialDir, `${readmeFilename}.ejs`))
379
416
  }
@@ -398,6 +435,7 @@ class InitComand extends BaseCommand {
398
435
  Console.help(
399
436
  `Start the exercises by running the following command on your terminal: $ learnpack start`
400
437
  )
438
+ process.exit(0)
401
439
  }
402
440
  }
403
441