@academyjs/rover
Version:
Rover allows you to learn programming interactively.
166 lines • 7.64 kB
JavaScript
;
/**
* Copyright (c) AcademyJS and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.main = void 0;
require("source-map-support/register");
const commander_1 = require("commander");
const chalk_1 = __importDefault(require("chalk"));
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
const mocha_1 = __importDefault(require("./driver/mocha"));
const excercises_1 = __importDefault(require("./excercises"));
const handleRunComplete = (errors) => { };
const validateSolution = (handle, configuration) => __awaiter(void 0, void 0, void 0, function* () {
const driver = new mocha_1.default({
reporter: "spec",
});
/* Since `require` is invoked from `./driver`, we need to force prepend `..`
* to the excercise file path.
*/
driver.resolveFile = (file) => `../excercises/${file}`;
const index = excercises_1.default.indexOf(handle);
if (index < 0) {
console.log(`${chalk_1.default.redBright("[error]")} Cannot find excercise ${chalk_1.default.bold(handle)}. Please update to the latest version and try again.`);
return;
}
driver.addFile(excercises_1.default[index]);
driver.run(handleRunComplete);
});
const extractMeta = () => new Promise((resolve) => {
const handleComplete = (meta, suites) => {
resolve({ meta, suites });
};
const driver = new mocha_1.default({
dryRun: true,
reporter: "json_all",
reporterOption: {
onComplete: handleComplete,
},
});
/* Since `require` is invoked from `./driver`, we need to force prepend `..`
* to the excercise file path.
*/
driver.resolveFile = (file) => `../${file}`;
driver.addFiles(...excercises_1.default.map((excerciseFile) => `./excercises/${excerciseFile}`));
driver.run(handleRunComplete);
});
const generateMeta = (configuration) => __awaiter(void 0, void 0, void 0, function* () {
const { meta } = yield extractMeta();
const json = JSON.stringify(meta, null, 2);
if (configuration.file) {
try {
fs_1.default.mkdirSync(path_1.default.dirname(configuration.file), { recursive: true });
fs_1.default.writeFileSync(configuration.file, json);
}
catch (error) {
console.error(`${chalk_1.default.redBright("[error]")} Cannot write output to "${configuration.file}". (${error.message})\n`);
console.log(json);
}
}
else {
console.log(json);
}
});
const listExercises = (configuration) => __awaiter(void 0, void 0, void 0, function* () {
const { meta } = yield extractMeta();
const { suites } = meta.suites[0];
const filteredSuites = configuration.tags.length === 0
? suites
: suites.filter((suite) => suite.tags.some((tag) => configuration.tags.includes(tag)));
if (filteredSuites.length > 0) {
console.log();
for (let i = 0; i < filteredSuites.length; i++) {
const suite = filteredSuites[i];
console.log(` ${(i + 1 + ".").padEnd(4, " ")} ${chalk_1.default.yellowBright(suite.handle.padEnd(30, " "))}\n ${chalk_1.default.bold(suite.title)}\n ${suite.tags.join(", ")}\n`);
}
}
});
const showExercise = (configuration) => __awaiter(void 0, void 0, void 0, function* () {
const { handle } = configuration;
const { suites } = yield extractMeta();
const suite = suites[handle];
if (!suite) {
console.log(`${chalk_1.default.redBright("[error]")} Unknown excercise ${chalk_1.default.bold(handle)}`);
return;
}
console.log(`\n${chalk_1.default.yellowBright.bold(suite.handle)}\n\n${chalk_1.default.bold(suite.title)}\n\n${suite.description}\n\n`);
for (const test of suite.tests) {
console.log(` ${chalk_1.default.green("✔")} ${chalk_1.default.bold(test.title)}\n ${test.description}\n`);
}
});
const packageData = require("../../package");
const configureCommands = () => {
const program = new commander_1.Command();
program.version(packageData.version);
const submitCommand = new commander_1.Command();
submitCommand
.name("submit")
.argument("<handle>", "the handle for the exercise")
.option("--print-error", "print the standard error generated by the solution", true)
.option("--print-output", "print the standard output generated by the solution", true)
.alias("x")
.description("validate your solution and submit the results")
.action((handle) => __awaiter(void 0, void 0, void 0, function* () {
const configuration = Object.assign(Object.assign({}, program.opts()), submitCommand.opts());
yield validateSolution(handle, configuration);
}));
program.addCommand(submitCommand);
const listCommand = new commander_1.Command();
listCommand
.name("list")
.alias("ls")
.argument("[tags...]", "tags to filter the result by")
.description("list exercises")
.action((tags) => __awaiter(void 0, void 0, void 0, function* () {
const configuration = Object.assign(Object.assign({ tags }, program.opts()), listCommand.opts());
yield listExercises(configuration);
}));
program.addCommand(listCommand);
const showCommand = new commander_1.Command();
showCommand
.name("show")
.alias("s")
.argument("<handle>", "handle of the exercise to show")
.description("prints the details of an exercise")
.action((handle) => __awaiter(void 0, void 0, void 0, function* () {
const configuration = Object.assign(Object.assign({ handle }, program.opts()), showCommand.opts());
yield showExercise(configuration);
}));
program.addCommand(showCommand);
const metaCommand = new commander_1.Command();
metaCommand
.name("meta")
.argument("[file]", "the resulting output file (default: standard output stream)", null)
.alias("m")
.description("extract excercise metadata as JSON")
.action((file) => __awaiter(void 0, void 0, void 0, function* () {
const configuration = Object.assign(Object.assign({ file }, program.opts()), metaCommand.opts());
yield generateMeta(configuration);
}));
program.addCommand(metaCommand);
return program;
};
const main = () => {
console.log(chalk_1.default.bold(`rover ${packageData.version} ${chalk_1.default.greenBright("(https://academyjs.com/rover)")}`));
const program = configureCommands();
program.parse(process.argv);
};
exports.main = main;
//# sourceMappingURL=index.js.map