feat: add redirect processing script
This commit is contained in:
2
apps/scandic-redirect/.gitignore
vendored
Normal file
2
apps/scandic-redirect/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
scripts/csv/*.csv
|
||||
scripts/json/*.json
|
||||
@@ -6,3 +6,20 @@ This function will be called by the `web` app's middleware to check if the incom
|
||||
The "source of truth" for which URLs should be redirected where will be provided by the SEO team and put in a JSON file within this app.
|
||||
|
||||
If no match for the incoming request is found, the request is passed on through the middleware.
|
||||
|
||||
## Update the redirects from the source
|
||||
|
||||
The Excel source file used is located at:
|
||||
|
||||
https://scandichotelsab.sharepoint.com/:x:/s/921-ContentNewweb/ETGStOQAARtJhJXG9dy8ijYBccpmKhLVjS2SF_2E69QrAQ
|
||||
|
||||
- Open it
|
||||
- Each domain/language has its own sheet
|
||||
- Export each sheet into their respective language code
|
||||
- File > Export > Download as CSV UTF-8
|
||||
- Save as [lang].csv in `./scripts/csv` folder
|
||||
- Run the `update` script target
|
||||
- E.g. `yarn workspace @scandic-hotels/scandic-redirect update`
|
||||
- Commit and push the JSON files in `./netlify/functions/data`.
|
||||
- Create a PR
|
||||
- Profit!
|
||||
|
||||
@@ -5,5 +5,11 @@
|
||||
"packageManager": "yarn@4.6.0",
|
||||
"dependencies": {
|
||||
"@netlify/functions": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"convert-csv-to-json": "^3.4.0"
|
||||
},
|
||||
"scripts": {
|
||||
"update": "node ./scripts/update.mjs"
|
||||
}
|
||||
}
|
||||
|
||||
0
apps/scandic-redirect/scripts/csv/.gitkeep
Normal file
0
apps/scandic-redirect/scripts/csv/.gitkeep
Normal file
0
apps/scandic-redirect/scripts/json/.gitkeep
Normal file
0
apps/scandic-redirect/scripts/json/.gitkeep
Normal file
138
apps/scandic-redirect/scripts/update.mjs
Normal file
138
apps/scandic-redirect/scripts/update.mjs
Normal file
@@ -0,0 +1,138 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
import csvToJson from 'convert-csv-to-json';
|
||||
|
||||
const langs = ['da', 'de', 'en', 'fi', 'no', 'sv'];
|
||||
const csvHeaders = {
|
||||
current: 'Current URL',
|
||||
redirect: 'Redirect URL',
|
||||
};
|
||||
|
||||
function csvFilePath(lang) {
|
||||
return `${import.meta.dirname}/csv/${lang}.csv`;
|
||||
}
|
||||
|
||||
function jsonFilePath(lang) {
|
||||
return `${import.meta.dirname}/json/${lang}.json`;
|
||||
}
|
||||
|
||||
function outputFilepath(lang) {
|
||||
return path.resolve(
|
||||
import.meta.dirname,
|
||||
`../netlify/functions/data/${lang}.json`
|
||||
);
|
||||
}
|
||||
|
||||
function removeDomain(str) {
|
||||
return str.replace(
|
||||
/^https?:\/\/((www|test|stage|prod)\.)?scandichotels.(com|de|dk|fi|no|se)/,
|
||||
''
|
||||
);
|
||||
}
|
||||
|
||||
function akamaiRedirect(str) {
|
||||
return str.replace(
|
||||
/^https?:\/\/((www|test|stage|prod)\.)?scandichotels.(com|de|dk|fi|no|se)/,
|
||||
(...match) => {
|
||||
if (match[3]) {
|
||||
switch (match[3]) {
|
||||
case 'com':
|
||||
return '/en';
|
||||
case 'de':
|
||||
return '/de';
|
||||
case 'dk':
|
||||
return '/da';
|
||||
case 'fi':
|
||||
return '/fi';
|
||||
case 'no':
|
||||
return '/no';
|
||||
case 'se':
|
||||
return '/sv';
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function checkPrerequisites() {
|
||||
const missingLangs = langs.reduce((acc, lang) => {
|
||||
const filepath = csvFilePath(lang);
|
||||
if (!fs.existsSync(filepath)) {
|
||||
acc.push(filepath);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
if (missingLangs.length > 0) {
|
||||
console.error(`Missing CSV file:\n${missingLangs.join('\n')}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// convert-csv-to-json writes async without callback support
|
||||
// so we workaround it be overriding console.log which it uses when it is done
|
||||
async function convertCsvToJson() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const _consoleLog = console.log;
|
||||
let resolved = 0;
|
||||
console.log = function (str) {
|
||||
if (str.indexOf('File saved:') >= 0) {
|
||||
resolved++;
|
||||
}
|
||||
|
||||
if (resolved === langs.length) {
|
||||
console.log = _consoleLog;
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
|
||||
for (const lang of langs) {
|
||||
csvToJson
|
||||
.utf8Encoding()
|
||||
.fieldDelimiter(',')
|
||||
.generateJsonFileFromCsv(csvFilePath(lang), jsonFilePath(lang));
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
reject('timeout');
|
||||
}, 5000);
|
||||
});
|
||||
}
|
||||
|
||||
async function makeOutput() {
|
||||
for (const lang of langs) {
|
||||
try {
|
||||
const json = JSON.parse(
|
||||
fs.readFileSync(jsonFilePath(lang), {
|
||||
encoding: 'utf-8',
|
||||
})
|
||||
);
|
||||
|
||||
if (Array.isArray(json)) {
|
||||
const finalUrls = json.reduce((acc, url) => {
|
||||
const from = removeDomain(akamaiRedirect(url[csvHeaders.current]));
|
||||
const to = removeDomain(url[csvHeaders.redirect]);
|
||||
|
||||
return {
|
||||
...acc,
|
||||
[from]: to,
|
||||
};
|
||||
}, {});
|
||||
|
||||
fs.writeFileSync(outputFilepath(lang), JSON.stringify(finalUrls), {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
} else {
|
||||
throw new Error(`JSON was not an array: ${jsonFilePath(lang)}`);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkPrerequisites();
|
||||
await convertCsvToJson();
|
||||
await makeOutput();
|
||||
@@ -7052,6 +7052,7 @@ __metadata:
|
||||
resolution: "@scandic-hotels/scandic-redirect@workspace:apps/scandic-redirect"
|
||||
dependencies:
|
||||
"@netlify/functions": "npm:^3.0.0"
|
||||
convert-csv-to-json: "npm:^3.4.0"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@@ -11775,6 +11776,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"convert-csv-to-json@npm:^3.4.0":
|
||||
version: 3.4.0
|
||||
resolution: "convert-csv-to-json@npm:3.4.0"
|
||||
checksum: 10c0/06ec3cb348591322b9b2083464eff41907688d6eb4cb8b364d7d969ea08eb559d872733292034f72dcf404fe3150def092194ccfe14d89ded3b35dfc694fdb87
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"convert-source-map@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "convert-source-map@npm:2.0.0"
|
||||
|
||||
Reference in New Issue
Block a user