Skip to content

Commit

Permalink
feat(settings): replaces dynamic import with getting a ready static m…
Browse files Browse the repository at this point in the history
…odule loader (#46)

* fix(settings): replaces dynamic import with getting a ready static module loader

* feat(settings): adds a script to automatically update locales

* fix(scripts): optimizes the script by reducing the number of i/o operations to one

* fix(scripts): uses the node_modules package as the source and adds the call to package.json

---------

Co-authored-by: Alex Komz <[email protected]>
  • Loading branch information
a1eksandrk and Alex Komz authored Jan 25, 2024
1 parent 174ae2a commit d9f46a8
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 2 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"test:watch": "jest --watchAll",
"typecheck": "tsc --noEmit",
"prepublishOnly": "npm run lint && npm run test && npm run build",
"updateLocales": "node scripts/updateLocales.js",
"prepare": "husky install"
},
"files": [
Expand Down
75 changes: 75 additions & 0 deletions scripts/updateLocales.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Fetches and writes to the locale file from github dayjs
* node.js >= 20 lts
* @module Locale
* */

const fs = require('node:fs');
const fsPromises = require('node:fs/promises');

const VALID_FILE_PATTERN = /^((?!index).)*.js$/;
const LOCALES_PATH = 'src/settings/locales.ts';
const LOCALES_DIR_PATH = 'node_modules/dayjs/locale';

const getLocalesList = async (localesDirPath) => {
if (fs.existsSync(localesDirPath)) {
const localesList = await fsPromises.readdir(localesDirPath);
return localesList.filter((locale) => VALID_FILE_PATTERN.test(locale));
}

throw new Error(
'The script was called before the dayjs library was installed, install it and try again',
);
};

const createLocalesFile = async (localesPath) => {
if (fs.existsSync(localesPath)) {
await fsPromises.rm(localesPath);
}

return await fsPromises.open(localesPath, 'w');
};

const buildLocalesContent = (localesList) => {
const isEmptyStr = (s) => !s.length || !s;

const localeChunks = [];

localeChunks.push("type LocaleLoader = () => Promise<typeof import('dayjs/locale/*.js')>;\n");
localeChunks.push('export const localeLoaders: Record<string, LocaleLoader> = {');

localesList.forEach((locale) => {
if (isEmptyStr(locale)) return;

const name = locale.substring(0, locale.lastIndexOf('.'));
const localeName = name.includes('-') ? `'${name}'` : name;

localeChunks.push(` ${localeName}: () => import('dayjs/locale/${locale}'),`);
});

localeChunks.push('};\n');

return localeChunks.join('\n');
};

(async function () {
try {
const localesList = await getLocalesList(LOCALES_DIR_PATH);

console.info('Locales loaded successfully');

Check warning on line 59 in scripts/updateLocales.js

View workflow job for this annotation

GitHub Actions / Verify Files

Unexpected console statement

const localeFile = await createLocalesFile(LOCALES_PATH);

console.info(`File "${LOCALES_PATH}" created successfully`);

Check warning on line 63 in scripts/updateLocales.js

View workflow job for this annotation

GitHub Actions / Verify Files

Unexpected console statement

const localesContent = buildLocalesContent(localesList);

console.info(`File content built successfully`);

Check warning on line 67 in scripts/updateLocales.js

View workflow job for this annotation

GitHub Actions / Verify Files

Unexpected console statement

await localeFile.appendFile(localesContent);

console.info(`Object "localeLoaders" written in file "${LOCALES_PATH}" successfully`);

Check warning on line 71 in scripts/updateLocales.js

View workflow job for this annotation

GitHub Actions / Verify Files

Unexpected console statement
} catch (error) {
console.error(error);

Check warning on line 73 in scripts/updateLocales.js

View workflow job for this annotation

GitHub Actions / Verify Files

Unexpected console statement
}
})();
147 changes: 147 additions & 0 deletions src/settings/locales.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
type LocaleLoader = () => Promise<typeof import('dayjs/locale/*.js')>;

export const localeLoaders: Record<string, LocaleLoader> = {
af: () => import('dayjs/locale/af.js'),
am: () => import('dayjs/locale/am.js'),
'ar-dz': () => import('dayjs/locale/ar-dz.js'),
'ar-iq': () => import('dayjs/locale/ar-iq.js'),
'ar-kw': () => import('dayjs/locale/ar-kw.js'),
'ar-ly': () => import('dayjs/locale/ar-ly.js'),
'ar-ma': () => import('dayjs/locale/ar-ma.js'),
'ar-sa': () => import('dayjs/locale/ar-sa.js'),
'ar-tn': () => import('dayjs/locale/ar-tn.js'),
ar: () => import('dayjs/locale/ar.js'),
az: () => import('dayjs/locale/az.js'),
be: () => import('dayjs/locale/be.js'),
bg: () => import('dayjs/locale/bg.js'),
bi: () => import('dayjs/locale/bi.js'),
bm: () => import('dayjs/locale/bm.js'),
'bn-bd': () => import('dayjs/locale/bn-bd.js'),
bn: () => import('dayjs/locale/bn.js'),
bo: () => import('dayjs/locale/bo.js'),
br: () => import('dayjs/locale/br.js'),
bs: () => import('dayjs/locale/bs.js'),
ca: () => import('dayjs/locale/ca.js'),
cs: () => import('dayjs/locale/cs.js'),
cv: () => import('dayjs/locale/cv.js'),
cy: () => import('dayjs/locale/cy.js'),
da: () => import('dayjs/locale/da.js'),
'de-at': () => import('dayjs/locale/de-at.js'),
'de-ch': () => import('dayjs/locale/de-ch.js'),
de: () => import('dayjs/locale/de.js'),
dv: () => import('dayjs/locale/dv.js'),
el: () => import('dayjs/locale/el.js'),
'en-au': () => import('dayjs/locale/en-au.js'),
'en-ca': () => import('dayjs/locale/en-ca.js'),
'en-gb': () => import('dayjs/locale/en-gb.js'),
'en-ie': () => import('dayjs/locale/en-ie.js'),
'en-il': () => import('dayjs/locale/en-il.js'),
'en-in': () => import('dayjs/locale/en-in.js'),
'en-nz': () => import('dayjs/locale/en-nz.js'),
'en-sg': () => import('dayjs/locale/en-sg.js'),
'en-tt': () => import('dayjs/locale/en-tt.js'),
en: () => import('dayjs/locale/en.js'),
eo: () => import('dayjs/locale/eo.js'),
'es-do': () => import('dayjs/locale/es-do.js'),
'es-mx': () => import('dayjs/locale/es-mx.js'),
'es-pr': () => import('dayjs/locale/es-pr.js'),
'es-us': () => import('dayjs/locale/es-us.js'),
es: () => import('dayjs/locale/es.js'),
et: () => import('dayjs/locale/et.js'),
eu: () => import('dayjs/locale/eu.js'),
fa: () => import('dayjs/locale/fa.js'),
fi: () => import('dayjs/locale/fi.js'),
fo: () => import('dayjs/locale/fo.js'),
'fr-ca': () => import('dayjs/locale/fr-ca.js'),
'fr-ch': () => import('dayjs/locale/fr-ch.js'),
fr: () => import('dayjs/locale/fr.js'),
fy: () => import('dayjs/locale/fy.js'),
ga: () => import('dayjs/locale/ga.js'),
gd: () => import('dayjs/locale/gd.js'),
gl: () => import('dayjs/locale/gl.js'),
'gom-latn': () => import('dayjs/locale/gom-latn.js'),
gu: () => import('dayjs/locale/gu.js'),
he: () => import('dayjs/locale/he.js'),
hi: () => import('dayjs/locale/hi.js'),
hr: () => import('dayjs/locale/hr.js'),
ht: () => import('dayjs/locale/ht.js'),
hu: () => import('dayjs/locale/hu.js'),
'hy-am': () => import('dayjs/locale/hy-am.js'),
id: () => import('dayjs/locale/id.js'),
is: () => import('dayjs/locale/is.js'),
'it-ch': () => import('dayjs/locale/it-ch.js'),
it: () => import('dayjs/locale/it.js'),
ja: () => import('dayjs/locale/ja.js'),
jv: () => import('dayjs/locale/jv.js'),
ka: () => import('dayjs/locale/ka.js'),
kk: () => import('dayjs/locale/kk.js'),
km: () => import('dayjs/locale/km.js'),
kn: () => import('dayjs/locale/kn.js'),
ko: () => import('dayjs/locale/ko.js'),
ku: () => import('dayjs/locale/ku.js'),
ky: () => import('dayjs/locale/ky.js'),
lb: () => import('dayjs/locale/lb.js'),
lo: () => import('dayjs/locale/lo.js'),
lt: () => import('dayjs/locale/lt.js'),
lv: () => import('dayjs/locale/lv.js'),
me: () => import('dayjs/locale/me.js'),
mi: () => import('dayjs/locale/mi.js'),
mk: () => import('dayjs/locale/mk.js'),
ml: () => import('dayjs/locale/ml.js'),
mn: () => import('dayjs/locale/mn.js'),
mr: () => import('dayjs/locale/mr.js'),
'ms-my': () => import('dayjs/locale/ms-my.js'),
ms: () => import('dayjs/locale/ms.js'),
mt: () => import('dayjs/locale/mt.js'),
my: () => import('dayjs/locale/my.js'),
nb: () => import('dayjs/locale/nb.js'),
ne: () => import('dayjs/locale/ne.js'),
'nl-be': () => import('dayjs/locale/nl-be.js'),
nl: () => import('dayjs/locale/nl.js'),
nn: () => import('dayjs/locale/nn.js'),
'oc-lnc': () => import('dayjs/locale/oc-lnc.js'),
'pa-in': () => import('dayjs/locale/pa-in.js'),
pl: () => import('dayjs/locale/pl.js'),
'pt-br': () => import('dayjs/locale/pt-br.js'),
pt: () => import('dayjs/locale/pt.js'),
rn: () => import('dayjs/locale/rn.js'),
ro: () => import('dayjs/locale/ro.js'),
ru: () => import('dayjs/locale/ru.js'),
rw: () => import('dayjs/locale/rw.js'),
sd: () => import('dayjs/locale/sd.js'),
se: () => import('dayjs/locale/se.js'),
si: () => import('dayjs/locale/si.js'),
sk: () => import('dayjs/locale/sk.js'),
sl: () => import('dayjs/locale/sl.js'),
sq: () => import('dayjs/locale/sq.js'),
'sr-cyrl': () => import('dayjs/locale/sr-cyrl.js'),
sr: () => import('dayjs/locale/sr.js'),
ss: () => import('dayjs/locale/ss.js'),
'sv-fi': () => import('dayjs/locale/sv-fi.js'),
sv: () => import('dayjs/locale/sv.js'),
sw: () => import('dayjs/locale/sw.js'),
ta: () => import('dayjs/locale/ta.js'),
te: () => import('dayjs/locale/te.js'),
tet: () => import('dayjs/locale/tet.js'),
tg: () => import('dayjs/locale/tg.js'),
th: () => import('dayjs/locale/th.js'),
tk: () => import('dayjs/locale/tk.js'),
'tl-ph': () => import('dayjs/locale/tl-ph.js'),
tlh: () => import('dayjs/locale/tlh.js'),
tr: () => import('dayjs/locale/tr.js'),
tzl: () => import('dayjs/locale/tzl.js'),
'tzm-latn': () => import('dayjs/locale/tzm-latn.js'),
tzm: () => import('dayjs/locale/tzm.js'),
'ug-cn': () => import('dayjs/locale/ug-cn.js'),
uk: () => import('dayjs/locale/uk.js'),
ur: () => import('dayjs/locale/ur.js'),
'uz-latn': () => import('dayjs/locale/uz-latn.js'),
uz: () => import('dayjs/locale/uz.js'),
vi: () => import('dayjs/locale/vi.js'),
'x-pseudo': () => import('dayjs/locale/x-pseudo.js'),
yo: () => import('dayjs/locale/yo.js'),
'zh-cn': () => import('dayjs/locale/zh-cn.js'),
'zh-hk': () => import('dayjs/locale/zh-hk.js'),
'zh-tw': () => import('dayjs/locale/zh-tw.js'),
zh: () => import('dayjs/locale/zh.js'),
};
5 changes: 3 additions & 2 deletions src/settings/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import cloneDeep from 'lodash/cloneDeep';
import dayjs from '../dayjs';
import {normalizeTimeZone} from '../timeZone';

import {localeLoaders} from './locales';
import type {UpdateLocaleConfig} from './types';

class Settings {
Expand All @@ -22,8 +23,8 @@ class Settings {
if (!this.isLocaleLoaded(locale)) {
try {
const localeInLowerCase = locale.toLocaleLowerCase();
// https://github.com/iamkun/dayjs/issues/792#issuecomment-639961997
await import(`dayjs/locale/${localeInLowerCase}.js`);
const localeLoader = localeLoaders[localeInLowerCase];
await localeLoader();
this.loadedLocales.add(localeInLowerCase);
} catch (error) {
throw new Error(
Expand Down

0 comments on commit d9f46a8

Please sign in to comment.