@americanexpress/holocron-dev-server
Version:
A micro-frontend dev server for Holocron Modules
153 lines (137 loc) • 5.45 kB
JavaScript
/*
* Copyright 2021 American Express Travel Related Services Company, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations
* under the License.
*/
import path from 'node:path';
import jsonParse from 'json-parse-context';
import { volume, ufs } from './virtual-file-system';
import { getModulesPath, getLocalesPathForModule } from './paths';
import { logModuleLanguagePacksLoaded } from './logs';
import { createLanguagePackWatcher } from './watcher';
export const localePathName = 'locale';
export const languagePackFileNames = ['copy', 'integration'];
export function readJsonFile(filePath) {
const json = ufs.readFileSync(filePath).toString();
return jsonParse(json);
}
export function loadModuleLanguagePack({
moduleName, modulePath, localePath = localePathName, locale,
}) {
let languagePackPath = path.join(modulePath, localePath, locale);
if (!ufs.existsSync(languagePackPath)) {
languagePackPath = path.join(modulePath, localePath, `${locale}.json`);
}
if (ufs.existsSync(languagePackPath)) {
const fileStats = ufs.statSync(languagePackPath);
if (fileStats.isDirectory()) {
const languagePack = {};
const scan = [
...languagePackFileNames,
locale,
moduleName,
];
scan
.map((fileName) => `${fileName}.json`)
.map((fileName) => path.join(languagePackPath, fileName))
.filter((filePath) => ufs.existsSync(filePath))
.forEach((filePath) => {
Object.assign(languagePack, readJsonFile(filePath));
}
);
const directories = ufs.readdirSync(languagePackPath, { withFileTypes: true })
.filter((files) => files.isDirectory()).map((files) => files.name);
if (directories.length > 0) {
directories.forEach((directoryName) => {
scan
.map((fileName) => path.join(languagePackPath, directoryName, `${fileName}.json`))
.filter((directoryFilePath) => ufs.existsSync(directoryFilePath))
.forEach((directoryFilePath) => {
languagePack[directoryName] = readJsonFile(directoryFilePath);
});
}
);
}
return languagePack;
}
if (fileStats.isFile()) {
return readJsonFile(languagePackPath);
}
}
return null;
}
export function loadModuleLanguagePacks({ moduleName, modulePath, localePath = localePathName }) {
const languagePacksPath = path.join(modulePath, localePath);
if (!ufs.existsSync(languagePacksPath)) return [];
return ufs
.readdirSync(languagePacksPath)
.map((locale) => locale.replace(/(\..*)$/, '').toLowerCase())
.map((locale) => [
locale,
loadModuleLanguagePack({
moduleName, modulePath, localePath, locale,
}),
])
.filter(([, languagePack]) => !!languagePack);
}
export function writeModuleLanguagePacksToVolume({
modulePath,
moduleName,
localePath = localePathName,
}) {
const languagePacks = loadModuleLanguagePacks({ moduleName, modulePath, localePath });
const locales = languagePacks.reduce(
(map, [locale, langPack]) => ({
...map,
[[locale, `${moduleName}.json`].join('/')]: JSON.stringify(langPack),
}),
{}
);
volume.fromJSON(locales, getModulesPath(moduleName));
return languagePacks.map(([locale]) => locale);
}
export function addModuleLanguagePackToVolume({ filePath, moduleName, locale }) {
const localeSymbol = locale.replace(/(\..*)$/, '').toLowerCase();
const modulePath = filePath.split('/').reduce((pathName, next) => (pathName.endsWith(moduleName) ? pathName : [pathName, next].join('/')), '');
const langPack = loadModuleLanguagePack({
moduleName, modulePath, locale: localeSymbol,
});
const bundlePath = getModulesPath([moduleName, localeSymbol, `${moduleName}.json`].join('/'));
volume.writeFileSync(bundlePath, JSON.stringify(langPack));
}
export function removeModuleLanguagePackFromVolume({ moduleName, locale }) {
const localeFilePath = getModulesPath(
[moduleName, locale.replace(/(\..*)$/, '').toLowerCase(), `${moduleName}.json`].join('/')
);
volume.unlinkSync(localeFilePath);
volume.rmdirSync(localeFilePath.replace(`/${moduleName}.json`, ''));
}
export function loadLanguagePacks({ modules = [] } = {}) {
const modulePaths = modules
.filter(({ modulePath }) => ufs.existsSync(getLocalesPathForModule(modulePath)))
.map(({ modulePath }) => modulePath);
if (modulePaths.length > 0) {
modulePaths.forEach((modulePath) => {
const [moduleName] = modulePath.split(path.sep).reverse();
const languagePacks = writeModuleLanguagePacksToVolume({ modulePath, moduleName });
logModuleLanguagePacksLoaded({ moduleName, languagePacks });
});
return createLanguagePackWatcher(
{ modules },
{
add: addModuleLanguagePackToVolume,
change: addModuleLanguagePackToVolume,
remove: removeModuleLanguagePackFromVolume,
}
);
}
return Promise.resolve();
}