diff --git a/client/gatsby-browser.js b/client/gatsby-browser.tsx similarity index 74% rename from client/gatsby-browser.js rename to client/gatsby-browser.tsx index 648cacd4682..2aa5006d0d3 100644 --- a/client/gatsby-browser.js +++ b/client/gatsby-browser.tsx @@ -1,6 +1,6 @@ +import type { GatsbyBrowser } from 'gatsby'; import { LocationProvider } from '@gatsbyjs/reach-router'; import cookies from 'browser-cookies'; -import PropTypes from 'prop-types'; import React from 'react'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; @@ -15,7 +15,9 @@ import GrowthBookProvider from './src/components/growth-book/growth-book-wrapper const store = createStore(); -export const wrapRootElement = ({ element }) => { +export const wrapRootElement: GatsbyBrowser['wrapRootElement'] = ({ + element +}) => { return ( @@ -31,19 +33,16 @@ export const wrapRootElement = ({ element }) => { ); }; -wrapRootElement.propTypes = { - element: PropTypes.any -}; +export const wrapPageElement: GatsbyBrowser['wrapPageElement'] = layoutSelector; -export const wrapPageElement = layoutSelector; +export const disableCorePrefetching: GatsbyBrowser['disableCorePrefetching'] = + () => true; -export const disableCorePrefetching = () => true; - -export const onRouteUpdate = () => { +export const onRouteUpdate: GatsbyBrowser['onRouteUpdate'] = () => { store.dispatch({ type: 'app.routeUpdated' }); }; -export const onClientEntry = () => { +export const onClientEntry: GatsbyBrowser['onClientEntry'] = () => { // Letting the users' browsers expire the cookie seems to have caused issues // for some users. Until we have time to investigate further, we should remove // the cookie on every page load. diff --git a/client/gatsby-config.js b/client/gatsby-config.ts similarity index 77% rename from client/gatsby-config.js rename to client/gatsby-config.ts index b1ec33814ef..f2e9faa7349 100644 --- a/client/gatsby-config.js +++ b/client/gatsby-config.ts @@ -1,15 +1,17 @@ -const path = require('path'); -const envData = require('./config/env.json'); -const { +import path from 'path'; +import type { GatsbyConfig } from 'gatsby'; + +import envData from './config/env.json'; +import { buildChallenges, replaceChallengeNodes, localeChallengesRootDir -} = require('./utils/build-challenges'); -const { pathPrefix } = require('./utils/gatsby/path-prefix'); +} from './utils/build-challenges'; +import { pathPrefix } from './utils/gatsby/path-prefix'; -const { curriculumLocale, homeLocation } = envData; +const { homeLocation } = envData; -module.exports = { +const config: GatsbyConfig = { flags: { DEV_SSR: false }, @@ -43,13 +45,14 @@ module.exports = { } }, { - resolve: require.resolve( + resolve: path.resolve( + __dirname, '../tools/client-plugins/gatsby-source-challenges' ), options: { name: 'challenges', source: buildChallenges, - onSourceChange: replaceChallengeNodes(curriculumLocale), + onSourceChange: replaceChallengeNodes(), curriculumPath: localeChallengesRootDir } }, @@ -63,3 +66,5 @@ module.exports = { } ] }; + +export default config; diff --git a/client/gatsby-node.js b/client/gatsby-node.ts similarity index 76% rename from client/gatsby-node.js rename to client/gatsby-node.ts index 3c02cc94bdd..c11f0e8e378 100644 --- a/client/gatsby-node.js +++ b/client/gatsby-node.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-require-imports, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access */ const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); const webpack = require('webpack'); @@ -8,7 +9,7 @@ exports.createPages = async function createPages({ actions, graphql, reporter -}) { +}: any) { if (!env.algoliaAPIKey || !env.algoliaAppId) { if (process.env.FREECODECAMP_NODE_ENV === 'production') { throw new Error( @@ -45,13 +46,15 @@ exports.createPages = async function createPages({ } `); - const superBlocks = allSuperBlockStructure.nodes.map(node => node.superBlock); - superBlocks.forEach(superBlock => { + const superBlocks = allSuperBlockStructure.nodes.map( + (node: { superBlock: string }) => node.superBlock + ); + superBlocks.forEach((superBlock: string) => { createSuperBlockIntroPages(createPage)({ superBlock }); }); }; -exports.onCreateWebpackConfig = ({ stage, actions }) => { +exports.onCreateWebpackConfig = ({ stage, actions }: any) => { const newPlugins = [ // We add the shims of the node globals to the global scope new webpack.ProvidePlugin({ @@ -73,18 +76,18 @@ exports.onCreateWebpackConfig = ({ stage, actions }) => { resolve: { fallback: { fs: false, - path: require.resolve('path-browserify'), - assert: require.resolve('assert'), - crypto: require.resolve('crypto-browserify'), - util: require.resolve('util/util'), - buffer: require.resolve('buffer'), - stream: require.resolve('stream-browserify'), - process: require.resolve('process/browser') + path: 'path-browserify', + assert: 'assert', + crypto: 'crypto-browserify', + util: 'util/util', + buffer: 'buffer', + stream: 'stream-browserify', + process: 'process/browser' } }, plugins: newPlugins, ignoreWarnings: [ - warning => { + (warning: Error) => { if (warning instanceof Error) { if (warning.message.includes('mini-css-extract-plugin')) { return true; @@ -96,7 +99,7 @@ exports.onCreateWebpackConfig = ({ stage, actions }) => { }); }; -exports.onCreateBabelConfig = ({ actions }) => { +exports.onCreateBabelConfig = ({ actions }: any) => { actions.setBabelPlugin({ name: '@babel/plugin-proposal-function-bind' }); @@ -105,7 +108,7 @@ exports.onCreateBabelConfig = ({ actions }) => { }); }; -exports.createSchemaCustomization = ({ actions }) => { +exports.createSchemaCustomization = ({ actions }: any) => { const { createTypes } = actions; // This hook is supported by the test runner, but is not currently used by the // client, so we have to tell Gatsby that it exists. @@ -116,3 +119,5 @@ exports.createSchemaCustomization = ({ actions }) => { `; createTypes(typeDefs); }; + +export {}; diff --git a/client/gatsby-ssr.js b/client/gatsby-ssr.tsx similarity index 69% rename from client/gatsby-ssr.js rename to client/gatsby-ssr.tsx index 3f18b44a28f..e95022e8f50 100644 --- a/client/gatsby-ssr.js +++ b/client/gatsby-ssr.tsx @@ -1,4 +1,4 @@ -import PropTypes from 'prop-types'; +import type { GatsbySSR } from 'gatsby'; import React from 'react'; import { I18nextProvider } from 'react-i18next'; import { Provider } from 'react-redux'; @@ -18,7 +18,7 @@ import GrowthBookProvider from './src/components/growth-book/growth-book-wrapper const store = createStore(); -export const wrapRootElement = ({ element }) => { +export const wrapRootElement: GatsbySSR['wrapRootElement'] = ({ element }) => { return ( @@ -30,13 +30,9 @@ export const wrapRootElement = ({ element }) => { ); }; -wrapRootElement.propTypes = { - element: PropTypes.any -}; +export const wrapPageElement: GatsbySSR['wrapPageElement'] = layoutSelector; -export const wrapPageElement = layoutSelector; - -export const onRenderBody = ({ +export const onRenderBody: GatsbySSR['onRenderBody'] = ({ pathname, setHeadComponents, setPreBodyComponents, @@ -47,15 +43,21 @@ export const onRenderBody = ({ setPostBodyComponents(getPostBodyComponents(pathname)); }; -export const onPreRenderHTML = ({ +export const onPreRenderHTML: GatsbySSR['onPreRenderHTML'] = ({ getHeadComponents, replaceHeadComponents }) => { + const isBootstrapScript = (key: React.Key | null) => + key === 'bootstrap-min-preload' || key === 'bootstrap-min'; + const headComponents = getHeadComponents(); headComponents.sort((x, y) => { - if (x.key === 'bootstrap-min-preload' || x.key === 'bootstrap-min') { + const xKey = React.isValidElement(x) ? x.key : null; + const yKey = React.isValidElement(y) ? y.key : null; + + if (isBootstrapScript(xKey)) { return -1; - } else if (y.key === 'bootstrap-min-preload' || y.key === 'bootstrap-min') { + } else if (isBootstrapScript(yKey)) { return 1; } return 0; diff --git a/client/package.json b/client/package.json index a0e8541c8c3..c6d7cb1f1c4 100644 --- a/client/package.json +++ b/client/package.json @@ -17,7 +17,7 @@ }, "homepage": "https://github.com/freeCodeCamp/freeCodeCamp#readme", "author": "freeCodeCamp ", - "main": "none", + "main": "index.js", "scripts": { "build": "NODE_OPTIONS=\"--max-old-space-size=7168 --no-deprecation\" gatsby build --prefix-paths", "clean": "gatsby clean", diff --git a/client/tsconfig.json b/client/tsconfig.json index d7aed2c630a..d738b3c9fda 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -16,6 +16,8 @@ "skipLibCheck": true }, "include": [ + "gatsby-*.ts", + "gatsby-*.tsx", "i18n/**/*", "plugins/**/*", "src/**/*",