Skip to content

Commit

Permalink
feat: download trending footer links json before builds (#1083)
Browse files Browse the repository at this point in the history
  • Loading branch information
scissorsneedfoodtoo authored Dec 16, 2024
1 parent 90b134c commit 420d5cd
Show file tree
Hide file tree
Showing 6 changed files with 263 additions and 35 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,7 @@ dist/
cypress/videos
cypress/screenshots

# Generated config
config/i18n/locales/**/trending.json

docker/languages/
33 changes: 1 addition & 32 deletions config/i18n/config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
const i18next = require('i18next');
const Backend = require('i18next-fs-backend');
const fetch = require('node-fetch');
const yaml = require('js-yaml');
const { readdirSync, lstatSync } = require('fs');
const { join } = require('path');
const {
Expand All @@ -18,40 +16,11 @@ i18next.use(Backend).init({
const isDirectory = lstatSync(joinedPath).isDirectory();
return isDirectory;
}),
ns: ['translations', 'meta-tags', 'links'],
ns: ['translations', 'meta-tags', 'links', 'trending'],
defaultNS: 'translations',
backend: {
loadPath: join(__dirname, `./locales/${currentLocale_i18n}/{{ ns }}.json`)
}
});

(async () => {
const url = `https://cdn.freecodecamp.org/universal/trending/${currentLocale_i18n}.yaml`;
const trendingYAML = await fetch(url)
.then(res => {
if (!res.ok) {
throw new Error(
`
----------------------------------------------------
Error: The CDN is missing the trending YAML file.
----------------------------------------------------
Unable to fetch the ${currentLocale_i18n} footer: ${res.statusText}
`
);
}
return res;
})
.then(res => res.text());
const trendingJSON = yaml.load(trendingYAML);

i18next.addResources(currentLocale_i18nISOCode, 'trending', trendingJSON);
})().catch(err => {
console.log(err); // Log js-yaml or fetch errors
process.exit(1); // Forcefully exit
});

module.exports = i18next;
105 changes: 105 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@
"cypress:run:espanol": "npm run cypress -- run --spec 'cypress/e2e/espanol/**/*'",
"cypress:watch": "npm run cypress -- open",
"dev": "npm run develop",
"predevelop": "npm run clean",
"predevelop": "npm run clean && node ./tools/download-trending.js",
"develop": "cross-env ELEVENTY_ENV=dev NODE_OPTIONS=--max-old-space-size=8192 eleventy --serve",
"predevelop:ci": "npm run clean",
"predevelop:ci": "npm run clean && node ./tools/download-trending.js",
"develop:ci": "cross-env ELEVENTY_ENV=ci NODE_OPTIONS=--max-old-space-size=8192 eleventy --serve",
"prebuild": "npm run clean",
"prebuild": "npm run clean && node ./tools/download-trending.js",
"build": "cross-env ELEVENTY_ENV=prod NODE_OPTIONS=--max-old-space-size=8192 eleventy",
"build:ci": "cross-env ELEVENTY_ENV=ci eleventy",
"postbuild": "node ./config/i18n/generate-serve-config.js",
Expand Down Expand Up @@ -90,6 +90,7 @@
"i18next-fs-backend": "2.6.0",
"jest": "29.7.0",
"jest-json-schema-extended": "1.0.1",
"joi": "17.13.3",
"js-yaml": "4.1.0",
"jsdom": "24.1.3",
"libxmljs": "1.0.11",
Expand Down
82 changes: 82 additions & 0 deletions tools/download-trending.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
const { readFileSync, writeFileSync } = require('fs');
const path = require('path');
const fetch = require('node-fetch');
const yaml = require('js-yaml');

const { currentLocale_i18n } = require('../config');
const trendingSchemaValidator = require('./schemas/trending-schema');

const download = async clientLocale => {
const trendingURL = `https://cdn.freecodecamp.org/universal/trending/${clientLocale}.yaml`;
const trendingLocation = path.resolve(
__dirname,
`../config/i18n/locales/${clientLocale}/trending.json`
);

const loadLocalTrendingJSON = () => {
const localTrendingJSON = readFileSync(trendingLocation, 'utf8');

if (!localTrendingJSON) {
throw new Error(
`
----------------------------------------------------
Error: ${trendingLocation} is missing.
----------------------------------------------------
`
);
}

return localTrendingJSON;
};

const loadTrendingJSON = async () => {
try {
const res = await fetch(trendingURL);

if (!res.ok) {
throw new Error(
`
----------------------------------------------------
Error: The CDN is missing the trending YAML file.
----------------------------------------------------
Unable to fetch the ${clientLocale} footer: ${res.statusText}
`
);
}

const data = await res.text();
const trendingJSON = JSON.stringify(yaml.load(data));

return trendingJSON;
} catch (err) {
if (process.env.FREECODECAMP_NODE_ENV === 'production') {
throw new Error(err.message);
}

return loadLocalTrendingJSON();
}
};

const trendingJSON = await loadTrendingJSON();

writeFileSync(trendingLocation, trendingJSON);

const trendingObject = JSON.parse(trendingJSON);
const validationError = trendingSchemaValidator(trendingObject).error || null;

if (validationError) {
throw new Error(
`
----------------------------------------------------
Error: The trending JSON is invalid.
----------------------------------------------------
Unable to validate the ${clientLocale} trending JSON schema: ${validationError.message}
`
);
}
};

if (!currentLocale_i18n)
throw Error('currentLocale_i18n must be set to a valid locale');

download(currentLocale_i18n);
68 changes: 68 additions & 0 deletions tools/schemas/trending-schema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const Joi = require('joi');

const schema = Joi.object().keys({
article0title: Joi.string().required(),
article0link: Joi.string().uri({ scheme: 'https' }).required(),
article1title: Joi.string().required(),
article1link: Joi.string().uri({ scheme: 'https' }).required(),
article2title: Joi.string().required(),
article2link: Joi.string().uri({ scheme: 'https' }).required(),
article3title: Joi.string().required(),
article3link: Joi.string().uri({ scheme: 'https' }).required(),
article4title: Joi.string().required(),
article4link: Joi.string().uri({ scheme: 'https' }).required(),
article5title: Joi.string().required(),
article5link: Joi.string().uri({ scheme: 'https' }).required(),
article6title: Joi.string().required(),
article6link: Joi.string().uri({ scheme: 'https' }).required(),
article7title: Joi.string().required(),
article7link: Joi.string().uri({ scheme: 'https' }).required(),
article8title: Joi.string().required(),
article8link: Joi.string().uri({ scheme: 'https' }).required(),
article9title: Joi.string().required(),
article9link: Joi.string().uri({ scheme: 'https' }).required(),
article10title: Joi.string().required(),
article10link: Joi.string().uri({ scheme: 'https' }).required(),
article11title: Joi.string().required(),
article11link: Joi.string().uri({ scheme: 'https' }).required(),
article12title: Joi.string().required(),
article12link: Joi.string().uri({ scheme: 'https' }).required(),
article13title: Joi.string().required(),
article13link: Joi.string().uri({ scheme: 'https' }).required(),
article14title: Joi.string().required(),
article14link: Joi.string().uri({ scheme: 'https' }).required(),
article15title: Joi.string().required(),
article15link: Joi.string().uri({ scheme: 'https' }).required(),
article16title: Joi.string().required(),
article16link: Joi.string().uri({ scheme: 'https' }).required(),
article17title: Joi.string().required(),
article17link: Joi.string().uri({ scheme: 'https' }).required(),
article18title: Joi.string().required(),
article18link: Joi.string().uri({ scheme: 'https' }).required(),
article19title: Joi.string().required(),
article19link: Joi.string().uri({ scheme: 'https' }).required(),
article20title: Joi.string().required(),
article20link: Joi.string().uri({ scheme: 'https' }).required(),
article21title: Joi.string().required(),
article21link: Joi.string().uri({ scheme: 'https' }).required(),
article22title: Joi.string().required(),
article22link: Joi.string().uri({ scheme: 'https' }).required(),
article23title: Joi.string().required(),
article23link: Joi.string().uri({ scheme: 'https' }).required(),
article24title: Joi.string().required(),
article24link: Joi.string().uri({ scheme: 'https' }).required(),
article25title: Joi.string().required(),
article25link: Joi.string().uri({ scheme: 'https' }).required(),
article26title: Joi.string().required(),
article26link: Joi.string().uri({ scheme: 'https' }).required(),
article27title: Joi.string().required(),
article27link: Joi.string().uri({ scheme: 'https' }).required(),
article28title: Joi.string().required(),
article28link: Joi.string().uri({ scheme: 'https' }).required(),
article29title: Joi.string().required(),
article29link: Joi.string().uri({ scheme: 'https' }).required()
});

const trendingSchemaValidator = trendingObj => schema.validate(trendingObj);

module.exports = trendingSchemaValidator;

0 comments on commit 420d5cd

Please sign in to comment.