feat: migrate to pnpm for better workspace DX (#49293)

* feat: npm -> pnpm 

This resolves the issues with the gatsby client (gatsby-plugin-pnpm
deals with the fact that gatsby is relying on its own dependencies
being de-duped)
and challenge-editor (which doesn't seem to want to automatically install
codemirror and needed its own eslint config)

* fix: correct mocha path for curriculum tests

* fix: use select workspace with -F not -w

* fix: reorganise packages and restrict hoisting

pnpm works best if the workspaces keep their own dependencies, since
dependencies are not flattened and then what node resolves from a
require is predictable.

@types seem to be a special case and more care is required to prevent
them getting smushed together in the root (hence the .npmrc)

* fix: add types for tools + root

* fix: decouple challenge-auditor from client

* fix: add ui-components types

* fix(client): use the latest types for react 16

* fix: prettify

* fix: prettierignore pnpm-lock

* fix: relax hoisting

Turns out pnpm works just fine with types. I don't know what was going
wrong before, but there are no-longer any type conflicts.

* fix: add @redux-saga/core to fix eslint issue

It seems to only be redux-saga that import/named can't cope with, so it
is probably okay to work around this one.

* chore: add chai to tools/scripts/build

* fix: add store to root for cypress

* fix: allow cypress to download binaries

If we want to keep preventing cypress from downloading binaries, we can
figure out a workaround, but I'm allowing it to ease the transition to
pnpm.

My guess about why this is happening is that npm triggers Cypress's
postinstall script, but pnpm does not (because pnpm install only
installs if necessary, perferring to link)

* chore: re-enable pre/post scripts

* fix: update build scripts for client

Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>

* chore: update engines to use pnpm


* fix: enable choice of (super)block for tests

Only 'nix machines for now.

* chore: pin pnpm to version 7

* chore: remove last npms

Except web + curriculum-server. I'll update them when I start work on
them again.

* fix: lockfile check to catch any package-locks

* fix(action): install pnpm for upcoming tests

* chore: add nodemon to new api

Co-authored-by: Shaun Hamilton <shauhami020@gmail.com>
This commit is contained in:
Oliver Eyton-Williams
2023-03-02 19:17:44 +01:00
committed by GitHub
parent 66438c271f
commit d7848ae01a
81 changed files with 30413 additions and 55330 deletions

View File

@@ -55,6 +55,7 @@
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": [
"./client/tsconfig.json",
"./tsconfig.json",
"./api/tsconfig.json",
"./config/tsconfig.json",

View File

@@ -276,6 +276,10 @@ jobs:
# Validate the Download #
# All languages should go ABOVE this. #
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 7
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
@@ -290,15 +294,15 @@ jobs:
- name: Build Source Files
run: |
echo npm version $(npm -v)
npm ci
npm run create:config
npm run build:curriculum
npm run build:server
echo pnpm version $(pnpm -v)
pnpm install
pnpm run create:config
pnpm run build:curriculum
pnpm run build:server
- name: Lint and Format Files
run: |
npm run format:curriculum
pnpm run format:curriculum
# We do not need to run tests because they are run after the PR is created.

View File

@@ -31,6 +31,11 @@ jobs:
repository: freeCodeCamp/mobile
path: mobile
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 7
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
@@ -50,9 +55,9 @@ jobs:
- name: Install and Build
run: |
npm ci
npm run create:config
npm run build:curriculum
pnpm install
pnpm run create:config
pnpm run build:curriculum
- name: Generate mobile test files
run: |

View File

@@ -37,6 +37,11 @@ jobs:
repository: freeCodeCamp/client-config
path: client-config
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 7
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
@@ -52,10 +57,10 @@ jobs:
- name: Install and Build
run: |
npm ci
npm run build
pnpm install
pnpm run build
- name: Seed Database
run: npm run seed
run: pnpm run seed
- name: Move serve.json to Public Folder
run: cp client-config/serve.json client/public/serve.json
@@ -63,7 +68,7 @@ jobs:
uses: cypress-io/github-action@v4
with:
record: ${{ env.CYPRESS_RECORD_KEY != 0 }}
start: npm run start-ci
start: pnpm run start-ci
wait-on: http://localhost:8000
wait-on-timeout: 1200
config: baseUrl=http://localhost:8000

View File

@@ -30,6 +30,11 @@ jobs:
repository: freeCodeCamp/client-config
path: client-config
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 7
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
@@ -40,8 +45,8 @@ jobs:
- name: Install and Build
run: |
npm ci
npm run build
pnpm install
pnpm run build
- name: Move serve.json to Public Folder
run: cp client-config/serve.json client/public/serve.json
@@ -115,6 +120,11 @@ jobs:
sudo mv /usr/bin/firefox /usr/bin/firefox_old
sudo ln -s /opt/firefox/firefox /usr/bin/firefox
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 7
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
@@ -125,19 +135,19 @@ jobs:
- name: Install and Build
run: |
npm ci
npm run create:config
npm run build:curriculum
npm run build:server
pnpm install
pnpm run create:config
pnpm run build:curriculum
pnpm run build:server
- name: Seed Database
run: npm run seed
run: pnpm run seed
- name: Cypress run
uses: cypress-io/github-action@v4
with:
record: ${{ env.CYPRESS_RECORD_KEY != 0 }}
start: npm run start-ci
start: pnpm run start-ci
wait-on: http://localhost:8000
wait-on-timeout: 1200
config: baseUrl=http://localhost:8000

View File

@@ -15,18 +15,20 @@ jobs:
steps:
- name: Checkout Source Files
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 7
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Set freeCodeCamp Environment Variables
run: cp sample.env .env
- name: Install Dependencies
run: npm ci
run: pnpm install
- name: Validate Challenge Files
run: npm run audit-challenges
run: pnpm run audit-challenges

View File

@@ -17,22 +17,24 @@ jobs:
steps:
- name: Checkout Source Files
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 7
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Set freeCodeCamp Environment Variables
run: cp sample.env .env
- name: Install Dependencies
run: npm ci
run: pnpm install
- name: Validate Challenge Files
id: validate
run: npm run audit-challenges
run: pnpm run audit-challenges
- name: Create Comment
# Run if the validate challenge files step fails, specifically. Note that we need the failure() call for this step to trigger if the action fails.

View File

@@ -22,7 +22,10 @@ jobs:
steps:
- name: Checkout Source Files
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 7
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
@@ -35,6 +38,6 @@ jobs:
- name: Run Checks
run: |
echo npm version $(npm -v)
npm ci
npm run knip
echo pnpm version $(pnpm -v)
pnpm install
pnpm run knip

View File

@@ -33,7 +33,10 @@ jobs:
steps:
- name: Checkout Source Files
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 7
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
@@ -48,12 +51,12 @@ jobs:
- name: Lint Source Files
run: |
npm ci
npm run create:config
pnpm install
pnpm run create:config
npm i --prefix=curriculum-server
npm i --prefix=web
npm run build:curriculum
npm run lint
pnpm run build:curriculum
pnpm run lint
test:
name: Test
@@ -68,7 +71,10 @@ jobs:
steps:
- name: Checkout Source Files
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 7
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
@@ -83,9 +89,9 @@ jobs:
- name: Install Dependencies
run: |
npm ci
npm run create:config
npm run build:curriculum
pnpm install
pnpm run create:config
pnpm run build:curriculum
- name: Run Tests
run: npm test
run: pnpm test

View File

@@ -35,12 +35,17 @@ jobs:
- name: Check number of lockfiles
run: |
if [ $(find . -name 'package-lock.json' | grep -vc -e 'node_modules') -gt 1 ]
if [ $(find . -name 'package-lock.json' | grep -vc -e 'node_modules') -gt 0 ]
then
echo -e 'Error: found too many lockfiles in the repository.\nWe use npm workspaces to manage packages so all dependencies should be added to the root package-lock.json'
echo -e 'Error: found package-lock files in the repository.\nWe use pnpm workspaces to manage packages so all dependencies should be added via pnpm add'
exit 1
fi
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 7
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
@@ -56,13 +61,13 @@ jobs:
# currently, built as workspaces.
- name: Lint Source Files
run: |
echo npm version $(npm -v)
npm ci
npm run create:config
echo pnpm version $(pnpm -v)
pnpm install
pnpm run create:config
npm i --prefix=curriculum-server
npm i --prefix=web
npm run build:curriculum
npm run lint
pnpm run build:curriculum
pnpm run lint
test:
name: Test
@@ -78,6 +83,11 @@ jobs:
- name: Checkout Source Files
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 7
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
@@ -90,13 +100,13 @@ jobs:
- name: Install Dependencies
run: |
echo npm version $(npm -v)
npm ci
npm run create:config
npm run build:curriculum
echo pnpm version $(pnpm -v)
pnpm install
pnpm run create:config
pnpm run build:curriculum
- name: Run Tests
run: npm test
run: pnpm test
test-upcoming:
name: Test Upcoming Changes
@@ -112,6 +122,11 @@ jobs:
- name: Checkout Source Files
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 7
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
@@ -125,13 +140,13 @@ jobs:
- name: Install Dependencies
run: |
echo npm version $(npm -v)
npm ci
npm run create:config
npm run build:curriculum
echo pnpm version $(pnpm -v)
pnpm install
pnpm run create:config
pnpm run build:curriculum
- name: Run Tests
run: npm test
run: pnpm test
test-localization:
name: Localize
@@ -148,6 +163,11 @@ jobs:
- name: Checkout Source Files
uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3
- name: Setup pnpm
uses: pnpm/action-setup@v2
with:
version: 7
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3
with:
@@ -163,13 +183,13 @@ jobs:
CURRICULUM_LOCALE: ${{ matrix.locale }}
CLIENT_LOCALE: ${{ matrix.locale }}
run: |
echo npm version $(npm -v)
npm ci
npm run create:config
npm run build:curriculum
echo pnpm version $(pnpm -v)
pnpm install
pnpm run create:config
pnpm run build:curriculum
- name: Run Tests
env:
CURRICULUM_LOCALE: ${{ matrix.locale }}
CLIENT_LOCALE: ${{ matrix.locale }}
run: npm test
run: pnpm test

View File

@@ -44,28 +44,28 @@ tasks:
# so we should put all the heavy initialization here
init: >
cp sample.env .env &&
npm ci &&
gp sync-done npm-ci &&
pnpm install &&
gp sync-done pnpm-install &&
gp ports await 27017 &&
npm run seed &&
pnpm run seed &&
mongo --eval "db.fsyncLock(); db.fsyncUnlock()"
command: >
npm run create:config &&
npm run build:curriculum &&
pnpm run create:config &&
pnpm run build:curriculum &&
gp ports await 27017 &&
npm run develop:server
pnpm run develop:server
- name: client
before: export HOME_LOCATION=$(gp url 8000) && export API_LOCATION=$(gp url 3000) && export CYPRESS_BASE_URL=$(gp url 8000)
init: >
cd ./client &&
gp sync-await npm-ci &&
npm run predevelop &&
gp sync-await pnpm-install &&
pnpm run predevelop &&
cd ..
command: >
gp ports await 3000 &&
cd ./client &&
npm run develop -- -H '0.0.0.0'
pnpm run develop -- -H '0.0.0.0'
openMode: split-right
github:

View File

@@ -43,7 +43,7 @@ module.exports = {
if (files.length > 10) {
completedStages.add('markdown');
return 'npm run lint:challenges';
return 'pnpm run lint:challenges';
} else {
return files.map(
filename => `node ./tools/scripts/lint/index.js '${filename}'`

5
.npmrc
View File

@@ -1 +1,4 @@
CYPRESS_INSTALL_BINARY=0
auto-install-peers=true
strict-peer-dependencies=true
# TODO: consider reworking the scripts to avoid usage of pre/post scripts
enable-pre-post-scripts=true

View File

@@ -20,8 +20,8 @@ utils/get-lines.js
utils/get-lines.test.js
utils/validate.js
utils/validate.test.js
**/package-lock.json
pnpm-lock.yaml
web/.next
curriculum-server/data/curriculum.json
docs/**/*.md
client/src/components/Donation/types.js
client/src/components/Donation/types.js

View File

@@ -6,7 +6,7 @@
"private": true,
"engines": {
"node": ">=16",
"npm": ">=8"
"pnpm": "7"
},
"repository": {
"type": "git",

View File

@@ -30,7 +30,7 @@ if (process.env.WEBHOOK_PROXY_URL) {
nodemon({
ext: 'js json',
// --silent squashes an ELIFECYCLE error when the server exits
exec: 'npm run --silent babel-dev-server',
exec: 'pnpm run --silent babel-dev-server',
watch: path.resolve(__dirname, './server'),
spawn: true,
env: {

View File

@@ -14,7 +14,7 @@ module.exports = function mountLoopBackExplorer(app) {
// Do not print any message when the project is used as a component.
app.once('started', function () {
log(
'Run `npm install loopback-component-explorer` to enable ' +
'Run `pnpm add loopback-component-explorer` to enable ' +
'the LoopBack explorer'
);
});

View File

@@ -8,7 +8,8 @@
"@fastify/mongodb": "6.2.0",
"fastify": "4.13.0",
"fastify-auth0-verify": "^1.0.0",
"fastify-plugin": "^4.3.0"
"fastify-plugin": "^4.3.0",
"nodemon": "2.0.20"
},
"description": "The freeCodeCamp.org open-source codebase and curriculum",
"engines": {

View File

@@ -22,6 +22,7 @@ module.exports = {
},
pathPrefix: pathPrefix,
plugins: [
'gatsby-plugin-pnpm',
{
resolve: '@sentry/gatsby',
options: {

View File

@@ -6,7 +6,7 @@
"private": true,
"engines": {
"node": ">=16",
"npm": ">=8"
"pnpm": "7"
},
"repository": {
"type": "git",
@@ -19,25 +19,27 @@
"author": "freeCodeCamp <team@freecodecamp.org>",
"main": "none",
"scripts": {
"prebuild": "npm --prefix ../ run create:config && npm run build:workers -- --env production",
"prebuild": "pnpm -w run create:config && pnpm run build:workers --env production",
"build": "cross-env NODE_OPTIONS=\"--max-old-space-size=7168\" gatsby build --prefix-paths",
"build:workers": "cross-env NODE_OPTIONS=\"--max-old-space-size=7168\" webpack --config ./webpack-workers.js",
"clean": "gatsby clean",
"predevelop": "npm --prefix ../ run create:config && npm run build:workers -- --env development",
"predevelop": "pnpm -w run create:config && pnpm run build:workers --env development",
"develop": "cross-env NODE_OPTIONS=\"--max-old-space-size=5000\" gatsby develop --inspect=9230",
"lint": "ts-node ./i18n/schema-validation.ts",
"serve": "gatsby serve -p 8000",
"serve-ci": "serve -l 8000 -c serve.json public",
"prestand-alone": "npm run prebuild",
"prestand-alone": "pnpm run prebuild",
"stand-alone": "gatsby develop",
"validate-keys": "ts-node --project ../tsconfig.json ../tools/scripts/lint/validate-keys"
},
"dependencies": {
"@babel/plugin-proposal-export-default-from": "7.18.10",
"@babel/plugin-proposal-function-bind": "7.18.9",
"@babel/plugin-transform-runtime": "^7.19.6",
"@babel/polyfill": "7.12.1",
"@babel/preset-env": "7.20.2",
"@babel/preset-react": "7.18.6",
"@babel/runtime": "^7.20.13",
"@babel/standalone": "7.20.15",
"@fortawesome/fontawesome-svg-core": "6.3.0",
"@fortawesome/free-brands-svg-icons": "6.3.0",
@@ -51,12 +53,14 @@
"@growthbook/growthbook-react": "0.11.2",
"@loadable/component": "5.15.3",
"@reach/router": "1.3.4",
"@redux-saga/core": "^1.2.2",
"@sentry/gatsby": "6.19.7",
"@stripe/react-stripe-js": "1.16.5",
"@stripe/stripe-js": "1.47.0",
"@types/react-scrollable-anchor": "0.6.1",
"@testing-library/jest-dom": "5.16.5",
"algoliasearch": "4.14.3",
"assert": "2.0.0",
"babel-loader": "8.3.0",
"babel-plugin-preval": "5.1.0",
"babel-plugin-prismjs": "2.1.0",
"bezier-easing": "2.1.0",
@@ -67,6 +71,7 @@
"date-fns": "2.29.3",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.7",
"eslint": "7",
"final-form": "4.20.9",
"gatsby": "3.15.0",
"gatsby-cli": "3.15.0",
@@ -74,6 +79,7 @@
"gatsby-plugin-advanced-sitemap": "2.1.0",
"gatsby-plugin-create-client-paths": "3.15.0",
"gatsby-plugin-manifest": "3.15.0",
"gatsby-plugin-pnpm": "^1.2.10",
"gatsby-plugin-postcss": "4.15.0",
"gatsby-plugin-react-helmet": "4.15.0",
"gatsby-plugin-remove-serviceworker": "1.0.0",
@@ -136,7 +142,32 @@
"@codesee/tracker": "0.523.0",
"@testing-library/jest-dom": "5.16.5",
"@testing-library/react": "12.1.5",
"@types/chai": "^4.3.4",
"@types/enzyme": "^3.10.12",
"@types/enzyme-adapter-react-16": "1.0.6",
"@types/jest": "27.5.2",
"@types/jquery": "^3.5.16",
"@types/loadable__component": "5.13.4",
"@types/lodash-es": "^4.17.6",
"@types/prismjs": "^1.26.0",
"@types/reach__router": "1.3.11",
"@types/react": "16.14.35",
"@types/react-dom": "16.9.17",
"@types/react-gtm-module": "2.0.1",
"@types/react-helmet": "6.1.6",
"@types/react-instantsearch-core": "6.26.3",
"@types/react-instantsearch-dom": "6.12.3",
"@types/react-redux": "7.1.25",
"@types/react-responsive": "8.0.5",
"@types/react-scrollable-anchor": "0.6.0",
"@types/react-spinkit": "3.0.7",
"@types/react-test-renderer": "16.9.5",
"@types/react-transition-group": "4.4.5",
"@types/redux-actions": "2.6.2",
"@types/sanitize-html": "^2.8.0",
"@types/store": "^2.0.2",
"@types/testing-library__jest-dom": "^5.14.5",
"@types/validator": "^13.7.12",
"autoprefixer": "10.4.13",
"babel-plugin-transform-imports": "2.0.0",
"chokidar": "3.5.3",

View File

@@ -6,7 +6,7 @@
"private": true,
"engines": {
"node": ">=16",
"npm": ">=8"
"pnpm": "7"
},
"repository": {
"type": "git",

View File

@@ -6,7 +6,7 @@
"private": true,
"engines": {
"node": ">=16",
"npm": ">=8"
"pnpm": "7"
},
"repository": {
"type": "git",

View File

@@ -6,7 +6,8 @@ import { Col, Grid, Row } from '@freecodecamp/react-bootstrap';
import { graphql } from 'gatsby';
import React, { Component } from 'react';
import Helmet from 'react-helmet';
import { TFunction, withTranslation } from 'react-i18next';
import { withTranslation } from 'react-i18next';
import type { TFunction } from 'i18next';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';

19
client/tsconfig.json Normal file
View File

@@ -0,0 +1,19 @@
{
"compilerOptions": {
"lib": ["WebWorker", "DOM", "DOM.Iterable", "ES2020"],
"target": "es2020",
"module": "es2020",
"moduleResolution": "node",
"allowJs": true,
"jsx": "react",
"strict": true,
"forceConsistentCasingInFileNames": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"noEmit": true,
"resolveJsonModule": true,
"skipLibCheck": true
},
"include": ["i18n/**/*", "plugins/**/*", "src/**/*", "utils/**/*"]
}

View File

@@ -62,7 +62,7 @@ module.exports = (env = {}) => {
},
plugins: [
new CopyWebpackPlugin({
patterns: ['../node_modules/sass.js/dist/sass.sync.js']
patterns: ['./node_modules/sass.js/dist/sass.sync.js']
}),
new webpack.ProvidePlugin({
process: 'process/browser'

View File

@@ -6,7 +6,7 @@
"private": true,
"engines": {
"node": ">=16",
"npm": ">=8"
"pnpm": "7"
},
"repository": {
"type": "git",

View File

@@ -6,7 +6,7 @@
"private": true,
"engines": {
"node": ">=16",
"npm": ">=8"
"pnpm": "7"
},
"repository": {
"type": "git",
@@ -25,8 +25,8 @@
"delete-step": "cross-env CALLING_DIR=$INIT_CWD ts-node --project ../tsconfig.json ../tools/challenge-helper-scripts/delete-step",
"lint": "ts-node --project ../tsconfig.json lint-localized",
"update-step-titles": "cross-env CALLING_DIR=$INIT_CWD ts-node --project ../tsconfig.json ../tools/challenge-helper-scripts/update-step-titles",
"test": "ts-node ../node_modules/mocha/bin/mocha.js --delay --exit --reporter progress --bail",
"test:full-output": "cross-env FULL_OUTPUT=true ts-node ../node_modules/mocha/bin/mocha.js --delay --reporter progress"
"test": "ts-node ./node_modules/mocha/bin/mocha.js --delay --exit --reporter progress --bail",
"test:full-output": "cross-env FULL_OUTPUT=true ts-node ./node_modules/mocha/bin/mocha.js --delay --reporter progress"
},
"devDependencies": {
"@babel/core": "7.20.12",

View File

@@ -110,7 +110,7 @@ setup()
.catch(err => handleRejection(err));
async function setup() {
if (process.env.npm_config_superblock && process.env.npm_config_block) {
if (process.env.FCC_SUPERBLOCK && process.env.FCC_BLOCK) {
throw new Error(`Please do not use both a block and superblock as input.`);
}
@@ -152,9 +152,9 @@ async function setup() {
];
// the next few statements will filter challenges based on command variables
if (process.env.npm_config_superblock) {
if (process.env.FCC_SUPERBLOCK) {
const filter = stringSimilarity.findBestMatch(
process.env.npm_config_superblock,
process.env.FCC_SUPERBLOCK,
targetSuperBlockStrings
).bestMatch.target;
@@ -168,9 +168,9 @@ async function setup() {
}
}
if (process.env.npm_config_block) {
if (process.env.FCC_BLOCK) {
const filter = stringSimilarity.findBestMatch(
process.env.npm_config_block,
process.env.FCC_BLOCK,
targetBlockStrings
).bestMatch.target;
@@ -241,7 +241,7 @@ function populateTestsForLang({ lang, challenges, meta }) {
const challengeTitles = new ChallengeTitles();
const validateChallenge = challengeSchemaValidator();
if (!process.env.npm_config_block) {
if (!process.env.FCC_BLOCK) {
describe('Assert meta order', function () {
/** This array can be used to skip a superblock - we'll use this
* when we are working on the new project-based curriculum for

View File

@@ -5,7 +5,7 @@ const version = pkg.version;
(async () => {
console.log('Installing Cypress ' + version);
await execa('npm', ['run', 'cypress:install'], {
await execa('pnpm', ['run', 'cypress:install'], {
env: { CYPRESS_INSTALL_BINARY: version }
});
console.log('Cypress installed');

View File

@@ -13,7 +13,7 @@ module.exports = defineConfig({
config.env = config.env || {};
on('before:run', () => {
if (!existsSync('./config/curriculum.json')) {
execSync('npm run build:curriculum');
execSync('pnpm run build:curriculum');
}
});

View File

@@ -1,6 +1,6 @@
describe('Donate page', () => {
beforeEach(() => {
cy.exec('npm run seed -- --donor');
cy.exec('pnpm run seed -- --donor');
cy.login();
});

View File

@@ -1,12 +1,12 @@
describe('Donate page', () => {
before(() => {
cy.clearCookies();
cy.exec('npm run seed');
cy.exec('pnpm run seed');
cy.login();
});
after(() => {
cy.exec('npm run seed');
cy.exec('pnpm run seed');
});
const projects = [

View File

@@ -159,7 +159,7 @@ describe('Language menu keyboard accessibility', () => {
describe('Authenticated Navigation Menu', () => {
before(() => {
cy.clearCookies();
cy.exec('npm run seed');
cy.exec('pnpm run seed');
cy.login();
cy.get(selectors['toggle-button']).should('be.visible').click();
});
@@ -181,7 +181,7 @@ describe('Authenticated Navigation Menu', () => {
describe('Authenticated User Sign Out', () => {
before(() => {
cy.clearCookies();
cy.exec('npm run seed');
cy.exec('pnpm run seed');
});
beforeEach(() => {
cy.login();
@@ -207,7 +207,7 @@ describe('Authenticated User Sign Out', () => {
describe('Donor Navigation Menu', () => {
before(() => {
cy.clearCookies();
cy.exec('npm run seed -- --donor');
cy.exec('pnpm run seed -- --donor');
cy.login();
cy.visit('/donate');
});

View File

@@ -4,7 +4,7 @@ const introPageSelectors = {
describe('Certification intro page', () => {
before(() => {
cy.exec('npm run seed');
cy.exec('pnpm run seed');
cy.login();
});

View File

@@ -29,7 +29,7 @@ const projects = {
describe('Front End Development Libraries Superblock', () => {
before(() => {
cy.exec('npm run seed');
cy.exec('pnpm run seed');
cy.login();
cy.visit('/learn/front-end-development-libraries');
});
@@ -41,7 +41,7 @@ describe('Front End Development Libraries Superblock', () => {
});
describe('After submitting all 5 projects', () => {
before(() => {
cy.exec('npm run seed');
cy.exec('pnpm run seed');
cy.login();
cy.visit('/settings');
cy.setPrivacyTogglesToPublic();

View File

@@ -3,7 +3,7 @@ import '@testing-library/cypress/add-commands';
describe('Settings certifications area', () => {
describe('initially', () => {
before(() => {
cy.exec('npm run seed');
cy.exec('pnpm run seed');
cy.login();
});
@@ -23,7 +23,7 @@ describe('Settings certifications area', () => {
describe('after isHonest', () => {
before(() => {
cy.exec('npm run seed');
cy.exec('pnpm run seed');
cy.login();
});

View File

@@ -1,6 +1,6 @@
describe('Email input field', () => {
beforeEach(() => {
cy.exec('npm run seed');
cy.exec('pnpm run seed');
cy.login();
cy.visit('/settings');
});

View File

@@ -1,7 +1,7 @@
describe('User token widget on settings page,', function () {
describe('initially', function () {
beforeEach(() => {
cy.exec('npm run seed');
cy.exec('pnpm run seed');
cy.login();
});
@@ -15,7 +15,7 @@ describe('User token widget on settings page,', function () {
describe('after creating token', function () {
beforeEach(() => {
cy.exec('npm run seed');
cy.exec('pnpm run seed');
cy.login();
cy.visit(
'/learn/relational-database/learn-bash-by-building-a-boilerplate/build-a-boilerplate'

View File

@@ -2,7 +2,7 @@ const certifiedUser = '/certification/certifieduser/responsive-web-design';
describe('A certification,', function () {
before(() => {
cy.exec('npm run seed:certified-user');
cy.exec('pnpm run seed:certified-user');
});
describe('while viewing your own,', function () {

View File

@@ -1,11 +1,11 @@
describe('Top contributor in user profile', () => {
before(() => {
cy.clearCookies();
cy.exec('npm run seed -- --top-contributor');
cy.exec('pnpm run seed -- --top-contributor');
});
after(() => {
cy.exec('npm run seed');
cy.exec('pnpm run seed');
});
beforeEach(() => {

View File

@@ -1,7 +1,7 @@
describe('Public profile certifications', () => {
context('Signed in user viewing their own public profile', () => {
before(() => {
cy.exec('npm run seed:certified-user');
cy.exec('pnpm run seed:certified-user');
});
beforeEach(() => {

View File

@@ -7,7 +7,7 @@ describe('Privacy terms', () => {
}).as('updatePrivacyTerms');
// Seed dev user with `acceptedPrivacyTerms` unset
cy.exec('npm run seed -- --unset-privacy-terms');
cy.exec('pnpm run seed -- --unset-privacy-terms');
// Go to the homepage and log in manually so we can assert the following:
// 1. Redirection to /email-sign-up works properly
// 2. The /update-privacy-terms has not been requested

View File

@@ -1,6 +1,6 @@
describe('Report User', () => {
beforeEach(() => {
cy.exec('npm run seed');
cy.exec('pnpm run seed');
cy.login();
});
it('should be possible to report a user from their profile page', () => {

View File

@@ -1,6 +1,6 @@
describe('Donate page', () => {
it('Donation ', () => {
cy.exec('npm run seed');
cy.exec('pnpm run seed');
cy.login();
cy.visit('/donate');
cy.get('.donation-elements', { timeout: 10000 }).within(() => {

View File

@@ -22,7 +22,7 @@ module.exports = (on, config) => {
config.env = config.env || {};
on('before:run', () => {
if (!existsSync('../../config/curriculum.json')) {
execSync('npm run build:curriculum');
execSync('pnpm run build:curriculum');
}
});

View File

@@ -9,7 +9,7 @@ COPY --chown=node:node . .
ARG DOPPLER_TOKEN
RUN \
doppler secrets download doppler.encrypted.json &&\
npm ci --no-progress --ignore-scripts &&\
pnpm install --no-progress --ignore-scripts &&\
doppler run --fallback=doppler.encrypted.json --command="npm run create:config" &&\
doppler run --fallback=doppler.encrypted.json --command="npm run build:curriculum" &&\
doppler run --fallback=doppler.encrypted.json --command="npm run build:server"
@@ -18,7 +18,7 @@ FROM node:16-alpine as depends
USER node
WORKDIR /home/node/depends
COPY --chown=node:node . .
RUN npm ci --production --workspace=api-server --no-progress --ignore-scripts
RUN pnpm install --production --workspace=api-server --no-progress --ignore-scripts
FROM node:16-alpine
RUN npm i -g pm2@4

View File

@@ -10,7 +10,7 @@ ARG DOPPLER_TOKEN
RUN \
doppler secrets download doppler.encrypted.json &&\
# Install and donot ignore the scripts for sharp
npm ci --no-progress --ignore-scripts=false &&\
pnpm install --no-progress --ignore-scripts=false &&\
doppler run --fallback=doppler.encrypted.json --command="npm run create:config" &&\
doppler run --fallback=doppler.encrypted.json --command="npm run build:curriculum" &&\
doppler run --fallback=doppler.encrypted.json --command="npm run build:client"

View File

@@ -96,7 +96,7 @@ Currently, only members on the developer team can push to the production branche
4. Confirm that you are able to build the repository locally.
```
npm run clean-and-develop
pnpm run clean-and-develop
```
5. Move changes from `main` to `prod-staging` via a fast-forward merge
@@ -476,13 +476,13 @@ Provisioning VMs with the Code
6. Install dependencies
```console
npm ci
pnpm install
```
7. Build the server
```console
npm run prebuild && npm run build:curriculum && npm run build:server
pnpm run prebuild && pnpm run build:curriculum && pnpm run build:server
```
8. Start Instances
@@ -522,13 +522,13 @@ pm2 stop all
2. Install dependencies
```console
npm ci
pnpm install
```
3. Build the server
```console
npm run create:config && npm run build:curriculum && npm run build:server
pnpm run create:config && pnpm run build:curriculum && pnpm run build:server
```
4. Start Instances
@@ -824,8 +824,8 @@ ssh into the VM (hosted on Digital Ocean).
```console
cd tools
git pull origin master
npm ci
npm run build
pnpm install
pnpm run build
pm2 restart contribute-app
```

View File

@@ -28,25 +28,25 @@ To run tests against production builds, replace `dev` with `prd` below.
- To run all tests in the `./cypress` directory:
```console
npm run cypress:dev:run
pnpm run cypress:dev:run
```
- To run a single test:
```console
npm run cypress -- run --spec=cypress/<path_to_test_file>
pnpm run cypress -- run --spec=cypress/<path_to_test_file>
```
For example:
```console
npm run cypress -- run --spec=cypress/e2e/default/landing.js
pnpm run cypress -- run --spec=cypress/e2e/default/landing.js
```
- To create a development build, start the development server, and run all existing cypress end-to-end tests:
```console
npm run e2e:dev:run
pnpm run e2e:dev:run
```
## Cypress-GitPod Setup
@@ -64,19 +64,19 @@ mongod
- Seed the database
```console
npm run seed
pnpm run seed
```
- Develop the server and client
```console
npm run develop
pnpm run develop
```
### 2. Install Cypress Build Tools
```console
npm run cypress:install-build-tools
pnpm run cypress:install-build-tools
```
- When prompted in the terminal, select your keyboard layout by language/area

View File

@@ -204,13 +204,13 @@ A quick reference to the commands that you will need when working.
| command | description |
| -------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `npm test` | Run all JS tests in the system, including client, server, lint and challenge tests. |
| `npm run test-client` | Run the client test suite. |
| `npm run test:curriculum` | Run the curriculum test suite. |
| `npm run test:curriculum --block='Basic HTML and HTML5'` | Test a specific Block. |
| `npm run test:curriculum --superblock='responsive-web-design'` | Test a specific SuperBlock. |
| `npm run test-curriculum-full-output` | Run the curriculum test suite, without bailing after the first error |
| `npm run test-server` | Run the server test suite. |
| `npm run e2e` | Run the Cypress end to end tests. |
| `npm run clean` | Uninstalls all dependencies and cleans up caches. |
| `npm run storybook` | Starts Storybook for component library development. |
| `pnpm test` | Run all JS tests in the system, including client, server, lint and challenge tests. |
| `pnpm run test-client` | Run the client test suite. |
| `pnpm run test:curriculum` | Run the curriculum test suite. |
| `FCC_BLOCK='Basic HTML and HTML5' pnpm run test:curriculum` | Test a specific Block. |
| `FCC_SUPERBLOCK='responsive-web-design' pnpm run test:curriculum` | Test a specific SuperBlock. |
| `pnpm run test-curriculum-full-output` | Run the curriculum test suite, without bailing after the first error |
| `pnpm run test-server` | Run the server test suite. |
| `pnpm run e2e` | Run the Cypress end to end tests. |
| `pnpm run clean` | Uninstalls all dependencies and cleans up caches. |
| `pnpm run storybook` | Starts Storybook for component library development. |

View File

@@ -297,10 +297,10 @@ Once you have the files, you will need to place them in the correct directory. F
Update your `.env` file to use your new language for `CLIENT_LOCALE` and `CURRICULUM_LOCALE`.
Once these are in place, you should be able to run `npm run develop` to view your translated version of freeCodeCamp.
Once these are in place, you should be able to run `pnpm run develop` to view your translated version of freeCodeCamp.
> [!TIP]
> If you build the client in one language and then want to build it in a different language, you will need to use the command `npm run clean-and-develop` after changing the `.env` file, as Gatsby will cache the first language.
> If you build the client in one language and then want to build it in a different language, you will need to use the command `pnpm run clean-and-develop` after changing the `.env` file, as Gatsby will cache the first language.
> [!ATTENTION]
> While you may perform translations locally for the purpose of testing, we remind everyone that translations should _not_ be submitted through GitHub and should only be done through Crowdin. Be sure to reset your local codebase after you are done testing.

View File

@@ -191,14 +191,14 @@ When you are working on features for our upcoming curriculum `next-*` branches,
4. Resolve any conflicts, cleanup, install dependencies and run tests
```console
npm run clean
pnpm run clean
npm ci
npm run test:curriculum --superblock=<superblock-name>
pnpm install
FCC_SUPERBLOCK='<superblock-name>' pnpm run test:curriculum
# example:
# npm run test:curriculum --superblock=python-for-everybody
# FCC_SUPERBLOCK='python-for-everybody' pnpm run test:curriculum
```

View File

@@ -76,7 +76,7 @@ Some community members also develop on Windows natively with Git for Windows (Gi
| Prerequisite | Version | Notes |
| --------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------- |
| [Node.js](http://nodejs.org) | `18.x` | We use the "Active LTS" version, See [LTS Schedule](https://nodejs.org/en/about/releases/). |
| npm (comes bundled with Node) | `8.x` | We use the version bundled with Node.js Active LTS. |
| [pnpm](https://pnpm.io/installation) | `7.x` |- |
| [MongoDB Community Server](https://docs.mongodb.com/manual/administration/install-community/) | `4.2.x` | - |
> [!ATTENTION]
@@ -86,7 +86,7 @@ If Node.js is already installed on your machine, run the following commands to v
```console
node -v
npm -v
pnpm -v
```
> [!TIP]
@@ -221,7 +221,7 @@ The keys in the `.env` file are _not_ required to be changed to run the app loca
This step will install the dependencies required for the application to run:
```console
npm ci
pnpm install
```
#### Step 3: Start MongoDB and seed the database
@@ -261,7 +261,7 @@ Make sure to replace `3.6` with the version you have installed
Next, let's seed the database. In this step, we run the below command that fills the MongoDB server with some initial data sets that are required by services. These include a few schemas, among other things.
```console
npm run seed
pnpm run seed
```
#### Step 4: Start the freeCodeCamp client application and API server
@@ -269,7 +269,7 @@ npm run seed
You can now start up the API server and the client applications.
```console
npm run develop
pnpm run develop
```
This single command will fire up all the services, including the API server and the client applications available for you to work on.
@@ -281,7 +281,7 @@ The API serves endpoints at `http://localhost:3000`. The Gatsby app serves the c
While you are logged in, if you visit <http://localhost:3000/explorer> you should see the available APIs.
> [!WARNING]
> Clearing your cookies or running `npm run seed:certified-user` will log you out, and you will have to sign in again.
> Clearing your cookies or running `pnpm run seed:certified-user` will log you out, and you will have to sign in again.
If you have issues while installing it, check out the [troubleshooting section](troubleshooting-development-issues.md)
@@ -291,7 +291,7 @@ A quick reference to the commands that you will need when working locally.
| command | description |
| ----------------- | ----------------------------------------------------------------------------- |
| `npm ci` | Installs / re-install all dependencies and bootstraps the different services. |
| `npm run seed` | Creates authorized test users and inserts them into mongodb. |
| `npm run develop` | Starts the freeCodeCamp API Server and Client Applications. |
| `npm run clean` | Uninstalls all dependencies and cleans up caches. |
| `pnpm install` | Installs / re-install all dependencies and bootstraps the different services. |
| `pnpm run seed` | Creates authorized test users and inserts them into mongodb. |
| `pnpm run develop` | Starts the freeCodeCamp API Server and Client Applications. |
| `pnpm run clean` | Uninstalls all dependencies and cleans up caches. |

View File

@@ -12,4 +12,4 @@ If you see messages like
bash: change_volumes_owner.sh: No such file or directory
```
when you `npm run docker:init` this is likely the culprit.
when you `pnpm run docker:init` this is likely the culprit.

View File

@@ -457,17 +457,17 @@ Before you [create a pull request](how-to-open-a-pull-request.md) for your chang
1. To test all challenges run the below command from the root directory
```
npm run test:curriculum
pnpm run test:curriculum
```
2. You can also test a block or a superblock of challenges with these commands
```
npm run test:curriculum --block='Basic HTML and HTML5'
FCC_BLOCK='Basic HTML and HTML5' pnpm run test:curriculum
```
```
npm run test:curriculum --superblock=responsive-web-design
FCC_SUPERBLOCK='responsive-web-design' pnpm run test:curriculum
```
You are also able to test one challenge individually by performing the following steps:
@@ -481,7 +481,7 @@ You are also able to test one challenge individually by performing the following
2. Run the following for each challenge file for which you have changed (replacing `challenge-title-goes-here` with the full title of the challenge):
```
npm run test -- -g challenge-title-goes-here
pnpm run test -- -g challenge-title-goes-here
```
Once you have verified that each challenge you've worked on passes the tests, [please create a pull request](how-to-open-a-pull-request.md).

View File

@@ -10,7 +10,7 @@ These instructions will tell you how to use our challenge editor tool to work on
### Starting the Editor
To start the editor, make sure you are in the root freecodecamp directory. Then, run `npm run challenge-editor` to start both the client and the API that powers the editor.
To start the editor, make sure you are in the root freecodecamp directory. Then, run `pnpm run challenge-editor` to start both the client and the API that powers the editor.
The client will run on port `3300`, so you can access it at `http://localhost:3300`. The API runs on port `3200`, to avoid conflicts with the learn client and server. This will allow you to run the freeCodeCamp application at the same time as the editor, so you can test your changes locally.
@@ -60,7 +60,7 @@ The `tools/challenge-helper-scripts` folder contains tools to help facilitate th
### Create a new project
Run `npm run create-project` from the root directory. This opens up a command line ui that guides you through the process. Once that has finished, there should be a new challenge in the English curriculum that you can use for the first step of the project. For example, if you created a project called `test-project` in the Responsive Web Design certification, it would be in `curriculum/challenges/english/01-responsive-web-design/test-project`.
Run `pnpm run create-project` from the root directory. This opens up a command line ui that guides you through the process. Once that has finished, there should be a new challenge in the English curriculum that you can use for the first step of the project. For example, if you created a project called `test-project` in the Responsive Web Design certification, it would be in `curriculum/challenges/english/01-responsive-web-design/test-project`.
If you want to create new steps, the following tools simplify that process.
@@ -71,10 +71,10 @@ A one-off script that will automatically add the next step based on the last ste
#### How to run script:
1. Change to the directory of the project.
2. Run the following npm command:
2. Run the following command:
```bash
npm run create-next-step
pnpm run create-next-step
```
### create-empty-steps
@@ -86,10 +86,10 @@ A one-off script that automatically adds a specified number of steps. The challe
#### How to run script:
1. Change to the directory of the project.
2. Run the following npm command:
2. Run the following command:
```bash
npm run create-empty-steps X # where X is the number of steps to create.
pnpm run create-empty-steps X # where X is the number of steps to create.
```
### insert-step
@@ -101,10 +101,10 @@ A one-off script that automatically adds a new step at a specified position, inc
#### How to run script:
1. Change to the directory of the project.
2. Run the following npm command:
2. Run the following command:
```bash
npm run insert-step X # where X is the position to insert the new step.
pnpm run insert-step X # where X is the position to insert the new step.
```
### delete-step
@@ -116,10 +116,10 @@ A one-off script that deletes an existing step, decrementing all subsequent step
#### How to run script
1. Change to the directory of the project.
2. Run the following npm command:
2. Run the following command:
```bash
npm run delete-step X # where X is the step number to be deleted.
pnpm run delete-step X # where X is the step number to be deleted.
```
### update-step-titles
@@ -129,8 +129,8 @@ A one-off script that automatically updates the frontmatter in a project's markd
#### How to run script
1. Change to the directory of the project.
2. Run the following npm command:
2. Run the following command:
```bash
npm run update-step-titles
pnpm run update-step-titles
```

View File

@@ -30,7 +30,7 @@ A new component can be created using the following command from the root directo
```bash
cd tools/ui-components
npm run gen-component MyComponent
pnpm run gen-component MyComponent
```
The command will generate a new folder inside the `ui-components` directory, with the following files:
@@ -77,7 +77,7 @@ Use cases of the component should be added to the Storybook file (`.stories.tsx`
To start Storybook, run the following command from the root directory:
```bash
npm run storybook
pnpm run storybook
```
The Storybook page is available on [http://localhost:6006](http://localhost:6006).
@@ -89,7 +89,7 @@ We use [React Testing Library](https://testing-library.com/docs/react-testing-li
To run tests against the component library, run the following command from the root directory:
```bash
npm run test-ui-components
pnpm run test-ui-components
```
## Adding packages to the UI-Component library
@@ -97,7 +97,8 @@ npm run test-ui-components
We restrict adding new packages to the UI Components to help with the project's maintainability. In the rare chance that you think a dependency is needed, please check with the maintainers first and then use the following command to add a package:
```bash
npm i -w=tools/ui-components package_name
cd tools/ui-components
pnpm add package_name
```
### Useful links

View File

@@ -51,13 +51,13 @@ Install freeCodeCamp locally ([see the local setup guide](how-to-setup-freecodec
#### Serve and launch the documentation site only
```console
npm run docs:serve
pnpm run docs:serve
```
#### Serve the documentation site alongside freeCodeCamp locally:
```console
npm run develop
pnpm run develop
```
> The documentation site should be available at <http://localhost:3400>

View File

@@ -17,10 +17,10 @@ If you are on a different OS or are still facing issues, see [getting help](#get
When you build the client, Gatsby will cache the Fonts, language strings and UI. If one of them isn't cached, run the following:
```console
npm run clean
npm ci
npm run seed
npm run develop
pnpm run clean
pnpm install
pnpm run seed
pnpm run develop
```
OR
@@ -28,7 +28,7 @@ OR
Use the shortcut
```
npm run clean-and-develop
pnpm run clean-and-develop
```
If you continue to face issues with the build, cleaning up the workspace is recommend.
@@ -77,7 +77,7 @@ TCP 0.0.0.0:3000 DESKTOP LISTENING
While in development, your session is stored as cookies. Clearing them will sign you out of your development account.
Running `npm run seed:certified-user` will log you out, too. It will overwrite the development user in your local database.
Running `pnpm run seed:certified-user` will log you out, too. It will overwrite the development user in your local database.
### Issue getting 404 when navigating profile page

55038
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@
"private": true,
"engines": {
"node": ">=16",
"npm": ">=8"
"pnpm": "7"
},
"repository": {
"type": "git",
@@ -18,59 +18,44 @@
"homepage": "https://github.com/freeCodeCamp/freeCodeCamp#readme",
"author": "freeCodeCamp <team@freecodecamp.org>",
"main": "none",
"workspaces": [
"api",
"api-server",
"client",
"client/plugins/fcc-source-challenges",
"client/plugins/gatsby-remark-node-identity",
"curriculum",
"tools/challenge-editor/api",
"tools/challenge-editor/client",
"tools/challenge-helper-scripts",
"tools/challenge-parser",
"tools/scripts/build",
"tools/scripts/seed",
"tools/ui-components"
],
"scripts": {
"audit-challenges": "npm run create:config && ts-node tools/challenge-auditor/index.ts",
"audit-challenges": "pnpm run create:config && ts-node tools/challenge-auditor/index.ts",
"analyze-bundle": "webpack-bundle-analyzer",
"prebuild": "npm-run-all create:*",
"build": "npm-run-all -p build:*",
"build-workers": "cd ./client && npm run prebuild",
"build:client": "cd ./client && npm run build",
"build:curriculum": "cd ./curriculum && npm run build",
"build:server": "cd ./api-server && npm run build",
"build-workers": "cd ./client && pnpm run prebuild",
"build:client": "cd ./client && pnpm run build",
"build:curriculum": "cd ./curriculum && pnpm run build",
"build:server": "cd ./api-server && pnpm run build",
"challenge-editor": "npm-run-all -p challenge-editor:*",
"challenge-editor:client": "cd ./tools/challenge-editor/client && npm start",
"challenge-editor:server": "cd ./tools/challenge-editor/api && npm start",
"challenge-editor:client": "cd ./tools/challenge-editor/client && pnpm start",
"challenge-editor:server": "cd ./tools/challenge-editor/api && pnpm start",
"clean": "npm-run-all -p clean:*",
"clean-and-develop": "npm run clean && npm ci && npm run develop",
"clean:client": "cd ./client && npm run clean",
"clean-and-develop": "pnpm run clean && pnpm install && pnpm run develop",
"clean:client": "cd ./client && pnpm run clean",
"clean:curriculum": "npx --yes rimraf ./config/curriculum.json",
"clean:packages": "npx --yes rimraf ./**/node_modules",
"clean:server": "npx --yes rimraf ./api-server/lib",
"create:config": "tsc -p config && npm run ensure-env && npm run download-trending",
"create:config": "tsc -p config && pnpm run ensure-env && pnpm run download-trending",
"create:utils": "tsc -p utils",
"precypress": "node ./cypress-install.js",
"cypress": "cypress",
"cypress:dev:run": "npm run cypress -- run --spec cypress/e2e/default/**/*.js",
"cypress:dev:watch": "npm run cypress -- open",
"cypress:prd:run": "npm run cypress -- run --spec cypress/e2e/default/**/*.js",
"cypress:prd:watch": "npm run cypress -- open",
"cypress:dev:run": "pnpm run cypress -- run --spec cypress/e2e/default/**/*.js",
"cypress:dev:watch": "pnpm run cypress -- open",
"cypress:prd:run": "pnpm run cypress -- run --spec cypress/e2e/default/**/*.js",
"cypress:prd:watch": "pnpm run cypress -- open",
"cypress:install": "cypress install && echo 'for use with ./cypress-install.js'",
"cypress:install-build-tools": "sh ./cypress-install.sh",
"predevelop": "npm-run-all create:*",
"develop": "npm-run-all build:curriculum -p develop:*",
"develop:client": "npm run build:curriculum && cd ./client && npm run develop",
"develop:server": "npm run predevelop && cd ./api-server && npm run develop",
"develop:client": "pnpm run build:curriculum && cd ./client && pnpm run develop",
"develop:server": "pnpm run predevelop && cd ./api-server && pnpm run develop",
"docs:serve": "docsify serve ./docs -o --port 3400",
"e2e": "npm run e2e:dev:run",
"e2e": "pnpm run e2e:dev:run",
"e2e:dev:run": "start-test develop ':3000/status/ping|8000' cypress:dev:run",
"e2e:dev:watch": "start-test develop ':3000/status/ping|8000' cypress:dev:watch",
"e2e:prd:run": "npm run build && start-test ':3000/status/ping|8000' cypress:dev:run",
"e2e:prd:watch": "npm run build && start-test ':3000/status/ping|8000' cypress:dev:watch",
"e2e:prd:run": "pnpm run build && start-test ':3000/status/ping|8000' cypress:dev:run",
"e2e:prd:watch": "pnpm run build && start-test ':3000/status/ping|8000' cypress:dev:watch",
"download-trending": "ts-node ./tools/scripts/build/download-trending.ts",
"ensure-env": "cross-env DEBUG=fcc:* ts-node ./tools/scripts/build/ensure-env.ts",
"format": "run-s format:eslint format:prettier",
@@ -83,24 +68,24 @@
"hooks:uninstall": "node node_modules/husky/husky.js uninstall",
"knip": "npx -y knip@^1.0.0-beta.10 --include files",
"knip:all": "npx -y knip@^1.0.0-beta.10",
"prelint": "npm run -w=client predevelop",
"prelint": "pnpm run -F=client predevelop",
"lint": "npm-run-all create:* -p lint:*",
"lint:challenges": "cd ./curriculum && npm run lint",
"lint:challenges": "cd ./curriculum && pnpm run lint",
"lint:js": "eslint --max-warnings 0 .",
"lint:ts": "tsc && tsc -p config && tsc -p tools/ui-components && tsc -p utils",
"lint:prettier": "prettier --list-different .",
"seed": "cross-env DEBUG=fcc:* node ./tools/scripts/seed/seedAuthUser",
"seed:certified-user": "cross-env DEBUG=fcc:* node ./tools/scripts/seed/seedAuthUser certUser",
"serve:client": "cd ./client && npm run serve",
"serve:client-ci": "cd ./client && npm run serve-ci",
"serve:client": "cd ./client && pnpm run serve",
"serve:client-ci": "cd ./client && pnpm run serve-ci",
"start": "npm-run-all create:* -p develop:server serve:client",
"start-ci": "npm-run-all create:* -p start:server serve:client-ci",
"start:server": "cd ./api-server && npm start",
"storybook": "cd ./tools/ui-components && npm run storybook",
"start:server": "cd ./api-server && pnpm start",
"storybook": "cd ./tools/ui-components && pnpm run storybook",
"test": "run-s create:* build:curriculum build-workers test:*",
"test:source": "jest",
"test:curriculum": "cd ./curriculum && npm test",
"test-curriculum-full-output": "cd ./curriculum && npm run test:full-output",
"test:curriculum": "cd ./curriculum && pnpm test",
"test-curriculum-full-output": "cd ./curriculum && pnpm run test:full-output",
"test-client": "jest client",
"test-config": "jest config",
"test-curriculum-js": "jest curriculum",
@@ -125,36 +110,10 @@
"@testing-library/dom": "8.20.0",
"@testing-library/jest-dom": "5.16.5",
"@testing-library/user-event": "13.5.0",
"@types/chai": "4.3.4",
"@types/enzyme": "3.10.12",
"@types/enzyme-adapter-react-16": "1.0.6",
"@types/eslint": "7.29.0",
"@types/estree": "0.0.52",
"@types/inquirer": "8.2.6",
"@types/jest": "27.5.2",
"@types/jquery": "3.5.16",
"@types/loadable__component": "5.13.4",
"@types/lodash-es": "4.17.6",
"@types/lodash": "4.14.191",
"@types/node": "18.14.2",
"@types/prismjs": "1.26.0",
"@types/reach__router": "1.3.11",
"@types/react": "17.0.53",
"@types/react-dom": "17.0.19",
"@types/react-helmet": "6.1.6",
"@types/react-instantsearch-core": "6.26.3",
"@types/react-instantsearch-dom": "6.12.3",
"@types/react-monaco-editor": "0.16.0",
"@types/react-redux": "7.1.25",
"@types/react-responsive": "8.0.5",
"@types/react-spinkit": "3.0.7",
"@types/react-test-renderer": "17.0.2",
"@types/react-transition-group": "4.4.5",
"@types/redux-actions": "2.6.2",
"@types/sanitize-html": "2.8.0",
"@types/store": "2.0.2",
"@types/validator": "13.7.12",
"@typescript-eslint/eslint-plugin": "5.53.0",
"@typescript-eslint/parser": "5.53.0",
"babel-eslint": "10.1.0",
"babel-plugin-transform-imports": "2.0.0",
"cross-env": "7.0.3",
@@ -187,6 +146,7 @@
"process": "0.11.10",
"rimraf": "3.0.2",
"start-server-and-test": "1.15.5",
"store": "2.0.12",
"ts-node": "10.9.1",
"typescript": "4.9.5",
"webpack-bundle-analyzer": "4.8.0"

30002
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

15
pnpm-workspace.yaml Normal file
View File

@@ -0,0 +1,15 @@
packages:
- 'api'
- 'api-server'
- 'client'
- 'client/plugins/fcc-source-challenges'
- 'client/plugins/gatsby-remark-node-identity'
- 'curriculum'
- 'tools/challenge-editor/api'
- 'tools/challenge-editor/client'
- 'tools/challenge-helper-scripts'
- 'tools/challenge-parser'
- 'tools/crowdin'
- 'tools/scripts/build'
- 'tools/scripts/seed'
- 'tools/ui-components'

View File

@@ -10,9 +10,22 @@ config({ path: envPath });
import { availableLangs } from '../../config/i18n';
import { getChallengesForLang } from '../../curriculum/getChallenges';
import { SuperBlocks } from '../../config/certification-settings';
import { ChallengeNode } from '../../client/src/redux/prop-types';
import { getAuditedSuperBlocks } from '../../config/superblock-order';
// TODO: re-organise the types to a common 'types' folder that can be shared
// between the workspaces so we don't have to declare ChallengeNode here and in
// the client.
// This cannot be imported from the client, without causing tsc to attempt to
// compile the client (something it cannot do)
type ChallengeNode = {
block: string;
dashedName: string;
superBlock: SuperBlocks;
id: string;
challengeType: number;
};
const superBlockFolderMap = {
'responsive-web-design': '01-responsive-web-design',
'javascript-algorithms-and-data-structures':
@@ -53,7 +66,7 @@ const getChallenges = async (lang: string) => {
key => superBlock[key].challenges
);
return [...challengeArray, ...flatten(challengesForBlock)];
}, []) as unknown as ChallengeNode['challenge'][];
}, []) as unknown as ChallengeNode[];
};
/* eslint-enable @typescript-eslint/no-unsafe-return */

View File

@@ -16,6 +16,7 @@
"ts-node": "10.9.1"
},
"devDependencies": {
"@types/cors": "^2.8.13",
"@types/express": "4.17.17",
"dotenv": "16.0.3",
"shx": "0.3.4",

View File

@@ -9,19 +9,19 @@ const asyncExec = promisify(exec);
const toolsSwitch: ToolsSwitch = {
'create-next-step': directory => {
return asyncExec(`cd ${directory} && npm run create-next-step`);
return asyncExec(`cd ${directory} && pnpm run create-next-step`);
},
'create-empty-steps': (directory, num) => {
return asyncExec(`cd ${directory} && npm run create-empty-steps ${num}`);
return asyncExec(`cd ${directory} && pnpm run create-empty-steps ${num}`);
},
'insert-step': (directory, num) => {
return asyncExec(`cd ${directory} && npm run insert-step ${num}`);
return asyncExec(`cd ${directory} && pnpm run insert-step ${num}`);
},
'delete-step': (directory, num) => {
return asyncExec(`cd ${directory} && npm run delete-step ${num}`);
return asyncExec(`cd ${directory} && pnpm run delete-step ${num}`);
},
'update-step-titles': directory => {
return asyncExec(`cd ${directory} && npm run update-step-titles`);
return asyncExec(`cd ${directory} && pnpm run update-step-titles`);
}
};

View File

@@ -6,6 +6,7 @@
"@testing-library/jest-dom": "5.16.5",
"@testing-library/react": "12.1.5",
"@testing-library/user-event": "13.5.0",
"codemirror": "5",
"react": "16.14.0",
"react-codemirror2": "7.2.1",
"react-dom": "16.14.0",
@@ -33,8 +34,16 @@
"last 1 safari version"
]
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"devDependencies": {
"@types/codemirror": "5.60.7",
"@types/react": "16.14.0",
"@types/react-dom": "^16.9.17",
"cross-env": "7.0.3",
"eslint-plugin-react-hooks": "4.6.0",
"shx": "0.3.4"

View File

@@ -54,7 +54,7 @@ const SuperBlock = () => {
<p>
Want to create a new project? Open your terminal, point to the{' '}
<code>tools/challenge-helper-scripts</code> directory, and run{' '}
<code>npm run create-project</code>
<code>pnpm run create-project</code>
</p>
</div>
);

View File

@@ -262,6 +262,6 @@ void prompt([
)
.then(() =>
console.log(
'All set. Now use npm run clean:client in the root and it should be good to go.'
'All set. Now use pnpm run clean:client in the root and it should be good to go.'
)
);

View File

@@ -6,7 +6,7 @@
"private": true,
"engines": {
"node": ">=16",
"npm": ">=8"
"pnpm": "7"
},
"repository": {
"type": "git",
@@ -23,9 +23,12 @@
"create-project": "ts-node create-project"
},
"devDependencies": {
"@types/glob": "^8.0.1",
"@types/inquirer": "^8.2.5",
"@types/mock-fs": "4.13.1",
"bson-objectid": "2.0.4",
"cross-env": "7.0.3",
"glob": "^8.1.0",
"gray-matter": "4.0.3",
"inquirer": "8.2.5",
"prettier": "2.8.4",

View File

@@ -6,7 +6,7 @@
"private": true,
"engines": {
"node": ">=16",
"npm": ">=8"
"pnpm": "7"
},
"repository": {
"type": "git",

View File

@@ -2,6 +2,7 @@ import path from 'path';
import fs from 'fs';
import readdirp from 'readdirp';
// TODO: remove chai and use jest's assertion errors
import { AssertionError } from 'chai';
import envData from '../../../config/env.json';
import { SuperBlocks } from '../../../config/certification-settings';

View File

@@ -131,7 +131,7 @@ if (FREECODECAMP_NODE_ENV !== 'development') {
) {
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
console.log('Feature flags have been changed, cleaning client cache.');
const child = spawn('npm', ['run', 'clean:client']);
const child = spawn('pnpm', ['run', 'clean:client']);
child.stdout.setEncoding('utf8');
child.stdout.on('data', function (data) {
console.log(data);

View File

@@ -6,7 +6,7 @@
"private": true,
"engines": {
"node": ">=16",
"npm": ">=8"
"pnpm": "7"
},
"repository": {
"type": "git",
@@ -20,9 +20,13 @@
"main": "none",
"devDependencies": {
"@types/js-yaml": "4.0.5",
"@types/node-fetch": "2.6.2",
"chai": "4.3.7",
"debug": "4.3.4",
"dotenv": "16.0.3",
"joi": "17.7.0",
"js-yaml": "4.1.0",
"node-fetch": "2.6.9",
"readdirp": "3.6.0"
}
}

View File

@@ -6,7 +6,7 @@
"private": true,
"engines": {
"node": ">=16",
"npm": ">=8"
"pnpm": "7"
},
"repository": {
"type": "git",

View File

@@ -8,7 +8,7 @@
"private": true,
"engines": {
"node": ">=16",
"npm": ">=8"
"pnpm": "7"
},
"repository": {
"type": "git",
@@ -43,6 +43,9 @@
"@testing-library/jest-dom": "5.16.5",
"@testing-library/react": "12.1.5",
"@types/jest": "27.5.2",
"@types/react": "16.14.35",
"@types/react-dom": "^16.9.17",
"@types/testing-library__jest-dom": "^5",
"autoprefixer": "10.4.13",
"babel-loader": "8.3.0",
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
@@ -57,7 +60,7 @@
},
"scripts": {
"storybook": "start-storybook -p 6006",
"storybook:theming": "npm run storybook --no-manager-cache",
"storybook:theming": "pnpm run storybook --no-manager-cache",
"build-storybook": "build-storybook",
"build": "cross-env NODE_ENV=production rollup -c",
"build:css": "npx tailwindcss -i ./src/base.css -o ./dist/base.css --minify",

View File

@@ -8,8 +8,7 @@
"esModuleInterop": true,
"moduleResolution": "node",
"strict": true,
"noEmit": true,
"typeRoots": ["../../node_modules/@types"]
"noEmit": true
},
"ts-node": {
"compilerOptions": {

View File

@@ -14,7 +14,7 @@
"noEmit": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"types": ["node", "jest", "@testing-library/jest-dom", "cypress"]
"types": ["node", "jest", "cypress"]
},
// since ts-node compiles ts on the fly and then uses node, it needs to
// compile the scripts to commonjs (or node will complain about the requires)

View File

@@ -1,9 +1,5 @@
{
"include": [
"client/i18n/**/*",
"client/plugins/**/*",
"client/src/**/*",
"client/utils/**/*",
"curriculum/*.test.ts",
"tools/challenge-auditor/index.ts",
"tools/challenge-editor/**/*",

View File

@@ -11,7 +11,7 @@ cd ../curriculum-server
npm i
cd ../web
npm i
npm run dev
pnpm run dev
```
Now the server should be running on port 3000 and the client on port 8000.

View File

@@ -6,7 +6,7 @@
"private": true,
"engines": {
"node": ">=16",
"npm": ">=8"
"pnpm": "7"
},
"repository": {
"type": "git",