mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2025-12-19 18:18:27 -05:00
refactor: one eslint task per workspace (#63835)
This commit is contained in:
committed by
GitHub
parent
c9e83c5c6a
commit
1e0805fd72
4
.github/workflows/node.js-tests.yml
vendored
4
.github/workflows/node.js-tests.yml
vendored
@@ -68,9 +68,7 @@ jobs:
|
||||
- name: Lint Source Files
|
||||
run: |
|
||||
echo pnpm version $(pnpm -v)
|
||||
pnpm compile:ts
|
||||
pnpm run build:curriculum
|
||||
pnpm run lint
|
||||
pnpm turbo lint
|
||||
|
||||
# DONT REMOVE THIS JOB.
|
||||
# TODO: Refactor and use re-usable workflow and shared artifacts
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
const { ESLint } = require('eslint');
|
||||
|
||||
const cli = new ESLint();
|
||||
// if a lot of files are changed, it's faster to run prettier/eslint on the
|
||||
// whole project than to run them on each file separately
|
||||
module.exports = {
|
||||
'*.(js|ts|tsx)': async files => {
|
||||
const ignoredIds = await Promise.all(
|
||||
files.map(file => cli.isPathIgnored(file))
|
||||
);
|
||||
const lintableFiles = files.filter((_, i) => !ignoredIds[i]);
|
||||
|
||||
return [
|
||||
'eslint --max-warnings=0 --cache --fix ' + lintableFiles.join(' '),
|
||||
...files.map(filename => `prettier --write '${filename}'`)
|
||||
];
|
||||
},
|
||||
'*.!(js|ts|tsx|css)': files =>
|
||||
files.map(filename => `prettier --write --ignore-unknown '${filename}'`),
|
||||
|
||||
'./curriculum/challenges/**/*.md': files =>
|
||||
files.map(filename => `node ./tools/scripts/lint/index.js '${filename}'`),
|
||||
|
||||
'*.css': files => [
|
||||
...files.map(filename => `stylelint --fix '${filename}'`),
|
||||
...files.map(filename => `prettier --write '${filename}'`)
|
||||
]
|
||||
};
|
||||
7
.lintstagedrc.mjs
Normal file
7
.lintstagedrc.mjs
Normal file
@@ -0,0 +1,7 @@
|
||||
import { createLintStagedConfig } from '@freecodecamp/eslint-config/lintstaged';
|
||||
|
||||
export default {
|
||||
...createLintStagedConfig(import.meta.dirname),
|
||||
'./curriculum/challenges/**/*.md': files =>
|
||||
files.map(filename => `node ./tools/scripts/lint/index.js '${filename}'`)
|
||||
};
|
||||
4
api/.lintstagedrc.mjs
Normal file
4
api/.lintstagedrc.mjs
Normal file
@@ -0,0 +1,4 @@
|
||||
/* eslint-disable filenames-simple/naming-convention */
|
||||
import { createLintStagedConfig } from '@freecodecamp/eslint-config/lintstaged';
|
||||
|
||||
export default createLintStagedConfig(import.meta.dirname);
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable jsdoc/require-jsdoc */
|
||||
import { Static } from '@fastify/type-provider-typebox';
|
||||
import {
|
||||
ExamEnvironmentConfig,
|
||||
|
||||
36
api/eslint.config.js
Normal file
36
api/eslint.config.js
Normal file
@@ -0,0 +1,36 @@
|
||||
import { configTypeChecked, tsFiles } from '@freecodecamp/eslint-config/base';
|
||||
|
||||
import jsdoc from 'eslint-plugin-jsdoc';
|
||||
|
||||
/**
|
||||
* A shared ESLint configuration for the repository.
|
||||
*
|
||||
* @type {import("eslint").Linter.Config[]}
|
||||
* */
|
||||
export default [
|
||||
...configTypeChecked,
|
||||
{
|
||||
...jsdoc.configs['flat/recommended-typescript-error'],
|
||||
rules: {
|
||||
'jsdoc/require-jsdoc': [
|
||||
'error',
|
||||
{
|
||||
require: {
|
||||
ArrowFunctionExpression: true,
|
||||
ClassDeclaration: true,
|
||||
ClassExpression: true,
|
||||
FunctionDeclaration: true,
|
||||
FunctionExpression: true,
|
||||
MethodDefinition: true
|
||||
},
|
||||
|
||||
publicOnly: true
|
||||
}
|
||||
],
|
||||
|
||||
'jsdoc/require-description-complete-sentence': 'error',
|
||||
'jsdoc/tag-lines': 'off'
|
||||
},
|
||||
files: tsFiles
|
||||
}
|
||||
];
|
||||
@@ -40,6 +40,7 @@
|
||||
},
|
||||
"description": "The freeCodeCamp.org open-source codebase and curriculum",
|
||||
"devDependencies": {
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"@total-typescript/ts-reset": "0.5.1",
|
||||
"@types/jsonwebtoken": "9.0.5",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
@@ -48,6 +49,8 @@
|
||||
"@types/validator": "13.11.2",
|
||||
"@vitest/ui": "^3.2.4",
|
||||
"dotenv-cli": "7.3.0",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-plugin-jsdoc": "48.2.1",
|
||||
"jsdom": "^26.1.0",
|
||||
"msw": "^2.7.0",
|
||||
"prisma": "6.16.2",
|
||||
@@ -74,6 +77,7 @@
|
||||
"clean": "rm -rf dist",
|
||||
"develop": "tsx watch --clear-screen=false src/server.ts",
|
||||
"start": "FREECODECAMP_NODE_ENV=production node dist/server.js",
|
||||
"lint": "eslint --max-warnings 0",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"test:ui": "vitest --ui",
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable jsdoc/require-returns, jsdoc/require-param */
|
||||
import { type FastifyPluginCallbackTypebox } from '@fastify/type-provider-typebox';
|
||||
import { PrismaClientValidationError } from '@prisma/client/runtime/library.js';
|
||||
import { type FastifyInstance, type FastifyReply } from 'fastify';
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// TODO: enable this, since strings don't make good errors.
|
||||
/* eslint-disable @typescript-eslint/only-throw-error */
|
||||
/* eslint-disable jsdoc/require-returns, jsdoc/require-param */
|
||||
import {
|
||||
ExamEnvironmentAnswer,
|
||||
ExamEnvironmentConfig,
|
||||
|
||||
@@ -577,7 +577,6 @@ export const userRoutes: FastifyPluginCallbackTypebox = (
|
||||
done();
|
||||
};
|
||||
|
||||
// eslint-disable-next-line jsdoc/require-param, jsdoc/require-returns
|
||||
/**
|
||||
* Generate a new authorization token for the given user, and invalidates any existing tokens.
|
||||
*
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"include": ["**/*.ts"],
|
||||
"compilerOptions": {
|
||||
"target": "es2022",
|
||||
"module": "nodenext",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable jsdoc/require-jsdoc */
|
||||
import { beforeAll, afterAll, expect, vi } from 'vitest';
|
||||
import request from 'supertest';
|
||||
|
||||
@@ -46,13 +47,13 @@ export const getCookies = (setCookies: string[]): string => {
|
||||
* A wrapper around supertest that handles common setup for requests. Namely
|
||||
* setting the Origin header, cookies and CSRF token.
|
||||
*
|
||||
* @param resource - The URL of the resource to be requested
|
||||
* @param config - The configuration for the request
|
||||
* @param config.method - The HTTP method to be used
|
||||
* @param config.setCookies - The cookies to be set in the request
|
||||
* @param options - Additional options for the request
|
||||
* @param options.sendCSRFToken - Whether to send the CSRF token in the request (default: true)
|
||||
* @returns The request object
|
||||
* @param resource - The URL of the resource to be requested.
|
||||
* @param config - The configuration for the request.
|
||||
* @param config.method - The HTTP method to be used.
|
||||
* @param config.setCookies - The cookies to be set in the request.
|
||||
* @param options - Additional options for the request.
|
||||
* @param options.sendCSRFToken - Whether to send the CSRF token in the request (default: true).
|
||||
* @returns The request object.
|
||||
*/
|
||||
export function superRequest(
|
||||
resource: string,
|
||||
@@ -83,9 +84,9 @@ export function superRequest(
|
||||
* request function with the desired method and setCookies baked in.
|
||||
*
|
||||
* @param config
|
||||
* @param config.method - HTTP method
|
||||
* @param config.setCookies - Cookies to be set in the request
|
||||
* @returns A superRequest function with the desired method and setCookies
|
||||
* @param config.method - HTTP method.
|
||||
* @param config.setCookies - Cookies to be set in the request.
|
||||
* @returns A superRequest function with the desired method and setCookies.
|
||||
*/
|
||||
export function createSuperRequest(config: {
|
||||
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable filenames-simple/naming-convention */
|
||||
require('dotenv').config({ path: '../.env' });
|
||||
const config = {
|
||||
presets: [
|
||||
|
||||
4
client/.lintstagedrc.mjs
Normal file
4
client/.lintstagedrc.mjs
Normal file
@@ -0,0 +1,4 @@
|
||||
/* eslint-disable filenames-simple/naming-convention */
|
||||
import { createLintStagedConfig } from '@freecodecamp/eslint-config/lintstaged';
|
||||
|
||||
export default createLintStagedConfig(import.meta.dirname);
|
||||
78
client/eslint.config.mjs
Normal file
78
client/eslint.config.mjs
Normal file
@@ -0,0 +1,78 @@
|
||||
import {
|
||||
config,
|
||||
configTypeChecked,
|
||||
configReact,
|
||||
configTestingLibrary,
|
||||
jsFiles,
|
||||
tsFiles
|
||||
} from '@freecodecamp/eslint-config/base';
|
||||
import globals from 'globals';
|
||||
|
||||
import { defineConfig, globalIgnores } from 'eslint/config';
|
||||
|
||||
const baseLanguageOptions = {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.mocha,
|
||||
...globals.node,
|
||||
Promise: true,
|
||||
window: true,
|
||||
$: true,
|
||||
ga: true,
|
||||
jQuery: true,
|
||||
router: true,
|
||||
globalThis: true
|
||||
}
|
||||
};
|
||||
|
||||
const baseConfig = {
|
||||
settings: {
|
||||
react: {
|
||||
version: '16.4.2'
|
||||
},
|
||||
|
||||
'import/resolver': {
|
||||
typescript: true,
|
||||
node: true
|
||||
}
|
||||
},
|
||||
|
||||
rules: {
|
||||
'import/no-cycle': [
|
||||
2,
|
||||
{
|
||||
maxDepth: 2
|
||||
}
|
||||
],
|
||||
'react/prop-types': 'off',
|
||||
'react/jsx-no-useless-fragment': 'error'
|
||||
}
|
||||
};
|
||||
|
||||
// Order matters here; later configs can override settings in earlier ones.
|
||||
export default defineConfig(
|
||||
globalIgnores(['static', '.cache', 'public']),
|
||||
{
|
||||
files: jsFiles,
|
||||
extends: [configReact, configTestingLibrary, config],
|
||||
...baseConfig,
|
||||
languageOptions: {
|
||||
...baseLanguageOptions,
|
||||
|
||||
parserOptions: {
|
||||
babelOptions: {
|
||||
presets: ['@babel/preset-react'],
|
||||
configFile: './.babelrc.js'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
files: tsFiles,
|
||||
extends: [configReact, configTestingLibrary, configTypeChecked],
|
||||
...baseConfig,
|
||||
languageOptions: {
|
||||
...baseLanguageOptions
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -30,7 +30,7 @@
|
||||
"create:search-placeholder": "tsx ./tools/generate-search-placeholder",
|
||||
"predevelop": "pnpm run common-setup && pnpm run build:scripts --env development",
|
||||
"develop": "NODE_OPTIONS=\"--max-old-space-size=7168 --no-deprecation\" gatsby develop --inspect=9230",
|
||||
"lint": "tsx ./i18n/schema-validation.ts",
|
||||
"lint": "eslint --max-warnings 0",
|
||||
"serve": "gatsby serve -p 8000",
|
||||
"serve-ci": "serve -l 8000 -c serve.json public",
|
||||
"prestand-alone": "pnpm run prebuild",
|
||||
@@ -139,6 +139,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-syntax-dynamic-import": "7.8.3",
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"@testing-library/jest-dom": "^6.8.0",
|
||||
"@testing-library/react": "12.1.5",
|
||||
"@testing-library/react-hooks": "^8.0.1",
|
||||
@@ -169,6 +170,8 @@
|
||||
"babel-plugin-macros": "3.1.0",
|
||||
"core-js": "2.6.12",
|
||||
"dotenv": "16.4.5",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-plugin-flowtype": "^8.0.3",
|
||||
"gatsby-plugin-webpack-bundle-analyser-v2": "1.1.32",
|
||||
"i18next-fs-backend": "2.6.0",
|
||||
"joi": "17.12.2",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable filenames-simple/naming-convention */
|
||||
import { Router } from '@gatsbyjs/reach-router';
|
||||
import { withPrefix } from 'gatsby';
|
||||
import React from 'react';
|
||||
|
||||
4
curriculum/.lintstagedrc.mjs
Normal file
4
curriculum/.lintstagedrc.mjs
Normal file
@@ -0,0 +1,4 @@
|
||||
/* eslint-disable filenames-simple/naming-convention */
|
||||
import { createLintStagedConfig } from '@freecodecamp/eslint-config/lintstaged';
|
||||
|
||||
export default createLintStagedConfig(import.meta.dirname);
|
||||
26
curriculum/eslint.config.mjs
Normal file
26
curriculum/eslint.config.mjs
Normal file
@@ -0,0 +1,26 @@
|
||||
import { config } from '@freecodecamp/eslint-config/base';
|
||||
import { defineConfig } from 'eslint/config';
|
||||
import globals from 'globals';
|
||||
|
||||
/**
|
||||
* A shared ESLint configuration for the repository.
|
||||
*
|
||||
* @type {import("eslint").Linter.Config[]}
|
||||
* */
|
||||
export default defineConfig({
|
||||
extends: [config],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.mocha,
|
||||
...globals.node,
|
||||
Promise: true,
|
||||
window: true,
|
||||
$: true,
|
||||
ga: true,
|
||||
jQuery: true,
|
||||
router: true,
|
||||
globalThis: true
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -19,6 +19,7 @@
|
||||
"author": "freeCodeCamp <team@freecodecamp.org>",
|
||||
"scripts": {
|
||||
"build": "tsx ./src/generate/build-curriculum",
|
||||
"compile": "tsc --build --clean && tsc --build",
|
||||
"create-empty-steps": "CALLING_DIR=$INIT_CWD tsx --tsconfig ../tsconfig.json ../tools/challenge-helper-scripts/create-empty-steps",
|
||||
"create-next-challenge": "CALLING_DIR=$INIT_CWD tsx --tsconfig ../tsconfig.json ../tools/challenge-helper-scripts/create-next-challenge",
|
||||
"create-this-challenge": "CALLING_DIR=$INIT_CWD tsx --tsconfig ../tsconfig.json ../tools/challenge-helper-scripts/create-this-challenge",
|
||||
@@ -31,7 +32,8 @@
|
||||
"delete-step": "CALLING_DIR=$INIT_CWD tsx --tsconfig ../tsconfig.json ../tools/challenge-helper-scripts/delete-step",
|
||||
"delete-challenge": "CALLING_DIR=$INIT_CWD tsx --tsconfig ../tsconfig.json ../tools/challenge-helper-scripts/delete-challenge",
|
||||
"delete-task": "CALLING_DIR=$INIT_CWD tsx --tsconfig ../tsconfig.json ../tools/challenge-helper-scripts/delete-task",
|
||||
"lint": "tsx --tsconfig ../tsconfig.json src/lint-localized",
|
||||
"lint": "eslint --max-warnings 0",
|
||||
"lint-challenges": "tsx --tsconfig ../tsconfig.json src/lint-localized",
|
||||
"reorder-tasks": "CALLING_DIR=$INIT_CWD tsx --tsconfig ../tsconfig.json ../tools/challenge-helper-scripts/reorder-tasks",
|
||||
"update-challenge-order": "CALLING_DIR=$INIT_CWD tsx --tsconfig ../tsconfig.json ../tools/challenge-helper-scripts/update-challenge-order",
|
||||
"update-step-titles": "CALLING_DIR=$INIT_CWD tsx --tsconfig ../tsconfig.json ../tools/challenge-helper-scripts/update-step-titles",
|
||||
@@ -41,12 +43,14 @@
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.23.7",
|
||||
"@babel/register": "7.23.7",
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"@total-typescript/ts-reset": "^0.6.1",
|
||||
"@types/debug": "^4.1.12",
|
||||
"@types/js-yaml": "4.0.5",
|
||||
"@types/polka": "^0.5.7",
|
||||
"@types/string-similarity": "^4.0.2",
|
||||
"@vitest/ui": "^3.2.4",
|
||||
"eslint": "^9.39.1",
|
||||
"glob": "8.1.0",
|
||||
"joi": "17.12.2",
|
||||
"joi-objectid": "3.0.1",
|
||||
|
||||
4
e2e/.lintstagedrc.mjs
Normal file
4
e2e/.lintstagedrc.mjs
Normal file
@@ -0,0 +1,4 @@
|
||||
/* eslint-disable filenames-simple/naming-convention */
|
||||
import { createLintStagedConfig } from '@freecodecamp/eslint-config/lintstaged';
|
||||
|
||||
export default createLintStagedConfig(import.meta.dirname);
|
||||
@@ -16,9 +16,9 @@ test.beforeEach(async ({ page }) => {
|
||||
test.afterAll(
|
||||
async () =>
|
||||
await Promise.all([
|
||||
await execP('node ./tools/scripts/seed/seed-demo-user --certified-user'),
|
||||
await execP('node ./tools/scripts/seed/seed-surveys'),
|
||||
await execP('node ./tools/scripts/seed/seed-ms-username')
|
||||
execP('node ./tools/scripts/seed/seed-demo-user --certified-user'),
|
||||
execP('node ./tools/scripts/seed/seed-surveys'),
|
||||
execP('node ./tools/scripts/seed/seed-ms-username')
|
||||
])
|
||||
);
|
||||
|
||||
|
||||
12
e2e/eslint.config.js
Normal file
12
e2e/eslint.config.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import { configTypeChecked } from '@freecodecamp/eslint-config/base';
|
||||
|
||||
export default [
|
||||
...configTypeChecked,
|
||||
{
|
||||
rules: {
|
||||
'@typescript-eslint/no-unsafe-member-access': 'off',
|
||||
'@typescript-eslint/no-unsafe-call': 'off',
|
||||
'@typescript-eslint/no-unsafe-assignment': 'off'
|
||||
}
|
||||
}
|
||||
];
|
||||
14
e2e/package.json
Normal file
14
e2e/package.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "@freecodecamp/e2e",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"lint": "eslint --max-warnings 0"
|
||||
},
|
||||
"author": "freeCodeCamp <team@freecodecamp.org>",
|
||||
"license": "BSD-3-Clause",
|
||||
"packageManager": "pnpm@10.20.0",
|
||||
"devDependencies": {
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"eslint": "^9.39.1"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,13 @@
|
||||
import { baseConfig } from '@freecodecamp/eslint-config/base';
|
||||
import { configTypeChecked } from '@freecodecamp/eslint-config/base';
|
||||
import { defineConfig } from 'eslint/config';
|
||||
|
||||
export default baseConfig;
|
||||
export default defineConfig({
|
||||
// include all in root dir, but not subdirs:
|
||||
files: ['*.js', '*.ts', '*.mjs'],
|
||||
extends: [configTypeChecked],
|
||||
rules: {
|
||||
'@typescript-eslint/no-unsafe-member-access': 'off',
|
||||
'@typescript-eslint/no-unsafe-call': 'off',
|
||||
'@typescript-eslint/no-unsafe-assignment': 'off'
|
||||
}
|
||||
});
|
||||
|
||||
17
package.json
17
package.json
@@ -45,15 +45,13 @@
|
||||
"develop:client": "cd ./client && pnpm run develop",
|
||||
"develop:api": "cd ./api && pnpm run develop",
|
||||
"format": "run-s format:eslint format:prettier",
|
||||
"format:eslint": "eslint . --fix",
|
||||
"format:eslint": "eslint --fix",
|
||||
"format:prettier": "prettier --write .",
|
||||
"i18n-sync": "tsx ./tools/scripts/sync-i18n.ts",
|
||||
"knip": "npx -y knip@5 --include files",
|
||||
"knip:all": "npx -y knip@5 ",
|
||||
"prelint": "pnpm run -F=client predevelop",
|
||||
"lint": "NODE_OPTIONS=\"--max-old-space-size=7168\" npm-run-all compile:ts -p lint:*",
|
||||
"lint:challenges": "cd ./curriculum && pnpm run lint",
|
||||
"lint:js": "eslint --cache --max-warnings 0 .",
|
||||
"lint": "pnpm npm-run-all lint:*",
|
||||
"lint:challenges": "cd ./curriculum && pnpm run lint-challenges",
|
||||
"lint:ts": "tsc && tsc -p shared && tsc -p api && tsc -p client && tsc -p curriculum",
|
||||
"lint:prettier": "prettier --list-different .",
|
||||
"lint:css": "stylelint '**/*.css'",
|
||||
@@ -84,7 +82,8 @@
|
||||
"playwright:watch": "playwright test --ui-port=0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dotenv": "16.4.5"
|
||||
"dotenv": "16.4.5",
|
||||
"eslint": "^9.39.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
@@ -94,16 +93,12 @@
|
||||
"@types/lodash": "4.14.202",
|
||||
"@types/node": "20.12.8",
|
||||
"@types/testing-library__jest-dom": "^5.14.5",
|
||||
"@typescript-eslint/eslint-plugin": "8.24.0",
|
||||
"@typescript-eslint/parser": "8.23.0",
|
||||
"@vitest/eslint-plugin": "^1.3.12",
|
||||
"debug": "4.3.4",
|
||||
"eslint": "^9.39.1",
|
||||
"globals": "^15.14.0",
|
||||
"husky": "9.0.11",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"js-yaml": "3.14.1",
|
||||
"lint-staged": "^13.1.0",
|
||||
"lint-staged": "^16.2.7",
|
||||
"lodash": "4.17.21",
|
||||
"markdownlint": "0.33.0",
|
||||
"npm-run-all2": "5.0.2",
|
||||
|
||||
35
packages/eslint-config/.lintstagedrc.js
Normal file
35
packages/eslint-config/.lintstagedrc.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import { ESLint } from 'eslint';
|
||||
|
||||
export const createLintStagedConfig = cwd => {
|
||||
// cwd has to be passed to ESLint or it defaults to process.cwd(), i.e. the root
|
||||
// of the monorepo.
|
||||
const cli = new ESLint({ cwd });
|
||||
return {
|
||||
'*.(mjs|js|ts|tsx)': async files => {
|
||||
const ignoredIds = await Promise.all(
|
||||
files.map(file => cli.isPathIgnored(file))
|
||||
);
|
||||
|
||||
const lintableFiles = files.filter((_, i) => !ignoredIds[i]);
|
||||
const prettierCommand = [
|
||||
...files.map(filename => `prettier --write '${filename}'`)
|
||||
];
|
||||
|
||||
// There should be at least one lintable file if we reach here, but if not,
|
||||
// just run prettier.
|
||||
return lintableFiles.length === 0
|
||||
? prettierCommand
|
||||
: [
|
||||
'eslint --max-warnings=0 --cache --fix ' + lintableFiles.join(' '),
|
||||
...prettierCommand
|
||||
];
|
||||
},
|
||||
'*.!(mjs|js|ts|tsx|css)': files =>
|
||||
files.map(filename => `prettier --write --ignore-unknown '${filename}'`),
|
||||
|
||||
'*.css': files => [
|
||||
...files.map(filename => `stylelint --fix '${filename}'`),
|
||||
...files.map(filename => `prettier --write '${filename}'`)
|
||||
]
|
||||
};
|
||||
};
|
||||
@@ -1,147 +1,85 @@
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import path from 'node:path';
|
||||
|
||||
import { fixupConfigRules, fixupPluginRules } from '@eslint/compat';
|
||||
import js from '@eslint/js';
|
||||
import eslintConfigPrettier from 'eslint-config-prettier';
|
||||
import tseslint from 'typescript-eslint';
|
||||
import vitest from '@vitest/eslint-plugin';
|
||||
import { defineConfig, globalIgnores } from 'eslint/config';
|
||||
import noOnlyTests from 'eslint-plugin-no-only-tests';
|
||||
import filenamesSimple from 'eslint-plugin-filenames-simple';
|
||||
import globals from 'globals';
|
||||
import babelParser from '@babel/eslint-parser';
|
||||
import importPlugin from 'eslint-plugin-import';
|
||||
import jsxAllyPlugin from 'eslint-plugin-jsx-a11y';
|
||||
import prettierConfig from 'eslint-config-prettier';
|
||||
import { fixupConfigRules, fixupPluginRules } from '@eslint/compat';
|
||||
import reactPlugin from 'eslint-plugin-react';
|
||||
import jsxAllyPlugin from 'eslint-plugin-jsx-a11y';
|
||||
import importPlugin from 'eslint-plugin-import';
|
||||
import testingLibraryPlugin from 'eslint-plugin-testing-library';
|
||||
import vitest from '@vitest/eslint-plugin';
|
||||
import tsParser from '@typescript-eslint/parser';
|
||||
import tseslint from 'typescript-eslint';
|
||||
import jsdoc from 'eslint-plugin-jsdoc';
|
||||
import js from '@eslint/js';
|
||||
import babelParser from '@babel/eslint-parser'; // TODO: can we get away from using babel?
|
||||
|
||||
import { FlatCompat } from '@eslint/eslintrc';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const __dirname = import.meta.dirname;
|
||||
const compat = new FlatCompat({
|
||||
baseDirectory: __dirname,
|
||||
recommendedConfig: js.configs.recommended,
|
||||
allConfig: js.configs.all
|
||||
baseDirectory: __dirname
|
||||
});
|
||||
|
||||
export const baseConfig = tseslint.config(
|
||||
{
|
||||
ignores: [
|
||||
'client/static/**/*',
|
||||
'client/.cache/**/*',
|
||||
'client/public/**/*',
|
||||
'shared/**/*.js',
|
||||
'shared/**/*.d.ts',
|
||||
'docs/**/*.md',
|
||||
'**/playwright*.config.ts',
|
||||
'playwright/**/*',
|
||||
'shared-dist/**/*',
|
||||
'**/dist/**/*'
|
||||
]
|
||||
},
|
||||
export const jsFiles = ['**/*.js', '**/*.jsx', '**/*.mjs', '**/*.cjs'];
|
||||
export const tsFiles = ['**/*.ts', '**/*.tsx'];
|
||||
const testFiles = [
|
||||
'**/*.test.js',
|
||||
'**/*.test.jsx',
|
||||
'**/*.test.mjs',
|
||||
'**/*.test.cjs',
|
||||
'**/*.test.ts',
|
||||
'**/*.test.tsx'
|
||||
];
|
||||
|
||||
const base = defineConfig(
|
||||
globalIgnores(['dist', '.turbo']),
|
||||
js.configs.recommended,
|
||||
reactPlugin.configs['flat'].recommended,
|
||||
jsxAllyPlugin.flatConfigs.recommended,
|
||||
...fixupConfigRules(
|
||||
compat.extends(
|
||||
'plugin:react-hooks/recommended' // Note: at time of testing, upgrading to v5 creates false positives
|
||||
)
|
||||
),
|
||||
importPlugin.flatConfigs.recommended,
|
||||
// TODO: consider adding eslint-plugin-n ():
|
||||
// ...nodePlugin.configs["flat/mixed-esm-and-cjs"],
|
||||
prettierConfig,
|
||||
eslintConfigPrettier,
|
||||
{
|
||||
...vitest.configs.recommended,
|
||||
files: testFiles
|
||||
},
|
||||
{
|
||||
extends: [importPlugin.flatConfigs.recommended],
|
||||
settings: { 'import/resolver': { node: true, typescript: true } },
|
||||
rules: {
|
||||
// TODO: fix the errors, allow the rules.
|
||||
'import/no-named-as-default': 'off',
|
||||
'import/no-named-as-default-member': 'off'
|
||||
}
|
||||
},
|
||||
{
|
||||
plugins: {
|
||||
'no-only-tests': noOnlyTests,
|
||||
'filenames-simple': fixupPluginRules(filenamesSimple)
|
||||
},
|
||||
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.mocha,
|
||||
...globals.node,
|
||||
Promise: true,
|
||||
window: true,
|
||||
$: true,
|
||||
ga: true,
|
||||
jQuery: true,
|
||||
router: true,
|
||||
globalThis: true
|
||||
},
|
||||
|
||||
parser: babelParser,
|
||||
|
||||
parserOptions: {
|
||||
babelOptions: {
|
||||
presets: ['@babel/preset-react']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
settings: {
|
||||
react: {
|
||||
version: '16.4.2'
|
||||
},
|
||||
|
||||
'import/resolver': {
|
||||
typescript: true,
|
||||
node: true
|
||||
}
|
||||
},
|
||||
|
||||
// TODO: audit these rules and remove as many as possible, ideally we want
|
||||
// to rely on recommended configs.
|
||||
rules: {
|
||||
'import/no-unresolved': [
|
||||
2,
|
||||
{
|
||||
commonjs: true
|
||||
'filenames-simple/naming-convention': ['error'],
|
||||
'no-only-tests/no-only-tests': 'error'
|
||||
}
|
||||
],
|
||||
|
||||
'import/named': 'error',
|
||||
'import/no-named-as-default': 'off',
|
||||
'import/no-named-as-default-member': 'off',
|
||||
'import/order': 'error',
|
||||
|
||||
'import/no-cycle': [
|
||||
2,
|
||||
},
|
||||
{
|
||||
maxDepth: 2
|
||||
}
|
||||
],
|
||||
|
||||
'react/prop-types': 'off',
|
||||
'react/jsx-no-useless-fragment': 'error',
|
||||
'no-only-tests/no-only-tests': 'error',
|
||||
files: jsFiles,
|
||||
rules: {
|
||||
'no-unused-expressions': 'error', // This is so the js rules are more in line with the ts rules
|
||||
'filenames-simple/naming-convention': ['warn']
|
||||
'import/no-unresolved': [2, { commonjs: true }] // commonjs is necessary while we still use require()
|
||||
},
|
||||
languageOptions: {
|
||||
parser: babelParser,
|
||||
parserOptions: {
|
||||
requireConfigFile: false
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.ts?(x)'],
|
||||
extends: [
|
||||
tseslint.configs.recommended,
|
||||
// TODO: turn on type-aware rules
|
||||
// tseslint.configs.recommendedTypeChecked,
|
||||
importPlugin.flatConfigs['typescript']
|
||||
],
|
||||
|
||||
languageOptions: {
|
||||
parser: tsParser,
|
||||
|
||||
parserOptions: {
|
||||
projectService: true
|
||||
files: tsFiles,
|
||||
extends: [importPlugin.flatConfigs['typescript']],
|
||||
rules: {
|
||||
'import/no-unresolved': 'off' // handled by TS
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: tsFiles,
|
||||
rules: {
|
||||
'import/no-unresolved': 'off',
|
||||
'@typescript-eslint/naming-convention': 'off',
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
'warn',
|
||||
{
|
||||
@@ -151,71 +89,50 @@ export const baseConfig = tseslint.config(
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* A shared ESLint configuration for the repository.
|
||||
*
|
||||
* @type {import("eslint").Linter.Config[]}
|
||||
* */
|
||||
export const config = defineConfig(...base, {
|
||||
files: tsFiles,
|
||||
extends: [tseslint.configs.recommended]
|
||||
});
|
||||
|
||||
/**
|
||||
* A shared ESLint configuration with type aware linting
|
||||
*
|
||||
* @type {import("eslint").Linter.Config[]}
|
||||
* */
|
||||
export const configTypeChecked = defineConfig(
|
||||
...base,
|
||||
{
|
||||
files: [
|
||||
'client/**/*.ts?(x)',
|
||||
'api/**/*.ts',
|
||||
'shared/**/*.ts',
|
||||
'tools/client-plugins/**/*.ts',
|
||||
'tools/scripts/**/*.ts',
|
||||
'tools/challenge-helper-scripts/**/*.ts',
|
||||
'tools/challenge-auditor/**/*.ts',
|
||||
'e2e/**/*.ts'
|
||||
],
|
||||
files: tsFiles,
|
||||
extends: [tseslint.configs.recommendedTypeChecked]
|
||||
},
|
||||
{
|
||||
files: ['client/**/*.test.[jt]s?(x)'],
|
||||
|
||||
extends: [testingLibraryPlugin.configs['flat/react']]
|
||||
},
|
||||
{
|
||||
files: ['**/*.test.[jt]s?(x)'],
|
||||
plugins: { vitest },
|
||||
extends: [vitest.configs.recommended]
|
||||
},
|
||||
{
|
||||
files: ['e2e/*.ts'],
|
||||
|
||||
rules: {
|
||||
'@typescript-eslint/no-unsafe-member-access': 'off',
|
||||
'@typescript-eslint/no-unsafe-call': 'off',
|
||||
'@typescript-eslint/no-unsafe-assignment': 'off'
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
projectService: true
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['.lintstagedrc.js', '**/.babelrc.js', '**/404.tsx'],
|
||||
rules: {
|
||||
'filenames-simple/naming-convention': 'off'
|
||||
}
|
||||
},
|
||||
{
|
||||
extends: [
|
||||
jsdoc.configs['flat/recommended-typescript-error'],
|
||||
tseslint.configs.recommendedTypeChecked
|
||||
],
|
||||
files: ['**/api/src/**/*.ts'],
|
||||
|
||||
rules: {
|
||||
'jsdoc/require-jsdoc': [
|
||||
'error',
|
||||
{
|
||||
require: {
|
||||
ArrowFunctionExpression: true,
|
||||
ClassDeclaration: true,
|
||||
ClassExpression: true,
|
||||
FunctionDeclaration: true,
|
||||
FunctionExpression: true,
|
||||
MethodDefinition: true
|
||||
},
|
||||
|
||||
publicOnly: true
|
||||
}
|
||||
],
|
||||
|
||||
'jsdoc/require-description-complete-sentence': 'error',
|
||||
'jsdoc/tag-lines': 'off'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const configReact = [
|
||||
reactPlugin.configs['flat'].recommended,
|
||||
jsxAllyPlugin.flatConfigs.recommended,
|
||||
...fixupConfigRules(
|
||||
compat.extends(
|
||||
'plugin:react-hooks/recommended' // Note: at time of testing, upgrading to v5 creates false positives
|
||||
)
|
||||
)
|
||||
];
|
||||
|
||||
export const configTestingLibrary = defineConfig({
|
||||
files: testFiles,
|
||||
extends: [testingLibraryPlugin.configs['flat/react']]
|
||||
});
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
"./base": "./base.js"
|
||||
"./base": "./base.js",
|
||||
"./lintstaged": "./.lintstagedrc.js"
|
||||
},
|
||||
"author": "freeCodeCamp <team@freecodecamp.org>",
|
||||
"license": "BSD-3-Clause",
|
||||
@@ -14,6 +15,7 @@
|
||||
"@eslint/compat": "^1.2.6",
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@eslint/js": "^9.19.0",
|
||||
"@vitest/eslint-plugin": "^1.4.3",
|
||||
"eslint": "^9.39.1",
|
||||
"eslint-config-prettier": "10.0.1",
|
||||
"eslint-import-resolver-typescript": "^3.5.5",
|
||||
@@ -26,6 +28,6 @@
|
||||
"eslint-plugin-react-hooks": "4.6.0",
|
||||
"eslint-plugin-testing-library": "7.1.1",
|
||||
"typescript": "5.7.3",
|
||||
"typescript-eslint": "^8.23.0"
|
||||
"typescript-eslint": "^8.47.0"
|
||||
}
|
||||
}
|
||||
|
||||
3204
pnpm-lock.yaml
generated
3204
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -2,6 +2,7 @@ packages:
|
||||
- 'api'
|
||||
- 'client'
|
||||
- 'curriculum'
|
||||
- 'e2e'
|
||||
- 'shared'
|
||||
- 'tools/challenge-editor/api'
|
||||
- 'tools/challenge-editor/client'
|
||||
@@ -19,3 +20,6 @@ packageExtensions:
|
||||
'@testing-library/jest-dom':
|
||||
peerDependencies:
|
||||
vitest: '*'
|
||||
|
||||
hoistPattern:
|
||||
- '!*eslint*'
|
||||
|
||||
4
shared/.lintstagedrc.mjs
Normal file
4
shared/.lintstagedrc.mjs
Normal file
@@ -0,0 +1,4 @@
|
||||
/* eslint-disable filenames-simple/naming-convention */
|
||||
import { createLintStagedConfig } from '@freecodecamp/eslint-config/lintstaged';
|
||||
|
||||
export default createLintStagedConfig(import.meta.dirname);
|
||||
3
shared/eslint.config.js
Normal file
3
shared/eslint.config.js
Normal file
@@ -0,0 +1,3 @@
|
||||
import { configTypeChecked } from '@freecodecamp/eslint-config/base';
|
||||
|
||||
export default configTypeChecked;
|
||||
@@ -10,7 +10,9 @@
|
||||
"pnpm": ">=10"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "vitest"
|
||||
"test": "vitest",
|
||||
"compile": "tsc",
|
||||
"lint": "eslint --max-warnings 0"
|
||||
},
|
||||
"type": "module",
|
||||
"repository": {
|
||||
@@ -22,7 +24,9 @@
|
||||
},
|
||||
"homepage": "https://github.com/freeCodeCamp/freeCodeCamp#readme",
|
||||
"devDependencies": {
|
||||
"vitest": "^3.2.4",
|
||||
"@vitest/ui": "^3.2.4"
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"@vitest/ui": "^3.2.4",
|
||||
"eslint": "^9.39.1",
|
||||
"vitest": "^3.2.4"
|
||||
}
|
||||
}
|
||||
|
||||
4
tools/challenge-editor/api/.lintstagedrc.mjs
Normal file
4
tools/challenge-editor/api/.lintstagedrc.mjs
Normal file
@@ -0,0 +1,4 @@
|
||||
/* eslint-disable filenames-simple/naming-convention */
|
||||
import { createLintStagedConfig } from '@freecodecamp/eslint-config/lintstaged';
|
||||
|
||||
export default createLintStagedConfig(import.meta.dirname);
|
||||
3
tools/challenge-editor/api/eslint.config.mjs
Normal file
3
tools/challenge-editor/api/eslint.config.mjs
Normal file
@@ -0,0 +1,3 @@
|
||||
import { configTypeChecked } from '@freecodecamp/eslint-config/base';
|
||||
|
||||
export default configTypeChecked;
|
||||
@@ -1,11 +1,12 @@
|
||||
{
|
||||
"name": "@freecodecamp/challenge-editor",
|
||||
"name": "@freecodecamp/challenge-editor-api",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"description": "Editor to help with new challenge structure",
|
||||
"scripts": {
|
||||
"start": "tsx server.ts",
|
||||
"postinstall": "shx cp ./sample.env ./.env"
|
||||
"postinstall": "shx cp ./sample.env ./.env",
|
||||
"lint": "eslint --max-warnings 0"
|
||||
},
|
||||
"author": "freeCodeCamp",
|
||||
"license": "BSD-3-Clause",
|
||||
@@ -16,9 +17,11 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@total-typescript/ts-reset": "^0.6.1",
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"@types/cors": "^2.8.13",
|
||||
"@types/express": "4.17.21",
|
||||
"dotenv": "16.4.5",
|
||||
"eslint": "^9.39.1",
|
||||
"shx": "0.3.4",
|
||||
"typescript": "5.2.2"
|
||||
}
|
||||
|
||||
3
tools/challenge-editor/api/tsconfig.json
Normal file
3
tools/challenge-editor/api/tsconfig.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "../../../tsconfig-base.json"
|
||||
}
|
||||
@@ -58,15 +58,13 @@ export const getModules = async (
|
||||
|
||||
let modules: Module[] = [];
|
||||
|
||||
modules = await Promise.all(
|
||||
chapter.modules!.map(module => {
|
||||
modules = chapter.modules.map(module => {
|
||||
const modules = Object.entries(introData[superBlock]['modules']!);
|
||||
const moduleTrueName = modules.filter(
|
||||
x => x[0] === module.dashedName
|
||||
)[0][1];
|
||||
return { name: moduleTrueName, path: 'modules/' + module.dashedName };
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
modules: modules,
|
||||
|
||||
4
tools/challenge-editor/client/.lintstagedrc.mjs
Normal file
4
tools/challenge-editor/client/.lintstagedrc.mjs
Normal file
@@ -0,0 +1,4 @@
|
||||
/* eslint-disable filenames-simple/naming-convention */
|
||||
import { createLintStagedConfig } from '@freecodecamp/eslint-config/lintstaged';
|
||||
|
||||
export default createLintStagedConfig(import.meta.dirname);
|
||||
10
tools/challenge-editor/client/eslint.config.mjs
Normal file
10
tools/challenge-editor/client/eslint.config.mjs
Normal file
@@ -0,0 +1,10 @@
|
||||
import {
|
||||
configTypeChecked,
|
||||
configReact
|
||||
} from '@freecodecamp/eslint-config/base';
|
||||
|
||||
export default [
|
||||
...configTypeChecked,
|
||||
...configReact,
|
||||
{ settings: { react: { version: '17.0.2' } } }
|
||||
];
|
||||
@@ -14,14 +14,17 @@
|
||||
"scripts": {
|
||||
"start": "PORT=3300 vite",
|
||||
"build": "tsc && vite build",
|
||||
"lint": "eslint --max-warnings 0",
|
||||
"test": "echo \"no tests here yet\"",
|
||||
"postinstall": "shx cp ./sample.env ./.env"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"@types/codemirror": "5.60.15",
|
||||
"@types/react": "17.0.83",
|
||||
"@types/react-dom": "17.0.19",
|
||||
"@uiw/react-codemirror": "3.2.10",
|
||||
"eslint": "^9.39.1",
|
||||
"shx": "0.3.4"
|
||||
}
|
||||
}
|
||||
|
||||
4
tools/challenge-helper-scripts/.lintstagedrc.mjs
Normal file
4
tools/challenge-helper-scripts/.lintstagedrc.mjs
Normal file
@@ -0,0 +1,4 @@
|
||||
/* eslint-disable filenames-simple/naming-convention */
|
||||
import { createLintStagedConfig } from '@freecodecamp/eslint-config/lintstaged';
|
||||
|
||||
export default createLintStagedConfig(import.meta.dirname);
|
||||
3
tools/challenge-helper-scripts/eslint.config.mjs
Normal file
3
tools/challenge-helper-scripts/eslint.config.mjs
Normal file
@@ -0,0 +1,3 @@
|
||||
import { configTypeChecked } from '@freecodecamp/eslint-config/base';
|
||||
|
||||
export default configTypeChecked;
|
||||
@@ -23,13 +23,16 @@
|
||||
"create-project": "tsx create-project",
|
||||
"create-language-block": "tsx create-language-block",
|
||||
"create-quiz": "tsx create-quiz",
|
||||
"lint": "eslint --max-warnings 0",
|
||||
"test": "vitest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"@types/glob": "^8.0.1",
|
||||
"@types/inquirer": "^8.2.5",
|
||||
"@vitest/ui": "^3.2.4",
|
||||
"bson-objectid": "2.0.4",
|
||||
"eslint": "^9.39.1",
|
||||
"glob": "^8.1.0",
|
||||
"gray-matter": "4.0.3",
|
||||
"inquirer": "8.2.6",
|
||||
|
||||
3
tools/challenge-helper-scripts/tsconfig.json
Normal file
3
tools/challenge-helper-scripts/tsconfig.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "../../tsconfig-base.json"
|
||||
}
|
||||
4
tools/challenge-parser/.lintstagedrc.mjs
Normal file
4
tools/challenge-parser/.lintstagedrc.mjs
Normal file
@@ -0,0 +1,4 @@
|
||||
/* eslint-disable filenames-simple/naming-convention */
|
||||
import { createLintStagedConfig } from '@freecodecamp/eslint-config/lintstaged';
|
||||
|
||||
export default createLintStagedConfig(import.meta.dirname);
|
||||
13
tools/challenge-parser/eslint.config.mjs
Normal file
13
tools/challenge-parser/eslint.config.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
import { configTypeChecked } from '@freecodecamp/eslint-config/base';
|
||||
import globals from 'globals';
|
||||
|
||||
export default [
|
||||
...configTypeChecked,
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node // TODO: migrate to ESM and remove globals
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -19,6 +19,7 @@
|
||||
"author": "freeCodeCamp <team@freecodecamp.org>",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"lint": "eslint --max-warnings 0",
|
||||
"test": "vitest"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -54,6 +55,8 @@
|
||||
"unist-util-visit-children": "1.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"eslint": "^9.39.1",
|
||||
"unist-util-select": "3.0.4",
|
||||
"vitest": "^3.2.4"
|
||||
}
|
||||
|
||||
3
tools/challenge-parser/tsconfig.json
Normal file
3
tools/challenge-parser/tsconfig.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "../../tsconfig-base.json"
|
||||
}
|
||||
4
tools/client-plugins/browser-scripts/.lintstagedrc.mjs
Normal file
4
tools/client-plugins/browser-scripts/.lintstagedrc.mjs
Normal file
@@ -0,0 +1,4 @@
|
||||
/* eslint-disable filenames-simple/naming-convention */
|
||||
import { createLintStagedConfig } from '@freecodecamp/eslint-config/lintstaged';
|
||||
|
||||
export default createLintStagedConfig(import.meta.dirname);
|
||||
13
tools/client-plugins/browser-scripts/eslint.config.mjs
Normal file
13
tools/client-plugins/browser-scripts/eslint.config.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
import { configTypeChecked } from '@freecodecamp/eslint-config/base';
|
||||
import globals from 'globals';
|
||||
|
||||
export default [
|
||||
...configTypeChecked,
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node // TODO: migrate to ESM and remove globals
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -20,6 +20,7 @@
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"lint": "eslint --max-warnings 0",
|
||||
"build": "NODE_OPTIONS=\"--max-old-space-size=7168\" webpack -c webpack.config.cjs"
|
||||
},
|
||||
"type": "module",
|
||||
@@ -29,10 +30,12 @@
|
||||
"@babel/plugin-transform-runtime": "7.23.7",
|
||||
"@babel/preset-env": "7.23.7",
|
||||
"@babel/preset-typescript": "7.23.3",
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"@types/copy-webpack-plugin": "^8.0.1",
|
||||
"@typescript/vfs": "^1.6.0",
|
||||
"babel-loader": "8.3.0",
|
||||
"copy-webpack-plugin": "9.1.0",
|
||||
"eslint": "^9.39.1",
|
||||
"process": "0.11.10",
|
||||
"pyodide": "^0.23.3",
|
||||
"sass.js": "0.11.1",
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/* eslint-disable filenames-simple/naming-convention */
|
||||
import { createLintStagedConfig } from '@freecodecamp/eslint-config/lintstaged';
|
||||
|
||||
export default createLintStagedConfig(import.meta.dirname);
|
||||
@@ -0,0 +1,13 @@
|
||||
import { configTypeChecked } from '@freecodecamp/eslint-config/base';
|
||||
import globals from 'globals';
|
||||
|
||||
export default [
|
||||
...configTypeChecked,
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node // TODO: migrate to ESM and remove globals
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -8,6 +8,9 @@
|
||||
"node": ">=16",
|
||||
"pnpm": ">=10"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint --max-warnings 0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/freeCodeCamp/freeCodeCamp.git"
|
||||
@@ -17,5 +20,9 @@
|
||||
},
|
||||
"homepage": "https://github.com/freeCodeCamp/freeCodeCamp#readme",
|
||||
"author": "freeCodeCamp <team@freecodecamp.org>",
|
||||
"main": "gatsby-node.js"
|
||||
"main": "gatsby-node.js",
|
||||
"devDependencies": {
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"eslint": "^9.39.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/* eslint-disable filenames-simple/naming-convention */
|
||||
import { createLintStagedConfig } from '@freecodecamp/eslint-config/lintstaged';
|
||||
|
||||
export default createLintStagedConfig(import.meta.dirname);
|
||||
@@ -0,0 +1,13 @@
|
||||
import { configTypeChecked } from '@freecodecamp/eslint-config/base';
|
||||
import globals from 'globals';
|
||||
|
||||
export default [
|
||||
...configTypeChecked,
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node // TODO: migrate to ESM and remove globals
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -8,6 +8,9 @@
|
||||
"node": ">=16",
|
||||
"pnpm": ">=10"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint --max-warnings 0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/freeCodeCamp/freeCodeCamp.git"
|
||||
@@ -19,6 +22,8 @@
|
||||
"author": "freeCodeCamp <team@freecodecamp.org>",
|
||||
"main": "gatsby-node.js",
|
||||
"devDependencies": {
|
||||
"chokidar": "3.6.0"
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"chokidar": "3.6.0",
|
||||
"eslint": "^9.39.1"
|
||||
}
|
||||
}
|
||||
|
||||
4
tools/daily-challenges/.lintstagedrc.mjs
Normal file
4
tools/daily-challenges/.lintstagedrc.mjs
Normal file
@@ -0,0 +1,4 @@
|
||||
/* eslint-disable filenames-simple/naming-convention */
|
||||
import { createLintStagedConfig } from '@freecodecamp/eslint-config/lintstaged';
|
||||
|
||||
export default createLintStagedConfig(import.meta.dirname);
|
||||
3
tools/daily-challenges/eslint.config.js
Normal file
3
tools/daily-challenges/eslint.config.js
Normal file
@@ -0,0 +1,3 @@
|
||||
import { configTypeChecked } from '@freecodecamp/eslint-config/base';
|
||||
|
||||
export default configTypeChecked;
|
||||
@@ -126,12 +126,12 @@ export function combineChallenges({
|
||||
return challengeData;
|
||||
}
|
||||
|
||||
export function handleError(err: unknown, client: MongoClient) {
|
||||
export async function handleError(err: unknown, client: MongoClient) {
|
||||
if (err) {
|
||||
console.error('Oh noes!! Error seeding Daily Challenges.');
|
||||
console.error(err);
|
||||
try {
|
||||
client.close();
|
||||
await client.close();
|
||||
} catch {
|
||||
// no-op
|
||||
} finally {
|
||||
|
||||
@@ -3,13 +3,16 @@
|
||||
"version": "1.0.0",
|
||||
"main": "seed-daily-challenges.js",
|
||||
"scripts": {
|
||||
"seed-daily-challenges": "tsx seed-daily-challenges.ts"
|
||||
"seed-daily-challenges": "tsx seed-daily-challenges.ts",
|
||||
"lint": "eslint --max-warnings 0"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"description": "",
|
||||
"devDependencies": {
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"dotenv": "16.4.5",
|
||||
"eslint": "^9.39.1",
|
||||
"mongodb": "6.10.0",
|
||||
"tsx": "4.19.1",
|
||||
"typescript": "5.8.2"
|
||||
|
||||
3
tools/daily-challenges/tsconfig.json
Normal file
3
tools/daily-challenges/tsconfig.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "../../tsconfig-base.json"
|
||||
}
|
||||
4
tools/scripts/lint/.lintstagedrc.mjs
Normal file
4
tools/scripts/lint/.lintstagedrc.mjs
Normal file
@@ -0,0 +1,4 @@
|
||||
/* eslint-disable filenames-simple/naming-convention */
|
||||
import { createLintStagedConfig } from '@freecodecamp/eslint-config/lintstaged';
|
||||
|
||||
export default createLintStagedConfig(import.meta.dirname);
|
||||
13
tools/scripts/lint/eslint.config.mjs
Normal file
13
tools/scripts/lint/eslint.config.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
import { configTypeChecked } from '@freecodecamp/eslint-config/base';
|
||||
import globals from 'globals';
|
||||
|
||||
export default [
|
||||
...configTypeChecked,
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node // TODO: migrate to ESM and remove globals
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -15,10 +15,13 @@
|
||||
"homepage": "https://github.com/freeCodeCamp/freeCodeCamp#readme",
|
||||
"author": "freeCodeCamp <team@freecodecamp.org>",
|
||||
"scripts": {
|
||||
"lint": "eslint --max-warnings 0",
|
||||
"test": "vitest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"@vitest/ui": "^3.2.4",
|
||||
"eslint": "^9.39.1",
|
||||
"vitest": "^3.2.4"
|
||||
}
|
||||
}
|
||||
|
||||
3
tools/scripts/lint/tsconfig.json
Normal file
3
tools/scripts/lint/tsconfig.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "../../../tsconfig-base.json"
|
||||
}
|
||||
13
tools/scripts/seed-exams/eslint.config.mjs
Normal file
13
tools/scripts/seed-exams/eslint.config.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
import { configTypeChecked } from '@freecodecamp/eslint-config/base';
|
||||
import globals from 'globals';
|
||||
|
||||
export default [
|
||||
...configTypeChecked,
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node // TODO: migrate to ESM and remove globals
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -8,6 +8,9 @@
|
||||
"node": ">=16",
|
||||
"pnpm": ">=10"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint --max-warnings 0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/freeCodeCamp/freeCodeCamp.git"
|
||||
@@ -19,8 +22,10 @@
|
||||
"author": "freeCodeCamp <team@freecodecamp.org>",
|
||||
"main": "none",
|
||||
"devDependencies": {
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"debug": "4.3.4",
|
||||
"dotenv": "16.4.5",
|
||||
"eslint": "^9.39.1",
|
||||
"joi": "17.12.2",
|
||||
"joi-objectid": "3.0.1",
|
||||
"js-yaml": "4.1.0",
|
||||
|
||||
13
tools/scripts/seed/eslint.config.mjs
Normal file
13
tools/scripts/seed/eslint.config.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
import { configTypeChecked } from '@freecodecamp/eslint-config/base';
|
||||
import globals from 'globals';
|
||||
|
||||
export default [
|
||||
...configTypeChecked,
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node // TODO: migrate to ESM and remove globals
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -8,6 +8,9 @@
|
||||
"node": ">=16",
|
||||
"pnpm": ">=10"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint --max-warnings 0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/freeCodeCamp/freeCodeCamp.git"
|
||||
@@ -19,8 +22,10 @@
|
||||
"author": "freeCodeCamp <team@freecodecamp.org>",
|
||||
"main": "none",
|
||||
"devDependencies": {
|
||||
"@freecodecamp/eslint-config": "workspace:*",
|
||||
"debug": "4.3.4",
|
||||
"dotenv": "16.4.5",
|
||||
"eslint": "^9.39.1",
|
||||
"mongodb": "6.10.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"include": [
|
||||
"*.ts",
|
||||
"curriculum/*.test.ts",
|
||||
"e2e/**/*.ts",
|
||||
"tools/challenge-auditor/index.ts",
|
||||
|
||||
31
turbo.json
31
turbo.json
@@ -1,9 +1,34 @@
|
||||
{
|
||||
"$schema": "https://turborepo.com/schema.json",
|
||||
"tasks": {
|
||||
"lint": {
|
||||
"dependsOn": ["^lint"]
|
||||
"lint": {},
|
||||
"@freecodecamp/client#lint": {
|
||||
"dependsOn": [
|
||||
"@freecodecamp/curriculum#compile",
|
||||
"create:env",
|
||||
"build:scripts"
|
||||
]
|
||||
},
|
||||
"//#lint": {}
|
||||
"@freecodecamp/gatsby-source-challenges#lint": {
|
||||
"dependsOn": ["@freecodecamp/curriculum#compile"]
|
||||
},
|
||||
"@freecodecamp/scripts-lint#lint": {
|
||||
"dependsOn": ["@freecodecamp/client#create:trending"],
|
||||
"inputs": [
|
||||
"$TURBO_DEFAULT$",
|
||||
"$TURBO_ROOT$/client/i18n/locales/english/*"
|
||||
]
|
||||
},
|
||||
"//#lint": {
|
||||
"dependsOn": [
|
||||
"@freecodecamp/shared#compile",
|
||||
"@freecodecamp/curriculum#build"
|
||||
]
|
||||
},
|
||||
"compile": {},
|
||||
"create:trending": { "cache": false },
|
||||
"create:env": { "dependsOn": ["@freecodecamp/curriculum#compile"] },
|
||||
"build": { "dependsOn": ["compile"] },
|
||||
"build:scripts": {}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user