diff --git a/.eslintignore b/.eslintignore index b6b3ec9ff8..e528048818 100644 --- a/.eslintignore +++ b/.eslintignore @@ -5,6 +5,7 @@ api-server/src/public/** api-server/lib/** tools/contributor/** tools/scripts/build/ensure-env.js +tools/scripts/lint/validate-keys.js tools/scripts/build/tsconfig.tsbuildinfo config/i18n/all-langs.js config/certification-settings.js diff --git a/.eslintrc.json b/.eslintrc.json index 4d6f6fc7a9..332c7d8ff5 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -47,7 +47,7 @@ "project": [ "./tsconfig.json", "./tools/ui-components/tsconfig.json", - "./tools/scripts/build/tsconfig.json" + "./tools/tsconfig.json" ] }, "extends": [ diff --git a/.gitignore b/.gitignore index 527f49ec17..0719e79262 100644 --- a/.gitignore +++ b/.gitignore @@ -167,7 +167,8 @@ config/i18n/all-langs.js config/certification-settings.js tools/scripts/build/ensure-env.js -tools/scripts/build/tsconfig.tsbuildinfo +tools/tsconfig.tsbuildinfo +tools/scripts/lint/validate-keys.js ### vim ### # Swap diff --git a/.prettierignore b/.prettierignore index 449ccbf291..d782f937b9 100644 --- a/.prettierignore +++ b/.prettierignore @@ -10,4 +10,5 @@ config/certification-settings.js client/i18n/**/*.json docs/i18n **/package-lock.json -tools/scripts/build/ensure-env.js \ No newline at end of file +tools/scripts/build/ensure-env.js +tools/scripts/lint/validate-keys.js \ No newline at end of file diff --git a/client/package.json b/client/package.json index 3004952263..1caafa693e 100644 --- a/client/package.json +++ b/client/package.json @@ -19,18 +19,18 @@ "author": "freeCodeCamp ", "main": "none", "scripts": { - "prebuild": "tsc -p ../tools/scripts/build/ && node ../tools/scripts/build/ensure-env.js && npm run build:workers -- --env production", + "prebuild": "tsc -p ../tools/ && node ../tools/scripts/build/ensure-env.js && npm run build:workers -- --env production", "build": "node --max_old_space_size=7168 node_modules/gatsby-cli build --prefix-paths", "build:workers": "node --max_old_space_size=7168 node_modules/webpack-cli/bin/cli --config ./webpack-workers.js", "clean": "gatsby clean", - "predevelop": "tsc -p ../tools/scripts/build/ && node ../tools/scripts/build/ensure-env.js && npm run build:workers -- --env development", + "predevelop": "tsc -p ../tools/ && node ../tools/scripts/build/ensure-env.js && npm run build:workers -- --env development", "develop": "node --max_old_space_size=4000 node_modules/gatsby-cli develop --inspect=9230", "lint": "node ./i18n/schema-validation.js", "serve": "gatsby serve -p 8000", "serve-ci": "serve -l 8000 -c ../serve.json public", "prestand-alone": "npm run prebuild", "stand-alone": "gatsby develop", - "validate-keys": "node ./i18n/validate-keys.js" + "validate-keys": "tsc -p ../tools/ && node ../tools/scripts/lint/validate-keys.js" }, "dependencies": { "@babel/plugin-proposal-export-default-from": "7.16.0", diff --git a/package.json b/package.json index fdcfc2c978..d504afede7 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "build:server": "cd ./api-server && npm run build", "clean": "npm-run-all clean:build-files clean:client clean:server clean:packages clean:root-deps", "clean-and-develop": "npm run clean && npm ci && npm run develop", - "clean:build-files": "shx rm ./tools/scripts/build/tsconfig.tsbuildinfo", + "clean:build-files": "shx rm ./tools/tsconfig.tsbuildinfo", "clean:client": "cd ./client && npm run clean", "clean:curriculum": "shx rm ./config/curriculum.json", "clean:gatsby-site": "npm run clean:client", @@ -56,7 +56,7 @@ "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", - "ensure-env": "cd ./tools/scripts/build/ && tsc --incremental && cross-env DEBUG=fcc:* node ./ensure-env.js", + "ensure-env": "cd ./tools/ && tsc --incremental && cross-env DEBUG=fcc:* node ./scripts/build/ensure-env.js", "format": "run-s format:eslint format:prettier", "format:eslint": "eslint . --fix", "format:prettier": "prettier --write .", @@ -65,7 +65,7 @@ "lint": "npm-run-all ensure-env -p lint:*", "lint:challenges": "cd ./curriculum && npm run lint", "lint:js": "eslint --max-warnings 0 .", - "lint:ts": "tsc && tsc -p tools/ui-components && tsc -p tools/scripts/build", + "lint:ts": "tsc && tsc -p tools/ui-components && tsc -p tools", "lint:prettier": "prettier --list-different .", "postinstall": "npm run bootstrap", "seed": "cross-env DEBUG=fcc:* node ./tools/scripts/seed/seedAuthUser", diff --git a/tools/scripts/build/tsconfig.json b/tools/scripts/build/tsconfig.json deleted file mode 100644 index 32a028d99a..0000000000 --- a/tools/scripts/build/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "compilerOptions": { - "typeRoots": ["../../node_modules/@types"], - "types": ["node"] - } -} diff --git a/client/i18n/validate-keys.js b/tools/scripts/lint/validate-keys.ts similarity index 55% rename from client/i18n/validate-keys.js rename to tools/scripts/lint/validate-keys.ts index 264c0c1601..069596978c 100644 --- a/client/i18n/validate-keys.js +++ b/tools/scripts/lint/validate-keys.ts @@ -1,28 +1,32 @@ -const fs = require('fs'); -const path = require('path'); -const introObject = require('./locales/english/intro.json'); -const linksObject = require('./locales/english/links.json'); -const metaObject = require('./locales/english/meta-tags.json'); -const motivationObject = require('./locales/english/motivation.json'); -const translationsObject = require('./locales/english/translations.json'); -const trendingObject = require('./locales/english/trending.json'); +import fs from 'fs'; +import path from 'path'; +import introObject from '../../../client/i18n/locales/english/intro.json'; +import linksObject from '../../../client/i18n/locales/english/links.json'; +import metaObject from '../../../client/i18n/locales/english/meta-tags.json'; +import motivationObject from '../../../client/i18n/locales/english/motivation.json'; +import translationsObject from '../../../client/i18n/locales/english/translations.json'; +import trendingObject from '../../../client/i18n/locales/english/trending.json'; /** * Function to flatten a nested object. Written specifically for * our translation flow, the `namespace` value is used to create the * property chains that are used in the i18n replacement scripts. - * @param {Object} obj - * @param {string} namespace */ -const flattenAnObject = (obj, namespace = '') => { - const flattened = {}; - Object.keys(obj).forEach(key => { +const flattenAnObject = ( + obj: Record, + namespace = '' +): Record => { + const flattened: Record = {}; + Object.keys(obj).forEach((key: string) => { if (Array.isArray(obj[key])) { flattened[namespace ? `${namespace}.${key}` : key] = obj[key]; } else if (typeof obj[key] === 'object') { Object.assign( flattened, - flattenAnObject(obj[key], namespace ? `${namespace}.${key}` : key) + flattenAnObject( + obj[key] as Record, + namespace ? `${namespace}.${key}` : key + ) ); } else { flattened[namespace ? `${namespace}.${key}` : key] = obj[key]; @@ -31,25 +35,26 @@ const flattenAnObject = (obj, namespace = '') => { return flattened; }; -const translationKeys = Object.keys(flattenAnObject(translationsObject)); -const metaKeys = Object.keys(flattenAnObject(metaObject)); -const motivationKeys = Object.keys(flattenAnObject(motivationObject)); -const introKeys = Object.keys(flattenAnObject(introObject)); -const trendingKeys = Object.keys(flattenAnObject(trendingObject)); -const linksKeys = Object.keys(flattenAnObject(linksObject)); +const translationKeys: string[] = Object.keys( + flattenAnObject(translationsObject) +); +const metaKeys: string[] = Object.keys(flattenAnObject(metaObject)); +const motivationKeys: string[] = Object.keys(flattenAnObject(motivationObject)); +const introKeys: string[] = Object.keys(flattenAnObject(introObject)); +const trendingKeys: string[] = Object.keys(flattenAnObject(trendingObject)); +const linksKeys: string[] = Object.keys(flattenAnObject(linksObject)); /** * Recursively read through the directory, grabbing .js files * in each nested subdirectory and concatenating them all in * to one string. - * @param {String} filePath */ -const readComponentCode = filePath => { +const readComponentCode = (filePath: string): string => { let code = ''; - const isItFolder = fs.lstatSync(filePath).isDirectory(); + const isItFolder: boolean = fs.lstatSync(filePath).isDirectory(); if (isItFolder) { - const contents = fs.readdirSync(filePath); - contents.forEach(file => { + const contents: string[] = fs.readdirSync(filePath); + contents.forEach((file: string) => { code += readComponentCode(path.join(filePath + '/' + file)); }); } else { @@ -61,8 +66,10 @@ const readComponentCode = filePath => { return code; }; -const clientCodebase = readComponentCode(path.join(process.cwd() + '/src')); -const serverCodebase = readComponentCode( +const clientCodebase: string = readComponentCode( + path.join(process.cwd() + '/src') +); +const serverCodebase: string = readComponentCode( path.join(process.cwd() + '/../api-server/src/server') ); diff --git a/tools/tsconfig.json b/tools/tsconfig.json new file mode 100644 index 0000000000..c673ccc158 --- /dev/null +++ b/tools/tsconfig.json @@ -0,0 +1,13 @@ +{ + "include": [ + "./scripts/lint/validate-keys.ts", + "./scripts/build/ensure-env.ts" + ], + "compilerOptions": { + "esModuleInterop": true, + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "typeRoots": ["../node_modules/@types"], + "types": ["node"] + } +}