@procamp/cli 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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":";;;;;;;;;;;;AAAA,iCAA0B;AAC1B,+BAA+B;AAC/B,uCAAgC;AAChC,2CAAoC;AACpC,8BAA8B;AAC9B,6BAA6B;AAC7B,0CAAuC;AAEvC,SAAsB,KAAK;;QACzB,MAAM,SAAS,GAAG;YAChB;gBACE,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,QAAQ;gBACjB,QAAQ,EAAE,UAAU,KAAK;oBAEvB,MAAM,UAAU,GAAG,gBAAgB,CAAC;oBACpC,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC,MAAM,KAAK,CAAC;wBAAE,OAAO,mBAAmB,CAAC;oBAE9D,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;wBAC1B,OAAO,IAAI,CAAC;qBACb;oBAED,OAAO,qCAAqC,CAAC;gBAC/C,CAAC;aACF;YACD;gBACE,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,WAAW;gBACpB,IAAI,EAAE,GAAG;gBACT,QAAQ,EAAE,CAAC,QAAQ,EAAE,EAAE;oBACrB,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;wBACpC,OAAO,IAAA,aAAK,EAAC,2BAA2B,CAAC,CAAC;oBAC5C,OAAO,IAAI,CAAC;gBACd,CAAC;aACF;SACF,CAAC;QAEF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,sBAAsB,CAAC,CAAC;QACnE,IAAI,aAAa,CAAC;QAClB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;YAC9B,IAAI;gBACF,EAAE,CAAC,aAAa,CACd,UAAU,EACV;oBACE,UAAU,EAAE,UAAU;oBACtB,SAAS,EAAE,aAAa;oBACxB,aAAa,EAAE,kCAAkC;iBAClD,EACD,EAAE,MAAM,EAAE,CAAC,EAAE,CACd,CAAC;aACH;YAAC,OAAO,CAAC,EAAE;gBACV,MAAM,CAAC,CAAC;aACT;SACF;QACD,IAAI;YACF,aAAa,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;SAC/C;QAAC,OAAO,CAAC,EAAE;YACV,MAAM,CAAC,CAAC;SACT;QACD,kBAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;YAC1C,MAAM,UAAU,GAAG;gBACjB,UAAU,EAAE,aAAa,CAAC,UAAU;gBACpC,SAAS,EAAE,aAAa,CAAC,SAAS;gBAClC,aAAa,EAAE,aAAa,CAAC,aAAa;aAC3C,CAAC;YACF,MAAM,IAAI,mBACR,QAAQ,EAAE,OAAO,CAAC,KAAK,EACvB,QAAQ,EAAE,OAAO,CAAC,QAAQ,IACvB,UAAU,CACd,CAAC;YACF,IAAI,WAAW,GAAG,EAAE,CAAC;YACrB,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;gBACvC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;gBACjC,WAAW,IAAI,GAAG,IAAI,IAAI,KAAK,EAAE,CAAC;gBAClC,IAAI,CAAC,KAAK,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;oBAC5B,WAAW,IAAI,GAAG,CAAC;iBACpB;aACF;YACD,IAAI,WAAW,GAAG;gBAChB,MAAM,EAAE,KAAK;gBACb,cAAc,EAAE,mCAAmC;aACpD,CAAC;YACF,eAAK;iBACF,IAAI,CACH,uEAAuE,EACvE,WAAW,EACX;gBACE,OAAO,EAAE,WAAW;aACrB,CACF;iBACA,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;gBACZ,IAAI,OAAe,CAAC;gBAEpB,IAAI,cAAc,IAAI,GAAG,CAAC,IAAI;oBAC5B,OAAO,GAAG,IAAA,oBAAU,EAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAE9C,EAAE,CAAC,SAAS,CACV,UAAU,kCAEL,UAAU,GACV,OAAO,GAEZ,EAAE,MAAM,EAAE,CAAC,EAAE,EACb,CAAC,GAAG,EAAE,EAAE;oBACN,IAAI,GAAG,EAAE;wBACP,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAAC;qBAClD;gBACH,CAAC,CACF,CAAC;gBACF,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,WAAW,CAAC,CAAC;gBACtD,OAAO;YACT,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;gBACX,IAAI,UAAU,IAAI,CAAC;oBACjB,IAAI,MAAM,IAAI,CAAC,CAAC,QAAQ;wBACtB,IAAI,mBAAmB,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI;4BACxC,IAAA,aAAK,EAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC;gBAEpD,OAAO;YACT,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACL,CAAC;CAAA;AApHD,sBAoHC","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
|
+
|