Skip to content

Commit

Permalink
refactor(client): fixed/hid type errors + extended isPoly (freeCodeCa…
Browse files Browse the repository at this point in the history
  • Loading branch information
ojeytonwilliams authored Feb 3, 2025
1 parent 25c964a commit d2effda
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 41 deletions.
12 changes: 6 additions & 6 deletions client/src/templates/Challenges/classic/saved-challenges.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,39 @@ import type {
import { mergeChallengeFiles } from './saved-challenges';

const jsChallenge = {
id: '1',
contents: 'js contents',
fileKey: 'jsFileKey',
name: 'name',
ext: 'js' as const,
head: 'head',
tail: 'tail',
history: [],
seed: 'original js contents'
seed: 'original js contents',
path: 'index.js'
};

const cssChallenge = {
id: '2',
contents: 'css contents',
fileKey: 'cssFileKey',
name: 'name',
ext: 'css' as const,
head: 'head',
tail: 'tail',
history: [],
seed: 'original css contents'
seed: 'original css contents',
path: 'styles.css'
};

const htmlChallenge = {
id: '3',
contents: 'html contents',
fileKey: 'htmlFileKey',
name: 'name',
ext: 'html' as const,
head: 'head',
tail: 'tail',
history: [],
seed: 'original html contents'
seed: 'original html contents',
path: 'index.html'
};

const savedJsChallenge: SavedChallengeFile = {
Expand Down
24 changes: 15 additions & 9 deletions client/src/templates/Challenges/utils/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ const jsWorkerExecutor = new WorkerExecutor(jsTestEvaluator, {
terminateWorker: true
});

type ApplyFunctionProps = (file: ChallengeFile) => Promise<ChallengeFile>;
type ApplyFunctionProps = (
file: ChallengeFile
) => Promise<ChallengeFile> | ChallengeFile;

const applyFunction =
(fn: ApplyFunctionProps) => async (file: ChallengeFile) => {
Expand Down Expand Up @@ -80,7 +82,7 @@ function buildSourceMap(challengeFiles: ChallengeFile[]): Source | undefined {
(sources, challengeFile) => {
sources.index += challengeFile.source || '';
sources.contents = sources.index;
sources.original[challengeFile.history[0]] = challengeFile.source;
sources.original[challengeFile.history[0]] = challengeFile.source ?? null;
sources.editableContents += challengeFile.editableContents || '';
return sources;
},
Expand Down Expand Up @@ -235,11 +237,11 @@ export async function buildDOMChallenge(
);
const isMultifile = challengeFiles.length > 1;

// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const transformers =
isMultifile && hasJsx
? getMultifileJSXTransformers(options)
: getTransformers(options);
// I'm reasonably sure this is fine, but we need to migrate transformers to
// TypeScript to be sure.
const transformers: ApplyFunctionProps[] = (isMultifile && hasJsx
? getMultifileJSXTransformers(options)
: getTransformers(options)) as unknown as ApplyFunctionProps[];

const pipeLine = composeFunctions(...transformers);
const usesTestRunner = options?.usesTestRunner ?? false;
Expand Down Expand Up @@ -274,7 +276,9 @@ export async function buildJSChallenge(
options: BuildOptions
): Promise<BuildResult> {
if (!challengeFiles) throw Error('No challenge files provided');
const pipeLine = composeFunctions(...getTransformers(options));
const pipeLine = composeFunctions(
...(getTransformers(options) as unknown as ApplyFunctionProps[])
);

const finalFiles = await Promise.all(challengeFiles?.map(pipeLine));
const error = finalFiles.find(({ error }) => error)?.error;
Expand Down Expand Up @@ -311,7 +315,9 @@ export async function buildPythonChallenge({
challengeFiles
}: BuildChallengeData): Promise<BuildResult> {
if (!challengeFiles) throw new Error('No challenge files provided');
const pipeLine = composeFunctions(...getPythonTransformers());
const pipeLine = composeFunctions(
...(getPythonTransformers() as unknown as ApplyFunctionProps[])
);
const finalFiles = await Promise.all(challengeFiles.map(pipeLine));
const error = finalFiles.find(({ error }) => error)?.error;

Expand Down
10 changes: 5 additions & 5 deletions client/utils/__fixtures__/challenges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ChallengeFile } from "../../src/redux/prop-types";

export const challengeFiles: ChallengeFile[] = [
{
id: '0',
contents: 'some ts',
error: null,
ext: 'ts',
Expand All @@ -14,9 +13,9 @@ export const challengeFiles: ChallengeFile[] = [
tail: '',
editableRegionBoundaries: [],
usesMultifileEditor: true,
path: 'index.ts',
},
{
id: '1',
contents: 'some css',
error: null,
ext: 'css',
Expand All @@ -28,9 +27,9 @@ export const challengeFiles: ChallengeFile[] = [
tail: '',
editableRegionBoundaries: [],
usesMultifileEditor: true,
path: 'styles.css',
},
{
id: '2',
contents: 'some html',
error: null,
ext: 'html',
Expand All @@ -42,9 +41,9 @@ export const challengeFiles: ChallengeFile[] = [
tail: '',
editableRegionBoundaries: [],
usesMultifileEditor: true,
path: 'index.html',
},
{
id: '3',
contents: 'some js',
error: null,
ext: 'js',
Expand All @@ -56,9 +55,9 @@ export const challengeFiles: ChallengeFile[] = [
tail: '',
editableRegionBoundaries: [],
usesMultifileEditor: true,
path: 'script.js',
},
{
id: '4',
contents: 'some jsx',
error: null,
ext: 'jsx',
Expand All @@ -70,5 +69,6 @@ export const challengeFiles: ChallengeFile[] = [
tail: '',
editableRegionBoundaries: [],
usesMultifileEditor: true,
path: 'index.jsx',
}
]
59 changes: 38 additions & 21 deletions shared/utils/polyvinyl.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
// originally based off of https://github.com/gulpjs/vinyl
import invariant from 'invariant';

export type Ext = 'js' | 'html' | 'css' | 'jsx' | 'ts';
const exts = ['js', 'html', 'css', 'jsx', 'ts'] as const;
export type Ext = (typeof exts)[number];

export type ChallengeFile = {
export type IncompleteChallengeFile = {
fileKey: string;
ext: Ext;
name: string;
contents: string;
};

export type ChallengeFile = IncompleteChallengeFile & {
editableRegionBoundaries?: number[];
editableContents?: string;
usesMultifileEditor?: boolean;
error?: unknown;
head: string;
tail: string;
seed: string;
contents: string;
source?: string | null;
id: string;
path: string;
history: string[];
};

Expand Down Expand Up @@ -65,25 +69,39 @@ export function createPoly<Rest>({
}

export function isPoly(poly: unknown): poly is ChallengeFile {
return (
!!poly &&
typeof poly === 'object' &&
'contents' in poly &&
function hasProperties(poly: unknown): poly is Record<string, unknown> {
return (
!!poly &&
typeof poly === 'object' &&
'contents' in poly &&
'name' in poly &&
'ext' in poly &&
'fileKey' in poly &&
'head' in poly &&
'tail' in poly &&
'seed' in poly &&
'history' in poly
);
}

const hasCorrectTypes = (poly: Record<string, unknown>): boolean =>
typeof poly.contents === 'string' &&
'name' in poly &&
typeof poly.name === 'string' &&
'ext' in poly &&
typeof poly.ext === 'string' &&
'history' in poly &&
Array.isArray(poly.history)
);
exts.includes(poly.ext as Ext) &&
typeof poly.fileKey === 'string' &&
typeof poly.head === 'string' &&
typeof poly.tail === 'string' &&
typeof poly.seed === 'string' &&
Array.isArray(poly.history);

return hasProperties(poly) && hasCorrectTypes(poly);
}

function checkPoly(poly: ChallengeFile) {
invariant(
isPoly(poly),
'function should receive a PolyVinyl, but got %s',
poly
JSON.stringify(poly)
);
}

Expand All @@ -102,15 +120,14 @@ export function setContent(

// This is currently only used to add back properties that are not stored in the
// database.
export function regeneratePathAndHistory(poly: ChallengeFile) {
const newPath = poly.name + '.' + poly.ext;
const newPoly = {
...poly,
export function regeneratePathAndHistory(file: IncompleteChallengeFile) {
const newPath = file.name + '.' + file.ext;
const newFile = {
...file,
path: newPath,
history: [newPath]
};
checkPoly(newPoly);
return newPoly;
return newFile;
}

async function clearHeadTail(polyP: Promise<ChallengeFile>) {
Expand Down

0 comments on commit d2effda

Please sign in to comment.