From a894eccc004410d82d1b1d9aac122b3190343df7 Mon Sep 17 00:00:00 2001 From: Celine Kurpershoek Date: Tue, 18 Jan 2022 15:04:20 +0100 Subject: [PATCH 1/5] feat(missing-translations-check): add a start for validating the project messages vs the translated strings --- package.json | 3 +- src/cli.ts | 11 +++++- src/collect.ts | 22 ++++-------- src/utils/findjs.ts | 20 +++++++++++ src/validate.ts | 39 +++++++++++++++++++++ yarn.lock | 82 ++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 158 insertions(+), 19 deletions(-) create mode 100644 src/utils/findjs.ts create mode 100644 src/validate.ts diff --git a/package.json b/package.json index 00d4c3e..94a35d0 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,8 @@ "commander": "^7.0.0", "dotenv": "^8.2.0", "mkdirp": "^1.0.4", - "shelljs": "^0.8.4" + "shelljs": "^0.8.4", + "ts-node": "^10.4.0" }, "devDependencies": { "@types/commander": "^2.12.2", diff --git a/src/cli.ts b/src/cli.ts index f11531a..0744cbd 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -3,6 +3,7 @@ import upload from "./upload"; import download from "./download"; import collect from "./collect"; import deleteBranch from "./delete-branch"; +import validate from "./validate"; import config from "./config"; class BranchNameOption extends Option { @@ -18,7 +19,7 @@ const main = async (argv: string[]) => { program .name("mollie-crowdin") - .usage(" [options]") + .usage(" [options]") .version(version); program @@ -75,6 +76,14 @@ const main = async (argv: string[]) => { }); }); + program + .command("validate ") + .description("Validate if all translations keys have been translated") + // .addOption("languages") + .action(async (glob: string) => { + await validate(glob); + }); + program.parse(argv); }; diff --git a/src/collect.ts b/src/collect.ts index 2bd20be..557b28d 100644 --- a/src/collect.ts +++ b/src/collect.ts @@ -1,28 +1,18 @@ import { sync } from "mkdirp"; -import shell from "shelljs"; -import path from "path"; import config from "./config"; import log from "./utils/logging"; +import findjs from "./utils/findjs"; import prettify from "./utils/prettify"; export default async (glob: string) => { log.info("Extracting messages"); sync(config.INTL_DIR); - const cmd = [ - path.join(process.cwd(), "node_modules", ".bin", "formatjs"), - "extract", - `"${glob}"`, - "--out-file", - config.TRANSLATIONS_FILE, - "--format", - "crowdin", - ]; - - const { stderr } = shell.exec(cmd.join(" ")); - - if (stderr) { - log.error(stderr); + try { + await findjs(glob, config.TRANSLATIONS_FILE); + } catch (error) { + // @TODO: the error we get from findjs should be a string + log.error("Error: findjs could not get messages"); process.exit(1); } diff --git a/src/utils/findjs.ts b/src/utils/findjs.ts new file mode 100644 index 0000000..0e63f86 --- /dev/null +++ b/src/utils/findjs.ts @@ -0,0 +1,20 @@ +import shell from "shelljs"; +import path from "path"; + +export default async (glob: string, filename: string) => { + const cmd = [ + path.join(process.cwd(), "node_modules", ".bin", "formatjs"), + "extract", + `"${glob}"`, + "--out-file", + filename, + "--format", + "crowdin", + ]; + + const { stderr } = shell.exec(cmd.join(" ")); + + if (stderr) { + throw stderr; + } +}; diff --git a/src/validate.ts b/src/validate.ts new file mode 100644 index 0000000..3b4c21c --- /dev/null +++ b/src/validate.ts @@ -0,0 +1,39 @@ +/** + * Get all translation keys from project //collect + * Get all translations for languages + * Check if every language has the translation keys from project + */ + +import findjs from "./utils/findjs"; +import log from "./utils/logging"; +import fs from "fs"; +import config from "./config"; + +// probably we need some ts parser to get typescript files in node +import tsNode from "ts-node"; + +export default async (glob: string) => { + console.log("Validating messages"); + tsNode.register({}); + // @TODO: for testing purposes we created a temporary file + const temporaryFileName = "temp.json"; + + try { + await findjs(glob, temporaryFileName); + } catch (error) { + // @TODO: the error we get from findjs should be a string + log.error("Error: findjs could not get messages"); + process.exit(1); + } + + const projectStrings = fs.readFileSync(temporaryFileName, "utf-8"); + const projectStringsJSON = JSON.parse(projectStrings); + const { translationsMap } = require(config.TRANSLATIONS_DIR + "/de.ts"); + + // @TODO: as mvp just looping over keys to check if they exist + Object.keys(projectStringsJSON).forEach(key => { + if (!(key in translationsMap)) { + console.log("missing", key); + } + }); +}; diff --git a/yarn.lock b/yarn.lock index 04c5200..faad65d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -860,6 +860,18 @@ dependencies: axios "^0.21.1" +"@cspotcode/source-map-consumer@0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" + integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== + +"@cspotcode/source-map-support@0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" + integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== + dependencies: + "@cspotcode/source-map-consumer" "0.8.0" + "@formatjs/cli@^3.0.5": version "3.0.5" resolved "https://registry.yarnpkg.com/@formatjs/cli/-/cli-3.0.5.tgz#816203a7918bc2757e9f43ce38fde11095f1f237" @@ -1168,6 +1180,26 @@ dependencies: type-detect "4.0.8" +"@tsconfig/node10@^1.0.7": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" + integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + +"@tsconfig/node12@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" + integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + +"@tsconfig/node14@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" + integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + +"@tsconfig/node16@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" + integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== + "@types/babel__core@^7.1.7": version "7.1.12" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.12.tgz#4d8e9e51eb265552a7e4f1ff2219ab6133bdfb2d" @@ -1477,6 +1509,11 @@ acorn-walk@^6.0.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + acorn@^6.0.1: version "6.4.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" @@ -1487,6 +1524,11 @@ acorn@^7.1.0, acorn@^7.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== +acorn@^8.4.1: + version "8.7.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" + integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -1567,6 +1609,11 @@ anymatch@^3.0.3: normalize-path "^3.0.0" picomatch "^2.0.4" +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -2257,6 +2304,11 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -2422,6 +2474,11 @@ diff-sequences@^25.2.6: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg== +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" @@ -4574,7 +4631,7 @@ make-dir@^3.0.0, make-dir@^3.0.2: dependencies: semver "^6.0.0" -make-error@1.x: +make-error@1.x, make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -6355,6 +6412,24 @@ ts-jest@^25.3.1: semver "6.x" yargs-parser "18.x" +ts-node@^10.4.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7" + integrity sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A== + dependencies: + "@cspotcode/source-map-support" "0.7.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + yn "3.1.1" + tsconfig-paths@^3.9.0: version "3.9.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" @@ -6829,6 +6904,11 @@ yargs@^15.3.1: y18n "^4.0.0" yargs-parser "^18.1.2" +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" From 40fbfb46cbe75f44d2851dbdca310c74936dc432 Mon Sep 17 00:00:00 2001 From: Willem Stuursma Date: Thu, 20 Jan 2022 16:15:07 +0100 Subject: [PATCH 2/5] Basic validation of translation files --- package.json | 2 +- src/collect.ts | 9 +- src/utils/{findjs.ts => formatjs.ts} | 4 +- src/validate.ts | 79 +++++++--- yarn.lock | 213 ++++++++++++++++----------- 5 files changed, 198 insertions(+), 109 deletions(-) rename src/utils/{findjs.ts => formatjs.ts} (87%) diff --git a/package.json b/package.json index 94a35d0..f35ff66 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "dotenv": "^8.2.0", "mkdirp": "^1.0.4", "shelljs": "^0.8.4", - "ts-node": "^10.4.0" + "tempy": "^2.0.0" }, "devDependencies": { "@types/commander": "^2.12.2", diff --git a/src/collect.ts b/src/collect.ts index 557b28d..4989b11 100644 --- a/src/collect.ts +++ b/src/collect.ts @@ -1,18 +1,17 @@ import { sync } from "mkdirp"; import config from "./config"; import log from "./utils/logging"; -import findjs from "./utils/findjs"; +import formatjs from "./utils/formatjs"; import prettify from "./utils/prettify"; export default async (glob: string) => { log.info("Extracting messages"); - sync(config.INTL_DIR); + sync(config.INTL_DIR); // Create storage dir for transations if not exists try { - await findjs(glob, config.TRANSLATIONS_FILE); + await formatjs(glob, config.TRANSLATIONS_FILE); } catch (error) { - // @TODO: the error we get from findjs should be a string - log.error("Error: findjs could not get messages"); + log.error(`FormatJS was unable to scan the source files: ${error.message}`); process.exit(1); } diff --git a/src/utils/findjs.ts b/src/utils/formatjs.ts similarity index 87% rename from src/utils/findjs.ts rename to src/utils/formatjs.ts index 0e63f86..21f66e8 100644 --- a/src/utils/findjs.ts +++ b/src/utils/formatjs.ts @@ -7,7 +7,7 @@ export default async (glob: string, filename: string) => { "extract", `"${glob}"`, "--out-file", - filename, + `"${filename}"`, "--format", "crowdin", ]; @@ -15,6 +15,6 @@ export default async (glob: string, filename: string) => { const { stderr } = shell.exec(cmd.join(" ")); if (stderr) { - throw stderr; + throw new Error(stderr); } }; diff --git a/src/validate.ts b/src/validate.ts index 3b4c21c..53a5e17 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -3,37 +3,78 @@ * Get all translations for languages * Check if every language has the translation keys from project */ - -import findjs from "./utils/findjs"; +import config from "./config"; +import formatjs from "./utils/formatjs"; import log from "./utils/logging"; import fs from "fs"; -import config from "./config"; - -// probably we need some ts parser to get typescript files in node -import tsNode from "ts-node"; +import path from "path"; +import * as ts from "typescript"; +// import tempy from "tempy"; +import chalk from "chalk"; export default async (glob: string) => { - console.log("Validating messages"); - tsNode.register({}); - // @TODO: for testing purposes we created a temporary file - const temporaryFileName = "temp.json"; + log.info("Collecting message keys from source files..."); + + const language = "de"; + + /* + * Create a temporary file for FormatJS, this way we won't mess with the existing file which is under version control. + */ + const temporaryFileName = "tempy.json" // tempy.file({extension: "json"}); try { - await findjs(glob, temporaryFileName); + await formatjs(glob, temporaryFileName); } catch (error) { - // @TODO: the error we get from findjs should be a string - log.error("Error: findjs could not get messages"); + log.error(`FormatJS was unable to scan the source files: ${error.message}`); process.exit(1); } - const projectStrings = fs.readFileSync(temporaryFileName, "utf-8"); - const projectStringsJSON = JSON.parse(projectStrings); - const { translationsMap } = require(config.TRANSLATIONS_DIR + "/de.ts"); + const projectMessagesJson = fs.readFileSync(temporaryFileName, "utf-8"); + fs.unlinkSync(temporaryFileName); // File is no longer needed. + + log.info(`Retrieving ${chalk.bold(language)} translations from project...`); + + const projectMessages = JSON.parse(projectMessagesJson); + const messageKeys = Object.keys(projectMessages); + + const projectTranslations = getTranslatedMessages(language); // @TODO: as mvp just looping over keys to check if they exist - Object.keys(projectStringsJSON).forEach(key => { - if (!(key in translationsMap)) { - console.log("missing", key); + // improvements; ensure keys are different + // have the correct placeholders + + let badApples = 0; + + messageKeys.forEach(messageKey => { + if (!(messageKey in projectTranslations)) { + + log.error(`Missing message key ${chalk.bold(messageKey)} in language ${chalk.bold(language)}.`); + + badApples++; } }); + + log.info(`Completed check, all ${messageKeys.length} keys are present for translation.`); + log.info(`Found ${badApples} problems with the translations.`); + + if (badApples > 0) { + process.exit(1); + } }; + +function getTranslatedMessages(lang: string) +{ + const translationsFile = path.join(config.TRANSLATIONS_DIR, lang + ".ts"); + + + const translationTypeScriptExport = fs.readFileSync(translationsFile,"utf-8"); + + const roo = ts.transpileModule(translationTypeScriptExport, { + compilerOptions: { + removeComments: true, + module: ts.ModuleKind.CommonJS + } + }); + + return eval(roo.outputText); +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index a9c54fa..b4b3f86 100644 --- a/yarn.lock +++ b/yarn.lock @@ -860,18 +860,6 @@ dependencies: axios "^0.21.1" -"@cspotcode/source-map-consumer@0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" - integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== - -"@cspotcode/source-map-support@0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" - integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== - dependencies: - "@cspotcode/source-map-consumer" "0.8.0" - "@formatjs/cli@^3.0.5": version "3.0.5" resolved "https://registry.yarnpkg.com/@formatjs/cli/-/cli-3.0.5.tgz#816203a7918bc2757e9f43ce38fde11095f1f237" @@ -1180,26 +1168,6 @@ dependencies: type-detect "4.0.8" -"@tsconfig/node10@^1.0.7": - version "1.0.8" - resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" - integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== - -"@tsconfig/node12@^1.0.7": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" - integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== - -"@tsconfig/node14@^1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" - integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== - -"@tsconfig/node16@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" - integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== - "@types/babel__core@^7.1.7": version "7.1.12" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.12.tgz#4d8e9e51eb265552a7e4f1ff2219ab6133bdfb2d" @@ -1509,11 +1477,6 @@ acorn-walk@^6.0.1: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== -acorn-walk@^8.1.1: - version "8.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" - integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== - acorn@^6.0.1: version "6.4.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" @@ -1524,11 +1487,6 @@ acorn@^7.1.0, acorn@^7.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.4.1: - version "8.7.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf" - integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ== - aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -1609,11 +1567,6 @@ anymatch@^3.0.3: normalize-path "^3.0.0" picomatch "^2.0.4" -arg@^4.1.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1665,6 +1618,11 @@ array-includes@^3.1.1, array-includes@^3.1.2: get-intrinsic "^1.0.1" is-string "^1.0.5" +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -2304,11 +2262,6 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" -create-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -2329,6 +2282,13 @@ cross-spawn@^7.0.0: shebang-command "^2.0.0" which "^2.0.1" +crypto-random-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-4.0.0.tgz#5a3cc53d7dd86183df5da0312816ceeeb5bb1fc2" + integrity sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA== + dependencies: + type-fest "^1.0.1" + cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -2454,6 +2414,20 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" +del@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" + integrity sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ== + dependencies: + globby "^11.0.1" + graceful-fs "^4.2.4" + is-glob "^4.0.1" + is-path-cwd "^2.2.0" + is-path-inside "^3.0.2" + p-map "^4.0.0" + rimraf "^3.0.2" + slash "^3.0.0" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -2474,10 +2448,12 @@ diff-sequences@^25.2.6: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg== -diff@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" doctrine@1.5.0: version "1.5.0" @@ -3007,6 +2983,17 @@ fast-glob@^3.2.4: micromatch "^4.0.2" picomatch "^2.2.1" +fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -3264,6 +3251,13 @@ glob-parent@^5.0.0, glob-parent@^5.1.0: dependencies: is-glob "^4.0.1" +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" @@ -3293,6 +3287,18 @@ globalyzer@0.1.0: resolved "https://registry.yarnpkg.com/globalyzer/-/globalyzer-0.1.0.tgz#cb76da79555669a1519d5a8edf093afaa0bf1465" integrity sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q== +globby@^11.0.1: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + globrex@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098" @@ -3455,6 +3461,11 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== +ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -3701,6 +3712,16 @@ is-obj@^1.0.1: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= +is-path-cwd@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== + +is-path-inside@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + is-plain-obj@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" @@ -3743,6 +3764,11 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + is-string@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" @@ -4631,7 +4657,7 @@ make-dir@^3.0.0, make-dir@^3.0.2: dependencies: semver "^6.0.0" -make-error@1.x, make-error@^1.1.1: +make-error@1.x: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== @@ -4667,7 +4693,7 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.3.0: +merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -4699,6 +4725,14 @@ micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" +micromatch@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + mime-db@1.45.0: version "1.45.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" @@ -5188,6 +5222,11 @@ picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1, picomatch@^2.2.2: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== +picomatch@^2.2.3: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -5675,7 +5714,7 @@ rimraf@2.6.3: dependencies: glob "^7.1.3" -rimraf@^3.0.0: +rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -6278,6 +6317,22 @@ table@^5.2.3: slice-ansi "^2.1.0" string-width "^3.0.0" +temp-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e" + integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg== + +tempy@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tempy/-/tempy-2.0.0.tgz#c434b89486e112151d5e91ef25592c8ee6fec4f6" + integrity sha512-m+QReZVhpa0Y56fmfoLFRZN4aDFdd3qVd8a9k3RfyTw/1utVYNg+Ar4BY6l4/TlkhYCCJFfhYWt9uy0127buJg== + dependencies: + del "^6.0.0" + is-stream "^3.0.0" + temp-dir "^2.0.0" + type-fest "^2.0.0" + unique-string "^3.0.0" + terminal-link@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" @@ -6416,24 +6471,6 @@ ts-jest@^25.3.1: semver "6.x" yargs-parser "18.x" -ts-node@^10.4.0: - version "10.4.0" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7" - integrity sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A== - dependencies: - "@cspotcode/source-map-support" "0.7.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - yn "3.1.1" - tsconfig-paths@^3.9.0: version "3.9.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" @@ -6567,6 +6604,16 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +type-fest@^1.0.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" + integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== + +type-fest@^2.0.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.10.0.tgz#0ee9c3cd411efb3bba434065d32235592d3644cf" + integrity sha512-u2yreDMllFI3VCpWt0rKrGs/E2LO0YHBwiiOIj+ilQh9+ALMaa4lNBSdoDvuHN3cbKcYk9L1BXP49x9RT+o/SA== + typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -6627,6 +6674,13 @@ uniq@^1.0.1: resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= +unique-string@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-3.0.0.tgz#84a1c377aff5fd7a8bc6b55d8244b2bd90d75b9a" + integrity sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ== + dependencies: + crypto-random-string "^4.0.0" + universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -6908,11 +6962,6 @@ yargs@^15.3.1: y18n "^4.0.0" yargs-parser "^18.1.2" -yn@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" - integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== - yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" From dcf5dbb9df1d73e1593e0f611e960e732baeb8ed Mon Sep 17 00:00:00 2001 From: Willem Stuursma Date: Thu, 20 Jan 2022 16:27:16 +0100 Subject: [PATCH 3/5] Add check if the translation is the same as the source message --- src/validate.ts | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/validate.ts b/src/validate.ts index 53a5e17..871f390 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -47,9 +47,18 @@ export default async (glob: string) => { messageKeys.forEach(messageKey => { if (!(messageKey in projectTranslations)) { + /* + * Message is not present in the translations file. + */ + log.error(`Missing message ${chalk.bold(messageKey)} in language ${chalk.bold(language)}.`); - log.error(`Missing message key ${chalk.bold(messageKey)} in language ${chalk.bold(language)}.`); + badApples++; + } else if (projectMessages[messageKey].message == projectTranslations[messageKey]) { + /* + * Message is the same in the translations file as in the source file. + */ + log.error(`Untranslated message ${chalk.bold(messageKey)} in language ${chalk.bold(language)}.`); badApples++; } }); @@ -64,17 +73,19 @@ export default async (glob: string) => { function getTranslatedMessages(lang: string) { + /* + * Only Typescript is supported, sorry! + */ const translationsFile = path.join(config.TRANSLATIONS_DIR, lang + ".ts"); - const translationTypeScriptExport = fs.readFileSync(translationsFile,"utf-8"); - const roo = ts.transpileModule(translationTypeScriptExport, { + const transpileOutput = ts.transpileModule(translationTypeScriptExport, { compilerOptions: { removeComments: true, module: ts.ModuleKind.CommonJS } }); - return eval(roo.outputText); + return eval(transpileOutput.outputText); } \ No newline at end of file From ee62e84b073064e0171080b9f349348c318ef96f Mon Sep 17 00:00:00 2001 From: Willem Stuursma Date: Thu, 20 Jan 2022 16:38:48 +0100 Subject: [PATCH 4/5] Allow language to be specified via the options --- src/cli.ts | 8 +++---- src/validate.ts | 55 ++++++++++++++++++++++++------------------------- 2 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/cli.ts b/src/cli.ts index 0744cbd..401758a 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -78,10 +78,10 @@ const main = async (argv: string[]) => { program .command("validate ") - .description("Validate if all translations keys have been translated") - // .addOption("languages") - .action(async (glob: string) => { - await validate(glob); + .description("Validate if all translations keys have been translated for a set of languages") + .requiredOption("-l, --language ", "Language to validate, e.g. \"nl\".") + .action(async (glob: string, options) => { + await validate(glob, options); }); program.parse(argv); diff --git a/src/validate.ts b/src/validate.ts index 871f390..184e9c3 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -12,11 +12,9 @@ import * as ts from "typescript"; // import tempy from "tempy"; import chalk from "chalk"; -export default async (glob: string) => { +export default async (glob: string, options: { language: string[]; }) => { log.info("Collecting message keys from source files..."); - const language = "de"; - /* * Create a temporary file for FormatJS, this way we won't mess with the existing file which is under version control. */ @@ -32,38 +30,39 @@ export default async (glob: string) => { const projectMessagesJson = fs.readFileSync(temporaryFileName, "utf-8"); fs.unlinkSync(temporaryFileName); // File is no longer needed. - log.info(`Retrieving ${chalk.bold(language)} translations from project...`); + let badApples = 0; - const projectMessages = JSON.parse(projectMessagesJson); - const messageKeys = Object.keys(projectMessages); + options.language.forEach((language: string) => { - const projectTranslations = getTranslatedMessages(language); + log.info(`Retrieving ${chalk.bold(language)} translations from project...`); - // @TODO: as mvp just looping over keys to check if they exist - // improvements; ensure keys are different - // have the correct placeholders + const projectMessages = JSON.parse(projectMessagesJson); + const messageKeys = Object.keys(projectMessages); - let badApples = 0; + const projectTranslations = getTranslatedMessages(language); - messageKeys.forEach(messageKey => { - if (!(messageKey in projectTranslations)) { - /* - * Message is not present in the translations file. - */ - log.error(`Missing message ${chalk.bold(messageKey)} in language ${chalk.bold(language)}.`); - - badApples++; - } else if (projectMessages[messageKey].message == projectTranslations[messageKey]) { - - /* - * Message is the same in the translations file as in the source file. - */ - log.error(`Untranslated message ${chalk.bold(messageKey)} in language ${chalk.bold(language)}.`); - badApples++; - } + // @TODO: as mvp just looping over keys to check if they exist + // have the correct placeholders + + messageKeys.forEach(messageKey => { + if (!(messageKey in projectTranslations)) { + /* + * Message is not present in the translations file. + */ + log.error(`Missing message ${chalk.bold(messageKey)} in language ${chalk.bold(language)}.`); + + badApples++; + } else if (projectMessages[messageKey].message == projectTranslations[messageKey]) { + + /* + * Message is the same in the translations file as in the source file. + */ + log.error(`Untranslated message ${chalk.bold(messageKey)} in language ${chalk.bold(language)}.`); + badApples++; + } + }); }); - log.info(`Completed check, all ${messageKeys.length} keys are present for translation.`); log.info(`Found ${badApples} problems with the translations.`); if (badApples > 0) { From 4f09641d9640a44441ccd549475ae741e08c3919 Mon Sep 17 00:00:00 2001 From: Willem Stuursma Date: Mon, 24 Jan 2022 16:00:58 +0100 Subject: [PATCH 5/5] Fix eslint problems --- src/cli.ts | 9 +++++++-- src/validate.ts | 44 +++++++++++++++++++++++++++++--------------- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/cli.ts b/src/cli.ts index 401758a..88378ce 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -78,8 +78,13 @@ const main = async (argv: string[]) => { program .command("validate ") - .description("Validate if all translations keys have been translated for a set of languages") - .requiredOption("-l, --language ", "Language to validate, e.g. \"nl\".") + .description( + "Validate if all translations keys have been translated for a set of languages" + ) + .requiredOption( + "-l, --language ", + 'Language to validate, e.g. "nl".' + ) .action(async (glob: string, options) => { await validate(glob, options); }); diff --git a/src/validate.ts b/src/validate.ts index 184e9c3..f57b896 100644 --- a/src/validate.ts +++ b/src/validate.ts @@ -9,16 +9,15 @@ import log from "./utils/logging"; import fs from "fs"; import path from "path"; import * as ts from "typescript"; -// import tempy from "tempy"; import chalk from "chalk"; -export default async (glob: string, options: { language: string[]; }) => { +export default async (glob: string, options: { language: string[] }) => { log.info("Collecting message keys from source files..."); /* * Create a temporary file for FormatJS, this way we won't mess with the existing file which is under version control. */ - const temporaryFileName = "tempy.json" // tempy.file({extension: "json"}); + const temporaryFileName = "messages.json.tmp"; try { await formatjs(glob, temporaryFileName); @@ -32,8 +31,7 @@ export default async (glob: string, options: { language: string[]; }) => { let badApples = 0; - options.language.forEach((language: string) => { - + options.language.forEach((language: string): void => { log.info(`Retrieving ${chalk.bold(language)} translations from project...`); const projectMessages = JSON.parse(projectMessagesJson); @@ -49,15 +47,24 @@ export default async (glob: string, options: { language: string[]; }) => { /* * Message is not present in the translations file. */ - log.error(`Missing message ${chalk.bold(messageKey)} in language ${chalk.bold(language)}.`); + log.error( + `Missing message ${chalk.bold(messageKey)} in language ${chalk.bold( + language + )}.` + ); badApples++; - } else if (projectMessages[messageKey].message == projectTranslations[messageKey]) { - + } else if ( + projectMessages[messageKey].message === projectTranslations[messageKey] + ) { /* * Message is the same in the translations file as in the source file. */ - log.error(`Untranslated message ${chalk.bold(messageKey)} in language ${chalk.bold(language)}.`); + log.error( + `Untranslated message ${chalk.bold( + messageKey + )} in language ${chalk.bold(language)}.` + ); badApples++; } }); @@ -70,21 +77,28 @@ export default async (glob: string, options: { language: string[]; }) => { } }; -function getTranslatedMessages(lang: string) -{ +/** + * Get the translations that are in the project and convert them to an object. Returns an object with the keys being + * the message keys and each value being an object with the keys message and optionally description. + * @param lang + */ +function getTranslatedMessages(lang: string): object { /* * Only Typescript is supported, sorry! */ const translationsFile = path.join(config.TRANSLATIONS_DIR, lang + ".ts"); - const translationTypeScriptExport = fs.readFileSync(translationsFile,"utf-8"); + const translationTypeScriptExport = fs.readFileSync( + translationsFile, + "utf-8" + ); const transpileOutput = ts.transpileModule(translationTypeScriptExport, { compilerOptions: { removeComments: true, - module: ts.ModuleKind.CommonJS - } + module: ts.ModuleKind.CommonJS, + }, }); return eval(transpileOutput.outputText); -} \ No newline at end of file +}