mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
refactor: (slightly) decentralize type checking (#64163)
This commit is contained in:
committed by
GitHub
parent
176bba6c15
commit
37ce134123
@@ -1,13 +1,13 @@
|
||||
import fs from 'fs';
|
||||
import { getProjectPath } from './helpers/get-project-info';
|
||||
import { getMetaData } from './helpers/project-metadata';
|
||||
import { getProjectPath } from './helpers/get-project-info.js';
|
||||
import { getMetaData } from './helpers/project-metadata.js';
|
||||
import {
|
||||
createStepFile,
|
||||
deleteStepFromMeta,
|
||||
getChallenge,
|
||||
insertStepIntoMeta,
|
||||
updateStepTitles
|
||||
} from './utils';
|
||||
} from './utils.js';
|
||||
|
||||
async function deleteStep(stepNum: number): Promise<void> {
|
||||
if (stepNum < 1) {
|
||||
|
||||
@@ -4,15 +4,14 @@
|
||||
*/
|
||||
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
import path, { join } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import ObjectID from 'bson-objectid';
|
||||
import { Meta } from './helpers/project-metadata';
|
||||
import { getArgValue } from './helpers/get-arg-value';
|
||||
import { join } from 'path';
|
||||
import { ObjectId } from 'bson';
|
||||
import { Meta } from './helpers/project-metadata.js';
|
||||
import { getArgValue } from './helpers/get-arg-value.js';
|
||||
import {
|
||||
getDailyJavascriptChallengeTemplate,
|
||||
getDailyPythonChallengeTemplate
|
||||
} from './helpers/get-challenge-template';
|
||||
} from './helpers/get-challenge-template.js';
|
||||
|
||||
const numberOfChallengesToCreate = getArgValue(process.argv);
|
||||
|
||||
@@ -20,9 +19,6 @@ if (numberOfChallengesToCreate > 10) {
|
||||
throw new Error('Are you sure you want to create that many challenges?');
|
||||
}
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const curriculumPath = join(__dirname, '../../curriculum');
|
||||
|
||||
const structureBlocksPath = join(curriculumPath, '/structure/blocks');
|
||||
@@ -58,7 +54,7 @@ for (let i = 0; i < numberOfChallengesToCreate; i++) {
|
||||
);
|
||||
}
|
||||
|
||||
const challengeId = new ObjectID();
|
||||
const challengeId = new ObjectId();
|
||||
const newChallengeNumber = numberOfJsChallenges + 1;
|
||||
|
||||
createDailyJsChallenge({
|
||||
@@ -74,7 +70,7 @@ for (let i = 0; i < numberOfChallengesToCreate; i++) {
|
||||
}
|
||||
|
||||
interface CreateDailyChallengeOptions {
|
||||
challengeId: ObjectID;
|
||||
challengeId: ObjectId;
|
||||
challengeNumber: number;
|
||||
meta: Meta;
|
||||
}
|
||||
@@ -89,7 +85,6 @@ function createDailyJsChallenge({
|
||||
challengeOrder: [
|
||||
...meta.challengeOrder,
|
||||
{
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
id: challengeId.toString(),
|
||||
title: `Challenge ${challengeNumber}: Placeholder`
|
||||
}
|
||||
@@ -105,7 +100,7 @@ function createDailyJsChallenge({
|
||||
|
||||
const jsChallengePath = join(
|
||||
jsChallengesPath,
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
|
||||
`${challengeId.toString()}.md`
|
||||
);
|
||||
|
||||
@@ -122,7 +117,6 @@ function createDailyPyChallenge({
|
||||
challengeOrder: [
|
||||
...meta.challengeOrder,
|
||||
{
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
id: challengeId.toString(),
|
||||
title: `Challenge ${challengeNumber}: Placeholder`
|
||||
}
|
||||
@@ -138,7 +132,7 @@ function createDailyPyChallenge({
|
||||
|
||||
const pyChallengePath = join(
|
||||
pyChallengesPath,
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
|
||||
`${challengeId.toString()}.md`
|
||||
);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getArgValue } from './helpers/get-arg-value';
|
||||
import { createEmptySteps } from './commands';
|
||||
import { getArgValue } from './helpers/get-arg-value.js';
|
||||
import { createEmptySteps } from './commands.js';
|
||||
|
||||
void createEmptySteps(getArgValue(process.argv));
|
||||
|
||||
@@ -2,35 +2,35 @@ import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import { prompt } from 'inquirer';
|
||||
import { format } from 'prettier';
|
||||
import ObjectID from 'bson-objectid';
|
||||
import { ObjectId } from 'bson';
|
||||
|
||||
import {
|
||||
SuperBlocks,
|
||||
languageSuperBlocks,
|
||||
chapterBasedSuperBlocks
|
||||
} from '../../shared/config/curriculum';
|
||||
} from '../../shared-dist/config/curriculum.js';
|
||||
|
||||
import { BlockLayouts, BlockLabel } from '../../shared/config/blocks';
|
||||
import { BlockLayouts, BlockLabel } from '../../shared-dist/config/blocks.js';
|
||||
import {
|
||||
getContentConfig,
|
||||
writeBlockStructure,
|
||||
getSuperblockStructure,
|
||||
createBlockFolder
|
||||
} from '../../curriculum/src/file-handler';
|
||||
import { superBlockToFilename } from '../../curriculum/src/build-curriculum';
|
||||
import { getBaseMeta } from './helpers/get-base-meta';
|
||||
import { createIntroMD } from './helpers/create-intro';
|
||||
createBlockFolder,
|
||||
getSuperblockStructure
|
||||
} from '../../curriculum/src/file-handler.js';
|
||||
import { superBlockToFilename } from '../../curriculum/src/build-curriculum.js';
|
||||
import { getBaseMeta } from './helpers/get-base-meta.js';
|
||||
import { createIntroMD } from './helpers/create-intro.js';
|
||||
import {
|
||||
createDialogueFile,
|
||||
createQuizFile,
|
||||
getAllBlocks,
|
||||
validateBlockName
|
||||
} from './utils';
|
||||
} from './utils.js';
|
||||
import {
|
||||
updateSimpleSuperblockStructure,
|
||||
updateChapterModuleSuperblockStructure
|
||||
} from './helpers/create-project';
|
||||
import { getLangFromSuperBlock } from './helpers/get-lang-from-superblock';
|
||||
} from './helpers/create-project.js';
|
||||
import { getLangFromSuperBlock } from './helpers/get-lang-from-superblock.js';
|
||||
|
||||
const helpCategories = [
|
||||
'English',
|
||||
@@ -80,7 +80,7 @@ async function createLanguageBlock(
|
||||
await updateIntroJson(superBlock, block, title);
|
||||
|
||||
const challengeLang = getLangFromSuperBlock(superBlock);
|
||||
let challengeId: ObjectID;
|
||||
let challengeId: ObjectId;
|
||||
|
||||
if (blockLabel === BlockLabel.quiz) {
|
||||
challengeId = await createQuizChallenge(
|
||||
@@ -157,7 +157,7 @@ async function createMetaJson(
|
||||
block: string,
|
||||
title: string,
|
||||
helpCategory: string,
|
||||
challengeId: ObjectID,
|
||||
challengeId: ObjectId,
|
||||
blockLabel?: BlockLabel,
|
||||
blockLayout?: string
|
||||
) {
|
||||
@@ -178,7 +178,6 @@ async function createMetaJson(
|
||||
|
||||
newMeta.challengeOrder = [
|
||||
{
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
id: challengeId.toString(),
|
||||
title: challengeTitle
|
||||
}
|
||||
@@ -191,7 +190,7 @@ async function createDialogueChallenge(
|
||||
superBlock: SuperBlocks,
|
||||
block: string,
|
||||
challengeLang: string
|
||||
): Promise<ObjectID> {
|
||||
): Promise<ObjectId> {
|
||||
const { blockContentDir } = getContentConfig('english') as {
|
||||
blockContentDir: string;
|
||||
};
|
||||
@@ -210,7 +209,7 @@ async function createQuizChallenge(
|
||||
title: string,
|
||||
questionCount: number,
|
||||
challengeLang: string
|
||||
): Promise<ObjectID> {
|
||||
): Promise<ObjectId> {
|
||||
return createQuizFile({
|
||||
projectPath: await createBlockFolder(block),
|
||||
title: title,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import ObjectID from 'bson-objectid';
|
||||
import { getTemplate } from './helpers/get-challenge-template';
|
||||
import { newChallengePrompts } from './helpers/new-challenge-prompts';
|
||||
import { getProjectPath } from './helpers/get-project-info';
|
||||
import { getMetaData, updateMetaData } from './helpers/project-metadata';
|
||||
import { createChallengeFile } from './utils';
|
||||
import { ObjectId } from 'bson';
|
||||
import { getTemplate } from './helpers/get-challenge-template.js';
|
||||
import { newChallengePrompts } from './helpers/new-challenge-prompts.js';
|
||||
import { getProjectPath } from './helpers/get-project-info.js';
|
||||
import { getMetaData, updateMetaData } from './helpers/project-metadata.js';
|
||||
import { createChallengeFile } from './utils.js';
|
||||
|
||||
const createNextChallenge = async () => {
|
||||
const path = getProjectPath();
|
||||
@@ -11,14 +11,13 @@ const createNextChallenge = async () => {
|
||||
const options = await newChallengePrompts();
|
||||
const template = getTemplate(options.challengeType);
|
||||
|
||||
const challengeId = new ObjectID();
|
||||
const challengeId = new ObjectId();
|
||||
const challengeText = template({ ...options, challengeId });
|
||||
|
||||
createChallengeFile(options.dashedName, challengeText, path);
|
||||
|
||||
const meta = getMetaData();
|
||||
meta.challengeOrder.push({
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
id: challengeId.toString(),
|
||||
title: options.title
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getLastStep } from './helpers/get-last-step-file-number';
|
||||
import { insertStep } from './commands';
|
||||
import { getLastStep } from './helpers/get-last-step-file-number.js';
|
||||
import { insertStep } from './commands.js';
|
||||
|
||||
void insertStep(getLastStep().stepNum + 1);
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import ObjectID from 'bson-objectid';
|
||||
import { getTemplate } from './helpers/get-challenge-template';
|
||||
import { newTaskPrompts } from './helpers/new-task-prompts';
|
||||
import { getProjectPath } from './helpers/get-project-info';
|
||||
import { getMetaData, updateMetaData } from './helpers/project-metadata';
|
||||
import { ObjectId } from 'bson';
|
||||
import { getTemplate } from './helpers/get-challenge-template.js';
|
||||
import { newTaskPrompts } from './helpers/new-task-prompts.js';
|
||||
import { getProjectPath } from './helpers/get-project-info.js';
|
||||
import { getMetaData, updateMetaData } from './helpers/project-metadata.js';
|
||||
import {
|
||||
createChallengeFile,
|
||||
getChallenge,
|
||||
updateTaskMeta,
|
||||
updateTaskMarkdownFiles
|
||||
} from './utils';
|
||||
import { getInputType } from './helpers/get-input-type';
|
||||
} from './utils.js';
|
||||
import { getInputType } from './helpers/get-input-type.js';
|
||||
|
||||
const createNextTask = async () => {
|
||||
const { challengeType } = await newTaskPrompts();
|
||||
@@ -32,9 +32,9 @@ const createNextTask = async () => {
|
||||
|
||||
const path = getProjectPath();
|
||||
const template = getTemplate(options.challengeType);
|
||||
const challengeId = new ObjectID();
|
||||
const challengeId = new ObjectId();
|
||||
const challengeText = template({ ...options, challengeId });
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
|
||||
const challengeIdString = challengeId.toString();
|
||||
|
||||
createChallengeFile(challengeIdString, challengeText, path);
|
||||
|
||||
@@ -2,31 +2,31 @@ import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import { prompt } from 'inquirer';
|
||||
import { format } from 'prettier';
|
||||
import ObjectID from 'bson-objectid';
|
||||
import { ObjectId } from 'bson';
|
||||
|
||||
import {
|
||||
SuperBlocks,
|
||||
chapterBasedSuperBlocks
|
||||
} from '../../shared/config/curriculum';
|
||||
import { BlockLayouts, BlockLabel } from '../../shared/config/blocks';
|
||||
} from '../../shared-dist/config/curriculum.js';
|
||||
import { BlockLayouts, BlockLabel } from '../../shared-dist/config/blocks.js';
|
||||
import {
|
||||
createBlockFolder,
|
||||
writeBlockStructure
|
||||
} from '../../curriculum/src/file-handler';
|
||||
import { superBlockToFilename } from '../../curriculum/src/build-curriculum';
|
||||
} from '../../curriculum/src/file-handler.js';
|
||||
import { superBlockToFilename } from '../../curriculum/src/build-curriculum.js';
|
||||
import {
|
||||
createQuizFile,
|
||||
createStepFile,
|
||||
validateBlockName,
|
||||
getAllBlocks
|
||||
} from './utils';
|
||||
import { getBaseMeta } from './helpers/get-base-meta';
|
||||
import { createIntroMD } from './helpers/create-intro';
|
||||
} from './utils.js';
|
||||
import { getBaseMeta } from './helpers/get-base-meta.js';
|
||||
import { createIntroMD } from './helpers/create-intro.js';
|
||||
import {
|
||||
ChapterModuleSuperblockStructure,
|
||||
updateChapterModuleSuperblockStructure,
|
||||
updateSimpleSuperblockStructure
|
||||
} from './helpers/create-project';
|
||||
} from './helpers/create-project.js';
|
||||
|
||||
const helpCategories = [
|
||||
'HTML-CSS',
|
||||
@@ -181,7 +181,7 @@ async function createMetaJson(
|
||||
block: string,
|
||||
title: string,
|
||||
helpCategory: string,
|
||||
challengeId: ObjectID,
|
||||
challengeId: ObjectId,
|
||||
order?: number,
|
||||
blockLabel?: string,
|
||||
blockLayout?: string
|
||||
@@ -201,13 +201,13 @@ async function createMetaJson(
|
||||
newMeta.name = title;
|
||||
newMeta.dashedName = block;
|
||||
newMeta.helpCategory = helpCategory;
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
|
||||
newMeta.challengeOrder = [{ id: challengeId.toString(), title: 'Step 1' }];
|
||||
|
||||
await writeBlockStructure(block, newMeta);
|
||||
}
|
||||
|
||||
async function createFirstChallenge(block: string): Promise<ObjectID> {
|
||||
async function createFirstChallenge(block: string): Promise<ObjectId> {
|
||||
// TODO: would be nice if the extension made sense for the challenge, but, at
|
||||
// least until react I think they're all going to be html anyway.
|
||||
const challengeSeeds = [
|
||||
@@ -231,7 +231,7 @@ async function createQuizChallenge(
|
||||
block: string,
|
||||
title: string,
|
||||
questionCount: number
|
||||
): Promise<ObjectID> {
|
||||
): Promise<ObjectId> {
|
||||
return createQuizFile({
|
||||
projectPath: await createBlockFolder(block),
|
||||
title: title,
|
||||
|
||||
@@ -2,18 +2,18 @@ import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import { prompt } from 'inquirer';
|
||||
import { format } from 'prettier';
|
||||
import ObjectID from 'bson-objectid';
|
||||
import { ObjectId } from 'bson';
|
||||
|
||||
import { SuperBlocks } from '../../shared/config/curriculum';
|
||||
import { SuperBlocks } from '../../shared-dist/config/curriculum.js';
|
||||
import {
|
||||
createBlockFolder,
|
||||
writeBlockStructure
|
||||
} from '../../curriculum/src/file-handler';
|
||||
import { superBlockToFilename } from '../../curriculum/src/build-curriculum';
|
||||
import { createQuizFile, getAllBlocks, validateBlockName } from './utils';
|
||||
import { getBaseMeta } from './helpers/get-base-meta';
|
||||
import { createIntroMD } from './helpers/create-intro';
|
||||
import { updateSimpleSuperblockStructure } from './helpers/create-project';
|
||||
} from '../../curriculum/src/file-handler.js';
|
||||
import { superBlockToFilename } from '../../curriculum/src/build-curriculum.js';
|
||||
import { createQuizFile, getAllBlocks, validateBlockName } from './utils.js';
|
||||
import { getBaseMeta } from './helpers/get-base-meta.js';
|
||||
import { createIntroMD } from './helpers/create-intro.js';
|
||||
import { updateSimpleSuperblockStructure } from './helpers/create-project.js';
|
||||
|
||||
const helpCategories = [
|
||||
'HTML-CSS',
|
||||
@@ -93,13 +93,13 @@ async function createMetaJson(
|
||||
block: string,
|
||||
title: string,
|
||||
helpCategory: string,
|
||||
challengeId: ObjectID
|
||||
challengeId: ObjectId
|
||||
) {
|
||||
const newMeta = getBaseMeta('Quiz');
|
||||
newMeta.name = title;
|
||||
newMeta.dashedName = block;
|
||||
newMeta.helpCategory = helpCategory;
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
|
||||
newMeta.challengeOrder = [{ id: challengeId.toString(), title: title }];
|
||||
|
||||
await writeBlockStructure(block, newMeta);
|
||||
@@ -110,7 +110,7 @@ async function createQuizChallenge(
|
||||
block: string,
|
||||
title: string,
|
||||
questionCount: number
|
||||
): Promise<ObjectID> {
|
||||
): Promise<ObjectId> {
|
||||
return createQuizFile({
|
||||
projectPath: await createBlockFolder(block),
|
||||
title: title,
|
||||
|
||||
@@ -6,18 +6,17 @@
|
||||
* filename. Change the `challengeId` at the bottom to use the dashed name if
|
||||
* you want that.
|
||||
*/
|
||||
import ObjectID from 'bson-objectid';
|
||||
import { ObjectId } from 'bson';
|
||||
|
||||
import {
|
||||
getBlockStructure,
|
||||
writeBlockStructure
|
||||
} from '../../curriculum/src/file-handler';
|
||||
import { createChallengeFile } from './utils';
|
||||
import { getProjectPath } from './helpers/get-project-info';
|
||||
import { getBlock, type Meta } from './helpers/project-metadata';
|
||||
} from '../../curriculum/src/file-handler.js';
|
||||
import { createChallengeFile } from './utils.js';
|
||||
import { getProjectPath } from './helpers/get-project-info.js';
|
||||
import { getBlock, type Meta } from './helpers/project-metadata.js';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
const challengeId = new ObjectID().toString();
|
||||
const challengeId = new ObjectId().toString();
|
||||
|
||||
/***** Only change code below this line *****/
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { unlink } from 'fs/promises';
|
||||
import { prompt } from 'inquirer';
|
||||
import { getProjectPath } from './helpers/get-project-info';
|
||||
import { getMetaData, updateMetaData } from './helpers/project-metadata';
|
||||
import { getFileName } from './helpers/get-file-name';
|
||||
import { getProjectPath } from './helpers/get-project-info.js';
|
||||
import { getMetaData, updateMetaData } from './helpers/project-metadata.js';
|
||||
import { getFileName } from './helpers/get-file-name.js';
|
||||
|
||||
const deleteChallenge = async () => {
|
||||
const path = getProjectPath();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { deleteStep } from './commands';
|
||||
import { getArgValue } from './helpers/get-arg-value';
|
||||
import { deleteStep } from './commands.js';
|
||||
import { getArgValue } from './helpers/get-arg-value.js';
|
||||
|
||||
void deleteStep(getArgValue(process.argv));
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { unlink } from 'fs/promises';
|
||||
import { prompt } from 'inquirer';
|
||||
import { getProjectPath } from './helpers/get-project-info';
|
||||
import { getFileName } from './helpers/get-file-name';
|
||||
import { getProjectPath } from './helpers/get-project-info.js';
|
||||
import { getFileName } from './helpers/get-file-name.js';
|
||||
import {
|
||||
deleteChallengeFromMeta,
|
||||
updateTaskMarkdownFiles,
|
||||
updateTaskMeta
|
||||
} from './utils';
|
||||
import { isTaskChallenge } from './helpers/task-helpers';
|
||||
import { getMetaData } from './helpers/project-metadata';
|
||||
} from './utils.js';
|
||||
import { isTaskChallenge } from './helpers/task-helpers.js';
|
||||
import { getMetaData } from './helpers/project-metadata.js';
|
||||
|
||||
const deleteTask = async () => {
|
||||
const path = getProjectPath();
|
||||
|
||||
@@ -2,11 +2,11 @@ import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||
import {
|
||||
getSuperblockStructure,
|
||||
writeSuperblockStructure
|
||||
} from '../../../curriculum/src/file-handler';
|
||||
} from '../../../curriculum/src/file-handler.js';
|
||||
import {
|
||||
updateChapterModuleSuperblockStructure,
|
||||
updateSimpleSuperblockStructure
|
||||
} from './create-project';
|
||||
} from './create-project.js';
|
||||
|
||||
vi.mock('../../../curriculum/src/file-handler');
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
import {
|
||||
getSuperblockStructure,
|
||||
writeSuperblockStructure
|
||||
} from '../../../curriculum/src/file-handler';
|
||||
import { insertInto } from './utils';
|
||||
} from '../../../curriculum/src/file-handler.js';
|
||||
import { insertInto } from './utils.js';
|
||||
|
||||
export async function updateSimpleSuperblockStructure(
|
||||
block: string,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { getArgValue } from './get-arg-value';
|
||||
import { getArgValue } from './get-arg-value.js';
|
||||
|
||||
describe('getArgValue helper', () => {
|
||||
it('should throw if there no arguments', () => {
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
/* eslint-disable @typescript-eslint/no-base-to-string */
|
||||
import ObjectID from 'bson-objectid';
|
||||
import { ObjectId } from 'bson';
|
||||
|
||||
const sanitizeTitle = (title: string) => {
|
||||
return title.includes(':') || title.includes("'") ? `"${title}"` : title;
|
||||
};
|
||||
|
||||
interface ChallengeOptions {
|
||||
challengeId: ObjectID;
|
||||
challengeId: ObjectId;
|
||||
title: string;
|
||||
dashedName: string;
|
||||
challengeType: string;
|
||||
@@ -359,7 +358,7 @@ Do the assignment.
|
||||
`;
|
||||
|
||||
interface DailyCodingChallengeOptions {
|
||||
challengeId: ObjectID;
|
||||
challengeId: ObjectId;
|
||||
challengeNumber: number;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import fs from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import { getFileName } from './get-file-name';
|
||||
import { getFileName } from './get-file-name.js';
|
||||
|
||||
const basePath = join(process.cwd(), '__fixtures__');
|
||||
const commonPath = join(basePath, 'curriculum', 'challenges');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { readdir } from 'fs/promises';
|
||||
import matter from 'gray-matter';
|
||||
import { getProjectPath } from './get-project-info';
|
||||
import { getProjectPath } from './get-project-info.js';
|
||||
|
||||
export const getFileName = async (id: string): Promise<string | null> => {
|
||||
const path = getProjectPath();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { prompt } from 'inquirer';
|
||||
import { ChallengeLang } from '../../../shared/config/curriculum';
|
||||
import { challengeTypes } from '../../../shared/config/challenge-types';
|
||||
import { ChallengeLang } from '../../../shared-dist/config/curriculum.js';
|
||||
import { challengeTypes } from '../../../shared-dist/config/challenge-types.js';
|
||||
|
||||
export const getInputType = async (
|
||||
challengeType: string,
|
||||
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
ChallengeLang,
|
||||
SuperBlocks,
|
||||
superBlockToSpeechLang
|
||||
} from '../../../shared/config/curriculum';
|
||||
} from '../../../shared-dist/config/curriculum.js';
|
||||
|
||||
export const getLangFromSuperBlock = (
|
||||
superBlock: SuperBlocks
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { last } from 'lodash';
|
||||
import { getMetaData } from './project-metadata';
|
||||
import { getMetaData } from './project-metadata.js';
|
||||
|
||||
function getLastStep(): { stepNum: number } {
|
||||
const meta = getMetaData();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { getProjectName, getProjectPath } from './get-project-info';
|
||||
import { getProjectName, getProjectPath } from './get-project-info.js';
|
||||
|
||||
describe('getProjectPath helper', () => {
|
||||
it('should return the calling dir path', () => {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import ObjectID from 'bson-objectid';
|
||||
import { getStepTemplate } from './get-step-template';
|
||||
import { ObjectId } from 'bson';
|
||||
import { getStepTemplate } from './get-step-template.js';
|
||||
|
||||
const props = {
|
||||
challengeId: new ObjectID('60d4ebe4801158d1abe1b18f'),
|
||||
challengeId: new ObjectId('60d4ebe4801158d1abe1b18f'),
|
||||
challengeSeeds: [
|
||||
{
|
||||
contents: '',
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/no-base-to-string */
|
||||
import ObjectID from 'bson-objectid';
|
||||
import { insertErms } from './insert-erms';
|
||||
import { ObjectId } from 'bson';
|
||||
import { insertErms } from './insert-erms.js';
|
||||
|
||||
// Builds a block
|
||||
function getCodeBlock(label: string, content?: string) {
|
||||
@@ -21,7 +20,7 @@ ${content}`
|
||||
}
|
||||
|
||||
type StepOptions = {
|
||||
challengeId: ObjectID;
|
||||
challengeId: ObjectId;
|
||||
challengeSeeds: ChallengeSeed[];
|
||||
stepNum: number;
|
||||
challengeType?: number;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { insertErms } from './insert-erms';
|
||||
import { insertErms } from './insert-erms.js';
|
||||
|
||||
describe('insertErms helper', () => {
|
||||
const code = `<h1>Hello World</h1>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { prompt } from 'inquirer';
|
||||
import { challengeTypes } from '../../../shared/config/challenge-types';
|
||||
import { getLastStep } from './get-last-step-file-number';
|
||||
import { challengeTypes } from '../../../shared-dist/config/challenge-types.js';
|
||||
import { getLastStep } from './get-last-step-file-number.js';
|
||||
|
||||
export const newChallengePrompts = async (): Promise<{
|
||||
title: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { prompt } from 'inquirer';
|
||||
import { challengeTypes } from '../../../shared/config/challenge-types';
|
||||
import { challengeTypes } from '../../../shared-dist/config/challenge-types.js';
|
||||
|
||||
const taskChallenges = [
|
||||
challengeTypes.multipleChoice,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { join } from 'path';
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { getBlockStructure } from '../../../curriculum/src/file-handler';
|
||||
import { getMetaData } from './project-metadata';
|
||||
import { getBlockStructure } from '../../../curriculum/src/file-handler.js';
|
||||
import { getMetaData } from './project-metadata.js';
|
||||
|
||||
vi.mock('../../../curriculum/src/file-handler');
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ import path from 'path';
|
||||
import {
|
||||
getBlockStructure,
|
||||
writeBlockStructure
|
||||
} from '../../../curriculum/src/file-handler';
|
||||
import { getProjectPath } from './get-project-info';
|
||||
} from '../../../curriculum/src/file-handler.js';
|
||||
import { getProjectPath } from './get-project-info.js';
|
||||
|
||||
export type Meta = {
|
||||
name: string;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { insertInto } from './utils';
|
||||
import { insertInto } from './utils.js';
|
||||
|
||||
describe('insertInto', () => {
|
||||
it('should not modify the original array', () => {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import ObjectID from 'bson-objectid';
|
||||
import { ObjectId } from 'bson';
|
||||
import { prompt } from 'inquirer';
|
||||
import { getTemplate } from './helpers/get-challenge-template';
|
||||
import { newChallengePrompts } from './helpers/new-challenge-prompts';
|
||||
import { getProjectPath } from './helpers/get-project-info';
|
||||
import { getMetaData, updateMetaData } from './helpers/project-metadata';
|
||||
import { createChallengeFile } from './utils';
|
||||
import { getTemplate } from './helpers/get-challenge-template.js';
|
||||
import { newChallengePrompts } from './helpers/new-challenge-prompts.js';
|
||||
import { getProjectPath } from './helpers/get-project-info.js';
|
||||
import { getMetaData, updateMetaData } from './helpers/project-metadata.js';
|
||||
import { createChallengeFile } from './utils.js';
|
||||
|
||||
const insertChallenge = async () => {
|
||||
const path = getProjectPath();
|
||||
@@ -27,13 +27,12 @@ const insertChallenge = async () => {
|
||||
);
|
||||
|
||||
const template = getTemplate(options.challengeType);
|
||||
const challengeId = new ObjectID();
|
||||
const challengeId = new ObjectId();
|
||||
const challengeText = template({ ...options, challengeId });
|
||||
createChallengeFile(options.dashedName, challengeText, path);
|
||||
|
||||
const meta = getMetaData();
|
||||
meta.challengeOrder.splice(indexToInsert, 0, {
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
id: challengeId.toString(),
|
||||
title: options.title
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getArgValue } from './helpers/get-arg-value';
|
||||
import { insertStep } from './commands';
|
||||
import { getArgValue } from './helpers/get-arg-value.js';
|
||||
import { insertStep } from './commands.js';
|
||||
|
||||
void insertStep(getArgValue(process.argv));
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import ObjectID from 'bson-objectid';
|
||||
import { ObjectId } from 'bson';
|
||||
import { prompt } from 'inquirer';
|
||||
import { getTemplate } from './helpers/get-challenge-template';
|
||||
import { newTaskPrompts } from './helpers/new-task-prompts';
|
||||
import { getProjectPath } from './helpers/get-project-info';
|
||||
import { getTemplate } from './helpers/get-challenge-template.js';
|
||||
import { newTaskPrompts } from './helpers/new-task-prompts.js';
|
||||
import { getProjectPath } from './helpers/get-project-info.js';
|
||||
import {
|
||||
createChallengeFile,
|
||||
getChallenge,
|
||||
insertChallengeIntoMeta,
|
||||
updateTaskMeta,
|
||||
updateTaskMarkdownFiles
|
||||
} from './utils';
|
||||
import { getMetaData } from './helpers/project-metadata';
|
||||
import { getInputType } from './helpers/get-input-type';
|
||||
} from './utils.js';
|
||||
import { getMetaData } from './helpers/project-metadata.js';
|
||||
import { getInputType } from './helpers/get-input-type.js';
|
||||
|
||||
const insertChallenge = async () => {
|
||||
const challenges = getMetaData().challengeOrder;
|
||||
@@ -45,9 +45,9 @@ const insertChallenge = async () => {
|
||||
|
||||
const path = getProjectPath();
|
||||
const template = getTemplate(challengeType);
|
||||
const challengeId = new ObjectID();
|
||||
const challengeId = new ObjectId();
|
||||
const challengeText = template({ ...options, challengeId });
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
|
||||
const challengeIdString = challengeId.toString();
|
||||
|
||||
createChallengeFile(challengeIdString, challengeText, path);
|
||||
|
||||
@@ -28,10 +28,11 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"@total-typescript/ts-reset": "^0.6.1",
|
||||
"@types/glob": "^8.0.1",
|
||||
"@types/inquirer": "^8.2.5",
|
||||
"@vitest/ui": "^3.2.4",
|
||||
"bson-objectid": "2.0.4",
|
||||
"bson": "^7.0.0",
|
||||
"eslint": "^9.39.1",
|
||||
"glob": "^8.1.0",
|
||||
"gray-matter": "4.0.3",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { updateTaskMeta, updateTaskMarkdownFiles } from './utils';
|
||||
import { updateTaskMeta, updateTaskMarkdownFiles } from './utils.js';
|
||||
|
||||
const reorderTasks = async () => {
|
||||
await updateTaskMeta();
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
import '@total-typescript/ts-reset';
|
||||
@@ -1,3 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig-base.json"
|
||||
"extends": "../../tsconfig-base.json",
|
||||
"include": ["**/*.ts"],
|
||||
"compilerOptions": {
|
||||
"module": "node16",
|
||||
"moduleResolution": "node16"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { prompt } from 'inquirer';
|
||||
|
||||
import { getMetaData, updateMetaData } from './helpers/project-metadata';
|
||||
import { getMetaData, updateMetaData } from './helpers/project-metadata.js';
|
||||
|
||||
const updateChallengeOrder = async () => {
|
||||
const oldChallengeOrder = getMetaData().challengeOrder;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import { updateStepTitles } from './utils';
|
||||
import { updateStepTitles } from './utils.js';
|
||||
|
||||
updateStepTitles();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from 'fs';
|
||||
import path, { join } from 'path';
|
||||
import matter from 'gray-matter';
|
||||
import ObjectID from 'bson-objectid';
|
||||
import { ObjectId } from 'bson';
|
||||
import { vi, describe, it, expect, afterEach } from 'vitest';
|
||||
|
||||
vi.mock('fs', () => {
|
||||
@@ -22,9 +22,9 @@ vi.mock('gray-matter', () => {
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock('bson-objectid', () => {
|
||||
vi.mock('bson', () => {
|
||||
return {
|
||||
default: vi.fn(() => ({ toString: () => mockChallengeId }))
|
||||
ObjectId: vi.fn(() => ({ toString: () => mockChallengeId }))
|
||||
};
|
||||
});
|
||||
|
||||
@@ -46,15 +46,15 @@ vi.mock('./helpers/project-metadata', () => {
|
||||
});
|
||||
|
||||
const mockChallengeId = '60d35cf3fe32df2ce8e31b03';
|
||||
import { getStepTemplate } from './helpers/get-step-template';
|
||||
import { getStepTemplate } from './helpers/get-step-template.js';
|
||||
import {
|
||||
createChallengeFile,
|
||||
createStepFile,
|
||||
insertStepIntoMeta,
|
||||
updateStepTitles,
|
||||
validateBlockName
|
||||
} from './utils';
|
||||
import { updateMetaData } from './helpers/project-metadata';
|
||||
} from './utils.js';
|
||||
import { updateMetaData } from './helpers/project-metadata.js';
|
||||
|
||||
const block = 'utils-project';
|
||||
const projectPath = join(
|
||||
@@ -81,9 +81,8 @@ describe('Challenge utils helper scripts', () => {
|
||||
challengeType: 0
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
expect(step.toString()).toEqual(mockChallengeId);
|
||||
expect(ObjectID).toHaveBeenCalledTimes(1);
|
||||
expect(ObjectId).toHaveBeenCalledTimes(1);
|
||||
|
||||
// Internal tasks
|
||||
// - Should generate a template for the step that is being created
|
||||
@@ -144,7 +143,7 @@ describe('Challenge utils helper scripts', () => {
|
||||
|
||||
await insertStepIntoMeta({
|
||||
stepNum: 3,
|
||||
stepId: new ObjectID(mockChallengeId)
|
||||
stepId: new ObjectId(mockChallengeId)
|
||||
});
|
||||
|
||||
expect(updateMetaData).toHaveBeenCalledWith({
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import ObjectID from 'bson-objectid';
|
||||
import { ObjectId } from 'bson';
|
||||
import matter from 'gray-matter';
|
||||
import { uniq } from 'lodash';
|
||||
|
||||
import { challengeTypes } from '../../shared/config/challenge-types';
|
||||
import { parseCurriculumStructure } from '../../curriculum/src/build-curriculum';
|
||||
import { parseMDSync } from '../challenge-parser/parser';
|
||||
import { getMetaData, updateMetaData } from './helpers/project-metadata';
|
||||
import { getProjectPath } from './helpers/get-project-info';
|
||||
import { ChallengeSeed, getStepTemplate } from './helpers/get-step-template';
|
||||
import { challengeTypes } from '../../shared-dist/config/challenge-types.js';
|
||||
import { parseCurriculumStructure } from '../../curriculum/src/build-curriculum.js';
|
||||
import { parseMDSync } from '../challenge-parser/parser/index.js';
|
||||
import { getMetaData, updateMetaData } from './helpers/project-metadata.js';
|
||||
import { getProjectPath } from './helpers/get-project-info.js';
|
||||
import { ChallengeSeed, getStepTemplate } from './helpers/get-step-template.js';
|
||||
import {
|
||||
isTaskChallenge,
|
||||
getTaskNumberFromTitle
|
||||
} from './helpers/task-helpers';
|
||||
import { getTemplate } from './helpers/get-challenge-template';
|
||||
} from './helpers/task-helpers.js';
|
||||
import { getTemplate } from './helpers/get-challenge-template.js';
|
||||
|
||||
interface Options {
|
||||
stepNum: number;
|
||||
@@ -53,8 +53,8 @@ const createStepFile = ({
|
||||
challengeSeeds = [],
|
||||
isFirstChallenge = false,
|
||||
challengeLang
|
||||
}: Options): ObjectID => {
|
||||
const challengeId = new ObjectID();
|
||||
}: Options): ObjectId => {
|
||||
const challengeId = new ObjectId();
|
||||
|
||||
const template = getStepTemplate({
|
||||
challengeId,
|
||||
@@ -65,7 +65,6 @@ const createStepFile = ({
|
||||
challengeLang
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
fs.writeFileSync(`${projectPath}${challengeId.toString()}.md`, template);
|
||||
|
||||
return challengeId;
|
||||
@@ -85,8 +84,8 @@ const createQuizFile = ({
|
||||
dashedName,
|
||||
questionCount,
|
||||
challengeLang
|
||||
}: QuizOptions): ObjectID => {
|
||||
const challengeId = new ObjectID();
|
||||
}: QuizOptions): ObjectId => {
|
||||
const challengeId = new ObjectId();
|
||||
const challengeType = challengeTypes.quiz.toString();
|
||||
const template = getTemplate(challengeType);
|
||||
|
||||
@@ -98,7 +97,7 @@ const createQuizFile = ({
|
||||
questionCount,
|
||||
challengeLang
|
||||
});
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
|
||||
fs.writeFileSync(`${projectPath}${challengeId.toString()}.md`, quizText);
|
||||
return challengeId;
|
||||
};
|
||||
@@ -109,8 +108,8 @@ const createDialogueFile = ({
|
||||
}: {
|
||||
projectPath: string;
|
||||
challengeLang: string;
|
||||
}): ObjectID => {
|
||||
const challengeId = new ObjectID();
|
||||
}): ObjectId => {
|
||||
const challengeId = new ObjectId();
|
||||
const challengeType = challengeTypes.dialogue.toString();
|
||||
const template = getTemplate(challengeType);
|
||||
|
||||
@@ -121,19 +120,19 @@ const createDialogueFile = ({
|
||||
dashedName: 'dialogue-1-im-tom',
|
||||
challengeLang
|
||||
});
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
|
||||
fs.writeFileSync(`${projectPath}${challengeId.toString()}.md`, dialogueText);
|
||||
return challengeId;
|
||||
};
|
||||
|
||||
interface InsertOptions {
|
||||
stepNum: number;
|
||||
stepId: ObjectID;
|
||||
stepId: ObjectId;
|
||||
}
|
||||
|
||||
interface InsertChallengeOptions {
|
||||
index: number;
|
||||
id: ObjectID;
|
||||
id: ObjectId;
|
||||
title: string;
|
||||
}
|
||||
|
||||
@@ -145,7 +144,6 @@ async function insertChallengeIntoMeta({
|
||||
const existingMeta = getMetaData();
|
||||
const challengeOrder = [...existingMeta.challengeOrder];
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
challengeOrder.splice(index, 0, { id: id.toString(), title });
|
||||
await updateMetaData({ ...existingMeta, challengeOrder });
|
||||
}
|
||||
@@ -153,7 +151,7 @@ async function insertChallengeIntoMeta({
|
||||
async function insertStepIntoMeta({ stepNum, stepId }: InsertOptions) {
|
||||
const existingMeta = getMetaData();
|
||||
const oldOrder = [...existingMeta.challengeOrder];
|
||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||
|
||||
oldOrder.splice(stepNum - 1, 0, { id: stepId.toString(), title: '' });
|
||||
// rename all the files in challengeOrder
|
||||
const challengeOrder = oldOrder.map(({ id }, index) => ({
|
||||
|
||||
Reference in New Issue
Block a user