@procamp/cli 0.0.1
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/dist/bin/index.d.ts +3 -0
- package/dist/bin/index.js +51 -0
- package/dist/bin/index.js.map +1 -0
- package/dist/command/generate.d.ts +1 -0
- package/dist/command/generate.js +202 -0
- package/dist/command/generate.js.map +1 -0
- package/dist/command/init.d.ts +1 -0
- package/dist/command/init.js +58 -0
- package/dist/command/init.js.map +1 -0
- package/dist/command/login.d.ts +1 -0
- package/dist/command/login.js +116 -0
- package/dist/command/login.js.map +1 -0
- package/dist/command/new.d.ts +1 -0
- package/dist/command/new.js +41 -0
- package/dist/command/new.js.map +1 -0
- package/dist/command/pack.d.ts +1 -0
- package/dist/command/pack.js +32 -0
- package/dist/command/pack.js.map +1 -0
- package/dist/command/publish.d.ts +1 -0
- package/dist/command/publish.js +95 -0
- package/dist/command/publish.js.map +1 -0
- package/dist/command/validate.d.ts +1 -0
- package/dist/command/validate.js +9 -0
- package/dist/command/validate.js.map +1 -0
- package/dist/index.d.ts +0 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/course.d.ts +27 -0
- package/dist/interfaces/course.js +3 -0
- package/dist/interfaces/course.js.map +1 -0
- package/dist/utils/error.d.ts +1 -0
- package/dist/utils/error.js +8 -0
- package/dist/utils/error.js.map +1 -0
- package/dist/utils/getUserId.d.ts +1 -0
- package/dist/utils/getUserId.js +15 -0
- package/dist/utils/getUserId.js.map +1 -0
- package/package.json +58 -0
- package/readme.md +32 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
#! /usr/bin/env node
|
2
|
+
"use strict";
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
4
|
+
exports.program = void 0;
|
5
|
+
const commander_1 = require("commander");
|
6
|
+
const generate_1 = require("../command/generate");
|
7
|
+
const init_1 = require("../command/init");
|
8
|
+
const login_1 = require("../command/login");
|
9
|
+
const new_1 = require("../command/new");
|
10
|
+
const pack_1 = require("../command/pack");
|
11
|
+
const publish_1 = require("../command/publish");
|
12
|
+
const validate_1 = require("../command/validate");
|
13
|
+
const error_1 = require("../utils/error");
|
14
|
+
const { version, name, description } = require('../../package.json');
|
15
|
+
exports.program = new commander_1.Command();
|
16
|
+
exports.program.name(name).version(version).description(description);
|
17
|
+
exports.program
|
18
|
+
.command('init')
|
19
|
+
.description('Initialise project configuration ')
|
20
|
+
.option('-d, --directory <directory>', 'Directory to initialise project', process.cwd())
|
21
|
+
.action(init_1.initCourse);
|
22
|
+
exports.program
|
23
|
+
.command('new <projectName>')
|
24
|
+
.description('Generate course project')
|
25
|
+
.action(new_1.createCourse);
|
26
|
+
exports.program
|
27
|
+
.command('pack')
|
28
|
+
.description('Compress files')
|
29
|
+
.option('-d, --directory <directory>', 'Directory to compress', process.cwd())
|
30
|
+
.action(pack_1.zipCourse);
|
31
|
+
exports.program
|
32
|
+
.command('publish')
|
33
|
+
.description('Publish file to service')
|
34
|
+
.action(publish_1.publishCourse);
|
35
|
+
exports.program
|
36
|
+
.command('validate')
|
37
|
+
.description('Validate course folder structure')
|
38
|
+
.action(validate_1.validate);
|
39
|
+
exports.program
|
40
|
+
.command('generate course')
|
41
|
+
.alias('g')
|
42
|
+
.description('Generating Course with blueprint.yml')
|
43
|
+
.action(generate_1.generateCourse);
|
44
|
+
exports.program.command('login').description('Login to procamp').action(login_1.login);
|
45
|
+
exports.program.on('command:*', ([command]) => {
|
46
|
+
(0, error_1.error)(`Erreur : commande "${command}" inconnue`);
|
47
|
+
exports.program.help();
|
48
|
+
process.exit(1);
|
49
|
+
});
|
50
|
+
exports.program.parse(process.argv);
|
51
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bin/index.ts"],"names":[],"mappings":";;;;AAEA,yCAAoC;AACpC,kDAAqD;AACrD,0CAA6C;AAC7C,4CAAyC;AACzC,wCAA8C;AAC9C,0CAA4C;AAC5C,gDAAmD;AACnD,kDAA+C;AAC/C,0CAAuC;AACvC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAExD,QAAA,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AACrC,eAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;AAE7D,eAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,mCAAmC,CAAC;KAChD,MAAM,CACL,6BAA6B,EAC7B,iCAAiC,EACjC,OAAO,CAAC,GAAG,EAAE,CACd;KACA,MAAM,CAAC,iBAAU,CAAC,CAAC;AAEtB,eAAO;KACJ,OAAO,CAAC,mBAAmB,CAAC;KAC5B,WAAW,CAAC,yBAAyB,CAAC;KACtC,MAAM,CAAC,kBAAY,CAAC,CAAC;AAExB,eAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,gBAAgB,CAAC;KAC7B,MAAM,CAAC,6BAA6B,EAAE,uBAAuB,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;KAC7E,MAAM,CAAC,gBAAS,CAAC,CAAC;AAErB,eAAO;KACJ,OAAO,CAAC,SAAS,CAAC;KAClB,WAAW,CAAC,yBAAyB,CAAC;KACtC,MAAM,CAAC,uBAAa,CAAC,CAAC;AAEzB,eAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CAAC,kCAAkC,CAAC;KAC/C,MAAM,CAAC,mBAAQ,CAAC,CAAC;AAGpB,eAAO;KACJ,OAAO,CAAC,iBAAiB,CAAC;KAC1B,KAAK,CAAC,GAAG,CAAC;KACV,WAAW,CAAC,sCAAsC,CAAC;KACnD,MAAM,CAAC,yBAAc,CAAC,CAAC;AAE1B,eAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,MAAM,CAAC,aAAK,CAAC,CAAC;AACvE,eAAO,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE;IACpC,IAAA,aAAK,EAAC,sBAAsB,OAAO,YAAY,CAAC,CAAC;IACjD,eAAO,CAAC,IAAI,EAAE,CAAC;IACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AACH,eAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC","sourcesContent":["#! /usr/bin/env node\n\nimport { Command } from 'commander';\nimport { generateCourse } from '../command/generate';\nimport { initCourse } from '../command/init';\nimport { login } from '../command/login';\nimport { createCourse } from '../command/new';\nimport { zipCourse } from '../command/pack';\nimport { publishCourse } from '../command/publish';\nimport { validate } from '../command/validate';\nimport { error } from '../utils/error';\nconst { version, name, description } = require('../../package.json');\n\nexport const program = new Command();\nprogram.name(name).version(version).description(description);\n\nprogram\n .command('init')\n .description('Initialise project configuration ')\n .option(\n '-d, --directory <directory>',\n 'Directory to initialise project',\n process.cwd()\n )\n .action(initCourse);\n\nprogram\n .command('new <projectName>')\n .description('Generate course project')\n .action(createCourse);\n\nprogram\n .command('pack')\n .description('Compress files')\n .option('-d, --directory <directory>', 'Directory to compress', process.cwd())\n .action(zipCourse);\n\nprogram\n .command('publish')\n .description('Publish file to service')\n .action(publishCourse);\n\nprogram\n .command('validate')\n .description('Validate course folder structure')\n .action(validate);\n\n// Commande pour générer un chapitre\nprogram\n .command('generate course')\n .alias('g')\n .description('Generating Course with blueprint.yml')\n .action(generateCourse);\n\nprogram.command('login').description('Login to procamp').action(login);\nprogram.on('command:*', ([command]) => {\n error(`Erreur : commande \"${command}\" inconnue`);\n program.help();\n process.exit(1);\n});\nprogram.parse(process.argv);\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function generateCourse(): Promise<void>;
|
@@ -0,0 +1,202 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9
|
+
});
|
10
|
+
};
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
12
|
+
exports.generateCourse = void 0;
|
13
|
+
const fs = require("fs-extra");
|
14
|
+
const inquirer_1 = require("inquirer");
|
15
|
+
const yaml = require("js-yaml");
|
16
|
+
const path = require("path");
|
17
|
+
const error_1 = require("../utils/error");
|
18
|
+
const getUserId_1 = require("../utils/getUserId");
|
19
|
+
const deleteFolder = (srcDir, arrayObject) => __awaiter(void 0, void 0, void 0, function* () {
|
20
|
+
if (fs.existsSync(srcDir)) {
|
21
|
+
const entries = fs.readdirSync(srcDir, { withFileTypes: true });
|
22
|
+
const directories = entries
|
23
|
+
.filter((dirent) => dirent.isDirectory())
|
24
|
+
.map((dirent) => dirent.name);
|
25
|
+
const names = arrayObject.map((obj) => obj.title);
|
26
|
+
let deleteFolder = [];
|
27
|
+
for (let directory of directories) {
|
28
|
+
const dir = directory
|
29
|
+
.toString()
|
30
|
+
.slice(directory.toString().indexOf('-') + 1)
|
31
|
+
.replaceAll('-', ' ');
|
32
|
+
if (!names.includes(dir)) {
|
33
|
+
deleteFolder.push(directory);
|
34
|
+
}
|
35
|
+
}
|
36
|
+
if (deleteFolder.length !== 0) {
|
37
|
+
const { confirm } = yield inquirer_1.default.prompt({
|
38
|
+
type: 'confirm',
|
39
|
+
message: `We found folders not listed in the structure of your course: \n ${deleteFolder} \n Do you want to delete them ?`,
|
40
|
+
name: 'confirm',
|
41
|
+
default: 'y'
|
42
|
+
});
|
43
|
+
if (confirm) {
|
44
|
+
deleteFolder.forEach((directory) => {
|
45
|
+
fs.rmSync(path.join(srcDir, directory), {
|
46
|
+
recursive: true,
|
47
|
+
force: true
|
48
|
+
});
|
49
|
+
});
|
50
|
+
console.log('Unlisted folders deleted');
|
51
|
+
}
|
52
|
+
else {
|
53
|
+
console.log('Deletion aborted.');
|
54
|
+
return;
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
});
|
59
|
+
const updateCourse = (srcDir, fileDir, object, i) => __awaiter(void 0, void 0, void 0, function* () {
|
60
|
+
if (fs.existsSync(srcDir)) {
|
61
|
+
const entries = fs.readdirSync(srcDir, { withFileTypes: true });
|
62
|
+
if (entries.length === 0)
|
63
|
+
fs.ensureDirSync(fileDir);
|
64
|
+
else {
|
65
|
+
const directories = entries
|
66
|
+
.filter((dirent) => dirent.isDirectory())
|
67
|
+
.map((dirent) => dirent.name);
|
68
|
+
const file = directories.find((file) => {
|
69
|
+
return (file
|
70
|
+
.toString()
|
71
|
+
.slice(file.toString().indexOf('-') + 1)
|
72
|
+
.localeCompare(object.title.toString().replaceAll(' ', '-')) === 0);
|
73
|
+
});
|
74
|
+
if (file) {
|
75
|
+
const filePath = path.join(srcDir, file);
|
76
|
+
if (Number(file.toString().slice(0, file.toString().indexOf('-'))) !==
|
77
|
+
i + 1) {
|
78
|
+
yield fs.move(filePath, fileDir, { overwrite: true });
|
79
|
+
}
|
80
|
+
}
|
81
|
+
else {
|
82
|
+
fs.ensureDirSync(fileDir);
|
83
|
+
}
|
84
|
+
}
|
85
|
+
}
|
86
|
+
else
|
87
|
+
yield fs.mkdir(fileDir);
|
88
|
+
});
|
89
|
+
function generateCourse() {
|
90
|
+
return __awaiter(this, void 0, void 0, function* () {
|
91
|
+
const configFile = path.join(process.cwd(), 'blueprint.yaml');
|
92
|
+
if (fs.existsSync(configFile)) {
|
93
|
+
const { name } = yield inquirer_1.default.prompt({
|
94
|
+
type: 'input',
|
95
|
+
name: 'name',
|
96
|
+
message: 'What is the name of the folder?',
|
97
|
+
default: 'course'
|
98
|
+
});
|
99
|
+
const baseDir = name;
|
100
|
+
const fileContents = fs.readFileSync(configFile, 'utf8');
|
101
|
+
const courses = yaml.load(fileContents);
|
102
|
+
const courseData = Object.assign({}, courses);
|
103
|
+
try {
|
104
|
+
let configContent = (0, getUserId_1.getUserId)();
|
105
|
+
fs.ensureDir(baseDir, () => __awaiter(this, void 0, void 0, function* () {
|
106
|
+
if (fs.existsSync(baseDir)) {
|
107
|
+
const courseInfo = courseData.course;
|
108
|
+
const meta = {
|
109
|
+
title: baseDir,
|
110
|
+
author: courseInfo.author,
|
111
|
+
description: courseInfo.description,
|
112
|
+
version: courseInfo.version,
|
113
|
+
courseId: courseInfo.courseId,
|
114
|
+
userId: configContent['sub']
|
115
|
+
};
|
116
|
+
try {
|
117
|
+
yield fs.writeJson(`${baseDir}/meta.json`, meta, {
|
118
|
+
spaces: 2
|
119
|
+
});
|
120
|
+
yield fs.writeFile(`${baseDir}/README.md`, '');
|
121
|
+
}
|
122
|
+
catch (e) {
|
123
|
+
throw e;
|
124
|
+
}
|
125
|
+
}
|
126
|
+
}));
|
127
|
+
if ('chapters' in courseData) {
|
128
|
+
const chapters = courseData.chapters;
|
129
|
+
yield deleteFolder(baseDir, chapters);
|
130
|
+
for (let i = 0; i < chapters.length; i++) {
|
131
|
+
const chapter = chapters[i];
|
132
|
+
const chapterDir = `${baseDir}/${(i + 1)
|
133
|
+
.toString()
|
134
|
+
.padStart(2, '0')}-${chapter.title.replace(/[:\s]+/g, '-')}`;
|
135
|
+
yield updateCourse(baseDir, chapterDir, chapter, i);
|
136
|
+
const chapterMeta = {
|
137
|
+
title: chapter.title,
|
138
|
+
order: i + 1
|
139
|
+
};
|
140
|
+
yield fs.writeJson(`${chapterDir}/meta.json`, chapterMeta, {
|
141
|
+
spaces: 2
|
142
|
+
});
|
143
|
+
if ('lessons' in chapter) {
|
144
|
+
const lessons = chapter.lessons;
|
145
|
+
yield deleteFolder(chapterDir, lessons);
|
146
|
+
for (let j = 0; j < lessons.length; j++) {
|
147
|
+
const lesson = lessons[j];
|
148
|
+
const lessonDir = `${chapterDir}/${(j + 1)
|
149
|
+
.toString()
|
150
|
+
.padStart(2, '0')}-${lesson.title.replace(/[:\s]+/g, '-')}`;
|
151
|
+
yield updateCourse(chapterDir, lessonDir, lesson, j);
|
152
|
+
const lessonMeta = {
|
153
|
+
title: lesson.title,
|
154
|
+
objectives: lesson.objectives,
|
155
|
+
order: j + 1
|
156
|
+
};
|
157
|
+
yield fs.writeJson(`${lessonDir}/meta.json`, lessonMeta, {
|
158
|
+
spaces: 2
|
159
|
+
});
|
160
|
+
if ('assessments' in lesson) {
|
161
|
+
const assessments = lesson.assessments;
|
162
|
+
yield deleteFolder(lessonDir, assessments);
|
163
|
+
for (let k = 0; k < assessments.length; k++) {
|
164
|
+
const assessment = assessments[k];
|
165
|
+
const assessmentDir = `${lessonDir}/${(k + 1)
|
166
|
+
.toString()
|
167
|
+
.padStart(2, '0')}-${assessment.title.replace(/[:\s]+/g, '-')}`;
|
168
|
+
yield updateCourse(lessonDir, assessmentDir, assessment, k);
|
169
|
+
yield fs.writeFile(`${assessmentDir}/README.md`, '');
|
170
|
+
yield fs.ensureDir(`${assessmentDir}/app-a`);
|
171
|
+
if (assessment.solution === true)
|
172
|
+
yield fs.ensureDir(`${assessmentDir}/app-b`);
|
173
|
+
}
|
174
|
+
}
|
175
|
+
else {
|
176
|
+
const assessmentDir = `${lessonDir}/${(1)
|
177
|
+
.toString()
|
178
|
+
.padStart(2, '0')}-${lesson.title.replace(/[:\s]+/g, '-')}`;
|
179
|
+
fs.ensureDirSync(assessmentDir);
|
180
|
+
yield fs.writeFile(`${assessmentDir}/README.md`, '');
|
181
|
+
yield fs.ensureDir(`${assessmentDir}/app-a/src/lib`);
|
182
|
+
}
|
183
|
+
}
|
184
|
+
}
|
185
|
+
else
|
186
|
+
return (0, error_1.error)(`I can't find lessons in the chapter ${i + 1}`);
|
187
|
+
}
|
188
|
+
}
|
189
|
+
else
|
190
|
+
return (0, error_1.error)("You haven't chapters in your blueprint.yaml");
|
191
|
+
console.log('Folder structure created');
|
192
|
+
}
|
193
|
+
catch (err) {
|
194
|
+
(0, error_1.error)('Error creating folder structure: ' + err);
|
195
|
+
}
|
196
|
+
}
|
197
|
+
else
|
198
|
+
return (0, error_1.error)('We need the blueprint.yaml file to create a course');
|
199
|
+
});
|
200
|
+
}
|
201
|
+
exports.generateCourse = generateCourse;
|
202
|
+
//# sourceMappingURL=generate.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/command/generate.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs-extra';\nimport inquirer from 'inquirer';\nimport * as yaml from 'js-yaml';\nimport * as path from 'path';\nimport { course, courseInfo } from '../interfaces/course';\nimport { error } from '../utils/error';\nimport { getUserId } from '../utils/getUserId';\n\nconst deleteFolder = async (srcDir, arrayObject) => {\n if (fs.existsSync(srcDir)) {\n const entries = fs.readdirSync(srcDir, { withFileTypes: true });\n const directories = entries\n .filter((dirent) => dirent.isDirectory())\n .map((dirent) => dirent.name);\n const names = arrayObject.map((obj) => obj.title);\n let deleteFolder: string[] = [];\n for (let directory of directories) {\n const dir = directory\n .toString()\n .slice(directory.toString().indexOf('-') + 1)\n .replaceAll('-', ' ');\n if (!names.includes(dir)) {\n deleteFolder.push(directory);\n }\n }\n if (deleteFolder.length !== 0) {\n const { confirm } = await inquirer.prompt({\n type: 'confirm',\n message: `We found folders not listed in the structure of your course: \\n ${deleteFolder} \\n Do you want to delete them ?`,\n name: 'confirm',\n default: 'y'\n });\n\n if (confirm) {\n deleteFolder.forEach((directory) => {\n fs.rmSync(path.join(srcDir, directory), {\n recursive: true,\n force: true\n });\n });\n console.log('Unlisted folders deleted');\n } else {\n console.log('Deletion aborted.');\n return;\n }\n }\n }\n};\n\nconst updateCourse = async (srcDir, fileDir, object, i) => {\n if (fs.existsSync(srcDir)) {\n const entries = fs.readdirSync(srcDir, { withFileTypes: true });\n if (entries.length === 0) fs.ensureDirSync(fileDir);\n else {\n const directories = entries\n .filter((dirent) => dirent.isDirectory())\n .map((dirent) => dirent.name);\n const file = directories.find((file) => {\n return (\n file\n .toString()\n .slice(file.toString().indexOf('-') + 1)\n .localeCompare(object.title.toString().replaceAll(' ', '-')) === 0\n );\n });\n\n if (file) {\n const filePath = path.join(srcDir, file);\n if (\n Number(file.toString().slice(0, file.toString().indexOf('-'))) !==\n i + 1\n ) {\n await fs.move(filePath, fileDir, { overwrite: true });\n }\n } else {\n fs.ensureDirSync(fileDir);\n }\n }\n } else await fs.mkdir(fileDir);\n};\n\nexport async function generateCourse() {\n const configFile = path.join(process.cwd(), 'blueprint.yaml');\n if (fs.existsSync(configFile)) {\n const { name } = await inquirer.prompt({\n type: 'input',\n name: 'name',\n message: 'What is the name of the folder?',\n default: 'course'\n });\n const baseDir = name;\n const fileContents = fs.readFileSync(configFile, 'utf8');\n const courses: any = yaml.load(fileContents);\n const courseData: course = { ...courses };\n\n try {\n let configContent = getUserId();\n\n fs.ensureDir(baseDir, async () => {\n if (fs.existsSync(baseDir)) {\n const courseInfo = courseData.course;\n const meta: courseInfo = {\n title: baseDir,\n author: courseInfo.author,\n description: courseInfo.description,\n version: courseInfo.version,\n courseId: courseInfo.courseId,\n userId: configContent['sub']\n };\n\n try {\n await fs.writeJson(`${baseDir}/meta.json`, meta, {\n spaces: 2\n });\n await fs.writeFile(`${baseDir}/README.md`, '');\n } catch (e) {\n throw e;\n }\n }\n });\n\n if ('chapters' in courseData) {\n const chapters = courseData.chapters;\n await deleteFolder(baseDir, chapters);\n for (let i = 0; i < chapters.length; i++) {\n const chapter = chapters[i];\n const chapterDir = `${baseDir}/${(i + 1)\n .toString()\n .padStart(2, '0')}-${chapter.title.replace(/[:\\s]+/g, '-')}`;\n await updateCourse(baseDir, chapterDir, chapter, i);\n\n // Create meta.json for chapter\n const chapterMeta = {\n title: chapter.title,\n order: i + 1\n };\n\n await fs.writeJson(`${chapterDir}/meta.json`, chapterMeta, {\n spaces: 2\n });\n\n if ('lessons' in chapter) {\n const lessons = chapter.lessons;\n await deleteFolder(chapterDir, lessons);\n for (let j = 0; j < lessons.length; j++) {\n const lesson = lessons[j];\n const lessonDir = `${chapterDir}/${(j + 1)\n .toString()\n .padStart(2, '0')}-${lesson.title.replace(/[:\\s]+/g, '-')}`;\n await updateCourse(chapterDir, lessonDir, lesson, j);\n\n // Create meta.json for lesson\n const lessonMeta = {\n title: lesson.title,\n objectives: lesson.objectives,\n order: j + 1\n };\n await fs.writeJson(`${lessonDir}/meta.json`, lessonMeta, {\n spaces: 2\n });\n\n if ('assessments' in lesson) {\n const assessments = lesson.assessments;\n await deleteFolder(lessonDir, assessments);\n for (let k = 0; k < assessments.length; k++) {\n const assessment = assessments[k];\n const assessmentDir = `${lessonDir}/${(k + 1)\n .toString()\n .padStart(2, '0')}-${assessment.title.replace(\n /[:\\s]+/g,\n '-'\n )}`;\n await updateCourse(lessonDir, assessmentDir, assessment, k);\n\n // Create meta.json for assessment\n // const assessmentMeta = {\n // title: assessment.title,\n // description: assessment.description,\n // language: assessment.language,\n // solution: assessment.solution,\n // order: k + 1,\n // };\n //await fsExtra.writeJson(`${assessmentDir}/meta.json`, assessmentMeta, {spaces: 2});\n await fs.writeFile(`${assessmentDir}/README.md`, '');\n\n // Create app-a and app-b folders inside assessment folder\n await fs.ensureDir(`${assessmentDir}/app-a`);\n\n if (assessment.solution === true)\n await fs.ensureDir(`${assessmentDir}/app-b`);\n }\n } else {\n const assessmentDir = `${lessonDir}/${(1)\n .toString()\n .padStart(2, '0')}-${lesson.title.replace(/[:\\s]+/g, '-')}`;\n fs.ensureDirSync(assessmentDir);\n // await fsExtra.writeJson(`${assessmentDir}/meta.json`, \"\");\n await fs.writeFile(`${assessmentDir}/README.md`, '');\n // Create app-a folders inside assessment folder\n await fs.ensureDir(`${assessmentDir}/app-a/src/lib`);\n }\n }\n } else return error(`I can't find lessons in the chapter ${i + 1}`);\n }\n } else return error(\"You haven't chapters in your blueprint.yaml\");\n\n console.log('Folder structure created');\n } catch (err) {\n error('Error creating folder structure: ' + err);\n }\n } else return error('We need the blueprint.yaml file to create a course');\n}\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function initCourse(opt: any): void;
|
@@ -0,0 +1,58 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.initCourse = void 0;
|
4
|
+
const fs = require("fs-extra");
|
5
|
+
const inquirer_1 = require("inquirer");
|
6
|
+
const path = require("path");
|
7
|
+
const error_1 = require("../utils/error");
|
8
|
+
const getUserId_1 = require("../utils/getUserId");
|
9
|
+
function initCourse(opt) {
|
10
|
+
const directory = opt.directory;
|
11
|
+
const questions = [
|
12
|
+
{
|
13
|
+
type: 'input',
|
14
|
+
name: 'title',
|
15
|
+
message: 'What is the title of the Folder?',
|
16
|
+
default: path.basename(directory)
|
17
|
+
},
|
18
|
+
{
|
19
|
+
type: 'input',
|
20
|
+
name: 'author',
|
21
|
+
message: 'Author ?',
|
22
|
+
default: ''
|
23
|
+
},
|
24
|
+
{
|
25
|
+
type: 'input',
|
26
|
+
name: 'description',
|
27
|
+
message: 'What is the course description ?',
|
28
|
+
default: ''
|
29
|
+
},
|
30
|
+
{
|
31
|
+
type: 'input',
|
32
|
+
name: 'courseId',
|
33
|
+
message: 'What is the course id?',
|
34
|
+
default: ''
|
35
|
+
}
|
36
|
+
];
|
37
|
+
let configContent = (0, getUserId_1.getUserId)();
|
38
|
+
inquirer_1.default.prompt(questions).then((answers) => {
|
39
|
+
if (!answers.courseId || answers.courseId.length === 0)
|
40
|
+
return (0, error_1.error)('Course id must be not null');
|
41
|
+
const meta = {
|
42
|
+
title: answers.title,
|
43
|
+
author: answers.author,
|
44
|
+
description: answers.description,
|
45
|
+
courseId: answers.courseId,
|
46
|
+
userId: configContent['sub']
|
47
|
+
};
|
48
|
+
const filename = 'meta.json';
|
49
|
+
const filepath = path.join(directory, filename);
|
50
|
+
fs.writeFile(filepath, JSON.stringify(meta), (err) => {
|
51
|
+
if (err)
|
52
|
+
throw err;
|
53
|
+
console.log(`Le fichier ${filename} a été créé avec succès dans le répertoire ${directory} !`);
|
54
|
+
});
|
55
|
+
});
|
56
|
+
}
|
57
|
+
exports.initCourse = initCourse;
|
58
|
+
//# sourceMappingURL=init.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/command/init.ts"],"names":[],"mappings":";;;AAAA,+BAA+B;AAC/B,uCAAgC;AAChC,6BAA6B;AAC7B,0CAAuC;AACvC,kDAA+C;AAE/C,SAAgB,UAAU,CAAC,GAAG;IAC5B,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,CAAC;IAChC,MAAM,SAAS,GAAG;QAChB;YACE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,kCAAkC;YAC3C,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;SAClC;QACD;YACE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,UAAU;YACnB,OAAO,EAAE,EAAE;SACZ;QACD;YACE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,kCAAkC;YAC3C,OAAO,EAAE,EAAE;SACZ;QACD;YACE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,wBAAwB;YACjC,OAAO,EAAE,EAAE;SACZ;KACF,CAAC;IACF,IAAI,aAAa,GAAG,IAAA,qBAAS,GAAE,CAAC;IAChC,kBAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;QAC1C,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC;YACpD,OAAO,IAAA,aAAK,EAAC,4BAA4B,CAAC,CAAC;QAE7C,MAAM,IAAI,GAAG;YACX,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC;SAC7B,CAAC;QACF,MAAM,QAAQ,GAAG,WAAW,CAAC;QAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAEhD,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE;YACnD,IAAI,GAAG;gBAAE,MAAM,GAAG,CAAC;YACnB,OAAO,CAAC,GAAG,CACT,cAAc,QAAQ,8CAA8C,SAAS,IAAI,CAClF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAlDD,gCAkDC","sourcesContent":["import * as fs from 'fs-extra';\nimport inquirer from 'inquirer';\nimport * as path from 'path';\nimport { error } from '../utils/error';\nimport { getUserId } from '../utils/getUserId';\n\nexport function initCourse(opt) {\n const directory = opt.directory;\n const questions = [\n {\n type: 'input',\n name: 'title',\n message: 'What is the title of the Folder?',\n default: path.basename(directory)\n },\n {\n type: 'input',\n name: 'author',\n message: 'Author ?',\n default: ''\n },\n {\n type: 'input',\n name: 'description',\n message: 'What is the course description ?',\n default: ''\n },\n {\n type: 'input',\n name: 'courseId',\n message: 'What is the course id?',\n default: ''\n }\n ];\n let configContent = getUserId();\n inquirer.prompt(questions).then((answers) => {\n if (!answers.courseId || answers.courseId.length === 0)\n return error('Course id must be not null');\n\n const meta = {\n title: answers.title,\n author: answers.author,\n description: answers.description,\n courseId: answers.courseId,\n userId: configContent['sub']\n };\n const filename = 'meta.json';\n const filepath = path.join(directory, filename);\n\n fs.writeFile(filepath, JSON.stringify(meta), (err) => {\n if (err) throw err;\n console.log(\n `Le fichier ${filename} a été créé avec succès dans le répertoire ${directory} !`\n );\n });\n });\n}\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function login(): Promise<void>;
|
@@ -0,0 +1,116 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9
|
+
});
|
10
|
+
};
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
12
|
+
exports.login = void 0;
|
13
|
+
const axios_1 = require("axios");
|
14
|
+
const fs = require("fs-extra");
|
15
|
+
const inquirer_1 = require("inquirer");
|
16
|
+
const jwt_decode_1 = require("jwt-decode");
|
17
|
+
const os = require("node:os");
|
18
|
+
const path = require("path");
|
19
|
+
const error_1 = require("../utils/error");
|
20
|
+
function login() {
|
21
|
+
return __awaiter(this, void 0, void 0, function* () {
|
22
|
+
const questions = [
|
23
|
+
{
|
24
|
+
type: 'input',
|
25
|
+
name: 'email',
|
26
|
+
message: 'Email:',
|
27
|
+
validate: function (input) {
|
28
|
+
const emailRegex = /^\S+@\S+\.\S+$/;
|
29
|
+
if (input.toString().length === 0)
|
30
|
+
return 'Email not be null';
|
31
|
+
if (emailRegex.test(input)) {
|
32
|
+
return true;
|
33
|
+
}
|
34
|
+
return 'Please enter a valid email address.';
|
35
|
+
}
|
36
|
+
},
|
37
|
+
{
|
38
|
+
type: 'password',
|
39
|
+
name: 'password',
|
40
|
+
message: 'Password:',
|
41
|
+
mask: '*',
|
42
|
+
validate: (password) => {
|
43
|
+
if (!password || password.length === 0)
|
44
|
+
return (0, error_1.error)('Password must be not null');
|
45
|
+
return true;
|
46
|
+
}
|
47
|
+
}
|
48
|
+
];
|
49
|
+
const configPath = path.join(os.homedir(), '.procamp-config.json');
|
50
|
+
let configContent;
|
51
|
+
if (!fs.existsSync(configPath)) {
|
52
|
+
try {
|
53
|
+
fs.writeJSONSync(configPath, {
|
54
|
+
grant_type: 'password',
|
55
|
+
client_id: 'procamp-cli',
|
56
|
+
client_secret: 'ntVrw42swn4eD5nrIePMPg3R8kQFND6x'
|
57
|
+
}, { spaces: 2 });
|
58
|
+
}
|
59
|
+
catch (e) {
|
60
|
+
throw e;
|
61
|
+
}
|
62
|
+
}
|
63
|
+
try {
|
64
|
+
configContent = yield fs.readJSON(configPath);
|
65
|
+
}
|
66
|
+
catch (e) {
|
67
|
+
throw e;
|
68
|
+
}
|
69
|
+
inquirer_1.default.prompt(questions).then((answers) => {
|
70
|
+
const clientData = {
|
71
|
+
grant_type: configContent.grant_type,
|
72
|
+
client_id: configContent.client_id,
|
73
|
+
client_secret: configContent.client_secret
|
74
|
+
};
|
75
|
+
const data = Object.assign({ username: answers.email, password: answers.password }, clientData);
|
76
|
+
let bodyContent = '';
|
77
|
+
const entries = Object.entries(data);
|
78
|
+
for (let i = 0; i < entries.length; i++) {
|
79
|
+
const [name, value] = entries[i];
|
80
|
+
bodyContent += `${name}=${value}`;
|
81
|
+
if (i !== entries.length - 1) {
|
82
|
+
bodyContent += '&';
|
83
|
+
}
|
84
|
+
}
|
85
|
+
let headersList = {
|
86
|
+
Accept: '*/*',
|
87
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
88
|
+
};
|
89
|
+
axios_1.default
|
90
|
+
.post('https://auth.procamp.dev/realms/procamp/protocol/openid-connect/token', bodyContent, {
|
91
|
+
headers: headersList
|
92
|
+
})
|
93
|
+
.then((res) => {
|
94
|
+
let decoded;
|
95
|
+
if ('access_token' in res.data)
|
96
|
+
decoded = (0, jwt_decode_1.default)(res.data.access_token);
|
97
|
+
fs.writeJSON(configPath, Object.assign(Object.assign({}, clientData), decoded), { spaces: 2 }, (err) => {
|
98
|
+
if (err) {
|
99
|
+
console.error('Error writing config file:', err);
|
100
|
+
}
|
101
|
+
});
|
102
|
+
console.log('You are \x1b[32m%s\x1b[0m', 'connected');
|
103
|
+
return;
|
104
|
+
})
|
105
|
+
.catch((e) => {
|
106
|
+
if ('response' in e)
|
107
|
+
if ('data' in e.response)
|
108
|
+
if ('error_description' in e.response.data)
|
109
|
+
(0, error_1.error)(`${e.response.data.error_description}`);
|
110
|
+
return;
|
111
|
+
});
|
112
|
+
});
|
113
|
+
});
|
114
|
+
}
|
115
|
+
exports.login = login;
|
116
|
+
//# sourceMappingURL=login.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/command/login.ts"],"names":[],"mappings":"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","sourcesContent":["import axios from 'axios';\nimport * as fs from 'fs-extra';\nimport inquirer from 'inquirer';\nimport jwt_decode from 'jwt-decode';\nimport * as os from 'node:os';\nimport * as path from 'path';\nimport { error } from '../utils/error';\n\nexport async function login() {\n const questions = [\n {\n type: 'input',\n name: 'email',\n message: 'Email:',\n validate: function (input) {\n // Basic email format validation using a regular expression\n const emailRegex = /^\\S+@\\S+\\.\\S+$/;\n if (input.toString().length === 0) return 'Email not be null';\n\n if (emailRegex.test(input)) {\n return true;\n }\n\n return 'Please enter a valid email address.';\n }\n },\n {\n type: 'password',\n name: 'password',\n message: 'Password:',\n mask: '*',\n validate: (password) => {\n if (!password || password.length === 0)\n return error('Password must be not null');\n return true;\n }\n }\n ];\n\n const configPath = path.join(os.homedir(), '.procamp-config.json');\n let configContent;\n if (!fs.existsSync(configPath)) {\n try {\n fs.writeJSONSync(\n configPath,\n {\n grant_type: 'password',\n client_id: 'procamp-cli',\n client_secret: 'ntVrw42swn4eD5nrIePMPg3R8kQFND6x'\n },\n { spaces: 2 }\n );\n } catch (e) {\n throw e;\n }\n }\n try {\n configContent = await fs.readJSON(configPath);\n } catch (e) {\n throw e;\n }\n inquirer.prompt(questions).then((answers) => {\n const clientData = {\n grant_type: configContent.grant_type,\n client_id: configContent.client_id,\n client_secret: configContent.client_secret\n };\n const data = {\n username: answers.email,\n password: answers.password,\n ...clientData\n };\n let bodyContent = '';\n const entries = Object.entries(data);\n for (let i = 0; i < entries.length; i++) {\n const [name, value] = entries[i];\n bodyContent += `${name}=${value}`;\n if (i !== entries.length - 1) {\n bodyContent += '&';\n }\n }\n let headersList = {\n Accept: '*/*',\n 'Content-Type': 'application/x-www-form-urlencoded'\n };\n axios\n .post(\n 'https://auth.procamp.dev/realms/procamp/protocol/openid-connect/token',\n bodyContent,\n {\n headers: headersList\n }\n )\n .then((res) => {\n let decoded: object;\n\n if ('access_token' in res.data)\n decoded = jwt_decode(res.data.access_token);\n\n fs.writeJSON(\n configPath,\n {\n ...clientData,\n ...decoded\n },\n { spaces: 2 },\n (err) => {\n if (err) {\n console.error('Error writing config file:', err);\n }\n }\n );\n console.log('You are \\x1b[32m%s\\x1b[0m', 'connected');\n return;\n })\n .catch((e) => {\n if ('response' in e)\n if ('data' in e.response)\n if ('error_description' in e.response.data)\n error(`${e.response.data.error_description}`);\n\n return;\n });\n });\n}\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function createCourse(projectName: any): Promise<void>;
|
@@ -0,0 +1,41 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9
|
+
});
|
10
|
+
};
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
12
|
+
exports.createCourse = void 0;
|
13
|
+
const fs = require("fs-extra");
|
14
|
+
const inquirer_1 = require("inquirer");
|
15
|
+
const path = require("path");
|
16
|
+
const init_1 = require("./init");
|
17
|
+
function createCourse(projectName) {
|
18
|
+
return __awaiter(this, void 0, void 0, function* () {
|
19
|
+
const { confirm } = yield inquirer_1.default.prompt({
|
20
|
+
type: 'confirm',
|
21
|
+
message: `Are you sure you want to generate a new project named ${projectName} ?`,
|
22
|
+
name: 'confirm',
|
23
|
+
default: 'y'
|
24
|
+
});
|
25
|
+
if (!confirm) {
|
26
|
+
console.log('Aborted.');
|
27
|
+
return;
|
28
|
+
}
|
29
|
+
fs.mkdirSync(projectName, { recursive: true });
|
30
|
+
console.log(`${projectName} course project generated!`);
|
31
|
+
const pathfolder = path.join(process.cwd(), projectName);
|
32
|
+
if (fs.existsSync(pathfolder)) {
|
33
|
+
(0, init_1.initCourse)({
|
34
|
+
directory: pathfolder
|
35
|
+
});
|
36
|
+
return;
|
37
|
+
}
|
38
|
+
});
|
39
|
+
}
|
40
|
+
exports.createCourse = createCourse;
|
41
|
+
//# sourceMappingURL=new.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"new.js","sourceRoot":"","sources":["../../src/command/new.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,+BAA+B;AAC/B,uCAAgC;AAChC,6BAA6B;AAC7B,iCAAoC;AAEpC,SAAsB,YAAY,CAAC,WAAW;;QAC5C,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,kBAAQ,CAAC,MAAM,CAAC;YACxC,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,yDAAyD,WAAW,IAAI;YACjF,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,GAAG;SACb,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,EAAE;YACZ,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACxB,OAAO;SACR;QACD,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,GAAG,WAAW,4BAA4B,CAAC,CAAC;QACxD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;QACzD,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;YAC7B,IAAA,iBAAU,EAAC;gBACT,SAAS,EAAE,UAAU;aACtB,CAAC,CAAC;YACH,OAAO;SACR;IACH,CAAC;CAAA;AArBD,oCAqBC","sourcesContent":["import * as fs from 'fs-extra';\nimport inquirer from 'inquirer';\nimport * as path from 'path';\nimport { initCourse } from './init';\n\nexport async function createCourse(projectName) {\n const { confirm } = await inquirer.prompt({\n type: 'confirm',\n message: `Are you sure you want to generate a new project named ${projectName} ?`,\n name: 'confirm',\n default: 'y'\n });\n\n if (!confirm) {\n console.log('Aborted.');\n return;\n }\n fs.mkdirSync(projectName, { recursive: true });\n console.log(`${projectName} course project generated!`);\n const pathfolder = path.join(process.cwd(), projectName);\n if (fs.existsSync(pathfolder)) {\n initCourse({\n directory: pathfolder\n });\n return;\n }\n}\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function zipCourse(options: any): void;
|
@@ -0,0 +1,32 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.zipCourse = void 0;
|
4
|
+
const AdmZip = require("adm-zip");
|
5
|
+
const fs = require("fs-extra");
|
6
|
+
const path = require("path");
|
7
|
+
const error_1 = require("../utils/error");
|
8
|
+
function zipCourse(options) {
|
9
|
+
console.log(`Compressing ${options.directory}...`);
|
10
|
+
const output = '.output.zip';
|
11
|
+
const zip = new AdmZip();
|
12
|
+
const sourceDirectory = path.resolve(options.directory);
|
13
|
+
if (fs.existsSync(sourceDirectory)) {
|
14
|
+
const filesToIgnore = ['_MACOSX', 'node_modules'];
|
15
|
+
zip.addLocalFolder(sourceDirectory, '', function (filename) {
|
16
|
+
for (const files of filesToIgnore) {
|
17
|
+
if (filename.startsWith(files)) {
|
18
|
+
return false;
|
19
|
+
}
|
20
|
+
}
|
21
|
+
return !filename.startsWith('.');
|
22
|
+
});
|
23
|
+
const outputFilePath = path.join(sourceDirectory, output);
|
24
|
+
zip.writeZip(outputFilePath);
|
25
|
+
console.log(`${sourceDirectory} compressed to ${output} in directory ${sourceDirectory}`);
|
26
|
+
}
|
27
|
+
else {
|
28
|
+
(0, error_1.error)(`${options.directory} does not exist`);
|
29
|
+
}
|
30
|
+
}
|
31
|
+
exports.zipCourse = zipCourse;
|
32
|
+
//# sourceMappingURL=pack.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"pack.js","sourceRoot":"","sources":["../../src/command/pack.ts"],"names":[],"mappings":";;;AAAA,kCAAkC;AAClC,+BAA+B;AAC/B,6BAA6B;AAC7B,0CAAuC;AAEvC,SAAgB,SAAS,CAAC,OAAO;IAC/B,OAAO,CAAC,GAAG,CAAC,eAAe,OAAO,CAAC,SAAS,KAAK,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,aAAa,CAAC;IAC7B,MAAM,GAAG,GAAG,IAAI,MAAM,EAAE,CAAC;IACzB,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACxD,IAAI,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE;QAClC,MAAM,aAAa,GAAG,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;QAClD,GAAG,CAAC,cAAc,CAAC,eAAe,EAAE,EAAE,EAAE,UAAU,QAAQ;YACxD,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE;gBACjC,IAAI,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE;oBAC9B,OAAO,KAAK,CAAC;iBACd;aACF;YACD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QACH,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;QAC1D,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;QAC7B,OAAO,CAAC,GAAG,CACT,GAAG,eAAe,kBAAkB,MAAM,iBAAiB,eAAe,EAAE,CAC7E,CAAC;KACH;SAAM;QACL,IAAA,aAAK,EAAC,GAAG,OAAO,CAAC,SAAS,iBAAiB,CAAC,CAAC;KAC9C;AACH,CAAC;AAvBD,8BAuBC","sourcesContent":["import * as AdmZip from 'adm-zip';\nimport * as fs from 'fs-extra';\nimport * as path from 'path';\nimport { error } from '../utils/error';\n\nexport function zipCourse(options) {\n console.log(`Compressing ${options.directory}...`);\n const output = '.output.zip';\n const zip = new AdmZip();\n const sourceDirectory = path.resolve(options.directory);\n if (fs.existsSync(sourceDirectory)) {\n const filesToIgnore = ['_MACOSX', 'node_modules'];\n zip.addLocalFolder(sourceDirectory, '', function (filename) {\n for (const files of filesToIgnore) {\n if (filename.startsWith(files)) {\n return false;\n }\n }\n return !filename.startsWith('.');\n });\n const outputFilePath = path.join(sourceDirectory, output);\n zip.writeZip(outputFilePath);\n console.log(\n `${sourceDirectory} compressed to ${output} in directory ${sourceDirectory}`\n );\n } else {\n error(`${options.directory} does not exist`);\n }\n}\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function publishCourse(): Promise<void>;
|
@@ -0,0 +1,95 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9
|
+
});
|
10
|
+
};
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
12
|
+
exports.publishCourse = void 0;
|
13
|
+
const course_validator_1 = require("@procamp/course-validator");
|
14
|
+
const axios_1 = require("axios");
|
15
|
+
const FormData = require("form-data");
|
16
|
+
const fs = require("fs-extra");
|
17
|
+
const os = require("os");
|
18
|
+
const path = require("path");
|
19
|
+
const error_1 = require("../utils/error");
|
20
|
+
const pack_1 = require("./pack");
|
21
|
+
function publishCourse() {
|
22
|
+
return __awaiter(this, void 0, void 0, function* () {
|
23
|
+
const directory = process.cwd();
|
24
|
+
const filenameConf = path.join(directory, 'meta.json');
|
25
|
+
if (fs.existsSync(filenameConf)) {
|
26
|
+
const data = yield fs.readFile(filenameConf, { encoding: 'utf-8' });
|
27
|
+
const meta = JSON.parse(data);
|
28
|
+
if (meta.courseId && meta.courseId.length !== 0) {
|
29
|
+
const courseId = meta.courseId;
|
30
|
+
const filePathZip = path.join(directory, '.output.zip');
|
31
|
+
const configPath = path.join(os.homedir(), '.procamp-config.json');
|
32
|
+
let configContent;
|
33
|
+
if (fs.existsSync(configPath)) {
|
34
|
+
try {
|
35
|
+
configContent = yield fs.readJSON(configPath);
|
36
|
+
}
|
37
|
+
catch (e) {
|
38
|
+
throw e;
|
39
|
+
}
|
40
|
+
if (!('userID' in meta) || meta.userID.length !== 0) {
|
41
|
+
if ('sub' in configContent)
|
42
|
+
yield fs.writeJson(filenameConf, Object.assign(Object.assign({}, meta), { userId: configContent['sub'] }), { spaces: 2 });
|
43
|
+
}
|
44
|
+
}
|
45
|
+
else
|
46
|
+
return (0, error_1.error)("I don't find config file.Please log in ");
|
47
|
+
yield (0, course_validator_1.validateCourse)(directory);
|
48
|
+
const postZipfile = () => {
|
49
|
+
if (fs.existsSync(filePathZip)) {
|
50
|
+
const fileStream = fs.createReadStream(filePathZip);
|
51
|
+
const form = new FormData();
|
52
|
+
form.append('file', fileStream);
|
53
|
+
axios_1.default
|
54
|
+
.post(`https://course-manager.procamp.dev/api/courses/${courseId}`, form, {
|
55
|
+
headers: {
|
56
|
+
'x-api-key': configContent['api-key']
|
57
|
+
}
|
58
|
+
})
|
59
|
+
.then((response) => {
|
60
|
+
console.log(response.data);
|
61
|
+
})
|
62
|
+
.catch((err) => {
|
63
|
+
if ('response' in err)
|
64
|
+
if ('data' in err.response) {
|
65
|
+
const data = err.response.data;
|
66
|
+
if ('statusCode' in data && 'message' in data)
|
67
|
+
(0, error_1.error)('Error publishing folder: ' +
|
68
|
+
data.message +
|
69
|
+
'. Error ' +
|
70
|
+
data.statusCode);
|
71
|
+
}
|
72
|
+
});
|
73
|
+
}
|
74
|
+
};
|
75
|
+
if (!fs.existsSync(filePathZip)) {
|
76
|
+
(0, pack_1.zipCourse)({
|
77
|
+
directory: directory
|
78
|
+
});
|
79
|
+
postZipfile();
|
80
|
+
return;
|
81
|
+
}
|
82
|
+
return postZipfile();
|
83
|
+
}
|
84
|
+
else {
|
85
|
+
return (0, error_1.error)("Course Id key don't exist or null in meta.json.\n" +
|
86
|
+
'Please complete course id');
|
87
|
+
}
|
88
|
+
}
|
89
|
+
else {
|
90
|
+
return (0, error_1.error)('meta.json file does not exist');
|
91
|
+
}
|
92
|
+
});
|
93
|
+
}
|
94
|
+
exports.publishCourse = publishCourse;
|
95
|
+
//# sourceMappingURL=publish.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../src/command/publish.ts"],"names":[],"mappings":"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","sourcesContent":["import { validateCourse } from '@procamp/course-validator';\nimport axios from 'axios';\nimport * as FormData from 'form-data';\nimport * as fs from 'fs-extra';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { error } from '../utils/error';\nimport { zipCourse } from './pack';\n\nexport async function publishCourse() {\n const directory = process.cwd();\n const filenameConf = path.join(directory, 'meta.json');\n\n if (fs.existsSync(filenameConf)) {\n const data = await fs.readFile(filenameConf, { encoding: 'utf-8' });\n const meta = JSON.parse(data);\n if (meta.courseId && meta.courseId.length !== 0) {\n const courseId: string = meta.courseId;\n const filePathZip = path.join(directory, '.output.zip');\n const configPath = path.join(os.homedir(), '.procamp-config.json');\n let configContent: any;\n if (fs.existsSync(configPath)) {\n try {\n configContent = await fs.readJSON(configPath);\n } catch (e) {\n throw e;\n }\n if (!('userID' in meta) || meta.userID.length !== 0) {\n if ('sub' in configContent)\n await fs.writeJson(\n filenameConf,\n { ...meta, userId: configContent['sub'] },\n { spaces: 2 }\n );\n }\n } else return error(\"I don't find config file.Please log in \");\n\n await validateCourse(directory);\n const postZipfile = () => {\n if (fs.existsSync(filePathZip)) {\n const fileStream = fs.createReadStream(filePathZip);\n const form = new FormData();\n form.append('file', fileStream);\n axios\n .post(\n `https://course-manager.procamp.dev/api/courses/${courseId}`,\n form,\n {\n headers: {\n 'x-api-key': configContent['api-key']\n }\n }\n )\n .then((response) => {\n console.log(response.data);\n })\n .catch((err) => {\n if ('response' in err)\n if ('data' in err.response) {\n const data = err.response.data;\n if ('statusCode' in data && 'message' in data)\n error(\n 'Error publishing folder: ' +\n data.message +\n '. Error ' +\n data.statusCode\n );\n }\n });\n }\n };\n\n if (!fs.existsSync(filePathZip)) {\n zipCourse({\n directory: directory\n });\n postZipfile();\n return;\n }\n\n return postZipfile();\n } else {\n return error(\n \"Course Id key don't exist or null in meta.json.\\n\" +\n 'Please complete course id'\n );\n }\n } else {\n return error('meta.json file does not exist');\n }\n}\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function validate(): void;
|
@@ -0,0 +1,9 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.validate = void 0;
|
4
|
+
const course_validator_1 = require("@procamp/course-validator");
|
5
|
+
function validate() {
|
6
|
+
(0, course_validator_1.validateCourse)(process.cwd());
|
7
|
+
}
|
8
|
+
exports.validate = validate;
|
9
|
+
//# sourceMappingURL=validate.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/command/validate.ts"],"names":[],"mappings":";;;AAAA,gEAA2D;AAE3D,SAAgB,QAAQ;IACtB,IAAA,iCAAc,EAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;AAChC,CAAC;AAFD,4BAEC","sourcesContent":["import { validateCourse } from '@procamp/course-validator';\n\nexport function validate() {\n validateCourse(process.cwd());\n}\n"]}
|
package/dist/index.d.ts
ADDED
File without changes
|
package/dist/index.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"","sourcesContent":[""]}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
export interface assessments {
|
2
|
+
title: string;
|
3
|
+
description: string;
|
4
|
+
language: string;
|
5
|
+
solution: boolean;
|
6
|
+
}
|
7
|
+
export interface lessons {
|
8
|
+
title: string;
|
9
|
+
objectives: string[];
|
10
|
+
assessments?: assessments[];
|
11
|
+
}
|
12
|
+
export interface chapters {
|
13
|
+
title: string;
|
14
|
+
lessons: lessons[];
|
15
|
+
}
|
16
|
+
export interface courseInfo {
|
17
|
+
title: string;
|
18
|
+
author: string;
|
19
|
+
description: string;
|
20
|
+
version: string;
|
21
|
+
courseId: string;
|
22
|
+
userId?: string;
|
23
|
+
}
|
24
|
+
export interface course {
|
25
|
+
course: courseInfo;
|
26
|
+
chapters: chapters[];
|
27
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"course.js","sourceRoot":"","sources":["../../src/interfaces/course.ts"],"names":[],"mappings":"","sourcesContent":["export interface assessments {\n title: string;\n description: string;\n language: string;\n solution: boolean;\n}\nexport interface lessons {\n title: string;\n objectives: string[];\n assessments?: assessments[];\n}\nexport interface chapters {\n title: string;\n lessons: lessons[];\n}\n\nexport interface courseInfo {\n title: string;\n author: string;\n description: string;\n version: string;\n courseId: string;\n userId?: string;\n}\nexport interface course {\n course: courseInfo;\n chapters: chapters[];\n}\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function error(err: string): void;
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/utils/error.ts"],"names":[],"mappings":";;;AAAA,SAAgB,KAAK,CAAC,GAAW;IAC/B,OAAO,CAAC,KAAK,CAAC,uBAAuB,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;AACtD,CAAC;AAFD,sBAEC","sourcesContent":["export function error(err: string) {\n console.error('cmp \\x1b[31m%s\\x1b[0m', 'ERR!', err);\n}\n"]}
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare function getUserId(): any;
|
@@ -0,0 +1,15 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.getUserId = void 0;
|
4
|
+
const fs = require("fs-extra");
|
5
|
+
const os = require("os");
|
6
|
+
const path = require("path");
|
7
|
+
function getUserId() {
|
8
|
+
const configPath = path.join(os.homedir(), '.procamp-config.json');
|
9
|
+
if (fs.existsSync(configPath)) {
|
10
|
+
return fs.readJSONSync(configPath);
|
11
|
+
}
|
12
|
+
return;
|
13
|
+
}
|
14
|
+
exports.getUserId = getUserId;
|
15
|
+
//# sourceMappingURL=getUserId.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"getUserId.js","sourceRoot":"","sources":["../../src/utils/getUserId.ts"],"names":[],"mappings":";;;AAAA,+BAA+B;AAC/B,yBAAyB;AACzB,6BAA6B;AAE7B,SAAgB,SAAS;IACvB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,sBAAsB,CAAC,CAAC;IACnE,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;QAC7B,OAAO,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;KACpC;IACD,OAAO;AACT,CAAC;AAND,8BAMC","sourcesContent":["import * as fs from 'fs-extra';\nimport * as os from 'os';\nimport * as path from 'path';\n\nexport function getUserId() {\n const configPath = path.join(os.homedir(), '.procamp-config.json');\n if (fs.existsSync(configPath)) {\n return fs.readJSONSync(configPath);\n }\n return;\n}\n"]}
|
package/package.json
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
{
|
2
|
+
"name": "@procamp/cli",
|
3
|
+
"version": "0.0.1",
|
4
|
+
"description": "Procamp CLI",
|
5
|
+
"main": "dist/index.js",
|
6
|
+
"files": [
|
7
|
+
"dist/"
|
8
|
+
],
|
9
|
+
"bin": {
|
10
|
+
"camp": "dist/bin/index.js"
|
11
|
+
},
|
12
|
+
"scripts": {
|
13
|
+
"link:dev": "npm link --local",
|
14
|
+
"prepare": "husky install",
|
15
|
+
"build": "npm run clean && tsc",
|
16
|
+
"build:dev": "tsc -w",
|
17
|
+
"clean": "rimraf dist",
|
18
|
+
"release:patch": "npm run test && npm run build && npm version patch",
|
19
|
+
"postversion": "git push && git push --tags && npm publish",
|
20
|
+
"format": "prettier --write \"**/*.{js,ts,json}\"",
|
21
|
+
"test": "npm run clean && jest"
|
22
|
+
},
|
23
|
+
"keywords": [
|
24
|
+
"typescript",
|
25
|
+
"tsc"
|
26
|
+
],
|
27
|
+
"author": "Afrointelligence",
|
28
|
+
"license": "ISC",
|
29
|
+
"devDependencies": {
|
30
|
+
"@types/adm-zip": "^0.5.0",
|
31
|
+
"@types/fs-extra": "^11.0.1",
|
32
|
+
"@types/inquirer": "^9.0.3",
|
33
|
+
"@types/js-yaml": "^4.0.5",
|
34
|
+
"@types/node": "^18.16.4",
|
35
|
+
"@types/rimraf": "^4.0.5",
|
36
|
+
"husky": "^8.0.3",
|
37
|
+
"jwt-decode": "^3.1.2",
|
38
|
+
"prettier": "^2.8.8",
|
39
|
+
"rimraf": "^5.0.0",
|
40
|
+
"typescript": "^5.0.4"
|
41
|
+
},
|
42
|
+
"dependencies": {
|
43
|
+
"@procamp/course-validator": "^1.0.2",
|
44
|
+
"@types/jest": "^29.5.1",
|
45
|
+
"adm-zip": "^0.5.10",
|
46
|
+
"axios": "^1.4.0",
|
47
|
+
"commander": "^10.0.1",
|
48
|
+
"ejs": "^3.1.9",
|
49
|
+
"form-data": "^4.0.0",
|
50
|
+
"fs-extra": "^11.1.1",
|
51
|
+
"glob-promise": "^6.0.2",
|
52
|
+
"globby": "^11.1.0",
|
53
|
+
"inquirer": "^8.2.5",
|
54
|
+
"js-yaml": "^4.1.0",
|
55
|
+
"path": "^0.12.7",
|
56
|
+
"ts-jest": "^29.1.0"
|
57
|
+
}
|
58
|
+
}
|
package/readme.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Getting started with Cmp cli
|
2
|
+
|
3
|
+
This project was bootstrapped with [Cmp CLI](https://github.com/facebook/create-react-app)
|
4
|
+
|
5
|
+
### ENV
|
6
|
+
|
7
|
+
Copy content from .example.env to .env
|
8
|
+
## Available Scripts
|
9
|
+
|
10
|
+
You can create the course directory with:
|
11
|
+
### `cmp new`
|
12
|
+
|
13
|
+
In the course directory, you can run:
|
14
|
+
|
15
|
+
### `cmp init`
|
16
|
+
|
17
|
+
This command allows you to create a meta.json file that
|
18
|
+
contains race configurations such as the title, id .
|
19
|
+
|
20
|
+
### `cmp pack`
|
21
|
+
|
22
|
+
Archive the course, by default it archives
|
23
|
+
the current folder. The -d or --directory option
|
24
|
+
adds the path of the archived folder
|
25
|
+
|
26
|
+
### `cmp publish`
|
27
|
+
Publishes the course on the course manager platform. It uses the id in the meta.json
|
28
|
+
file for publishing the course
|
29
|
+
|
30
|
+
### `cmp g course`
|
31
|
+
Create course with blueprint.yaml
|
32
|
+
|